梯度
梯度是一个数学概念,梯度函数表示的是多元可微函数的向量域函数,在某一点的梯度是该多元可微函数在该点上的偏导数为分量的向量。
我们用导数衡量一元函数的变化情况,类似的,梯度是导数在多元函数中的推广,就像一元函数的导数表示这个函数图形的切线的斜率,如果多元函数在该点上的梯度不是零向量,则它的方向是这个函数在该点上最大增长的方向、而它的量是在这个方向上的增长率。
以上是维基百科对梯度的解释,更直观的理解是:在多元函数的任意一点,在它的任意方向都有一个值的变化率,将变化率最大的那个方向向量叫做梯度,大小(向量的模)就是沿这个方向的变化率。
梯度下降
我们经常用梯度下降的方法来优化机器学习算法,模型训练就是调整模型的权重$W$,来使得损失函数的值减小,一个不包含正则化项的损失函数可以表示为: $$L(W)=\frac{1}{N}\sum_1^NL_i(f(x_i, W), y_i)$$ 这里,$W$为模型参数,$N$为样本个数,$x_i$为第 $i$ 个样本的输入,$y_i$为第 $i$ 个样本的标签值。
为了最小化损失函数,即模型预测的结果尽可能贴近真实值,我们需要调整模型参数$W$, 梯度下降是目前最常用的一种方法。
奥古斯丁·路易斯·柯西(图片来源:wikipedia)
梯度下降(Gradient Descent)由法国数学家奥古斯丁·路易斯·柯西在1847年提出。
对于梯度下降法最直观的理解就是按照函数值减小最快的方向(梯度的负方向)进行迭代,直到进入一个局部最小值。
想象一个简单的例子,我们在一个小型的沙漠中,我们所处的位置可以用经度、纬度以及海拔高度来表示,经度和纬度为我们的自变量,也就是我们可以通过移动来改变经纬度。海拔高度是我们的损失函数,假设目标是得到最小的损失函数,那我们需要通过移动经纬度来达到一个海拔高度最低的点。
如果这个沙漠类似一个碗的形状,先环顾四周,找到下坡的方向(梯度),移动一米后继续观察四周,找到下坡的方向(梯度),继续移动…
一直到我们发现四周都是上坡的时候,我们就到了海拔最低的点了(数值解)。
梯度下降的更新公式为:$$W_{t+1} = W_t - \alpha\nabla f(W_t) $$ 这里$\alpha$表示学习率,为了控制梯度更新的幅度,学习率的选取也有很多不同的办法,一般是从一个较小的数开始,比如0.001。
随机梯度下降(SGD)
由于现在的模型越来越复杂,用来训练的样本量($N$)也越来越大,完整计算一次在所有样本上的梯度变得越来越慢,这意味着我们更新的频率会越来越慢,为了能更快的更新模型参数,现在主要是采用小批量的随机梯度下降来进行模型训练,即每次取一个批量内的样本来计算梯度,对模型参数进行更新,一般每个批量的大小(batch size)设置为32/64/128/256。
除了能加快模型更新的速度,我们通常认为,一个批量内样本的梯度带有一定的随机性,在一定程度上增加了噪音,可以起到降低模型过拟合的效果。
但是batch size具体设置为多少,很多时候是通过实际的训练效果来进行调整的。比如openai的GPT3模型训练的batch size是320万,作者认为大批量计算性能会更好,每台机器的并行度更高,通讯量也会变低,小模型使用大批量过拟合会更加严重,相对来说大模型使用大批量降低模型的噪音,问题没有那么大。
但是,直接使用SGD也会遇到一些问题:
- 梯度在某些方向变化的很大,而在一些方向变化的很小,那么优化过程就会表现的非常「震荡」。
- 在遇到鞍点(Saddle point)和或者局部最小点时,此时梯度为0,模型停止更新或被困在这些点附近。
动量(Momentum)
为了解决这些问题,可以采用带有动量的随机梯度下降法,在很多情况下能加快训练速度,降低训练时的震荡现象。
先来看看动量,动量是一个物理学概念,我们都知道动量p的公式: $$\vec{p} = m\vec{v}$$, m是物体的质量,v是物体的速度。动量法的梯度下降考虑了历史的梯度信息,为了不再有更多的公式出现,我们来描述一下动量法梯度下降的更新过程,每次的梯度更新需要考虑上一次的梯度,在上一次梯度的基础上通过叠加本次梯度的更新来进行调整,一般来说上一次梯度的权重 $\beta$ 为0.9(经验值)。
$$ v_t = \beta v_{t-1} + \eta\nabla_\theta J(\theta) $$ $$ \theta = \theta - v_t $$
动量法为什么会增加训练速度?来看看训练动画:
动量法是一个非常直观和容易理解的,很符合我们生活中的直觉:将小球从起始点放下,那么它的运动轨迹大体上和动量法的训练轨迹类似。
为什么能更快的训练呢?动量法叠加了历史的梯度信息,在一直下降的方向上,更新的会越来越快。
动量所累积的速度还能有助于「冲出」一些局部最小点或者鞍点:
在使用梯度下降法(特别是随机梯度下降)进行迭代时,如果有其中一个维度方向的变化非常大,体现在3d图中就是非常深的峡谷,那么梯度就会沿着这个方向来回震荡,如下图所示:
加入动量的方法是容易直观理解的,震荡的原因是因为每次迭代的方向几乎改变了180度,如果我们限制每次迭代方向的变化幅度,那么就可以很大程度上减少震荡的幅度。一个形象的比喻是开车的时候每次打方向都要考虑上一次的方向,从而不至于方向变化幅度的太大而导致震荡
发表于2012年的AlexNet就是采用动量法的梯度下降进行训练的。