机器学习——Logistic回归

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

参考《机器学习实战》

利用Logistic回归进行分类的主要思想:

根据现有数据对分类边界线建立回归公式,以此进行分类。

分类借助的Sigmoid函数:

Sigmoid函数图:

Sigmoid函数的作用:

将所有特征都乘上一个回归系数,然后将所有结果值相加,将这个总和代入Sigmoid函数中,进而得到一个0~1之间的数值。任何大于0.5的数据被分1类,小于0.5分入0类。

综上,Sigmoid的输入可以记为z:

所以向量w即是我们要通过最优化方法找的系数。

w向量的求解:

1)、梯度上升法(思想:沿函数梯度方向找函数最大值)

梯度上升法伪代码:

更新w系数的细节实现代码:

要注意的是,作者在这里dataMatrix的特征矢量维度比实际特征矢量多了一维。作者使用的数据是二维[x1,x2],而程序中增加了一维[x0=1,x1,x2].奇怪的是x0加在了最前面的位置,而不是最后的位置。此外,上图中画红线处的公式作者未给出由来,网上搜索了下,找到一篇博文,写得还不错。这里帖上点简要概述:

具体过程如下:(参考:http://blog.csdn.net/yangliuy/article/details/18504921?reload)

参数概率方程:

其中x为训练特征,y为x对应的类,θ为待估计参数

利用上式中y只取0或1的特点,刚好可以表示为:

似然函数:(这里就是Logistic Regression的目标函数,原书中并未指明,所以如果不网上找logistic的资料区先前学过机器学习,很无法理解书中的做法的)

对数似然函数:

所以极大似然估计:

从而得到梯度上升法的递归公式:

这里也就是上面的图中,我画红线处公式的由来了。

这里再上传下自己写的代码(未优化的logistic算法),代码中的数据来源仍是《机器学习实战》一书提供的数据:

#-*- coding:cp936 -*-importnumpy as npimportmatplotlib.pyplot as pltclassLog_REG():def__init__(self):

self._closed=FalsedefloadData(self, dataFile='testSet.txt'):

f_file=open(dataFile)

lines=f_file.readlines()

line_data=lines[0].strip().split()

self.num_feature= len(line_data) - 1self.xData= np.zeros((len(lines), self.num_feature + 1))

self.label= np.zeros((len(lines), 1))

self.num_label=len(lines)

line_cnt=0foriLineinlines:

line_data=iLine.strip().split()foriinrange(self.num_feature):

self.xData[line_cnt][i]=float(line_data[i])

self.xData[line_cnt][self.num_feature]= 1self.label[line_cnt]= float(line_data[-1])

line_cnt+=1def_sigmoid(self, z):return1.0 / (1 + np.exp(-z))defgradAscendClass(self):

maxIter= 500self.omiga= np.ones((1, self.num_feature+1))

xDataMat=np.matrix(self.xData)

alpha= 0.01self.omiga_record=[]foriinrange(maxIter):

h= self._sigmoid(self.omiga * xDataMat.transpose())#矩阵乘error = self.label -h.transpose()

self.omiga= self.omiga + alpha * (xDataMat.transpose()*error).transpose()

self.omiga_record.append(self.omiga)ifnp.sum(np.abs(error)) < self.num_label * 0.05:PRint"error very low",i

breakdefstochasticGradAscend(self):pass#maxIter = 150#self.omiga = np.ones((1,self.num_feature+1))#fordefplotResult(self):

self._close()ifself.num_feature != 2:print"Only plot data with 2 features!"returnlabel0x=[]

label0y=[]

label1x=[]

label1y=[]foriinrange(self.num_label):ifint(self.label[i]) == 1:

label1x.append(self.xData[i][0])

label1y.append(self.xData[i][1])else:

label0x.append(self.xData[i][0])

label0y.append(self.xData[i][1])

fig=plt.figure()

ax= fig.add_subplot(111)

ax.scatter(label0x, label0y, c='b',marker='o')

ax.scatter(label1x, label1y, c='r',marker='s')

minx=min(min(label0x),min(label1x))

maxx=max(max(label0x),max(label1x))

wx= np.arange(minx,maxx,0.1)

wy= (-self.omiga[0,2]-self.omiga[0,0]*wx)/self.omiga[0,1]

ax.plot(wx,wy)defplotIteration(self):

self._close()

iterTimes=len(self.omiga_record)

w0=[i[0][0,0]foriinself.omiga_record]

w1=[i[0][0,1]foriinself.omiga_record]

w2=[i[0][0,2]foriinself.omiga_record]

fig=plt.figure()

ax1= fig.add_subplot(3,1,1)

ax1.plot(range(iterTimes),w0,c='b')#,marker='*')plt.xlabel('w0')

ax2= fig.add_subplot(3,1,2)

ax2.plot(range(iterTimes),w1,c='r')#,marker='s')plt.xlabel('w1')

ax3= fig.add_subplot(3,1,3)

ax3.plot(range(iterTimes),w2,c='g')#,marker='o')plt.xlabel('w2')defshow(self):

plt.show()def_close(self):passif__name__=='__main__':

testclass=Log_REG()

testclass.loadData()

testclass.gradAscendClass()

testclass.plotResult()

testclass.plotIteration()

testclass.show()

显示结果:

分类结果

分类参数收敛结果

梯度上升(或下降)算法的改进:

当数据量很大时,上述梯度上升算法每次迭代都要对所有数据进行处理,会造成计算量异常庞大。解决的方法是引入随机梯度的思想。

随机梯度下降的基本原理是:不直接计算梯度的精确值,而是用梯度的无偏估计g(w)来代替梯度:

实际操作时,随机地选取单个数据而非整个数据集参与迭代,详细的原理推导可参见:http://www.52ml.net/2024.html

改进的随机梯度上升法:

defstochasticGradAscend2(self):

maxIter= 150self.omiga= np.ones((1,self.num_feature+1))

self.omiga_record=[]forjinrange(maxIter):

randRange=range(self.xData.shape[0])foriinrange(self.xData.shape[0]):

alpha= 4/(1.0+i+j)+0.01randIndex= int(random.uniform(0,len(randRange)-1))

index=randRange[randIndex]

h= self._sigmoid(np.matrix(self.omiga)[0]*np.matrix(self.xData[index,:]).transpose())

error= self.label[index]-h

self.omiga= self.omiga+alpha*error*self.xData[index,:]

self.omiga_record.append(np.matrix(self.omiga))del(randRange[randIndex])

从上图可以看出,改进后的随机梯度算法收敛很快,上图只对所有数据做150次迭代。

参考文献:

http://blog.csdn.net/yangliuy/article/details/18504921?reload

随机梯度:http://www.52ml.net/2024.html

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航