机器学习实战笔记2

来源:互联网 发布:大数据支撑平台 编辑:程序博客网 时间:2024/06/01 17:25

第5章 Logistic回归

原理

【实质和感知机有点像】

———————-补充:感知机————————-

定义

给定一个数据集:T={(x1,y1),(x2,y2),,(xN,yN)} , 其中xiϵRn,yiϵ{+1,1},i=1,2,N ,如果存在某个超平面S

wx+b=0

能够将数据集的正实例和负实例点完全正确划分到超平面的两侧,即对所有yi=+1的实例i ,有wxi+b>0 ,对所有的yi=1 的实例i ,有wxi+b<0 ,则称数据集T为线性可分数据集,否则,称数据集T线性不可分

学习策略

假设训练数据集是线性可分的,这样就存在一个超平面可以将训练集的正实例点和负实例点完全分开,即存在一组w,b,问题的关键就在于如何找到w,b,而这样的超平面下是没有误分类点的,我们的初始条件w0,b0 所对应的超平面肯定是有误分类点,我们需要不断的变化w,b 来使得超平面左右误分类点越来越少,这样判断的标准就是误分类点

我们选择误分类点到超平面的距离总和作为损失函数:

对于点x0 到超平面S的距离:

1||w|||wx0+b|

对于误分类点(xi,yi) ,有

yi(wxi+b)>0
,而正确分类的点必有yi>0,wxi+b>0 ,这样我们可以挑选出误分类点

假设超平面S的误分类点集合为M,所有误分类点到超平面S的总距离为

L(w,b)=1||w||xiϵMyi(wxi+b)

我们的目的是要使L(w)=0 而且||w|| 添加进来会使计算复杂化,至于是否会影响查找速度,可以参见SVM,此处略过

得感知机学习的损失函数为

L(w,b)=xiϵMyi(wxi+b)

我们要求解使得损失函数最小w,b

使用梯度下降法(至于为什么使用梯度下降法,而不是直接求导,解方程,下面有讲到),对损失函数求梯度

L(w,b)w=xiϵMyixi

L(w,b)b=xiϵMyi

统计学习方法中使用的是随机梯度下降法,就是遇到误分类点(xi,yi),单对该点求梯度,对w,b更新 (最小值,是沿梯度下降,因此是减去梯度)

wi+1=wi+ηyixi

bi+1=bi+ηyi

这里说一下,如果是梯度下降法,需要这样更新:

wi+1=wi+ηxiϵMyixi

bi+1=bi+ηxiϵMyi

具体算法及对偶形式就不叙述了。。。

【注】感知机和逻辑斯谛回归模型的一大区别在于损失函数,在梯度下降法中感知机针对的是误分类点,逻辑斯谛回归模型是对所有的点

———————-结束————————————–

给定Sigmoid函数和输入

Sigmoidσ(z)=11+ez

z=w0x0+w1x1++wnxn+b,wixi

统计学习方法中讲到:

二项逻辑斯谛回归模型(二分类)是如下条件概率分布:

P(Y=1|x)=ewx+b1+ewx+b

P(Y=0|x)=11+ewx+b

对于上式的w,x,b加以扩充修改

w=(w(1),w(2),,w(n),b),x=(x(1),x(2),,x(n),1)

条件概率分布变为

P(Y=1|x)=ewx1+ewx

P(Y=0|x)=11+ewx

继续分析影响上述条件变量的因素,一个事件的几率是指该事件发生的概率与该事件不发生的概率的比值。如果事件发生的概率为p,那么该事件发生的几率是p1p ,对逻辑斯谛回归而言,其对数几率为:

logP(Y=1|x)1P(Y=1|x)=wx

即输出Y=1的对数几率是输入x的线性函数,该线性函数的值越接近正无穷,概率值就越接近1;该线性函数的值越接近负无穷,概率值就越接近0,这样的模型就是逻辑斯谛回归模型

关于逻辑斯谛回归模型的参数估计

对于给定的训练数据集T=(x1,y1),(x2,y2),,(xN,yN),xiRn,yi0,1 ,下面使用极大似然估计法估计模型参数:

设:P(Y=1|x)=π(x) , P(Y=0|x)=1π(x)

其似然函数为

i=1N[π(xi)]yi[1π(xi)]1yi

对数似然函数为

L(w)=i=1N(yilogπ(xi)+(1yi)log(1π(xi)))

=i=1N(yilogπ(xi)1π(xi)+log(1π(xi)))

这里将

π(xi)=ewxi1+ewxi
代入上式

L(w)=i=1N(yiwxilog(1+ewxi))

似然估计法在找到似然函数L(w)后,对其求极大值,得到w的估计值

【至于极大似然估计法为什么是求解最大值,百科上讲到:极大似然估计是建立在这样的思想上:已知某个参数能使这个样本出现的概率最大,我们当然不会再去选择其他小概率的样本,所以干脆就把这个参数作为估计的真实值。】

大概意思就是说按照极大似然估计的方法对似然函数求解最大值,所对应的参数是使误分类点最小的参数。。。

这种多维下求解目标函数的最优化问题不同于一二维下直接求导,令导函数等于0,然后解出参数,多维下很难求解,于是有了梯度下降法等方法

我们通过参数的梯度来知道目标函数下降(上升)最快的方向,一点点的更新参数,使函数值向着极大值迈进,直到变化量小于某个阈值,停止

对对数似然函数求导:

Lw=i=1N(yixixiewxi1+ewxi)

wi+1=wi+αLw

不断的迭代w,直至L(wi+1)L(wi)的差值在某一个阈值内,停止迭代,所求的w为极优参数

【这里需要注意一点,机器学习实战中使用的函数是

P(Y=1|x)=11+ewx
,实质上是没有区别的,将统计学习方法中的函数分子分母同除ewx ,便可得到此式,对于机器学习实战中对应代码的公式: 即上面的梯度括号第二项分子分母同除ewxi 后的结果】

实例1

现有很多二维坐标系下的点,每个点上有一个标签,代表分类。如下所示:

-0.017612  14.053064  0-1.395634  4.662541   1-0.752157  6.538620   0-1.322371  7.152853   00.423363   11.054677  00.406704   7.067335   10.667394   12.741452  0-2.460150  6.866805   10.569411   9.548755   0

下面使用Logistis回归来进行分类预测

首先是数据加载,训练集如上所示,前两列为特征x(1),x(2),最后一列为类别yx 扩充为(1,x(1),x(2)),代码如下:

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])])#注意这里1的添加,这里代表的是b        labelMat.append(int(lineArr[2]))    return dataMat,labelMat

求解梯度,迭代数据,更新参数

def sigmoid(inX):    return 1.0/(1+exp(-inX))#dataMat为list,需要转化为ieNumPy矩阵def gradAscent(dataMat,labelMat):    dataMatrix=mat(dataMat)    labelMat=mat(labelMat).transpose()#转置    m,n=shape(dataMatrix)    alpha=0.001    maxCycles=500    weights=ones((n,1))#生成n行1列的值为1的矩阵    for k in range(maxCycles):        h=sigmoid(dataMatrix*weights)        error=(labelMat-h)        weights=weights+alpha*dataMatrix.transpose()*error    return weights

上面代码中的公式在前面是有推导过的,此处代码的亮点在于使用矩阵简化代码,如果用传统的计算不知多么复杂。下面详细讲解:

11..1x(1)1x(1)2..x(1)Nx(2)1x(2)2..x(2)Nw1w2w3=z1z2..zNSigmoid(y)=h1h2..hN

关于代码中的参数weights的更新:

借用前面的公式如下

Lw=i=1N(yixixiewxi1+ewxi)

对括号内的第二项分子分母同除ewxi

Lw=i=1N(yixixi1+ewxi)

=i=1N(yi11+ewxi)xi

=i=1N(yihi)1x(1)ix(2)i

即:

w1w2w3i+1=w1w2w3i+α1x(1)1x(2)11x(1)2x(2)2......1x(1)Nx(2)Ny1h1y2h2..yNhN

画决策边界

迭代500次获得参数weights,超平面即为weights[0]+weights[1:]*x=0

代码如下:

#分析数据,画出决策边界def plotBestFit(dataMat,labelMat,weights):    data0=[]    data1=[]    #分离数据为label为0的和为1的    for i in range(len(labelMat)):        if labelMat[i]==0:            data0.append(dataMat[i])        else:            data1.append(dataMat[i])    #这一块可以参考knn中的绘图部分    plt.scatter([x[1] for x in data0], [x[2] for x in data0], c='r', label='0')  # red    plt.scatter([x[1] for x in data1], [x[2] for x in data1], c='g', label='1')  # green    plt.legend()    x1=arange(-4,4,0.1)#生成-4,到3得列表,并且步长为0.1    #w1*x1+w2*x2+b=0,解出x2    x2=-(float(weights[0])+float(weights[1])*x1)/float(weights[2])#注意weight的格式,需要将其转为数值    plt.plot(x1,x2)    plt.show()

如下图所示:

这里写图片描述