1、概述

  Logistic regression(逻辑回归)是当前业界比较常用的机器学习方法,用于估计某种事物的可能性。

  在经典之作《数学之美》中也看到了它用于广告预测,也就是根据某广告被用 户点击的可能性,把最可能被用户点击的广告摆在用户能看到的地方,然后叫他“你点我啊!”用户点了,你就有钱收了。这就是为什么我们的电脑现在广告泛滥的 原因。还有类似的某用户购买某商品的可能性,某病人患有某种疾病的可能性啊等等。这个世界是随机的(当然了,人为的确定性系统除外,但也有可能有噪声或产生错误的结果,只是这个错误发生的可能性太小了,小到千万年不遇,小到忽略不计而已),所以万物的发生都可以用可能性或者几率(Odds)来表达。“几率”指的是某事物发生的可能性与不发生的可能性的比值。

Logistic regression可以用来回归,也可以用来分类,主要是二分类。

2、基本理论

2.1Logistic regression和Sigmoid函数

  回归:假设现在有一些数据点,我们用一条直线对这些点进行拟合(该条称为最佳拟合直线),这个拟合过程就称作回归。利用Logistic回归进行分类的思想是:根据现有数据对分类边界线建立回归公式,以此进行分类。这里的“回归”一词源于最佳拟合,表示找到最佳拟合参数,使用的是最优化算法。

  Sigmoid函数具体的计算公式如下:

    

          z=w0x0+w1x1+w2x2+...+wnxn, z=wTx  其中w是我们要找的最佳参数(系数),x是分类器的输入数据特征。

  当x为0时,Sigmoid函数值为0.5,随着x的增大,对应的Sigmoid值将逼近于1;而随着x的减小,Sigmoid值将逼近于0。如果横坐标刻度足够大(如下图所示),Sigmoid函数看起来很像一个阶跃函数。

    

  为了实现Logistic回归分类器,我们可以在每个特征上都乘以一个回归系数,然后把所有结果值相加,将这个总和代入Sigmoid函数中,进而得到一个范围在0-1之间的数值。任何大于0.5的数据被分入1类,小于0.5即被归入0类。所以,Logistic回归也可以被看作是一种概率估计。

2.2最优化理论

  由上述问题得到,我们现在的问题变成了:最佳回归系数时多少?

    z=w0x0+w1x1+w2x2+...+wnxnz=wT

  向量x是分类器的输入数据,向量w是我们要找的最佳参数(系数),从而使得分类器尽可能地精确,为了寻找最佳参数,需要用到最优化理论的一些知识。

  下面首先介绍梯度上升的最优化方法,我们将学习到如何使用该方法求得数据集的最佳参数。接下来,展示如何绘制梯度上升法产生的决策边界图,该图能将梯度上升法的分类效果可视化地呈现出来。最后我们将学习随机梯度上升法,以及如何对其进行修改以获得更好的结果。

2.2.1梯度上升法

  梯度上升法的基于的思想是:要找到某函数的最大值,最好的方法是沿着该函数的梯度方向探寻。则函数f(x,y)的梯度由下式表示:

  这个梯度意味着要沿x方向移动,沿y方向移动,其中,函数f(x,y)必须要在待计算的点上有定义并且可微。具体的函数例子如下图所示:

      

      注释:梯度上升算法到达每个点后都会重新估计移动的方向。从P0开始,计算完该点的梯度,函数就根据梯度移动到下一点P1。在P1点,梯度再次被重新计算,并沿新的梯度方向移动到P2。如此循环迭代,直到满足停止条件。迭代过程中,梯度算子总是保证我们能选取到最佳的移动方向。

  可以看到,梯度算子总是指向函数值增长最快的方向。这里所说的是移动方向,而未提到移动量的大小。该量值称为歩长,记作,用向量来表示的话,梯度上升算法的迭代公式如下:

  

  该公式将一直被迭代执行,直到达到某个停止条件为止,比如迭代次数达到某个指定值或算法达到可以允许的误差范围。

  事例(用梯度上升找到最佳参数)

  该数据中有100个样本点,每个点包含两个数值型特征:X1和X2。在此数据集上,我们将通过使用梯度上升法找到最佳回归系数,也就是说拟合出Logistic回归模型的最佳参数。在以下的数据集中,每行的前两个值分别是X1和X2,它们是数据特征,第三个值是数据对应的类别标签,为了方便计算,该函数还将X0的值设为1.0。

  testSet.txt数据集如下:

  

  梯度上升算法代码如下,建立一个logRegres.py的文件,添加如下代码:

#!/usr/bin/python
# -*- coding: utf-8 -*-
from numpy import *
#Logistic回归梯度上升优化算法
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])])  #获取X0,X1,X2的值
labelMat.append(int(lineArr[2]))    #获取最后一列的类别标签
return dataMat,labelMat def sigmoid(inX):
return 1.0/(1+exp(-inX)) def gradAscent(dataMatIn, classLabels):     #dataMatIn是一个2维Numpy数组
dataMatrix = mat(dataMatIn) #convert to NumPy matrix
labelMat = mat(classLabels).transpose() #convert to NumPy matrix
m,n = shape(dataMatrix)
alpha = 0.001
maxCycles = 500                         #迭代次数为500
weights = ones((n,1))                   #回归系数初始化为1  
for k in range(maxCycles): #heavy on matrix operations
h = sigmoid(dataMatrix*weights) #matrix mult
error = (labelMat - h) #vector subtraction
weights = weights + alpha * dataMatrix.transpose()* error #matrix mult
return weights

  在python提示符下,写下面代码:

>>>import logRegres
>>> dataArr,labelMat=logRegres.loadDataSet()
>>> logRegres.gradAscent(dataArr,labelMat)
matrix([[ 4.12414349],
[ 0.48007329],
[-0.6168482 ]])

解释:

>>> dataMat
matrix([[ 1.00000000e+00, -1.76120000e-02, 1.40530640e+01],
[ 1.00000000e+00, -1.39563400e+00, 4.66254100e+00],
...
[ 1.00000000e+00, 1.38861000e+00, 9.34199700e+00],
[ 1.00000000e+00, 3.17029000e-01, 1.47390250e+01]])
>>> labelMat
matrix([[0],
[1],
...
[0],
[0]])

  上面解出了一组回归系数,它确定了不同类别数据之间的分隔线。那么怎样画出该分隔线,从而使得优化过程便于理解,打开logRegres.py添加如下代码:

#画出数据即和Logisitic回归最佳拟合直线的函数
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]  #W0X0+W1X1+W2X2=0(X0=1),X2=(-W0-W1X1)/W2
ax.plot(x, y)
plt.xlabel('X1'); plt.ylabel('X2');
plt.show()

  运行程序清单,在python提示符下输入:

>>> from numpy import *
>>> reload(logRegres)
<module 'logRegres' from 'logRegres.pyc'>
>>> logRegres.plotBestFit(wei)
'''

  这个分类结果相当不错,从图上看只错分了两到四个点。但是,尽管例子简单且数据集很小,但是这个方法确需要大量的计算(300次乘法),下一节将对该算法稍作改进,从而使它能用在真实数据集上。

2.2.2随机梯度上升

  梯度上升算法在每次更新回归系数时都需要遍历整个数据集,该方法在处理1001个左右的数据集时尚克,但如果有数十亿样本和成千上万的特征,那么该方法的计算复杂度就太高了。

  一种改进方法是一次仅用一个样本点来更新回归系数,该方法称为随机梯度上升算法。由于可以在信仰本到来时对分类器进行增量式更新,因而随机梯度上升算法是一个在线学习算法。

  随机梯度上升算法代码如下,将下面代码添加到logRegres.py中:

#随机梯度上升函数
def stocGradAscent0(dataMatrix, classLabels):
m,n = shape(dataMatrix)
alpha = 0.01
weights = ones(n) #initialize to all ones
for i in range(m):
h = sigmoid(sum(dataMatrix[i]*weights))
error = classLabels[i] - h
weights = weights + alpha * error * dataMatrix[i]
return weights

  为了验证该方法的结果,我们在python提示符中输入以下命令:

>>> from numpy import *
>>> reload(logRegres)
<module 'logRegres' from 'logRegres.py'>
>>> dataArr,labelMat=logRegres.loadDataSet()
>>> weights=logRegres.stocGradAscent0(array(dataArr),labelMat)
>>> logRegres.plotBestFit(weights)

  随机梯度上升算法与梯度上升算法在代码上很相似,但有一些区别:

  梯度上升算法:变量h和误差error都是向量,有矩阵的转换过程

  随机梯度上升算法:变量h和误差error都是数值,没有矩阵的转换过程,所有的数据类型都是Numpy数组。

  由上述图得到的最佳拟合直线图,但拟合的直线没有那么完美,这里的分类器错分了三分之一的样本。一个判断优化算法优劣的可靠方法是看它是否收敛,也就是说参数是否达到了稳定值,是否还会不断地变化。

  对上述随机梯度上升算法上做了些修改,使其在整个数据集上运行200次,最终绘制的三个回归系数的变化情况如图所示:

  上图展示了随机梯度上升算法在200次迭代过程中(我们的数据库有100个样本,每个样本都对系数调整一次,所以共有200*100=20000次调整)回归系数的变化情况。由图中看到X2只经过了50次迭代就达到了稳定值,但X0和X1则需要更多次的迭代。另外值得注意的是,在大的波动停止后,还有一些小的波动。产生这种现象的原因是存在一些不能正确分类的样本点(数据集并非线性可分),在每次迭代时会引发系数的剧烈改变。我们期望算法能避免来回波动,从而收敛到某个值。另外,收敛速度也要加快。

2.2.3改进的随机梯度上升算法

  对上述随机梯度上升算法,我们做两处改进来避免上述的波动问题:

1) 在每次迭代时,调整更新步长alpha的值。随着迭代的进行,alpha越来越小,这会缓解系数的高频波动(也就是每次迭代系数改变得太大,跳的跨度太 大)。当然了,为了避免alpha随着迭代不断减小到接近于0(这时候,系数几乎没有调整,那么迭代也没有意义了),我们约束alpha一定大于一个稍微大点的常数项,具体见代码。

2)每次迭代,改变样本的优化顺序。也就是随机选择样本来更新回归系数。这样做可以减少周期性的波动,因为样本顺序的改变,使得每次迭代不再形成周期性。

  将下述代码添加到logRegres.py中:

#改进的随机梯度上升函数
def stocGradAscent1(dataMatrix, classLabels, numIter=150):
m,n = shape(dataMatrix)
weights = ones(n) #initialize to all ones
for j in range(numIter):
dataIndex = range(m)
for i in range(m):
alpha = 4/(1.0+j+i)+0.01 #j是迭代次数,i是样本点的下标,alpha每次迭代时需要调整
randIndex = int(random.uniform(0,len(dataIndex))) #随机选取样本来更新回归系数(减少周期波动)
h = sigmoid(sum(dataMatrix[randIndex]*weights))
error = classLabels[randIndex] - h
weights = weights + alpha * error * dataMatrix[randIndex]
del(dataIndex[randIndex])
return weights

  为了验证该方法的结果,我们在python提示符中输入以下命令:

>>> reload(logRegres)
<module 'logRegres' from 'logRegres.py'>
>>> dataArr,labelMat=logRegres.loadDataSet()
>>> weights=logRegres.stocGradAscent1(array(dataArr),labelMat)
>>> logRegres.plotBestFit(weights)

  

  改进算法增加了一个迭代次数作为第三个参数,如果该参数没有给定的话,算法将默认迭代150次,如果给定,那么算法将按照新的参数值进行迭代。与随机梯度上升算法中的回归系数类似,改进的随机梯度上升算法中的各个回归系数的变化情况如下:

  比较随机梯度上升和改进后的梯度上升,可以看到两点不同:

  1)系数不再出现周期性波动。

  2)系数可以很快的稳定下来,也就是快速收敛。这里只迭代了20次就收敛了。而上面的随机梯度下降需要迭代200次才能稳定。

3、Logistic回归的一般过程

  (1)收集数据:采用任何方法收集数据

  (2)准备数据:数据类型是数值型的,另外,结构化数据格式则最佳

  (3)分析数据:采用任意方法对数据进行分析

  (4)训练算法:大部分时间将用于训练,训练的目的是为了找到最佳的分类回归系数

  (5)测试算法:一旦训练步骤完成,分类将会很快

  (6)使用算法:首先,我们需要输入一些数据,并将其转换成对应的结构化数值;接着,基于训练好的回归系数就可以对这些数值进行简单的回归计算,判定它们属于哪个类别;在这之后,我们就可以在输出的类别上做一些其他分析工作。

4、Logistic回归优缺点

  优点:计算代价不高,易于理解和实现

  缺点:容易欠拟合,分类精度可能不高

  适用数据类型:数值型和标称型数据

【Machine Learning in Action --5】逻辑回归(LogisticRegression)的更多相关文章

  1. Machine Learning in action --LogisticRegession 逻辑回归

    本系列主要参考<机器学习实战>,使用python3编译环境,实现书中的相关代码. 1.基本算法 关于梯度上升算法和随机梯度上升算法的选择: 当数据集较小时,使用梯度上升算法: 当数据集较大 ...

  2. 机器学习实战(Machine Learning in Action)学习笔记————05.Logistic回归

    机器学习实战(Machine Learning in Action)学习笔记————05.Logistic回归 关键字:Logistic回归.python.源码解析.测试作者:米仓山下时间:2018- ...

  3. 《Machine Learning in Action》—— Taoye给你讲讲Logistic回归是咋回事

    在手撕机器学习系列文章的上一篇,我们详细讲解了线性回归的问题,并且最后通过梯度下降算法拟合了一条直线,从而使得这条直线尽可能的切合数据样本集,已到达模型损失值最小的目的. 在本篇文章中,我们主要是手撕 ...

  4. 《Machine Learning in Action》—— 浅谈线性回归的那些事

    <Machine Learning in Action>-- 浅谈线性回归的那些事 手撕机器学习算法系列文章已经肝了不少,自我感觉质量都挺不错的.目前已经更新了支持向量机SVM.决策树.K ...

  5. 【机器学习实战】Machine Learning in Action 代码 视频 项目案例

    MachineLearning 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远 Machine Learning in Action (机器学习实战) | ApacheCN(apa ...

  6. 学习笔记之机器学习实战 (Machine Learning in Action)

    机器学习实战 (豆瓣) https://book.douban.com/subject/24703171/ 机器学习是人工智能研究领域中一个极其重要的研究方向,在现今的大数据时代背景下,捕获数据并从中 ...

  7. 机器学习实战(Machine Learning in Action)学习笔记————07.使用Apriori算法进行关联分析

    机器学习实战(Machine Learning in Action)学习笔记————07.使用Apriori算法进行关联分析 关键字:Apriori.关联规则挖掘.频繁项集作者:米仓山下时间:2018 ...

  8. 《Machine Learning in Action》—— Taoye给你讲讲决策树到底是支什么“鬼”

    <Machine Learning in Action>-- Taoye给你讲讲决策树到底是支什么"鬼" 前面我们已经详细讲解了线性SVM以及SMO的初步优化过程,具体 ...

  9. K近邻 Python实现 机器学习实战(Machine Learning in Action)

    算法原理 K近邻是机器学习中常见的分类方法之间,也是相对最简单的一种分类方法,属于监督学习范畴.其实K近邻并没有显式的学习过程,它的学习过程就是测试过程.K近邻思想很简单:先给你一个训练数据集D,包括 ...

  10. 机器学习实战(Machine Learning in Action)学习笔记————10.奇异值分解(SVD)原理、基于协同过滤的推荐引擎、数据降维

    关键字:SVD.奇异值分解.降维.基于协同过滤的推荐引擎作者:米仓山下时间:2018-11-3机器学习实战(Machine Learning in Action,@author: Peter Harr ...

随机推荐

  1. TortoiseSVN 1.8 关于右键的设置

    以前用SVN但都是 IDE 自己集成的插件,最近使用 android studio 发现居然自己不带SVN command line插件,非得自己单独装一个,于是使用了 TortoiseSVN ,但用 ...

  2. Android使用Home键后应用程序重启的问题

    正常情况应该是在点击 home 按键后,程序在后台暂停运行,点击 后退键 才会退出应用的,但是今天遇到个问题,点击 home 键后,重新再打开应用却每次都返回应用启动页面,有些莫名其妙,一番googl ...

  3. Mysq 5.7l服务无法启动,没有报告任何错误

    昨天系统崩溃了,然后重装了Mysql 5.7 安装步骤和遇到问题及解决方案. 去官网下载Mysql 5.7的解压包(zip),解压到你要安装的目录. 我的安装目录是:D:\Java\Mysql 安装步 ...

  4. 解锁Oracle数据库用户

    Oracle数据库,如何解除数据库用户账户的锁定呢???如何修改口令呢??? 请问各位高手:Oracle数据库,如何解除数据库用户账户的锁定呢???如何修改口令呢???[万分感激各位高手的帮忙] 00 ...

  5. Python学习笔记——进阶篇【第九周】———线程、进程、协程篇(队列Queue和生产者消费者模型)

    Python之路,进程.线程.协程篇 本节内容 进程.与线程区别 cpu运行原理 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Ev ...

  6. asp.net时间范围查询

    1.首先要查询类表中的一个时间段,要明确我的数据库中只有一个时间字段,我们先将他拆分一下. if ($("#news_OpenTime").val() != "" ...

  7. 系统自动生成ID(比UUID.radom().tostring()要好看)

    public class test1 { public static void main(String[] args) { char[] para = {'A','B','C','D','E','F' ...

  8. iframe自适应高度处理方案

    第一种:这个方案能解决大多数自适应高度问题,方法是在iframe所要加载的页面上添加代码,把它的高度告诉iframe所在页面.缺点显而易见,如果iframe要加载的页面非常多而且不固定那么代码加起来很 ...

  9. 每个Web开发者必备的9个软技能

    对于一份工作,你可能专注于修炼自己的内功,会在不自觉中忽视软技能.硬技能决定你是否能得到工作,而软技能能够表明你是否适合这份工作和适应工作环境等.所有的公司都有属于自己的文化,并努力将这些文化传承下去 ...

  10. yii2.0 面包屑的使用

    yii2中面包屑是yii2自带的小部件,类似本网站的导航栏应该就是采用面包屑来完成的 例子如下,需要引入 yii\widgets\Breadcrumbs echo Breadcrumbs::widge ...