美文网首页
用Logistic回归分类模型判断用户所处运动状态

用Logistic回归分类模型判断用户所处运动状态

作者: apricoter | 来源:发表于2019-02-20 18:08 被阅读26次

    优点:
    计算代价不高,易于理解和实现。

    缺点:
    容易产生欠拟合;
    分类精度可能不高。

    应用领域:
    用于二分类领域,可以得出概率值,适用于根据分类概率排名的领域,如搜索排名等;
    Logistic 回归的扩展 softmax 可以应用于多分类领域,如手写字识别等;
    信用评估;
    测量市场营销的成功度;
    预测某个产品的收益;
    特定的某天是否会发生地震。
    通过手机设备搜集的用户运动数据,有六个与运动有关的自变量,其中3个与加速度有关,3个与运动方向有关

    通过sklearn的子模块linear_model中的Logistic回归模型

    # -----------------------第一步 建模 ----------------------- #
    #导入第三方模块
    import numpy as np
    import pandas as pd
    from sklearn import linear_model
    from sklearn import model_selection
    #读取数据
    sports=pd.read_csv("F:\Run or Walk.csv")
    sports.head()
    
    #处理数据,构建自变量矩阵
    X=sports.ix[:,sports.columns[4:]]
    X.head()
    
    #提取y变量
    y=sports.activity
    y.head()
    
    #拆分数据为训练集(75%)和测试集(25%)
    X_train,X_test,y_train,y_test=model_selection.train_test_split(X,y,test_size=0.25,random_state=1234)
    #利用训练集建模
    sklearn_logistic=linear_model.LogisticRegression()
    sklearn_logistic.fit(X_train,y_train)
    #返回模型的各个参数
    print(sklearn_logistic.intercept_,sklearn_logistic.coef_)
    
    # -----------------------第二步 预测构建混淆矩阵 ----------------------- #
    # 模型预测
    sklearn_predict = sklearn_logistic.predict(X_test)
    sklearn_predict
    
    # 预测结果统计
    pd.Series(sklearn_predict).head()
    
    pd.Series(sklearn_predict).value_counts()
    

    其中判断步行状态的样本有12121个,跑步状态的样本有10026个

    # 导入第三方模块
    from sklearn import metrics
    # 混淆矩阵
    cm = metrics.confusion_matrix(y_test, sklearn_predict, labels = [0,1])
    cm
    

    行表示实际的运动状态,列表示模型预测的运动状态

    # -----------------------第三步 绘制ROC曲线 ----------------------- #
    Accuracy = metrics.scorer.accuracy_score(y_test, sklearn_predict)
    Sensitivity = metrics.scorer.recall_score(y_test, sklearn_predict)
    Specificity = metrics.scorer.recall_score(y_test, sklearn_predict, pos_label=0)
    print('模型准确率为%.2f%%:' %(Accuracy*100))
    print('正例覆盖率为%.2f%%' %(Sensitivity*100))
    print('负例覆盖率为%.2f%%' %(Specificity*100))
    

    整体的预测准确率比较高

    还可以对混淆矩阵做可视化展现

    # 混淆矩阵的可视化
    # 导入第三方模块
    import seaborn as sns
    import matplotlib.pyplot as plt
    # 绘制热力图
    sns.heatmap(cm, annot = True, fmt = '.2e',cmap = 'GnBu')
    # 图形显示
    plt.show()
    

    颜色越深的区块代表样本量越多,从图中看出,主对角线上的区块颜色要比其他地方深很多,说明正确预测正例和负例的样本数目都很大

    # y得分为模型预测正例的概率
    y_score = sklearn_logistic.predict_proba(X_test)[:,1]
    # 计算不同阈值下,fpr和tpr的组合值,其中fpr表示1-Specificity,tpr表示Sensitivity
    fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)
    # 计算AUC的值
    roc_auc = metrics.auc(fpr,tpr)
    
    # 绘制面积图
    plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
    # 添加边际线
    plt.plot(fpr, tpr, color='black', lw = 1)
    # 添加对角线
    plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
    # 添加文本信息
    plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
    # 添加x轴与y轴标签
    plt.xlabel('1-Specificity')
    plt.ylabel('Sensitivity')
    # 显示图形
    plt.show()
    

    曲线下面积高达0.93,远远超过0.8,认定回归模型是合理的

    # -----------------------第四步 绘制K-S曲线 ----------------------- #
    # 自定义绘制ks曲线的函数
    def plot_ks(y_test, y_score, positive_flag):
        # 对y_test,y_score重新设置索引
        y_test.index = np.arange(len(y_test))
        #y_score.index = np.arange(len(y_score))
        # 构建目标数据集
        target_data = pd.DataFrame({'y_test':y_test, 'y_score':y_score})
        # 按y_score降序排列
        target_data.sort_values(by = 'y_score', ascending = False, inplace = True)
        # 自定义分位点
        cuts = np.arange(0.1,1,0.1)
        # 计算各分位点对应的Score值
        index = len(target_data.y_score)*cuts
        scores = target_data.y_score.iloc[index.astype('int')]
        # 根据不同的Score值,计算Sensitivity和Specificity
        Sensitivity = []
        Specificity = []
        for score in scores:
            # 正例覆盖样本数量与实际正例样本量
            positive_recall = target_data.loc[(target_data.y_test == positive_flag) & (target_data.y_score>score),:].shape[0]
            positive = sum(target_data.y_test == positive_flag)
            # 负例覆盖样本数量与实际负例样本量
            negative_recall = target_data.loc[(target_data.y_test != positive_flag) & (target_data.y_score<=score),:].shape[0]
            negative = sum(target_data.y_test != positive_flag)
            Sensitivity.append(positive_recall/positive)
            Specificity.append(negative_recall/negative)
        # 构建绘图数据
        plot_data = pd.DataFrame({'cuts':cuts,'y1':1-np.array(Specificity),'y2':np.array(Sensitivity), 
                                  'ks':np.array(Sensitivity)-(1-np.array(Specificity))})
        # 寻找Sensitivity和1-Specificity之差的最大值索引
        max_ks_index = np.argmax(plot_data.ks)
        plt.plot([0]+cuts.tolist()+[1], [0]+plot_data.y1.tolist()+[1], label = '1-Specificity')
        plt.plot([0]+cuts.tolist()+[1], [0]+plot_data.y2.tolist()+[1], label = 'Sensitivity')
        # 添加参考线
        plt.vlines(plot_data.cuts[max_ks_index], ymin = plot_data.y1[max_ks_index], 
                   ymax = plot_data.y2[max_ks_index], linestyles = '--')
        # 添加文本信息
        plt.text(x = plot_data.cuts[max_ks_index]+0.01,
                 y = plot_data.y1[max_ks_index]+plot_data.ks[max_ks_index]/2,
                 s = 'KS= %.2f' %plot_data.ks[max_ks_index])
        # 显示图例
        plt.legend()
        # 显示图形
        plt.show()
    
    # 调用自定义函数,绘制K-S曲线
    plot_ks(y_test = y_test, y_score = y_score, positive_flag = 1)
    

    中间的虚线表示在40%的分位点,计算最大差为0.71,即KS值,大于0.4,模型拟合效果不错。

    相关文章

      网友评论

          本文标题:用Logistic回归分类模型判断用户所处运动状态

          本文链接:https://www.haomeiwen.com/subject/tlyhyqtx.html