在一个多元函数中,某点的梯度方向代表函数增加最快的方向,梯度下降的原理就是,找到损失函数下降最快的方向(与梯度方向相反),然后往这个方向走,最后达到损失函数的最小值,如下图,从高的红色点到达了低的蓝色点,梯度下降就是这样一个过程
我们可以得到一个参数更新公式,把参数设为a, 梯度设为grad,那么
为什么要有个n呢,因为梯度方向只能表示当前位置函数增加最快的方向,对于复杂的函数,当我们改变位置的时候,这个梯度可能一直在变化,所以n代表我们每走一步的距离,我们慢慢的走下去,然后每走一步再找一次方向,这样就能走到最小的位置了
由于算法是往最低的地方走,当走到函数局部最小值的时候,周围都比较高,那么就可能困在这里了,无法达到全局最小值别急,当然,当损失函数是一个凸函数的时候,是没有局部最小值的,只有全局最小值,例如MSE就是一个凸函数
批量梯度下降指的是用整个向量经过矩阵运算来计算梯度,容易知道,这样算法会很慢,当训练集很大时,可能要花费很多时间
我们将每个训练集实例比作一个高山上的一个点,批量梯度下降就是算出这些点的整体趋势,然后向下运动,我们将在下面看到一种不同的想法
与批量梯度下降不同的是,随机梯度下降每次随机选择一个实例来计算梯度,这样大大减小了运行时间,并且,随机梯度下降可以摆脱局部最小值的问题,因为随机挑选,那么即使有一部分在局部最小值中,还有一部分的方向选择可以将困住的部分解救出。
训练集向量中的每一个实例对应于山上的某个点,随机梯度下降就是以某个点来抉择整体的下降趋势,可以预料到,下降的过程将不会那么顺利,但趋势是对的,可以看涨图来理解随机梯度下降与批量梯度下降的区别
当随机梯度下降算法的参数越接近最小值的时候,因为随机性,可能永远到达不了最小值,会在这周围运动
这里我们可以减小步长n,让每次变化的幅度小一点,这样我们就能更加靠近全局最小值了,这就被称作退火算法
import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import SGDRegressor
np.random.seed(42)
x = np.random.rand(100, 1)
y = 2 * x + np.random.rand(100, 1)
model = SGDRegressor(max_iter=1000, tol=1e-3, penalty=None, eta0=0.1)
model.fit(x, y)
pre_y = model.predict(x)
plt.scatter(x, y)
plt.plot(x, pre_y, "r-")
plt.show()
max_iter为下降批次,tol为损失函数阈值,penalty为不使用正则化(可自行搜索),eta0为最初的步长(之后会慢慢减小),整体意思就是当模型训练1000次或损失函数比0.001小时停止训练
可以看到拟合效果也很好
有了上面两种梯度下降的定义,小批量梯度下降应该也好理解了,它兼容二者的优点与缺点
训练快,容易到最小值,但是可能难以辨别局部最小值
当你使用GPU的时候,定义处理批次与GPU相同可以充分利用硬件资源,提高效率