An overview of gradient descent optimization algorithms
Sebastian Ruder
Insight Centre for Data Analytics, NUI Galway
Aylien Ltd., Dublin
摘要
梯度下降优化算法虽然越来越受欢迎,但由于其优缺点难以得到实际的解释,通常被用作黑盒优化器。这篇文章的目的是分析不同的算法,让读者直观的理解他们的使用。在这篇综述中,我们研究了梯度下降的不同变体,总结了挑战点,介绍了最常见的优化算法,回顾了并行和分布式环境中的体系结构,并研究了优化梯度下降的其他策略。
1 介绍
梯度下降法是最常用的优化算法之一,也是目前最常用的神经网络优化方法。同时,每一个最先进的深度学习库都包含各种算法的实现,来优化梯度下降算法(例如lasagne s2、caffe s3和keras 4文档)。然而,这些算法通常被用作黑盒优化器,因为很难找到它们优缺点的实际解释。
本文旨在为读者提供直观的对优化梯度下降不同算法展现,将有助于读者对它的使用。在第2节中,我们首先来看梯度下降的不同变体。然后我们将在第3节简要总结训练过程中的挑战。随后,在第4节中,我们将介绍最常见的优化算法,展示它们解决这些挑战的动机,以及如何推导它们的更新规则。之后,在第5节中,我们将简要介绍在并行和分布式环境中优化梯度下降的算法和体系结构。最后,我们将在第6节中考虑有助于优化梯度下降的其他策略。
梯度下降法是一种最小化目标函数J(θ)的方法,它通过更新参数的目标函数的负梯度方向计算模型的参数。学习率η的大小决定了我们采取的措施达成(当地)最低。换句话说,我们沿着目标函数创建的曲面的斜率向下走,直到到达一个山谷。
2 梯度下降变体
梯度下降法有三种变体,它们在计算目标函数梯度时使用的数据量不同。根据数据量,我们在参数更新的准确性和执行更新所需的时间之间进行权衡。
2.1 批量梯度下降
Vanilla梯度下降法,也就是批处理梯度下降法,对整个整个训练数据集计算成本函数的梯度w.r.t.参数θ。
由于我们需要计算整个数据集的梯度来执行一次更新,批处理梯度下降可能非常慢,对于不适合内存的数据集来说是非常棘手的。批量梯度下降法也不允许我们在线更新我们的模型,也就是说,不能实时更新新的例子。在代码中,批处理梯度下降看起来是这样的:
对于预先定义的时域数,我们首先计算整个数据集的参数向量params的损失函数的梯度向量params_grad。请注意,最先进的深度学习库提供了自动微分,能有效地计算梯度的一些参数。如果你自己推导梯度,那么梯度检查是一个好主意。
然后,我们按照梯度方向更新参数,学习速率决定更新的大小。批量梯度下降法保证收敛于凸误差曲面的全局最小值和非凸曲面的局部最小值。
2.2 随机梯度下降
相反,随机梯度下降(SGD)会更新每个训练示例x(i)和标签y(i)的参数。
批处理梯度下降法对大型数据集执行冗余计算,因为它在每个参数更新之前对类似的例子重新计算梯度。SGD通过一次执行一个更新来消除这种冗余。因此,它通常更快,也可以用于在线学习。SGD执行频繁的更新,其方差很大,导致目标函数波动很大,如图1所示。
当批量梯度下降收敛到参数所处盆地的最小值时,SGD s波动一方面使其能够跳到新的、潜在的更好的局部最小值。另一方面,这最终会使收敛变得复杂到最小值,因为SGD将继续超调。然而,已有研究表明,当我们缓慢降低学习速率时,SGD表现出与批量梯度下降相同的收敛行为,几乎可以肯定分别收敛到非凸优化和凸优化的局部最小值或全局最小值。它的代码片段只是在训练示例上添加了一个循环,并计算每个示例的梯度w.r.t.。请注意,正如6.1节中解释的那样,我们在每个时期都对训练数据进行清洗。
2.3 小批梯度下降
小批梯度下降法最终兼顾了这两方面的优点,并对n个小批训练示例执行更新。
a)减小参数更新的方差,使收敛更加稳定; b)可以利用高度优化的矩阵优化常见的最先进的深度学习库,使计算梯度w.r.t.一个小批非常有效。一般的小型批处理大小在50到256之间,但是可以根据不同的应用程序而有所不同。小批梯度下降法是神经网络训练中常用的一种算法,小批梯度下降法通常也使用SGD一词。注:在本文其余部分SGD的修改中,我们省略了一些参数。
在代码中,我们不再迭代示例,而是迭代大小为50的小批数据:
3 挑战
然而,普通的小批梯度下降法并不能保证很好的收敛性,但却提出了一些需要解决的挑战:
- 选择一个合适的学习速度是困难的。学习速率过小会导致收敛速度过慢,而学习速率过大会阻碍收敛,导致损失函数在最小值附近波动甚至发散。
- 学习率时间表方法[18]试图通过退火算法来调整训练期间的学习率,即根据预先定义的时间表或当各时期之间的目标变化低于阈值时降低学习率。然而,这些进度表和阈值必须提前定义,因此不能适应数据集的特征[4]。
- 此外,相同的学习率适用于所有参数更新。如果我们的数据是稀疏的,并且我们的特征具有非常不同的频率,我们可能不希望将它们全部更新到相同的程度,而是对很少发生的特征执行更大的更新。
- 最小化神经网络中常见的高度非凸误差函数的另一个关键挑战是避免陷入大量次优局部极小值。Dauphin et al.[5]认为,这种困难实际上并非来自局部极小值,而是来自鞍点,即一维向上和另一维向下倾斜的点。这些鞍点通常被误差相同的平台包围,这使得SGD难以逃脱,因为所有维度的梯度都接近于零。
4 梯度下降优化算法
下面,我们将概述深度学习社区广泛使用的一些算法,以应对上述挑战。我们不会讨论在高维数据集的实际计算中不可行的算法,例如二阶方法,如牛顿法7。
SGD(随机梯度下降法Stochastic gradient descent)在低谷的时候继续下降有些困难,也就是说,在某些区域,表面曲线在一个维度上要比在另一个维度上陡得多,这在局部优化附近是很常见的。在这些场景中,SGD在峡谷的斜坡上振荡,而只在底部朝着局部最优方向缓慢前进,如图2a所示。
Momentum [17]是一种帮助SGD在相关方向上加速和抑制振荡的方法,如图2b所示。它通过添加更新矢量的γ过去一小部分时间步当前更新矢量。
本质上,当使用momentum时,我们把一个球推下山,球在滚下坡时积累的动力,变得越来越快的路上(直到它达到终端速度,如果有空气阻力,即γ< 1。同样的事情发生在我们的参数更新:增加动量项的维渐变指向同一个方向,减少更新维度的梯度变化方向。因此,我们得到了更快的收敛和更少的振荡。
4.2 Nesterov加速梯度
然而,一个球滚下山,盲目地沿着山坡,将得到非常不令人满意的结果。我们希望有一个更聪明的球,一个知道它要去哪里的球,这样它就知道在山坡再次上升之前减速。
Nesterov加速梯度(NAG)[14]是一种给momentum预知的方法。我们知道,我们将使用我们的momentum γvt 1移动参数θ。计算θγvt 1因此给了我们一个近似的下一个位置参数(梯度是完整更新失踪),一个粗略的想法,我们的参数。
再次,我们设置了momentum的值。当计算momentum的时,要首先计算当前梯度(图3中蓝色的小向量),然后需要一个大跳的方向更新积累梯度(蓝色大向量),先使它大幅上涨之前积累的方向梯度(布朗向量),然后校正(绿色的向量)。这种预期更新可以防止我们走得太快,并提高响应能力,从而显著提高了RNNs在许多任务上的性能
现在,我们可以根据错误函数的斜率调整更新并相应地加快SGD,我们还希望根据每个参数的重要性调整更新,以执行更大或更小的更新。
4.3 Adagrad
自适应梯度算法: adaptive gradient algorithm
Adagrad[8]是一种基于梯度的优化算法,它实现了根据参数调整学习率,对不频繁的参数执行较大的更新,对频繁的参数执行较小的更新。因此,它非常适合处理稀疏数据。Dean等人在[6]中发现Adagrad极大地提高了SGD的鲁棒性,并将其用于在谷歌训练大型神经网络,这些神经网络在Youtube video os10中学会了识别猫等。此外,Pennington等人使用Adagrad来训练手套式的单词嵌入,因为不经常出现的单词需要比经常出现的单词大得多的更新。
以前,我们执行一个更新所有参数θ为每个参数θi使用相同的学习速率η。作为Adagrad使用不同的学习速率为每一个参数θi t在每一个时间步,我们首先显示Adagrad-per-parameter更新,然后向量化。
SGD更新每一个参数在每个时间步θi t就变成了:
在它的更新规则,Adagrad修改一般学习速率η为每个参数在每个时间步tθi基于过去θi梯度计算的:
Gt包含平方和的梯度的沿对角线的所有参数θ,我们现在可以通过执行以聪明元素矩阵向量乘法实现。
Adagrad的主要优点之一是它消除了手动调整学习速率的需要。大多数实现使用默认值0:01,并将其保留在该值。
Adagrad的主要缺点是它在分母上的平方梯度的累加:由于每增加一项都是正数,所以在训练过程中累加和不断增长。这反过来又会导致学习速率下降,最终变得无穷小,这时算法就不能再获得额外的知识。以下算法旨在解决这一缺陷。
4.4 Adadelta
Adadelta[22]是Adagrad的一个扩展,它试图减少其侵略性的单调下降的学习率。Adadelta没有累积所有过去的平方梯度,而是将过去梯度的累积窗口限制为某个固定大小的w。
梯度和递归定义为所有过去的平方梯度的衰减平均值,而不是低效地存储w以前的平方梯度。运行平均值E (g2) t在时间步然后决定(如γ一小部分类似于动量词)只有前面的平均和当前的梯度。
我们将γ类似的值设置为 momentum0:9左右。为了清晰起见,我们现在重写我们的vanilla SGD向量θt更新参数的更新:
我们以前推导的Adagrad的参数更新向量采用这种形式:
现在我们简单地将对角线矩阵Gt替换为过去平方梯度E[g2]t的衰减平均值:
由于分母只是梯度的均方根误差准则,我们可以用简写准则代替它:
作者注意到这次更新中的单元(以及SGD、Momentum或Adagrad中的单元)不匹配,也就是说,更新的假设单元应该与参数相同。为了实现这一点,他们首先定义了另一个指数衰减平均值,这次不是平方梯度而是平方参数更新:
因此,参数更新的均方根误差为:
从RMS[∆θ]t 是未知的,我们把它近似的RMS参数更新,直到前一个时间步。在前面的更新规则取代了学习速率η,RMS[∆θ]t−1最后收益率Adadelta更新规则为:
使用Adadelta,我们甚至不需要设置默认的学习率,因为它已经从更新规则中消除。