详解 Deep Learning 的各种优化器(二)
共 6365字,需浏览 13分钟
·
2021-07-16 10:28
本文将讲解以下概念:
Gradient Descent Batch Gradient Descent Stochastic Gradient Descent(SGD) Min-batch Gradient Descent Momentum Nesterov accelerated gradient(NAG) Adagrad Adadelta RMSprop Adam AdaMax Nadam AMSGrad
4.5 RMSprop
RMSprop 是一个未被发表的自适应学习率算法,该算法由 Geoff Hinton 提出。
RMSprop 和 Adadelta 在相同的时间内分别独立提出,均是为了应对 Adagrad 的急速下降的学习率的问题。实际上,RMSprop 是 Adadelta 的第一个更新向量的特例:
同样,RMSprop 将学习率分解成一个平方梯度的指数衰减的平均。Hinton 建议将 设置为 0.9,对于学习率 的一个合适的默认值为 0.001。
4.6 Adam
自适应矩估计( Adaptive Moment Estimation,Adam )是另一种每个参数的自适应学习率的方法。除了类似于 Adadelta 和 RMSprop 存储一个指数衰减的历史平方梯度的平均值 ,Adam 同时还保存了一个历史梯度的指数衰减均值 ,类似于动量。动量可以看成一个从斜坡上跑下来的球,而 Adam 的行为就像一个带有摩擦力的重球,因此它更喜欢误差表面上更为平缓的最小值。
我们计算过去和过去平方梯度的衰减均值 和 分别如下:
和 分别对应梯度的一阶矩(均值)和二阶矩(非确定的方差)的估计,正如该算法的名称。当 和 初始化为 0 向量时,Adam 的作者发现到它们都偏向于 0 ,尤其是在初始化步骤和当衰减率很小的时候(例如 和 趋向于 1 )
通过计算偏差校正的一阶矩和二阶估计来抵消偏差:
正如我们在 Adadelta 和 RMSprop 中看到那样,他们利用上述公式更新参数,由此生成了 Adam 的更新规则:
作者建议 取默认值为 0.9, 为 0.999, 为 。他们从经验上表明 Adam 在实际中表现很好,同时,与其他的自适应学习算法相比,其更有优势。
4.7 AdaMax
AdaMax 是 Adam 的一种变体,此方法对学习率的上限提供了一个更简单的范围。
在 Adam 中,单个权重的更新规则是将其梯度与当前梯度 和过去梯度的 范数(标量)成反比例缩放:
因此,我们可以推导出 范数:
虽然这样的变体会因为 值较大而在数值上变得不稳定(这也是为什么 和 范数在实际场景中广泛应用的原因),然而,当 时, 表现出极其稳定的特性。由此,AdaMax 的作者(Kingma and Ba, 2015)展示了由 得到的 拥有更好的稳定性。为了与 Adam 相区分,我们用 表示无穷范数约束 :
我们现在将上式插入到 Adam 更新公式:将 替换为 ,得到 AdaMax 的更新规则:
注意到 依赖于 max 运算,所以 AdaMax 不会像 Adam 中 和 趋向于 0 ,这也是为什么我们不需要去计算偏差校正。比较合适的参数设置:
4.8 Nadam
正如我们所见,Adam 可以被视为 RMSprop 和 momentum 的结合产物:RMSprop 提供历史平方梯度的指数衰减均值 ,而 Momentum 提供了历史梯度的指数衰减均值 。与此同时按照前文叙述 NAG(Nesterov accelerated gradient )是优于 Momentum 的。
Nadm(Nesterov-accelerated Adaptive Moment Estimation)就算结合了 Adam 和 NAG 的产物。为了将 NAG 融入 Adam 中,我们需要修改其 Momentum 部分 。
第一步,我们复习一下 Momentum 的更新规则:
其中, 是目标函数, 是动量的衰减项, 是步长(即为学习率),展开第三个等式可得:
以上再次说明了当前动量的前一个动量上前进了一步,也在当前梯度方向上前进了一步。
NAG 在计算梯度之前用动量步骤更新参数使得其在梯度方向上表现更为准确。我们只需要修改 NAG 中的梯度 :
Dozat 建议按照如下步骤修改 NAG:与应用两次动量步骤不同(一次更新梯度 ,一次更新参数 ),我们直接更新参数:
值得注意的是不同于上面扩展动量梯度更新规则方程利用动量 , 作者使用了当前动量向量 去梯度更新。为了加上 Nesterov momentum 到 Adam 中去,作者类似地用当前动量向量替换之前的动量向量。
首先,我们将 Adam 梯度更新规则列出来(注意我们不需要修改 ):
展开得到:
注意到 是上一步的动量向量偏差修正估计,对此作者进行用 如下替换:
为了方便起见,作者忽略了分母是 而不是 。这个方程看起来与我们上面的扩展动量更新规则非常相似。我们现在可以在此之上添加 Nesterov momentum ,只需要简单使用当前动量向量的偏置校正估计 替换上一步衰减动量的偏置估计校正 ,这样我们得到 Nadam 的梯度更新规则
4.9 AMSGrad
当自适应学习率算法成为训练神经网络的标准,从业者也注意到例如目标检测或者机器翻译并不是总能收敛到最优,并被带有 momentum 的 SGD 超越。
Reddi 等人将这个问题形式化,并且指出过去平方梯度的指数移动平均值是自适应学习率算法泛化行为不佳的原因。回顾一下,指数均值的引入原因:为了防止学习率随着训练变得无穷小,这是 Adagrad 算法的关键缺陷。然而这种梯度的短期记忆在其他场景中成为障碍。
在 Adam 收敛到次优解的设置中,就已经注意到某些 minibatch 提供了大且丰富的梯度,但这些 minibatch 的出现十分罕见,指数平均减弱了它们的影响并导致了收敛性差的问题。作者提供了一个简单的凸优化问题例子中可以观察到 Adam 有着相同的行为。
为了修复这种行为,作者提出了一种新的算法 - AMSGrad ,用历史平方梯度 的最大值而不是指数均值去更新参数。 与上面 Adam 中定义相同:
不同于直接使用 (或者偏置校正的 ),作者采用 和 的最大值:
这样,AMSGrad 算法的结果就不是一个递增的值,这避免了 Adam 所遇到的问题。为了简单起见,作者也删除了 Adam 中的 debiasing 步骤。完整的带偏置校正估计的 AMSGrad 更新规则如下:
相比于 Adam 作者在小数据集以及 CIFAR-10 上观察到更好的表现。然而,其他的实验中也展现了相同的或者更坏的表现(相比于 Adam)。AMSGrad 在实践中是否能够始终超越 Adam,还有待观察。
5. 其他优化算法
在 AMSGrad 之后出现了很多其他的优化器,包括:
AdamW:修复了 Adam 的权重衰减; QHAdam:在更新权重时将动量项与当前梯度解耦,在更新权重时将均方梯度项与当前平方梯度解耦; AggMo:结合了多个动量项 ;
更多更新的新优化器可以参考:An updated overview of recent gradient descent algorithms – John Chen – ML at Rice University (johnchenresearch.github.io)
6. 优化器算法可视化
从上图我们能够看到这些优化器在损失平面的等高线图( Beale 函数 )随着时间的行为。注意到 Adagrad,Adadelta,以及 RMSprop 几乎立即朝着正确的方向并以同样的速度收敛,与此同时 Momentum 和 NAG 偏离方向,行为类似球从山上滚下来的场景。然而相比于 Momentum ,NAG 能够迅速纠正方向。
第二张图展示了优化算法在鞍点的行为,一个维度具有正斜率,而另一个维度具有负斜率的点,正如之前提到的,这对 SGD 造成了困难。注意到,SGD、Momentum 和 NAG 发现很难打破对称性,尽管后者最终设法逃离了鞍点,而 Adagrad、RMSprop 和 Adadelta 迅速下降到负斜率。
正如我们所看到的,自适应学习率方法,即 Adagrad、Adadelta、RMSprop 和 Adam 是最合适的,并且为这些场景提供了最好的收敛性。
7. 如何挑选优化算法?
那么,我们现在应该使用哪个优化器?如果的输入数据稀疏,那么我们可能会使用其中一种自适应学习率方法获得最佳结果。另一个好处是我们不需要调整学习率,但可能会使用默认值获得最佳结果。
总的来说,RMSprop 是 Adagrad 的扩展,改进其学习率急剧下降的问题。这和 Adadelta 是一致的,只是 Adadelta 在分子更新规则中使用参数均方根进行更新。Adam 最终结合偏置校正和 momentum 到 RMSprop。到目前为止,RMSprop、Adadelta 以及 Adam 是非常相似的算法,在一些相近的场景下都表现十分优异。Kingma 等人表明随着梯度变得更稀疏,它的偏差校正有助于 Adam 在优化结束时略微优于 RMSprop。就此而言,Adam 可能是最佳的整体选择。
有趣的是,最近的许多论文使用朴素 SGD 没有Momentum 且使用简单的学习率表。正如已经显示的那样,SGD 通常可以找到最小值,但它可能比使用某些优化器花费的时间长得多,更依赖于稳健的初始化和模拟退火表,并且可能会卡在鞍点而不是局部最小值。因此,如果您关心快速收敛并训练深度或复杂的神经网络,就应该选择一种自适应学习率方法。
8. 并行以及分布 SGD
鉴于大规模数据解决方案的普遍性和低成本集群的可用性,分布式 SGD 以进一步加速是一个明确可行的选择。
SGD 本质上是连续的:一步一步朝着最低值前进。它可以提供良好的收敛性,但在超大型数据集上可能收敛十分缓慢。相比之下,异步 SGD 速度更快,但 worker 之间的不佳的通信会导致收敛效果差。此外,作者还可以在一台机器上并行化 SGD,而无需大型计算集群。以下是为优化并行化和分布式 SGD 提出的算法和架构。以下是为优化并行化和分布式 SGD 提出的算法和架构。
8.1 Hogwild!
Niu 等人介绍了一种更新方案叫做 Hogwild! 。这允许在 CPU 上并行执行 SGD 更新。允许处理器在不锁定参数的情况下访问共享内存。这仅在输入数据稀疏时才有效,因为每次更新只会修改所有参数的一小部分。他们表明,在这种情况下,更新方案几乎达到了最佳收敛速度,因为处理器不太可能覆盖有用信息。
8.2 Downpour SGD
Downpour SGD 是 Dean 等人使用的 SGD 的异步变体。在 Google 的 DistBelief 框架(TensorFlow 的前身)中。它在训练数据的子集上并行运行模型的多个副本。这些模型将它们的更新发送到一个参数服务器,该服务器分布在许多机器上。每台机器负责存储和更新模型参数的一小部分。但是,由于副本不相互通信,例如通过共享权重或更新,它们的参数不断面临发散的风险,阻碍收敛。
8.3 Delay-tolerant Algorithms for SGD
McMahan 和 Streeter 通过开发不仅适应过去梯度而且适应更新延迟的延迟容忍算法,将 AdaGrad 扩展到并行设置。这已被证明在实践中运作良好。
8.4 TensorFlow
TF 是谷歌开源的用于实施和部署大规模机器学习模型的框架。它基于他们在 DistBelief 方面的经验,并且已经在内部用于在大量移动设备和大规模分布式系统上执行计算。对于分布式执行,计算图被拆分为每个设备的子图,并使用发送/接收节点对进行通信。
8.5 Elastic Averaging SGD
zhang 等人。提出了弹性平均 SGD(EASGD),它将异步 SGD 的 worker 的参数与弹性力联系起来,即参数服务器存储的中心变量。这允许局部变量从中心变量进一步波动,这在理论上允许对参数空间进行更多探索。他们凭经验表明,这种增加的探索能力可以通过寻找新的局部最优来提高性能。
9. 优化 SGD 的其他策略
最后,作者介绍了可以与前面提到的任何算法一起使用的其他策略,以进一步提高 SGD 的性能。
9.1 混洗和课程式学习
通常,我们希望避免以有意义的顺序向我们的模型提供训练示例,因为这可能会使优化算法产生偏差。因此,在每个 epoch 之后打乱训练数据通常是一个好办法。
另一方面,对于我们旨在逐步解决更难问题的某些情况,以有意义的顺序提供训练示例实际上可能会提高性能和更好的收敛性。建立这种有意义的秩序的方法称为课程式学习。
Zaremba 和 Sutskever 只能训练 LSTM 来评估使用课程学习的简单程序,并表明组合或混合策略(通过对样本排序增加训练难度)比通过原始策略更好。
9.2 Batch Normalization
为了便于学习,我们通常通过用零均值和单位方差初始化参数的初始值来规范化参数的初始值。随着训练的进行和我们在不同程度上更新参数,我们失去了这种归一化,这会减慢训练并随着网络变得更深而放大变化。
Batch Normalization 为每个小批量重新建立这些标准化,并且更改也通过操作进行反向传播。通过将归一化作为模型架构的一部分,我们能够使用更高的学习率并且更少关注初始化参数。Batch Normalization 还充当正则化器,减少(有时甚至消除)对 Dropout 的需求。
9.3 提前停止训练
根据 Geoff Hinton 的说法:"Early stopping (is) beautiful free lunch" (NIPS 2015 Tutorial slides, slide 63)。因此,我们应该在训练期间始终查看测试集上的误差,如果的测试集误差没有得到足够的改善,则及时停止。
9.4 梯度噪声
Neelakantan 等人。添加遵循高斯分布的噪声 到每一次梯度更新:
他们根据以下规则对方差进行模拟退火:
他们表明,添加这种噪声会使网络对不良初始化更加鲁棒,并有助于训练特别深且复杂的网络。他们推测增加的噪声使模型有更多机会逃脱并找到新的局部最小值,这对于越深的模型越频繁。
参考资料
Deep Learning Optimization - Purdue Math An overview of gradient descent optimization algorithms 深度学习中的优化算法 梯度下降法- 维基百科,自由的百科全书 An Introduction to AdaGrad https://arxiv.org/pdf/1412.6980.pdf