【机器学习】逻辑回归(Logistic Regression)

注:最近开始学习《人工智能》选修课,老师提纲挈领的介绍了一番,听完课只了解了个大概,剩下的细节只能自己继续摸索。

从本质上讲:机器学习就是一个模型对外界的刺激(训练样本)做出反应,趋利避害(评价标准)。

1. 什么是逻辑回归?



许多人对线性回归都比较熟悉,但知道逻辑回归的人可能就要少的多。从大的类别上来说,逻辑回归是一种有监督的统计学习方法,主要用于对样本进行分类。

在线性回归模型中,输出一般是连续的,例如$$y = f(x) = ax + b$$,对于每一个输入的x,都有一个对应的y输出。模型的定义域和值域都可以是[-∞, +∞]。但是对于逻辑回归,输入可以是连续的[-∞, +∞],但输出一般是离散的,即只有有限多个输出值。例如,其值域可以只有两个值[0, 1],这两个值可以表示对样本的一种分类,存在/不存在、患病/健康等(突然又想起了莎士比亚的一句名言to be or not to be...),这就是最常见的二分类逻辑回归。因此,从整体上来说,通过逻辑回归模型,我们将在整个实数范围上的x映射到了有限个点上,这样就实现了对x的分类。因为每次拿过来一个x,经过逻辑回归分析,就可以将它归为某一类y中。

逻辑回归与线性回归的关系

逻辑回归也被称为广义线性回归模型,它与线性回归模型的形式基本上相同,都具有 ax+b,其中a和b是待求参数,其区别在于他们的因变量不同,多重线性回归直接将ax+b作为因变量,即y = ax+b,而logistic回归则通过函数S将ax+b对应一个隐状态p,p = S(ax+b),然后根据p与1-p的大小决定因变量的值。这里的函数S就是Sigmoid函数

$$S(t) = \frac{1}{1 + e^{-t}}$$

将t换成ax+b,可以得到逻辑回归模型的参数形式:$$p(x; a,b) = \frac{1}{1 + e^{-(ax+b)}}  ……(1)$$

图1:sigmoid函数的图像

通过函数S的作用,我们可以将输出的值限制在区间[0, 1]上,p(x)则可以用来表示概率p(y=1|x),即当一个x发生时,y被分到1那一组的概率。可是,等等,我们上面说y只有两种取值,但是这里却出现了一个区间[0, 1]是什么鬼??其实在真实情况下,我们最终得到的y的值是在[0, 1]这个区间上的一个数,然后我们可以选择一个阈值,通常是0.5,当y>0.5时,就将这个x归到1这一类,如果y<0.5就将x归到0这一类。但是阈值是可以调整的,比如说一个比较保守的人,可能将阈值设为0.9,也就是说有超过90%的把握,才相信这个x属于1这一类。

2. 数据准备



下面的数据来自《机器学习实战》中的示例:

-0.017612 14.053064 0
-1.395634 4.662541 1
-0.752157 6.538620 0
-1.322371 7.152853 0
0.423363 11.054677 0
0.406704 7.067335 1
0.667394 12.741452 0
-2.460150 6.866805 1
0.569411 9.548755 0
-0.026632 10.427743 0

3列10行,其中前两列为x1和x2的值,第3列表示y的值;10行表示取了10个样本点。

见到数据就可以比较直观的理解,我们可以如何利用这些数据(训练样本)来训练逻辑回归分类器,从而用训练好的模型来预测新的样本(检测样本)。

从式子(1)我们可以看到逻辑回归模型中有两个待定参数a(x的系数)和b(常数项),但是我们现在给出来的数据是二维的,因此就增加了一个参数:a0x0 + a1x1 + a2x2(其中x0 = 1,a0就是前面的b),这样统一起来后,就可以使用矩阵表示了(矩阵仅仅只是一种数学中的符号系统,比起前面展开的线性表示方式,用矩阵表示起来更加方便):

$$ \begin{bmatrix} a_0 \\ a_1 \\ a_2 \end{bmatrix}  \begin{bmatrix} x_0 & x_1 & x_2 \end{bmatrix} = a^{ \mathrm{ T } }X$$

将上面的式子带入到(1)式,我们就可以得到逻辑回归的另一种(高大上的)表示形式了:

$$p(x; a) = \frac{1}{1 + e^{-a^{ \mathrm{ T } }X}}  ……(2)$$

此时,可以很清楚的看到,我们后面的一些行动都是为了确定一个合适的a(注意,这里的a不是一个数值,而是一个向量),使得对于一个新来的X(这里的X也是一个向量),我们可以尽可能准确的给出一个y值,0或者1.

注:数据是二维的,也就是说这组观察样本中有两个自变量,或者两个特征(feature)。

3. 训练分类器



就像上面说的,训练分类器的过程,就是根据已经知道的数据(训练样本)确定一个比较合适的a(参数向量,回归系数)的过程。因为逻辑回归模型属于有监督的学习方法,因此上面示例数据中的第3列其实就是训练样本提供的"标准答案"。也就是说,这些数据是已经分好类的(两类,0或者1)。在训练阶段,我们要做的就是利用训练样本和(2)式中的模型,估计一个比较合适的参数a,使得仅通过前面两列数据(观察值/测量值)就可以估计一个值y‘,这个值应该尽可能接近"标准答案"y。

下面是估计回归系数a的值的过程,还是借鉴了《机器学习实战》中的代码,做了少量修改:

 1 ‘‘‘
 2 Created on Oct 27, 2010
 3 Logistic Regression Working Module
 4 @author: Peter
 5 ‘‘‘
 6 from numpy import *
 7 import os
 8
 9 path = ‘D:\MechineLearning\MLiA_SourceCode\machinelearninginaction\Ch05‘
10 training_sample = ‘trainingSample.txt‘
11 testing_sample = ‘testingSample.txt‘
12
13 # 从文件中读入训练样本的数据,同上面给出的示例数据
14 # 第20行中的1.0表示x0 = 1
15 def loadDataSet(p, file_n):
16     dataMat = []; labelMat = []
17     fr = open(os.path.join(p, file_n))
18     for line in fr.readlines():
19         lineArr = line.strip().split()
20         dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
21         labelMat.append(int(lineArr[2]))
22     return dataMat,labelMat
23
24 def sigmoid(inX):
25     return 1.0/(1+exp(-inX))
26
27 # 梯度上升法求回归系数a,由于样本量少,我将迭代次数改成了1000次
28 def gradAscent(dataMatIn, classLabels):
29     dataMatrix = mat(dataMatIn)             #convert to NumPy matrix
30     labelMat = mat(classLabels).transpose() #convert to NumPy matrix
31     m,n = shape(dataMatrix)
32     alpha = 0.001
33     maxCycles = 1000
34     weights = ones((n,1))
35     for k in range(maxCycles):              # heavy on matrix operations
36         h = sigmoid(dataMatrix*weights)     # matrix multiplication
37         error = (labelMat - h)              # vector subtraction
38         temp = dataMatrix.transpose()* error # matrix multiplication
39         weights = weights + alpha * temp  # 这里其实是与梯度上升是等价的
40     return weights
41
42 # 下面是我自己写的测试函数
43 def test_logistic_regression():
44     dataArr, labelMat = loadDataSet(path, training_sample)  # 读入训练样本中的原始数据
45     A = gradAscent(dataArr, labelMat)  # 回归系数a的值
46     h = sigmoid(mat(dataArr)*A)  #预测结果y‘的值
47     print(dataArr, labelMat)
48     print(A)
49     print(h)
50     # plotBestFit(A.getA())
51
52 test_logistic_regression()

上面代码的输出如下:

([[1.0, -0.017612, 14.053064], [1.0, -1.395634, 4.662541], [1.0, -0.752157, 6.53862], [1.0, -1.322371, 7.152853], [1.0, 0.423363, 11.054677], [1.0, 0.406704, 7.067335], [1.0, 0.667394, 12.741452], [1.0, -2.46015, 6.866805], [1.0, 0.569411, 9.548755], [1.0, -0.026632, 10.427743]], [0, 1, 0, 0, 0, 1, 0, 1, 0, 0])     #一个元组,包含两个数组:第一个数组是所有的训练样本中的观察值,也就是X,包括x0, x1, x2;第二个数组每组观察值对应的"标准答案"。

[[ 1.39174871]
[-0.5227482 ]
[-0.33100373]]  #这个列表就是本次预测出来的回归系数a,包括a0, a1, a2

[[ 0.03730313]
[ 0.64060602]
[ 0.40627881]
[ 0.4293251 ]
[ 0.07665396]
[ 0.23863652]
[ 0.0401329 ]
[ 0.59985228]
[ 0.11238742]
[ 0.11446212]]  # 这个数组是根据回归系数a和(2)式中的模型预测的值y‘,可以看出来与标准答案还是相差甚远。标红色的地方本应该是1,其它地方应该是0.

虽然预测的结果y‘不是非常接近y,但是也可以看出,如果我们取0.5作为阈值的话,可以将数据分为两类,其中一类包括原来y=1的两个样本,另一类包括原来y=0的所有样本和一个y=1的样本(分错了)。鉴于我们选择取的样本比较少(只有10个),这样的效果其实还算非常不错的!

4. 结果展示



上面已经求出了一组回归系数,它确定了不同类别数据之间的分割线。可以利用X内部(x1与x2之间的关系)的关系画出该分割线,从而更直观的感受到分类的效果。

添加下面一段代码:

 1 # 分类效果展示,参数weights就是回归系数
 2 def plotBestFit(weights):
 3     import matplotlib.pyplot as plt
 4     dataMat,labelMat=loadDataSet()
 5     dataArr = array(dataMat)
 6     n = shape(dataArr)[0]
 7     xcord1 = []; ycord1 = []
 8     xcord2 = []; ycord2 = []
 9     for i in range(n):
10         if int(labelMat[i])== 1:
11             xcord1.append(dataArr[i,1]); ycord1.append(dataArr[i,2])
12         else:
13             xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2])
14     fig = plt.figure()
15     ax = fig.add_subplot(111)
16     ax.scatter(xcord1, ycord1, s=30, c=‘red‘, marker=‘s‘)
17     ax.scatter(xcord2, ycord2, s=30, c=‘green‘)
18     x = arange(-3.0, 3.0, 0.1)
19     y = (-weights[0]-weights[1]*x)/weights[2]
20     ax.plot(x, y)
21     plt.xlabel(‘X1‘); plt.ylabel(‘X2‘);
22     plt.show()

将上面的test_logistic_regression()函数中的最后一句注释去掉,就可以看到分类的效果了。

这里说明一下上面代码中的第19行,这里设置了sigmoid函数的取值为1/2,也就是说去阈值为1/2来划分最后预测的结果。这样可以得到$$e^{-a^{ \mathrm{ T } }X} = 1$$,即-aTX=0,可以推出x2 = (-a0x0 - a1x1)/a2。同第19行,也就是说这里的y实际上是x2,而x是x1,表示的是x1与x2之间的关系。

分类效果图如下:

两个红色的点是原来y=1的样本,有一个分错了。这里相当于将所有的数据用二维坐标(x1, x2)表示了出来,更加回归参数画出的线将这些点一分为二。如果有新的样本,不知道在哪一类,只用将该点画在图上,看它在这条直线的哪一边就可以分类了。

下面是使用90个训练样本得到的结果:

可以看出一个非常明显的规律是,y=1的这一类样本具有更小的x2值,当x2相近时则具有更大的x1值。

此时计算出来的回归系数a为:

[[ 5.262118 ]
[ 0.60847797]
[-0.75168429]]

5. 预测新样本



添加一个预测函数,如下:

直接将上面计算出来的回归系数拿来使用,测试数据其实是《机器学习实战》这本书中的训练数据,我拆成了两份,前面90行用来做训练数据,后面10行用来当测试数据。

1 def predict_test_sample():
2     A = [5.262118, 0.60847797, -0.75168429]  # 上面计算出来的回归系数a
3     dataArr, labelMat = loadDataSet(path, testing_sample)
4     h_test = sigmoid(mat(dataArr) * mat(A).transpose())  # 将读入的数据和A转化成numpy中的矩阵
5     print(h_test)  # 预测的结果

调用上面的函数,可以得到以下结果:

括号里按照0.5为阈值进行分类:大于0.5的当做1,小于0.5的当做0

[[ 0.99714035]    (1)
[ 0.04035907]   (0)
[ 0.12535895]   (0)
[ 0.99048731]   (1)
[ 0.98075409]   (1)
[ 0.97708653]   (1)
[ 0.09004989]   (0)
[ 0.97884487]   (1)
[ 0.28594188]   (0)
[ 0.00359693]]   (0)

下面是原来的训练样本后十行的数据:

0.089392 -0.715300 1
1.825662 12.693808 0
0.197445 9.744638 0
0.126117 0.922311 1
-0.679797 1.220530 1
0.677983 2.556666 1
0.761349 10.693862 0
-2.168791 0.143632 1
1.388610 9.341997 0
0.317029 14.739025 0

如果按照0.5为分界线的话,我们利用前90个样本训练出来的分类器将后面10个样本的类型全部预测对了。

附件:

完整代码:https://github.com/OnlyBelter/Learning-AI/blob/master/Logistic_Regression.py

训练数据:https://github.com/OnlyBelter/Learning-AI/blob/master/Logistic_Regression-trainingSample.txt

测试数据:https://github.com/OnlyBelter/Learning-AI/blob/master/Logistic_Regression-testingSample.txt

参考:

http://baike.baidu.com/item/logistic%E5%9B%9E%E5%BD%92

https://en.wikipedia.org/wiki/Sigmoid_function

《机器学习实战》,哈林顿著,李锐等译,人民邮电出版社,2013年6月第一版

时间: 2024-10-27 03:34:24

【机器学习】逻辑回归(Logistic Regression)的相关文章

机器学习 (三) 逻辑回归 Logistic Regression

文章内容均来自斯坦福大学的Andrew Ng教授讲解的Machine Learning课程,本文是针对该课程的个人学习笔记,如有疏漏,请以原课程所讲述内容为准.感谢博主Rachel Zhang 的个人笔记,为我做个人学习笔记提供了很好的参考和榜样. § 3.  逻辑回归 Logistic Regression 1 分类Classification 首先引入了分类问题的概念——在分类(Classification)问题中,所需要预测的$y$是离散值.例如判断一封邮件是否属于垃圾邮件.判断一个在线交

机器学习笔记04:逻辑回归(Logistic regression)、分类(Classification)

之前我们已经大概学习了用线性回归(Linear Regression)来解决一些预测问题,详见: 1.<机器学习笔记01:线性回归(Linear Regression)和梯度下降(Gradient Decent)> 2.<机器学习笔记02:多元线性回归.梯度下降和Normal equation> 3.<机器学习笔记03:Normal equation及其与梯度下降的比较> 说明:本文章所有图片均属于Stanford机器学课程,转载请注明出处 面对一些类似回归问题,我们可

机器学习总结之逻辑回归Logistic Regression

机器学习总结之逻辑回归Logistic Regression 逻辑回归logistic regression,虽然名字是回归,但是实际上它是处理分类问题的算法.简单的说回归问题和分类问题如下: 回归问题:预测一个连续的输出. 分类问题:离散输出,比如二分类问题输出0或1. 逻辑回归常用于垃圾邮件分类,天气预测.疾病判断和广告投放. 一.假设函数 因为是一个分类问题,所以我们希望有一个假设函数,使得: 而sigmoid 函数可以很好的满足这个性质: 故假设函数: 其实逻辑回归为什么要用sigmoi

机器学习方法(五):逻辑回归Logistic Regression,Softmax Regression

技术交流QQ群:433250724,欢迎对算法.技术.应用感兴趣的同学加入. 前面介绍过线性回归的基本知识,线性回归因为它的简单,易用,且可以求出闭合解,被广泛地运用在各种机器学习应用中.事实上,除了单独使用,线性回归也是很多其他算法的组成部分.线性回归的缺点也是很明显的,因为线性回归是输入到输出的线性变换,拟合能力有限:另外,线性回归的目标值可以是(?∞,+∞),而有的时候,目标值的范围是[0,1](可以表示概率值),那么就不方便了. 逻辑回归可以说是最为常用的机器学习算法之一,最经典的场景就

逻辑回归(logistic regression)

logistic regression可以解决分类问题,即输出的结果只有0和1两种,比如,对于邮件的判断只有是或者否.这种分类问题使用传统的线性回归并不能很好的解决. 一个小例子 例如,当我们根据肿瘤的大小判断一个肿瘤是不是良性的时候,输出结果只有是或者否,用1和0表示,给定的样本点,并且我们使用传统的线性回归问题解决拟合的函数图像如下: 图像中我们可以根据拟合曲线,当输出值大于0.5(根据图像判断的值)的时候,确定输出的为恶性(即为1):当输出值小于0.5(根据图像判断的值)的时候,确定输出的

Coursera机器学习-第三周-逻辑回归Logistic Regression

Classification and Representation 1. Classification Linear Regression (线性回归)考虑的是连续值([0,1]之间的数)的问题,而Logistic Regression(逻辑回归)考虑的是离散值(例如只能取0或1而不能取0到1之间的数)的问题.举个例子,你需要根据以往季度的电力数据,预测下一季度的电力数据,这个时候需要使用的是线性回归,因为这个值是连续的,而不是离散的.而当你需要判断这个人抽烟还是不抽烟的问题时,就需要使用逻辑回

【机器学习】Octave 实现逻辑回归 Logistic Regression

34.62365962451697,78.0246928153624,0 30.28671076822607,43.89499752400101,0 35.84740876993872,72.90219802708364,0 60.18259938620976,86.30855209546826,1 79.0327360507101,75.3443764369103,1 45.08327747668339,56.3163717815305,0 61.10666453684766,96.51142

机器学习之逻辑回归(Logistic Regression)

"""逻辑回归中的Sigmoid函数"""   import numpy as np   import matplotlib.pyplot as plt     def sigmoid(t):   return 1/(1+np.exp(-t))     x=np.linspace(-10,10,500)   y=sigmoid(x)     plt.plot(x,y)   plt.show() 结果: 逻辑回归损失函数的梯度:   逻辑回归算法:

逻辑回归 logistic regression(1)逻辑回归的求解和概率解释

本系列内容大部分来自Standford公开课machine learning中Andrew老师的讲解,附加自己的一些理解,编程实现和学习笔记. 第一章 Logistic regression 1.逻辑回归 逻辑回归是一种监督学习的分类算法,相比较之前的线性回归算法,差别在于它是一个分类算法,这也意味着y不再是一个连续的值,而是{0,1}的离散值(两类问题的情况下). 当然这依然是一个判别学习算法,所谓判别学习算法,就是我们直接去预测后验 ,或者说直接预测判别函数的算法.当然相对应的生成学习算法,

sklearn逻辑回归(Logistic Regression,LR)调参指南

python信用评分卡建模(附代码,博主录制) https://study.163.com/course/introduction.htm?courseId=1005214003&utm_campaign=commission&utm_source=cp-400000000398149&utm_medium=share sklearn逻辑回归官网调参指南 https://scikit-learn.org/stable/modules/generated/sklearn.linear