1.梯度上升优化
1). 伪代码:
所有回归系数初始化为1-------------------weights = ones((colNum,1))
重复r次:
计算整个数据集的梯度gradient
使用alpha*gradient更新回归系数的向量
返回回归系数weights
2). 迭代r次的代码:
for k in range(r): #heavy on matrix operations h = sigmoid(dataMatrix*weights) #matrix mult error = (labelMat - h) #vector subtraction weights = weights + alpha * dataMatrix.transpose()* error #matrix mult
2.随机梯度上升
梯度上升算法每次更新回归系数都要遍历整个数据集(批处理),样本集数十亿时复杂度相当高。
一种改进方法是一次仅用一个样本点来更新回归系数(在线学习),该方法称为“随机梯度上升算法”。
1). 伪代码:
所有回归系数初始化为1
对数据集中每个样本:
计算该样本梯度gradient
使用alpha*gradient更新回归系数的向量
返回回归系数weights
2). 用每个样本点更新回归系数代码:
for i in range(m): h = sigmoid(sum(dataMatrix[i]*weights)) error = classLabels[i] - h weights = weights + alpha * error * dataMatrix[i]
3. 1与2比较:
1加载的是列表,用numpy.mat()转成矩阵计算,计算中是向量运算。2加载数据时就已通过numpy.array()转换列表数据为数组数据类型,计算中是数值运算。
4. 改进随机梯度上升
一种判断优化算法优劣的可靠方法是看它是否收敛,也就是说参数是否达到了稳定值,是否还会不断变化。
将2在整个数据集运行200次,绘制出X0,X1,X2三个回归系数的变化情况。发现1)系数2较快达到稳定值,2)大波动停止后,还有周期性小波动,原因是存在一些不能正确分类的样本点(数据及非线性可分),在每次迭代时引发系数剧烈改变。
期望改进:1)避免来回波动,从而收敛到某个值;2)加快收敛速度
改进随机梯度上升算法更新回归系数代码:
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 * dataMatrix[randIndex] del(dataIndex[randIndex])
改进之处:
1)alpha = 4/(1.0+j+i)+0.0001,alpha在每次迭代中都会作调整,缓解数据波动或高频波动。alpha每次减少1/(j+i),j是迭代次数,i表示本次迭代中第i个选出来的样本,当j<<max(i)时,alpha就不是严格下降的。类似模拟退火等其他优化算法中避免参数严格下降。另alpha永远不会减小到0,因为存在常数项,保证在多次迭代后新数据仍有影响。如要处理的问题是动态变化,可适当加大上述常数项,确保新值获得更大回归系数。
2)通过随机选取样本更新回归系数,减小周期波动。这种方法每次随机从列表中选出一个值,然后从列表删除改值(再进行下次迭代)。
效果:与梯度上升分割数据效果差不多,但迭代次数远小于后者,前者20次,后者500次。另系数周期性波动有缓解。
5.画图
Andrew Ng在Cousera ML课中用Octave绘制Decision Boundary,本节中用python matplot实现相同分隔线绘制。本节中还有参数在迭代中变化情况的绘制。
6.数据预处理
数据集来自UCI机器学习数据库http://archive.ics.uci.edu/ml/datasets/Horse+Colic。该数据集有的指标比较主观,有的难以测量(如疼痛程度等)。另数据集有30%数据缺失。
比较用Pandas,R,和Excel处理数据集中缺失值,Excel处理如此次数据量不大、结构不复杂的数据集较为方便。
用Excel将数据集保存为文本分隔文件,缺失值全部用0替换,NumPy数据类型不允许包含缺失值。选择0来替换,恰好适用于Logistic回归。回归系数更新公式如下:
weights = weights + alpha * error * dataMatrix[randIndex]
如果dataMatrix某个特征对应值为0,那么系数将不做更新。