逻辑回归(Logistic Regression)是一个非常经典的算法.逻辑回归用来处理不同的分类问题,目的是预测当前被观察对象属于哪个组,它会提供一个离散的二进制输出结果.因其简单、可并行化、可解释强深受工业界喜爱。逻辑回归假设数据服从伯努利分布,通过极大化似然函数的方法,运用梯度下降来求解参数,来达到将数据二分类的目的。回归模型一般来说都是指对连续值预测的一类模型,而分类模型都是指对离散值(类标)预测的一类模型。但是由于历史的原因虽然逻辑回归被称为回归,但它却是一个分类模型,这算是一个例外。

1. 逻辑回归算法原理

1.1 逻辑回归模型

使用逻辑函数通过估算概率来测量因变量(想要预测的标签)和一个或多个自变量之间的关系。如有两堆样本点,即二分类问题(Binary Classification),现在需要建立一个模型来对新输入的样本进行预测,判断其应该属于那个类别。对于这个问题的描述用线性回归来解决肯定是不行的,因为两者本就属于不同类型的问题。既然是解决分类问题,那么可以通过建立一个模型用来预测每个样本点属于其中一个类别的概率,如果>0.5那我们就可以认为该样本点属于这个类别,这样就能解决上述的二分类问题。可该怎么建立这个模型呢?在前面的线性回归中,通过建模来对新样本进行预测,其输出值为可能的任意实数。但此处既然是要得到一个样本所属类别的概率,那最直接的办法就是通过一个函数:,将映射至[0,1]的范围即可。由此,我们便得到了逻辑回归中的预测模型:

其中为未知参数,称为假设函数,当时,便可以认为样本属于正类,反之则认为属于负类。求出后,即可得到分类模型。

问题是,如果希望这个模型来做分类需要人为地设置阈值,比如规定y > 0.5最后的分类是1,y <=0.5 最后的分类是0。从表面上来看,这当然是可以的,但实际上这样操作会有很多问题。最大的问题在于如果简单地设计一个阈值来做判断,那么会导致最后的y是一个分段函数,而分段函数不连续,使得没有办法对它求梯度,为了解决这个问题,我们得找到一个平滑的函数使得既可以用来做分类,又可以解决梯度的问题。信息学家们找到了一个函数,它就是Sigmoid函数,将映射至[0,1]的范围,可以将它的表达式是:

它的函数图像如下:



逻辑回归模型对测试集图片的判定 逻辑回归 实现_逻辑回归算法原理

可以看到,sigmoid函数在x=0处取值0.5,在正无穷处极限是1,在负无穷处极限是0,并且函数连续,处处可导。sigmoid的函数值的取值范围是0-1,非常适合用来反映一个事物发生的概率。把表示x发生的概率,那么x不发生的概率就是。把发生和不发生看成是两个类别,那么sigmoid函数就转化成了分类函数,如果>0.5表示类别1,否则表示类别0.

到这里就很简单了,通过线性回归可以得到。也就是说在线性回归模型的外面套了一层sigmoid函数,通过计算出不同的y,从而获得不同的概率,最后得到不同的分类结果。

1.3 逻辑回归损失函数

当建立好模型之后就需要找到一种方法来求解模型中的未知参数。同线性回归一样,此时也需要通过一种间接的方式,即通过目标函数来刻画预测标签(label)与真实标签之间的差距。当最小化目标函数后,便能得到需要求解的参数。

  • 建立逻辑回归模型:表示样本总数,表示第个样本,表示第个样本的真实标签,表示第个样本为正类的预测概率.

当函数取得最小值的参数,就是要求的目标参数。原因在于,当取得最小值时就意味着此时所有样本的预测标签与真实标签之间的差距最小,这同时也是最小化目标函数的意义。因此,对于如何求解模型的问题就转化为了如何最小化目标函数了。

2. 逻辑回归算法代码实战

2.1 设计模拟数据集

选择生活中一个很简单的场景——考试。假设每个学生需要参加两门考试,两门考试的成绩相加得到最终成绩,现在有一批学生是否合格的数据。希望设计一个逻辑回归模型,帮助直接计算学生是否合格。为了防止sigmoid函数产生偏差,我们把每门课的成绩缩放到(0, 1)的区间内。两门课成绩相加超过140分就认为总体及格。

import numpy as npdef load_data():    x1 = np.random.rand(50,1)/2+0.5    x2 = np.random.rand(50,1)/2+0.5    y  = x1+x2    Y  = y>1.4    Y  = Y + 0    x = np.c_[np.ones(len(Y)),x1,x2]    return x,Y

这样得到的训练数据有两个特征,分别是学生两门课的成绩,还有一个偏移量1,用来记录常数的偏移量。

2.2 训练模型:实现sigmoid以及梯度下降的函数

def sigmoid(x):    return 1.0/(1+np.exp(-x))def gradAscent(data,classLabels):    X = np.mat(data)#np.mat([1,2,3])  #创建矩阵    Y = np.mat(classLabels)    m,n = np.shape(data)    #学习率    alpha = 0.01    iterations = 10000    wei  = np.ones((n,1))    for i in range(iterations):        y_hat = sigmoid(X*wei)        error = Y-y_hat        wei = wei + alpha*X.transpose()*error    return wei

这段函数实现的是批量梯度下降

2.3 求解

最后,把数据集以及逻辑回归的分割线绘制出来。

import matplotlib.pyplot as pltdef plotPic():    dataMat,labelMat = load_data()    #print(dataMat)    weis = gradAscent(dataMat,labelMat).getA()    n = np.shape(dataMat)[0]    xc1 = []    yc1 = []    xc2 = []    yc2 = []    #数据按照正负类别划分    for i in range(n):        if int(labelMat[i]) == 1:            xc1.append(dataMat[i][1])            yc1.append(dataMat[i][2])        else:            xc2.append(dataMat[i][1])            yc2.append(dataMat[i][2])    fig = plt.figure()    ax  = fig.add_subplot(111)    ax.scatter(xc1,yc1,s=30,c='red',marker='s')    ax.scatter(xc2,yc2,s=30,c='green')    #绘制分割线    x = np.arange(0.5,1,0.1)    y = (-weis[0]-weis[1]*x)/weis[2]    ax.plot(x,y)    plt.xlabel('X1')    plt.ylabel('X2')    plt.show()plotPic()



逻辑回归模型对测试集图片的判定 逻辑回归 实现_逻辑回归算法原理_02

可以发现,经过了1万次的迭代,得到的模型已经可以正确识别所有的样本了。

3 小结

今天总结了机器学习中的逻辑回归算法模型思想和实现方式:

  • 逻辑回归的适用性
  1. 用于概率预测。用于可能性预测时,得到的结果有可比性。比如根据模型进而预测在不同的自变量情况下,发生某病或某种情况的概率有多大;
  2. 用于分类。实际上跟预测有些类似,也是根据模型,判断某人属于某病或属于某种情况的概率有多大,也就是看一下这个人有多大的可能性是属于某病。进行分类时,仅需要设定一个阈值即可,可能性高于阈值是一类,低于阈值是另一类。
  3. 寻找危险因素。寻找某一疾病的危险因素等。
  4. 仅能用于线性问题。只有当目标和特征是线性关系时,才能用逻辑回归。在应用逻辑回归时注意两点:一是当知道模型是非线性时,不适用逻辑回归;二是当使用逻辑回归时,应注意选择和目标为线性关系的特征。
  5. 各特征之间不需要满足条件独立假设,但各个特征的贡献独立计算。
  • 逻辑回归优点:
  1. 速度快;
  2. 简单易于理解,直接看到各个特征的权重;
  3. 能容易地更新模型吸收新的数据;
  4. 如果想要一个概率框架,动态调整分类阀值。
  • 逻辑回归缺点:

特征处理复杂。需要归一化和较多的特征工程。