来源:原始 Jupyter Notebook。内容已转换为网页阅读格式;下载原文件

sklearn 中的梯度下降法

上面的求解过程中,我们每次的迭代都用到了所有样本,这样做可以让收敛速度最快,但是如果样本数非常多,计算性能就会变低,上面的例子中一共也就3个样本,所以不明显。像这种每次迭代都使用全部样本的方法,叫做 批量梯度下降(Batch gradient descend,BGD)。为了提高计算性能,可以在每次迭代中随机选取一个样本(或部分样本)用于计算,这样也可以保证收敛,虽然收敛的速度慢了点,但计算快很多,而且可以有效的避免陷入局部极小值情况。这种方法叫做 随机梯度下降(Stochastic gradient descend,SGD)。

sklearn 中的 SGDRegressor 实现的就是随机梯度下降算法。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import SGDRegressor

X = np.array([0,1,2])
Y = np.array([0.9, 3.1, 5.1])
#X = np.array([39.93, 42.05, 43.18])
#Y = np.array([199,   290,   298])

model = SGDRegressor(max_iter=1000, tol=0.01)
model.fit(X.reshape(-1,1), Y.ravel())

plt.plot(X, Y, 'k.')

x = [[0],[10]]
#x = [[30],[60]]
y = model.predict(x)

b = y[0]
a = (y[1]-b)/x[1][0]
print("a = {0}, b = {1}".format(a, b))

plt.plot(x, y, 'g-')
plt.show()

运行结果

a = 1.5356587127294614, b = 1.0052652195613447

运行结果

Notebook 运行结果

使用批量梯度下降法 BGD 时,每次迭代是对所有样本进行计算,当目标函数为凸函数时,BGD 一定能够得到全局最优解,并且计算过程可以转换为矩阵计算,易于并行实现;不过当样本数目很多时,训练过程会很慢。使用随机梯度下降法 SGD 可以加快训练速度,不过缺点也显而易见,它的准确度要低很多,得到的可能不是全局最优解。为了在两种方法的性能之间取得一个折衷,可以采用 小批量梯度下降法(Mini-batch Gradient Descent,简称 MBGD),MBGD 在每次更新参数时使用 b 个样本(一般为10)。

批量梯度下降的更新公式为:

θj:=θjα1mi=1m(hθ(x(i))y(i))xj(i) \theta_j := \theta_j - \alpha \frac{1}{m} \sum_{i=1}^{m} (h_{\theta}(x^{(i)})-y^{(i)})x_j^{(i)}

随机梯度下降的更新公式为(注意没有求和符号):

θj:=θjα(hθ(x(i))y(i))xj(i) \theta_j := \theta_j - \alpha (h_{\theta}(x^{(i)})-y^{(i)})x^{(i)}_j

小批量梯度下降的更新公式为:

θj:=θjα110k=i(i+9)(hθ(x(k))y(k))xj(k) \theta_j := \theta_j - \alpha \frac{1}{10} \sum_{k=i}^{(i+9)}(h_{\theta}(x^{(k)})-y^{(k)})x_j^{(k)}

参考