美文网首页
Task 01|基于逻辑回归的分类预测

Task 01|基于逻辑回归的分类预测

作者: 杏仁小核桃 | 来源:发表于2020-08-20 23:04 被阅读0次

    知识背景

    关于逻辑回归的几个问题

    逻辑回归相比线性回归,有何异同?

    逻辑回归和线性回归最大的不同点是逻辑回归解决的是分类问题,而线性回归解决的是回归问题。

    逻辑回归又可以认为是广义线性回归的一种特殊形式,其特殊之处在于目标(label/target)的取值服从二元分布。

    所谓逻辑回归是一种特殊的广义线性回归,我们可以通过狭义线性回归到逻辑回归的转化过程来理解。

    狭义线性回归的表达式可表示为:
    y = w*x+b

    如果我们希望这个模型可以对二分类任务做出预测,即满足0,1分布,那么希望预测出来的值经过某种转换后可以分布在0,1两个值附近。
    sigmoid函数可以做这样的转换,sigmoid函数的表达式为:

    \delta(z) = \frac {1}{1+e^{-z}}

    令:y=\delta(z)

    则:\log\frac{y}{1-y}=z=w*x+b

    可以看出,狭义线性回归采用y作为预测结果,逻辑回归则采用\log\frac{y}{1-y}作为预测结果。

    逻辑回归还可以表示为:
    y=sigmoid(w*x+b)

    通过以上步骤推演,我们知道逻辑回归就是在线性回归的基础上,再做一个sigmoid计算。所以它们都可以用相同的方法,比如梯度下降来求解参数。


    回归问题常用的性能度量指标

    • 点对点误差
      • MSE(Mean Square Error)均方误差 -- 预测数据和原始数据对应误差的平方和的均值
      • RMSE(Root Mean Square Error)-- 观测值与真实偏差的平方和与观测次数n比值的平方根,用来衡量观测值同真值之间的偏差
      • MAE(Mean Absolute Error)-- 计算模型输出与真实值之间的平均绝对误差
    • 带归一化的误差求解方法
      • MAPE(Mean Absolute Percentage Error)-- 不仅考虑预测值与真实值误差,还考虑误差与真实值之间的比例
      • MASE(Mean Absolute Scaled Error)-- 平均平方百分比误差
    • 点对面误差
      • R-Square决定系数(coefficient of determination)

    分类问题常用的性能度量指标

    • 准确率:

      所有预测正确的样本与所有样本的比例
      Accuracy=\frac{TP+TN}{TP+FN+TN+FP}

    • 精确率:

      预测为正的样本中有多少是真正的正样本
      Precision=\frac{TP}{TP+FP}

    • 召回率:

      样本中的正例有多少被预测正确了
      Recall=\frac{TP}{TP+FN}

    • F1值:

      精确率和召回率的调和值
      F1=2*\frac{Precision*Recall}{Precision+Recall}

    • AUC(Area Under Curve):

      ROC曲线下的面积,ROC曲线是通过取不同的阈值来分别计算在每个阈值下,FPR(False Positive Rate)和TPR(True Positive Rate)的值来绘制的。


    逻辑回归处理多标签分类问题时,一般怎么做?

    如果y不是在[0,1]中取值,而是在k个类别中取值,这时问题就变成一个多分类问题。有两种方式可以处理该问题:

    • 当K个类别不是互斥的时候,即存在样本可能属于多个标签的情况,我们可以训练k个二分类的逻辑回归分类器。第i个分类器用以区分样本是否可以归为第i类,训练分类器时需要把标签重新整理为“第i类标签”和“非第i类标签”两类。通过这样的方法,我们就可以解决每个样本可能拥有多个标签的情况。
    • 当K个类别互斥的时候,即每个样本只属于一个标签,可以假设每个样本属于不同标签的概率服从于几何分布,使用多项式逻辑回归(Softmax Regression)来进行分类。

    通过几个问题了解了逻辑回归后,接着就上代码来体验一番吧
    本文将使用sklearn和著名的鸢尾花数据集来用逻辑回归做分类预测

    学习目标

    • 了解逻辑回归理论
    • 掌握sklearn中LogisticsRegression的基本用法

    Step 1:读取数据

    import numpy as np
    import pandas as pd
    import seaborn as sns
    import matplotlib.pyplot as plt
    
    #load data
    from sklearn.datasets import load_iris
    
    data = load_iris() # 数据特征
    iris_labels = data.target # 数据标签
    iris_names = data.target_names #iris分类对应的名字
    iris_features = pd.DataFrame(data=data.data, columns=data.feature_names)
    

    查看数据基本信息,大致了解一下特征和标签

    # 查看数据基本信息
    
    iris_features.info()
    
    print(iris_features.head())
    print(iris_names)
    

    结果如下:

    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 150 entries, 0 to 149
    Data columns (total 4 columns):
     #   Column             Non-Null Count  Dtype  
    ---  ------             --------------  -----  
     0   sepal length (cm)  150 non-null    float64
     1   sepal width (cm)   150 non-null    float64
     2   petal length (cm)  150 non-null    float64
     3   petal width (cm)   150 non-null    float64
    dtypes: float64(4)
    memory usage: 4.8 KB
       sepal length (cm)  sepal width (cm)  petal length (cm)  petal width (cm)
    0                5.1               3.5                1.4               0.2
    1                4.9               3.0                1.4               0.2
    2                4.7               3.2                1.3               0.2
    3                4.6               3.1                1.5               0.2
    4                5.0               3.6                1.4               0.2
    ['setosa' 'versicolor' 'virginica']
    

    如上基本信息我们了解到:

    1. 一共有150个样本
    2. 每个样本有4个特征,都是float型。sepal length, sepal width, petal lengthpetal width分别代表花萼和花瓣的长宽。通过外观的长宽大小来判断植物的种类,也很符合人的学习习惯。
    3. 一共有3个标签:setosa, versicolor, virginica,分别代表3种花,在数据中表示为0, 1, 2.

    再看看数据集中3类样本分别占的比例:

    pd.Series(iris_labels).value_counts()
    

    结果发现:

    2    50
    1    50
    0    50
    

    一共150个样本,3种花每种分别50个,分布还是很平均的嘛。

    Step 2:数据可视化

    一图胜千言,通过可视化的方法能更快更直观地了解数据,找到数据的特征,能让数据的学习和训练达到事半功倍的效果。

    # 准备数据,为了不影响原数据,我们用原数据集的拷贝来画图
    iris_all = iris_features.copy()
    iris_all['label'] = iris_labels
    
    # 查看数据分布
    sns.pairplot(data=iris_all, diag_kind='hist', hue='label')
    plt.show()
    
    特征与标签组合的散点图

    从图中可以看出:

    • petal width和petal length的区分能力比较好
    • 蓝色的这个类别主要集中在左下,集中在petal width和petal length的值比较小的部分,说明这个种类的花瓣又窄又短

    通过箱线图来查看一下各个特征的数据分布:

    # 从箱线图查看各个特征数据分布
    
    for col in iris_features.columns:
        sns.boxplot(x='label', y = col, saturation=0.5, palette = 'pastel', data=iris_all)
        plt.title(col)
        plt.show()
    
    petal length (cm) petal width (cm) sepal length (cm) sepal width (cm)

    通过数据分布也能明显看出来,petal length 和 petal width 的数据在各类别内集中,且在各类别间有较明显的区分度。
    选取前三个特征绘制三维散点图:

    from mpl_toolkits.mplot3d import Axes3D
    
    fig = plt.figure(figsize=(10, 8))
    ax = fig.add_subplot(111, projection='3d')
    
    iris_all_class0 = iris_all[iris_all['label']==0].values
    iris_all_class1 = iris_all[iris_all['label']==1].values
    iris_all_class2 = iris_all[iris_all['label']==2].values
    
    ax.scatter(iris_all_class0[:,0], iris_all_class0[:,1], iris_all_class0[:,2], label='setosa')
    ax.scatter(iris_all_class1[:,0], iris_all_class1[:,1], iris_all_class1[:,2], label='versicolor')
    ax.scatter(iris_all_class2[:,0], iris_all_class2[:,1], iris_all_class2[:,2], label='virginica')
    
    ax.set_xlabel('sepal length')
    ax.set_ylabel('sepal width')
    ax.set_zlabel('petal length')
    
    plt.legend()
    plt.show()
    
    三维散点图

    三维散点图更清晰地看到了类别的区分。

    Step 3:逻辑回归二分类训练

    先用逻辑回归进行二分类训练,训练出一个区分0、1标签的分类器。

    # 分割数据集和训练集
    from sklearn.model_selection import train_test_split
    
    # 先选取类别为0和1的数据,进行二分类训练
    iris_features_part = iris_all[iris_all['label']<2]
    iris_labels_part = iris_features_part.pop('label').tolist()
    
    x_train, x_test, y_train, y_test = train_test_split(iris_features_part, iris_labels_part, test_size=0.3, random_state=2020)
    

    参数解释:

    • test_size: test数据占的比例,例如0.3表示test数据占30%,train数据占70%
    • random_state: 随机数种子,代表该组随机数的编号,在重复实验中能保证每次得到的随机数是相同的。当为None时,每次得到的结果就会是随机的。

    分好数据集,就可以用逻辑回归模型来训练了

    from sklearn.linear_model import LogisticRegression
    
    clf = LogisticRegression(random_state=0, solver='lbfgs')
    clf.fit(x_train, y_train)
    

    参数solver代表逻辑回归损失函数的优化方法,分别有4种方法,官方文档建议如下:

    • ‘liblinear’:Small dataset or L1 penalty
    • ‘lbfgs’、‘newton-cg’ or ‘sag’:Multinomial loss or large dataset
    • ‘sag’:Very Large dataset
      根据数据集的情况,我们选择了‘lbfgs’,这是拟牛顿法的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。
    # 在测试集和训练集上预测
    train_pred = clf.predict(x_train)
    test_pred = clf.predict(x_test)
    
    # 预测结果检验
    from sklearn import metrics
    
    print('The accuracy in train data: ', metrics.accuracy_score(y_train, train_pred))
    print('The accuracy in test data: ', metrics.accuracy_score(y_test, test_pred))
    

    结果如下:

    The accuracy in train data:  1.0
    The accuracy in test data:  1.0
    

    都达到了100%的准确率,就是这么秀~~
    查看在测试集上的混淆矩阵:

    confusion_matrix_result = metrics.confusion_matrix(test_pred, y_test)
    
    plt.figure(figsize=(10, 8))
    sns.heatmap(confusion_matrix_result, annot=True, cmap='Wistia_r')
    
    plt.xlabel('Predict labels')
    plt.ylabel('Actual labels')
    plt.show()
    
    二分类混淆矩阵

    Step 4:三种分类上的逻辑回归模型训练

    和二分类任务下的方法相似,这次来进行多分类训练。从文章开头的几个问题可知,这个多分类问题属于互斥的多分类问题,即每个样本只能属于一个分类,我们使用多项式逻辑回归模型就可以了。

    # 分割测试集和训练集(20%/80%)
    x_train, x_test, y_train, y_test = train_test_split(iris_features, iris_labels, test_size=0.2, random_state=2020)
    
    clf = LogisticRegression(random_state=0, solver='lbfgs')
    
    clf.fit(x_train, y_train)
    

    预测:

    # 在训练集和测试集上预测
    
    train_pred = clf.predict(x_train)
    test_pred = clf.predict(x_test)
    
    print('The accuracy in train data: ', metrics.accuracy_score(y_train, train_pred))
    print('The accuracy in test data: ', metrics.accuracy_score(y_test, test_pred))
    
    confusion_matrix_result = metrics.confusion_matrix(test_pred, y_test)
    
    plt.figure(figsize=(10, 8))
    sns.heatmap(confusion_matrix_result, annot=True, cmap='Wistia_r')
    
    plt.xlabel('Predict labels')
    plt.ylabel('Actual labels')
    
    plt.show()
    

    在三分类问题上的预测结果稍微有点偏差:

    The accuracy in train data:  0.9833333333333333
    The accuracy in test data:  0.8666666666666667
    
    三分类混淆矩阵

    从图中能看出来,在1和2这两个类别下分别有两个预测错误。我们在之前的数据可视化中也可以看出来,橙色和绿色两个类别的分解有点模糊,这和我们之前的认识是相符合的。

    总结

    逻辑回归虽然叫“回归”,但实际上是一种分类算法。由线性回归经过sigmoid函数变换而来,所以预测值在0~1之间,通常用来解决二分类问题。
    刚才用逻辑回归解决了二分类问题和多分类问题,这里的多分类问题是通过多项式损失函数优化来完成的,还可以将多个二分类逻辑回归模型组合来实现多分类。

    END

    相关文章

      网友评论

          本文标题:Task 01|基于逻辑回归的分类预测

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