Python语言描述机器学习之Logistic回归算法


Posted in Python onDecember 21, 2017

本文介绍机器学习中的Logistic回归算法,我们使用这个算法来给数据进行分类。Logistic回归算法同样是需要通过样本空间学习的监督学习算法,并且适用于数值型和标称型数据,例如,我们需要根据输入数据的特征值(数值型)的大小来判断数据是某种分类或者不是某种分类。

一、样本数据

在我们的例子中,我们有这样一些样本数据:

样本数据有3个特征值:X0X0,X1X1,X2X2

我们通过这3个特征值中的X1X1和X2X2来判断数据是否符合要求,即符合要求的为1,不符合要求的为0。

样本数据分类存放在一个数组中

我们在logRegres.py文件中编写如下函数来准备数据,并将数据打印观察一下:

#coding=utf-8
from numpy import *
def loadDataSet():
 dataMat = []; labelMat = []
 fr = open('testSet.txt')
 for line in fr.readlines():
  lineArr = line.strip().split()
  dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
  labelMat.append(int(lineArr[2]))
 return dataMat,labelMat
if __name__=='__main__':
 dataMat,labelMat=loadDataSet()
 print 'dataMat:\n',dataMat

我们来观察一下这个数据样本:

dataMat:
[[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], [1.0, 0.850433, 6.920334], [1.0, 1.347183, 13.1755], [1.0, 1.176813, 3.16702], [1.0, -1.781871, 9.097953], [1.0, -0.566606, 5.749003], [1.0, 0.931635, 1.589505], [1.0, -0.024205, 6.151823], [1.0, -0.036453, 2.690988], [1.0, -0.196949, 0.444165], [1.0, 1.014459, 5.754399], [1.0, 1.985298, 3.230619], [1.0, -1.693453, -0.55754], [1.0, -0.576525, 11.778922], [1.0, -0.346811, -1.67873], [1.0, -2.124484, 2.672471], [1.0, 1.217916, 9.597015], [1.0, -0.733928, 9.098687], [1.0, -3.642001, -1.618087], [1.0, 0.315985, 3.523953], [1.0, 1.416614, 9.619232], [1.0, -0.386323, 3.989286], [1.0, 0.556921, 8.294984], [1.0, 1.224863, 11.58736], [1.0, -1.347803, -2.406051], [1.0, 1.196604, 4.951851], [1.0, 0.275221, 9.543647], [1.0, 0.470575, 9.332488], [1.0, -1.889567, 9.542662], [1.0, -1.527893, 12.150579], [1.0, -1.185247, 11.309318], [1.0, -0.445678, 3.297303], [1.0, 1.042222, 6.105155], [1.0, -0.618787, 10.320986], [1.0, 1.152083, 0.548467], [1.0, 0.828534, 2.676045], [1.0, -1.237728, 10.549033], [1.0, -0.683565, -2.166125], [1.0, 0.229456, 5.921938], [1.0, -0.959885, 11.555336], [1.0, 0.492911, 10.993324], [1.0, 0.184992, 8.721488], [1.0, -0.355715, 10.325976], [1.0, -0.397822, 8.058397], [1.0, 0.824839, 13.730343], [1.0, 1.507278, 5.027866], [1.0, 0.099671, 6.835839], [1.0, -0.344008, 10.717485], [1.0, 1.785928, 7.718645], [1.0, -0.918801, 11.560217], [1.0, -0.364009, 4.7473], [1.0, -0.841722, 4.119083], [1.0, 0.490426, 1.960539], [1.0, -0.007194, 9.075792], [1.0, 0.356107, 12.447863], [1.0, 0.342578, 12.281162], [1.0, -0.810823, -1.466018], [1.0, 2.530777, 6.476801], [1.0, 1.296683, 11.607559], [1.0, 0.475487, 12.040035], [1.0, -0.783277, 11.009725], [1.0, 0.074798, 11.02365], [1.0, -1.337472, 0.468339], [1.0, -0.102781, 13.763651], [1.0, -0.147324, 2.874846], [1.0, 0.518389, 9.887035], [1.0, 1.015399, 7.571882], [1.0, -1.658086, -0.027255], [1.0, 1.319944, 2.171228], [1.0, 2.056216, 5.019981], [1.0, -0.851633, 4.375691], [1.0, -1.510047, 6.061992], [1.0, -1.076637, -3.181888], [1.0, 1.821096, 10.28399], [1.0, 3.01015, 8.401766], [1.0, -1.099458, 1.688274], [1.0, -0.834872, -1.733869], [1.0, -0.846637, 3.849075], [1.0, 1.400102, 12.628781], [1.0, 1.752842, 5.468166], [1.0, 0.078557, 0.059736], [1.0, 0.089392, -0.7153], [1.0, 1.825662, 12.693808], [1.0, 0.197445, 9.744638], [1.0, 0.126117, 0.922311], [1.0, -0.679797, 1.22053], [1.0, 0.677983, 2.556666], [1.0, 0.761349, 10.693862], [1.0, -2.168791, 0.143632], [1.0, 1.38861, 9.341997], [1.0, 0.317029, 14.739025]]
labelMat:
[0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0]

样本数据dataMat的第一列,也就是我们的特征值X0X0全部为1,这个问题我们之后在计算回归参数时需要注意理解。所有的样本数据一共100条,对应的分类结果也是100个。

那么,我们现在的问题是:
我们要找到样本空间中的特征值与分类结果的关系。设计一个函数或者功能,实现在输入一组特征值后,能够根据样本空间特征值与分类结果的关系,自动为输入的数据进行分类,即得到结果要么是1,要么是0。

二、Sigmoid函数

为了解决上一节我们提到的问题,我们这里先介绍一下Sigmoid函数:

Python语言描述机器学习之Logistic回归算法

这个函数有如下几个特征:

当z=0z=0时,值为0.50.5
当zz不断增大时,值将趋近于1
当zz不断减小时,值将趋近于0
我们来看一下函数的曲线图:

Python语言描述机器学习之Logistic回归算法

我们如果将样本空间的3个特征值X0X0、X1X1和X2X2的值代入到函数中,计算出一个结果。那么这个结果将是接近与我们的分类结果的(0到1之间的一个数值)。如果这个结果接近0那么我们就认为分类为0,如果结果接近1我们就认为分类为1。

以什么方式代入到函数中呢?其实简单的相加就可以,因为zz不断增大或者减小时,函数的值就相应的趋近于1或者0。我们使z=x0+x1+x2z=x0+x1+x2

Python语言描述机器学习之Logistic回归算法

但是实际的情况是我们的计算结果和实际的分类值,会有误差,甚至是完全不正确。为了矫正这个问题,我们为样本空间的3个特征值X0X0、X1X1和X2X2,一一定义一个回归系数w0w0、w1w1和w2w2,使这个误差减小。即使z=w0x0+w1x1+w2x2

Python语言描述机器学习之Logistic回归算法

其实不难想象,这组ww回归系数的值决定了我们计算结果的准确性,甚至是正确性。也就是说,这组ww的值反应了样本空间分类的规则。
那么,我们在输入一组样本之外的数据时,配合正确的ww回归系数,我们就能得到比较接近样本空间分类规则的分类结果。
问题又来了,我们怎么来得到这样一组ww回归系数呢?

三、梯度上升法

梯度上升法,是在函数的梯度方向上,不断的迭代计算参数值,以找到一个最大的参数值。迭代公式如下:

Python语言描述机器学习之Logistic回归算法

其中,αα为步长,Δσ(w)Δσ(w)为σ(w)σ(w)函数梯度。关于梯度的推导请参考这里。作者的数学能力有限,就不做说明了。

最后,我们可以得到梯度的计算公式:

Python语言描述机器学习之Logistic回归算法

那么,迭代公式如下:

Python语言描述机器学习之Logistic回归算法

公式说明:

wk+1wk+1为本次迭代XX特征项的回归系数结果
wkwk为上一次迭代XX特征项的回归系数结果
αα为每次迭代向梯度方向移动的步长
xixi为XX特征项中第i个元素
yiyi是样本中第i条记录的分类样本结果
σ(xi,wk)σ(xi,wk)是样本中第i条记录,使用sigmoid函数和wkwk作为回归系数计算的分类结果
[yi−σ(xi,wk)][yi−σ(xi,wk)]是样本第i条记录对应的分类结果值,与sigmoid函数使用wkwk作为回归系数计算的分类结果值的误差值。

现在,我们有了计算回归系数的公式,下面我们在logRegres.py文件中来实现一个函数,实现计算样本空间的回归系数,并打印一下我们的结果:

def gradAscent(dataMatIn, classLabels):
 dataMatrix = mat(dataMatIn)    #100行3列
 #print dataMatrix
 labelMat = mat(classLabels).transpose() #100行1列
 #print 'labelMat:\n',labelMat
 print 'labelMat 的形状:rowNum=',shape(labelMat)[0],'colNum=',shape(labelMat)[1]
 rowNum,colNum = shape(dataMatrix)
 alpha = 0.001
 maxCycles = 500
 weights = ones((colNum,1)) #3行1列
 #print shape(dataMatrix)
 #print shape(weights)
 #print shape(labelMat)
 for k in range(maxCycles):    #heavy on matrix operations
  h = sigmoid(dataMatrix*weights)  #100行1列
  #print h
  error = (labelMat - h)    #vector subtraction
  weights = weights + alpha * dataMatrix.transpose()* error #3行1列
 return weights
if __name__=='__main__':
 dataMat,labelMat=loadDataSet()
 #weights=gradAscent(dataMat,labelMat)
 #print 'dataMat:\n',dataMat
 #print 'labelMat:\n',labelMat
 print weights

打印结果:

回归系数:
[[ 4.12414349]
 [ 0.48007329]
 [-0.6168482 ]]

为了验证我们计算的回顾系数的准确性,我们观察一下样本空间的散点图和回归系数的拟合曲线。我们以z(x1,x2)=w0+w1x1+w2x2作为我们的拟合函数,在坐标系中画出它的拟合曲线。以样本空间中X1X1和X2X2的值作为横坐标和纵坐标,画出样本空间的散点。代码如下:

def plotBestFit(weights):
 import matplotlib.pyplot as plt
 dataMat,labelMat=loadDataSet()
 dataArr = array(dataMat)
 n = shape(dataArr)[0] 
 xcord1 = []; ycord1 = []
 xcord2 = []; ycord2 = []
 for i in range(n):
  if int(labelMat[i])== 1:
   xcord1.append(dataArr[i,1]); ycord1.append(dataArr[i,2])
  else:
   xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2])
 fig = plt.figure()
 ax = fig.add_subplot(111)
 ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
 ax.scatter(xcord2, ycord2, s=30, c='green')
 x = arange(-3.0, 3.0, 0.1)
 y = (-weights[0]-weights[1]*x)/weights[2]
 y = y.transpose()
 ax.plot(x, y)
 plt.xlabel('X1'); plt.ylabel('X2');
 plt.show()
if __name__=='__main__':
 dataMat,labelMat=loadDataSet()
 weights=gradAscent(dataMat,labelMat)
 print '回归系数:\n',weights
 plotBestFit(weights)

运行后,我们得到如下图片:

Python语言描述机器学习之Logistic回归算法

通过我们的观察,我们的这个回归系数的算法还是比较准确的,拟合曲线将样本数据分成两部分,并且符合样本的分类规则。

接下来,我们来实现一个分类器,并测试这个分类器:

def classify0(targetData,weights):
 v = sigmoid(targetData*weights)
 if v>0.5:
  return 1.0
 else :
  return 0
def testClassify0():
 dataMat,labelMat=loadDataSet()
 examPercent=0.7
 row,col=shape(dataMat)
 exam=[]
 exam_label=[]
 test=[]
 test_label=[]
 for i in range(row):
  if i < row*examPercent:
   exam.append(dataMat[i])
   exam_label.append(labelMat[i])
  else:
   test.append(dataMat[i])
   test_label.append(labelMat[i])
 weights=gradAscent(exam,exam_label)
 errCnt=0
 trow,tcol=shape(test)
 for i in range(trow):
  v=int(classify0(test[i],weights))
  if v != int(test_label[i]):
   errCnt += 1
   print '计算值:',v,' 原值',test_label[i]
 print '错误率:',errCnt/trow
if __name__=='__main__':
 #dataMat,labelMat=loadDataSet()
 #weights=gradAscent(dataMat,labelMat)
 ##print 'dataMat:\n',dataMat
 ##print 'labelMat:\n',labelMat
 #print '回归系数:\n',weights
 #plotBestFit(weights)
 testClassify0()

分类器的实现很简单。我们使用之前的样本数据中的70条数据作为我们测试的样本数据,计算出回归系数。然后用分类器对剩下的30条记录进行分类,然后将结果和样本数据进行对比。最后打印出错误率。我们可以看到,错误率是0,近乎完美!我们可以修改测试样本在原样本空间的比例多测试几遍。那么,结论是我们的算法的准确率还不错!

那么,到这里问题就解决了吗?好像还差一点什么。我们来仔细研究一下我们计算回归系数的方法,不难发现,这个过程中我们用样本数据组成的矩阵进行了矩阵乘法。也就是说,为了计算回归系数,我们遍历了整个样本数据。

我们的问题又来了,我们例子中的样本数据只有100条,如果处理成千上万的样本数据,我们的计算回归系数的函数的计算复杂度会直线上升。下面我们来看看如何优化这个算法。

四、优化梯度上升算法——随机梯度上升法

我们在理解了回归系数迭代计算的公式

Python语言描述机器学习之Logistic回归算法

和我们实现的程序之后。我们将计算回归系数的方法进行如下改进:

def stocGradAscent0(dataMatrix, classLabels):
 m,n = shape(dataMatrix)
 alpha = 0.01
 weights = ones((n,1)) #initialize to all ones
 for i in range(m):
  h = sigmoid(sum(dataMatrix[i]*weights))
  error = classLabels[i] - h
  weights = weights + alpha * error * mat(dataMatrix[i]).transpose()
 return weights

每一次迭代计算回归系数时,只使用样本空间中的一个样本点来计算。我们通过程序生成一个样本散点和拟合曲线的图来看一下这个算法的准确程度:

Python语言描述机器学习之Logistic回归算法

不难看出跟之前的算法相差还是比较大的。原因是之前的算法是通过500次迭代算出的结果,后者只经过了100次迭代。那么这里要说明的问题是,回归系数在随着迭代次数的增加是趋于收敛的,并且收敛的过程是存在波动的。说白了,就是迭代的次数越多,越接近我们想要的那个值,但是由于样本的数据是非线性的,这个过程也会有一定的误差。具体的回归系数和迭代次数的关系大家可以参考一些教材,例如《机器学习实战》中的描述,这里就不做详细介绍了。
我们这里只介绍一下如何改进我们的算法,使我们的算法能够快速的收敛并减小波动。方法如下:

每次迭代随机的抽取一个样本点来计算回归向量
迭代的步长随着迭代次数增大而不断减少,但是永远不等于0

改进代码,并打印出拟合曲线和样本散点图:

def stocGradAscent1(dataMatrix, classLabels, numIter=150):
 m,n = shape(dataMatrix)
 weights = ones((n,1)) #initialize to all ones
 for j in range(numIter):
  dataIndex = range(m)
  for i in range(m):
   alpha = 4/(1.0+j+i)+0.0001 #apha decreases with iteration, does not 
   randIndex = int(random.uniform(0,len(dataIndex)))#go to 0 because of the constant
   h = sigmoid(sum(dataMatrix[randIndex]*weights))
   error = classLabels[randIndex] - h
   weights = weights + alpha * error * mat(dataMatrix[randIndex]).transpose()
   del(dataIndex[randIndex])
 return weights
if __name__=='__main__':
 dataMat,labelMat=loadDataSet()
 #weights=stocGradAscent0(dataMat,labelMat)
 weights=stocGradAscent1(dataMat,labelMat)
 #weights=gradAscent(dataMat,labelMat)
 #print 'dataMat:\n',dataMat
 #print 'labelMat:\n',labelMat
 #print '回归系数:\n',weights
 plotBestFit(weights)
 #testClassify0()

默认是150迭代的样本散点图和拟合曲线图:

Python语言描述机器学习之Logistic回归算法

不难看出准确程度与第一个算法很接近了!

五、总结

Logistic回归算法主要是利用了Sgimoid函数来为数据分类,分类的准确的关键取决于从样本空间中计算出的回归系数。我们使用梯度上升法来计算回归系数,并采用随机梯度上升法来改进了算法的性能。

以上就是本文关于Python语言描述机器学习之Logistic回归算法的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他Python和算法相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

Python 相关文章推荐
python中dir函数用法分析
Apr 17 Python
使用python调用zxing库生成二维码图片详解
Jan 10 Python
Python  pip安装lxml出错的问题解决办法
Feb 10 Python
详解Python如何生成词云的方法
Jun 01 Python
python 检查文件mime类型的方法
Dec 08 Python
Python面向对象程序设计中类的定义、实例化、封装及私有变量/方法详解
Feb 28 Python
GitHub 热门:Python 算法大全,Star 超过 2 万
Apr 29 Python
用sqlalchemy构建Django连接池的实例
Aug 29 Python
Python 余弦相似度与皮尔逊相关系数 计算实例
Dec 23 Python
tensorflow之获取tensor的shape作为max_pool的ksize实例
Jan 04 Python
python hmac模块验证客户端的合法性
Nov 07 Python
Python使用Beautiful Soup(BS4)库解析HTML和XML
Jun 05 Python
python Crypto模块的安装与使用方法
Dec 21 #Python
python编写Logistic逻辑回归
Dec 30 #Python
python+selenium识别验证码并登录的示例代码
Dec 21 #Python
python实现随机森林random forest的原理及方法
Dec 21 #Python
python编写分类决策树的代码
Dec 21 #Python
Python基于PyGraphics包实现图片截取功能的方法
Dec 21 #Python
用Python写王者荣耀刷金币脚本
Dec 21 #Python
You might like
异世界新番又来了,同样是从零开始,男主的年龄降到5岁
2020/04/09 日漫
PHPLog php 程序调试追踪工具
2009/09/09 PHP
网页游戏开发入门教程三(简单程序应用)
2009/11/02 PHP
PHP中怎样防止SQL注入分析
2014/10/23 PHP
PHP读书笔记整理_结构语句详解
2016/07/01 PHP
javascript ie6兼容position:fixed实现思路
2013/04/01 Javascript
你必须知道的Javascript知识点之&quot;单线程事件驱动&quot;的使用
2013/04/23 Javascript
JavaScript新窗口与子窗口传值详解
2014/02/11 Javascript
jQuery实现仿QQ头像闪烁效果的文字闪动提示代码
2015/11/03 Javascript
javascript面向对象程序设计高级特性经典教程(值得收藏)
2016/05/19 Javascript
javascript之with的使用(阿里云、淘宝使用代码分析)
2016/10/11 Javascript
Easyui使用Dialog行内按钮布局的实例
2017/07/27 Javascript
Javascript中的getter和setter初识
2017/08/17 Javascript
JavaScript实现的级联算法示例【省市二级联动功能】
2018/12/25 Javascript
laravel实现中文和英语互相切换的例子
2019/09/30 Javascript
解决vue初始化项目时,一直卡在Project description上的问题
2019/10/31 Javascript
TensorFlow卷积神经网络之使用训练好的模型识别猫狗图片
2019/03/14 Python
python验证码图片处理(二值化)
2019/11/01 Python
Python使用正则实现计算字符串算式
2019/12/29 Python
Selenium结合BeautifulSoup4编写简单的python爬虫
2020/11/06 Python
CSS3 简写animation
2012/05/10 HTML / CSS
Ted Baker英国官网:男士和女士服装及配件
2017/03/13 全球购物
菲律宾票务网站:StubHub菲律宾
2018/04/21 全球购物
意大利男装网店:Vrients
2019/05/02 全球购物
西班牙在线光学:Visual-Click
2020/06/22 全球购物
保安自我鉴定范文
2013/12/08 职场文书
阳光体育活动方案
2014/02/16 职场文书
护理专业毕业生自荐书
2014/05/24 职场文书
常务副县长“四风”个人对照检查材料思想汇报
2014/10/02 职场文书
党员自我剖析材料范文
2014/10/06 职场文书
2014年项目工作总结
2014/11/24 职场文书
2015年试用期自我评价范文
2015/03/10 职场文书
2019脱贫攻坚工作总结报告范本!
2019/08/06 职场文书
JS数组方法some、every和find的使用详情
2021/10/05 Javascript
Python可变集合和不可变集合的构造方法大全
2021/12/06 Python
Python机器学习应用之基于线性判别模型的分类篇详解
2022/01/18 Python