Logistic 回归

学习地址

分类classification

例子

  • 垃圾邮件分类
  • 肿瘤良性还是恶性

在这类预测问题中y是一个离散的值,只有{0,1}两种取值。
如果用线形回归模型计算分类,得出的hθ(x)可能远大于1或远小于0,而我们希望得到的是0或者1。所以,提出逻辑回归模型,让0<= hθ(x) <=1。逻辑回归实际是一个分类算法。

假设陈述

目的:当有一个分类问题时,用哪种方程表示假设函数。
逻辑回归模型要使得0<= hθ(x) <=1。
那么,令:hθ(x)=g(θTx)
而,g(z)=1/(1+e-z)
则,hθ(x)=1/(1+eTx)

假设函数hypothesis意义:估算对于输入的x,y=1的概率是多少

决策界线

  • 所谓决策界线就是讲将数据集划分为几个部分,当θ参数确定时很容易计算出边界线。
  • 边界线可能是直线也可能是曲线甚至是圆
  • 关于边界线的问题,我们知道边界线是将数据样本点分为几部分,比如一条直线分两部分,直线上方代表1,下方代表0,那么在G(θX)中,只要θX>=0,这个sigma函数就接近1。故只需边界线上点为0即可绘制出边界线了。如下图
    2019-07-16 22-12-36 的屏幕截图.png

代价函数

  1. 先来拟合logistic回归模型的参数θ,那么就需要定义用来拟合参数的优化目标或者叫代价函数。
  2. 如果选用线形回归模型中的代价函数会出现什么问题,在线形回归模型中假设函数hθ(x)是线形函数,而逻辑归回归模型中假设函数是非线形的,带入线形回归模型中所做出来的J(θ)是非凸函数,有很多局部最优解,而非线回归模型中碗状的凸函数。
  3. 有了上面理论,我们将线形回归模型中(hθ(x)-y)2记为Cost
  4. 应用于逻辑回归模型的代价函数Cost(hθ(x),y)=

    • -log( hθ(x) ) , if y=1
    • -log( 1-hθ(x) ) ,if y=0
  5. 如何理解代价函数:代价函数描述了预测结果与样本实际的偏离程度。当y=1,我们的hypothesis也为1时,Cost为0,这是对的(无偏差)这就说明预测对了;而如果预测结果趋于0,那么Cost趋向正无穷,说明与实际偏差很大。对于y=0的情况也是同理。

简化代价函数与梯度下降

逻辑回归代价函数J(θ):注意y只有两个值故容易合并
关于梯度下降推导:公式推导
2019-07-15 11-05-31 的屏幕截图.png
2019-07-15 11-13-25 的屏幕截图.png

  1. 为什么这样选择代价函数,事实上我们知道代价函数有很多,这个是根据统计学的极大似然估计法得出来的,这个函数有一个特点是它是的。
  2. 将J(θ)简化之后我们就可以尝试利用梯度下降来最小化它并得到最小化时的参数θ,再用参数来做预测。
  3. 梯度下降如下:
    2019-07-15 14-31-50 的屏幕截图.png
  4. 线形回归中的梯度下降同样可以应用到逻辑回归模型中,使得梯度下降收敛更快

高级优化

计算代价函数并不只有梯度下降算法。还有:

  • L-BFGS
  • BFGS
  • Conjugate gradient 共轭梯度法
    这些算法都不需要手动选择学习率α,也都比梯度下降算法快。但要比梯度下降更复杂。

这些高级算法一般封装在某个库中,可以直接调用。

多元分类:一对多

即: 待分类的对象 对 多个类别
比如:邮件,类别有家人、工作、朋友等

大致是对不同的类别设置不同的分类器:选择其中一种作为正,其余都为0,那么就可以得出不同的分类器,我们将数据输入到不同的分类器中选择hypothesis最大的最可信的那个。
2019-07-15 15-09-03 的屏幕截图.png
2019-07-15 15-10-02 的屏幕截图.png



补充

  1. Python Matplotlib 改变坐标轴的默认位置
  2. 课件

sklearn中的逻辑回归

Sigmoid函数

Sigmoid函数

  • 绘制函数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import numpy as np
    import matplotlib.pyplot as plt

    x=np.linspace(-10,10,10000)
    ax = plt.gca() # a表示axis
    ax.spines['right'].set_color('none') # 隐藏右边的线
    ax.spines['top'].set_color('none') # 隐藏上面的线
    ax.spines['bottom'].set_position(('data', 0)) # 设置纵轴起点
    ax.spines['left'].set_position(('data', 0)) # 设置横轴中点
    plt.plot(x,1/(1+np.power(np.e,-x)))
    plt.grid(True)
    plt.title('Figmoid Function')
    plt.show()

sigmoid 函数
Sigmoid函数是一个S型的函数,当自变量z趋近正无穷时,因变量g(z)趋近于1,而当z趋近负无穷时,g(z)趋近于0,它能够将任何实数映射到(0,1)区间,使其可用于将任意值函数转换为更适合二分类的函数。因为这个性质,Sigmoid函数也被当作是归一化的一种方法,与我们之前学过的MinMaxSclaer同理,是属于数据预处理中的“缩放”功能,可以将数据压缩到[0,1]之内。区别在于,MinMaxScaler归一化之后,是可以取到0和1的(最大值归一化后就是1,最小值归一化后就是0),但Sigmoid函数只是无限趋近于0和1

逻辑回归

  1. 逻辑回归对线性关系的拟合效果好到丧心病狂,相对的,逻辑回归在非线性数据的效果很多时候比瞎猜还不如,所以如果你已经知道数据之间的联系是非线性的,千万不要迷信逻辑回归
  2. 逻辑回归计算快
  3. 逻辑回归返回的分类结果不是固定的0,1,而是以小数形式呈现的类概率数字

sklearn中的逻辑回归

逻辑回归相关的类 说明
linear_model.LogisticRegression 逻辑回归回归分类器(又叫logit回归,最大熵分类器)
linear_model.LogisticRegressionCV 带交叉验证的逻辑回归分类器
linear_model.logistic_regression_path 计算Logistic回归模型以获得正则化参数的列表
linear_model.SGDClassifier 利用梯度下降求解的线性分类器(SVM,逻辑回归等等)
linear_model.SGDRegressor 利用梯度下降最小化正则化后的损失函数的线性回归模型
metrics.log_loss 对数损失,又称逻辑损失或交叉熵损失
其他会涉及的类 说明
metrics.confusion_matrix 混淆矩阵,模型评估指标之一
metrics.roc_auc_score ROC曲线,模型评估指标之一
metrics.accuracy_score 精确性,模型评估指标之一

linear_model.LogisticRegression

  • sklearn.linear_model.LogisticRegression (penalty=’l2’, dual=False, tol=0.0001, C=1.0, fit_intercept=True, intercept_scaling=1, class_weight=None, random_state=None, solver=’warn’, max_iter=100, multi_class=’warn’, verbose=0, warm_start=False, n_jobs=None)

重要参数 penalty & C

  • penaltyC都是正则化参数,正则化是用来防止模型过拟合的过程。常用的有L1正则化和L2正则化两种选项,分别通过在损失函数后加上参数向量θ的L1范式和L2范式的倍数来实现。
  • 这个增加的范式,被称为“正则项”,也被称为”惩罚项”。其中L1范数表现为参数向量中的每个参数的绝对值之和,L2范数表现为参数向量中的每个参数的平方和的开方值。
  • 损失函数
    逻辑回归损失函数
    C是用来控制正则化程度的超参数,n是方程中特征的总数,也是方程中参数的总数,j代表每个参数。在这里,J要大于等于1,是因为我们的参数向量θ中,第一个参数是θ0是我们的截距,它通常是不参与正则化的
    参数说明

学习曲线选择C

  • 逻辑回归的重要属性coef_,查看每个特征所对应的参数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.linear_model import LogisticRegression as RL
    from sklearn.datasets import load_breast_cancer
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import accuracy_score

    data=load_breast_cancer()
    X=data.data
    Y=data.target
    print(X.shape,Y.shape) # (569, 30) (569,)

    RL_L1=RL(penalty='l1',C=0.5,max_iter=1000) # 实例化并初始化参数
    RL_L2=RL(penalty='l2',C=0.5,max_iter=1000) # 实例化并初始化参数

    RL_L1=RL_L1.fit(X,Y) # 训练模型
    RL_L2=RL_L2.fit(X,Y)

    print(RL_L1.coef_)
    print(RL_L2.coef_.shape) # (1, 30)

可以看见,当选择L1正则化的时候,许多特征的参数都被设置为了0,这些特征在真正建模的时候,就不会出现在我们的模型当中了,而L2正则化则是对所有的特征都给出了参数。

  • 分别实例化L1和L2两种正则化方法并进行绘制学习曲线选择最佳C值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.linear_model import LogisticRegression as RL
    from sklearn.datasets import load_breast_cancer
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import accuracy_score

    data=load_breast_cancer()
    X_train,X_test,y_train,y_test=train_test_split(data.data,data.target,test_size=0.3,random_state=10) # 30%数据作为测试集,其余作为训练集

    l1=[]
    l2=[]
    l1_test=[]
    l2_test=[]
    for i in np.linspace(0.05,1,19): # C的可选值
    RL_l1=RL(penalty='l1',C=i,max_iter=1000)
    RL_l2=RL(penalty='l2',C=i,max_iter=1000)

    RL_l1=RL_l1.fit(X_train,y_train)
    l1.append(accuracy_score(RL_l1.predict(X_train),y_train))
    l1_test.append(accuracy_score(RL_l1.predict(X_test),y_test))

    RL_l2 = RL_l2.fit(X_train, y_train)
    l2.append(accuracy_score(RL_l2.predict(X_train), y_train))
    l2_test.append(accuracy_score(RL_l2.predict(X_test), y_test))

    graph=[l1,l2,l1_test,l2_test]
    color = ["green","black","lightgreen","gray"]
    label = ["l1","l2","l1test","l2test"]
    for i in range(len(graph)):
    plt.plot(np.linspace(0.05,1,19),graph[i],color[i],label=label[i])

    plt.legend(loc='best')
    plt.show()

学习曲线
可见,至少在我们的乳腺癌数据集下,两种正则化的结果区别不大。但随着C的逐渐变大,正则化的强度越来越小,模型在训练集和测试集上的表现都呈上升趋势,直到C=0.8左右,训练集上的表现依然在走高,但模型在未知数据集上的表现开始下跌,这时候就是出现了过拟合。我们可以认为,C设定为0.9会比较好。在实际使用时,基本就默认使用l2正则化,如果感觉到模型的效果不好,那就换L1试试看。