随机梯度下降

给定一个可微函数,理论上可以用解析法找到它的最小值:函数的最小值是导数为 0 的点,因此你只需找到所有导数为 0 的点,然后计算函数在其中哪个点具有最小值。

将这一方法应用于神经网络,就是用解析法求出最小损失函数对应的所有权重值。可以通过对方程 gradient(f)(W) = 0 求解 W 来实现这一方法。这是包含 N 个变量的多项式方程,其中 N 是网络中系数的个数。N=2 或 N=3 时可以对这样的方程求解,但对于实际的神经网络是无法求解的,因为参数的个数不会少于几千个,而且经常有上千万个。

相反,你可以使用基于当前在随机数据批量上的损失,一点一点地对参数进行调节。由于处理的是一个可微函数,你可以计算出它的梯度,从而有效地实现沿着梯度的反方向更新权重,损失每次都会变小一点。

(1) 抽取训练样本 x 和对应目标 y 组成的数据批量。

(2) 在 x 上运行网络,得到预测值 y_pred。

(3) 计算网络在这批数据上的损失,用于衡量 y_pred 和 y 之间的距离。

(4) 计算损失相对于网络参数的梯度[一次反向传播( backward pass)]。

(5) 将参数沿着梯度的反方向移动一点,比如 W -= step * gradient,从而使这批数据上的损失减小一点。

这很简单!我刚刚描述的方法叫作小批量随机梯度下降(mini-batch stochastic gradient descent,又称为小批量 SGD)。术语随机(stochastic)是指每批数据都是随机抽取的(stochastic 是 random在科学上的同义词)。图 1 给出了一维的情况,网络只有一个参数,并且只有一个训练样本。

打开网易新闻 查看精彩图片

图1 沿着一维损失函数曲线的随机梯度下降(一个需要学习的参数)

如你所见,直观上来看,为 step 因子选取合适的值是很重要的。如果取值太小,则沿着曲线的下降需要很多次迭代,而且可能会陷入局部极小点。如果取值太大,则更新权重值之后可能会出现在曲线上完全随机的位置。

注意,小批量 SGD 算法的一个变体是每次迭代时只抽取一个样本和目标,而不是抽取一批数据。这叫作真 SGD(有别于小批量 SGD)。还有另一种极端,每一次迭代都在所有数据上运行,这叫作批量 SGD。这样做的话,每次更新都更加准确,但计算代价也高得多。这两个极端之间的有效折中则是选择合理的批量大小。图 1 描述的是一维参数空间中的梯度下降,但在实践中需要在高维空间中使用梯度下降。

神经网络的每一个权重参数都是空间中的一个自由维度,网络中可能包含数万个甚至上百万个参数维度。为了让你对损失曲面有更直观的认识,你还可以将梯度下降沿着二维损失曲面可视化,如图 2 所示。但你不可能将神经网络的实际训练过程可视化,因为你无法用人类可以理解的方式来可视化 1 000 000 维空间。因此最好记住,在这些低维表示中形成的直觉在实践中不一定总是准确的。这在历史上一直是深度学习研究的问题来源。

打开网易新闻 查看精彩图片

图2 沿着二维损失曲面的梯度下降(两个需要学习的参数)

此外, SGD 还有多种变体,其区别在于计算下一次权重更新时还要考虑上一次权重更新,而不是仅仅考虑当前梯度值,比如带动量的 SGD、 Adagrad、 RMSProp 等变体。这些变体被称为优化方法( optimization method)或优化器( optimizer)。其中动量的概念尤其值得关注,它在许多变体中都有应用。动量解决了 SGD 的两个问题:收敛速度和局部极小点。图 3 给出了损失作为网络参数的函数的曲线。

打开网易新闻 查看精彩图片

图3 局部极小点和全局最小点

如你所见,在某个参数值附近,有一个局部极小点( local minimum):在这个点附近,向左移动和向右移动都会导致损失值增大。如果使用小学习率的 SGD 进行优化,那么优化过程可能会陷入局部极小点,导致无法找到全局最小点。使用动量方法可以避免这样的问题,这一方法的灵感来源于物理学。有一种有用的思维图像,就是将优化过程想象成一个小球从损失函数曲线上滚下来。如果小球的动量足够大,那么它不会卡在峡谷里,最终会到达全局最小点。动量方法的实现过程是每一步都移动小球,不仅要考虑当前的斜率值(当前的加速度),还要考虑当前的速度(来自于之前的加速度)。这在实践中的是指,更新参数 w 不仅要考虑当前的梯度值,还要考虑上一次的参数更新。