梯度下降算法每次更新回归系数时都要遍历整个数据集,该方法在处理100个左右的数据集时尚可,但如果有上亿(m)的的样本和上千(n)的特征那么该方法的时间复杂度太高了(O(m*n*k), k为迭代步数)。一种改进方法是一次仅用一个样本点来更新回归系数,时间复杂度仅为O(n*k),该方法称为随机梯度下降算法。由于可以在新样本到来时对分类器进行增量式更新,因而随机梯度下降算法是一个在线学习算法。与”在线学习“相对应,一次处理所有的数据称为”批处理“。
from numpy import *
import matplotlib.pyplot as plt
def stocGradDescend0_plot(dataSet, classLabels):
dataArray =array(dataSet)#数组
m,n = shape(dataArray)
alpha = 0.01
weights = ones(n) #initialize to all ones
k =20000
weights_iters = ones((k,n))
for i in range(k):
i_ = i % m
h = sigmoid(sum(dataArray[i_]*weights))
error = h- classLabels[i_] #单个数
weights -= alpha * error * dataArray[i_]#数和数组相乘,复杂度O(n)
weights_iters[i] = weights
plt.subplot(311)
plt.plot(range(k), weights_iters[:,0])
plt.xlabel("迭代次数(number of iterations)")
plt.ylabel("weight factor w0")
plt.subplot(312)
plt.plot(range(k), weights_iters[: ,1])
plt.xlabel("迭代次数(number of iterations)")
plt.ylabel("weight factor w1")
plt.subplot(313)
plt.plot(range(k), weights_iters[: ,2])
plt.xlabel("迭代次数(number of iterations)")
plt.ylabel("weight factor w2")
plt.tight_layout()
plt.show()
#return weights_iters
return weights
下图显示的是回归系数在20000次迭代中的波动情况。不难理解,产生这种现象的原因是存在一些不能正确分类的样本点(数据集并非线性可分)。我们期望能减少这种波动并加速收敛。
20000次迭代过后,分类的效果很不错。
为了减少波动,我们队上述代码作两处改进:
一、每次迭代动态调整步长 alpha,使之随着迭代次数不断减少。
二、上述代码中是顺序选择样本,并没有随机。我们改为随机选择样本。
def stocGradDescend1(dataSet, classLabels, numIter=150):
#这里迭代次数作为函数的关键字参数
dataArray =array(dataSet)
m,n = shape(dataArray)
weights = ones(n) #initialize to all ones
weights_iters = ones((numIter,n))#用于记录权重变换
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(dataArray[randIndex]*weights))
error = h-classLabels[randIndex]
weights -= alpha * error * dataArray[randIndex]
weights_iters[i] = weights
#plot weights
plt.subplot(311)
plt.plot(range(numIter), weights_iters[:,0])
plt.xlabel("迭代次数(number of iterations)")
plt.ylabel("weight factor w0")
plt.subplot(312)
plt.plot(range(numIter), weights_iters[: ,1])
plt.xlabel("迭代次数(number of iterations)")
plt.ylabel("weight factor w1")
plt.subplot(313)
plt.plot(range(numIter), weights_iters[: ,2])
plt.xlabel("迭代次数(number of iterations)")
plt.ylabel("weight factor w2")
plt.tight_layout()
plt.show()
#return weights_iters
return weights
可以看到,这次回归系数收敛的非常快,100多次迭代就已收敛。
分类效果也很好:
本文分享自 Python可视化编程机器学习OpenCV 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体分享计划 ,欢迎热爱写作的你一起参与!