本文主要参考了一下博客:

本文主要参考了一下博客:

  1. 深度学习最全优化方法总结比较(SGD,Adagrad,Adadelta,Adam,Adamax,Nadam)
  2. An overview of gradient descent optimization algorithms
  3. 梯度下降优化算法综述(An overview of gradient descent optimization algorithms的翻译)

梯度下降算法是最受欢迎的优化方法之一,同时也是最常用的神经网络优化算法。与此同时,现在各种最新的深度学习框架包含了各种各样梯度下降优化算法的实现(比如lasagne、caffe、keras的实现)。然而,这些算法经常被作为一个黑盒子进行使用,实用的关于它们的优缺点的解释却是很难找到的。

本文旨在为大家介绍各种优化算法以帮助大家更好的使用这些算法。我们首先介绍梯度下降方法的不同变种;然后简要总结一下训练过程中会遇到的挑战;接下来,我们会介绍最为常见的优化算法是如何尝试解决训练过程中遇到的问题以及这些尝试是如何影响它们的更新规则的。

梯度下降是一种最小化目标函数J(θ)的方法。它通过向目标函数的导数▽J(θ)反方向更新模型的参数θ,来达到这一目的。学习率η决定我们到达目标函数最小值的步伐大小。如果你对梯度下降算法不怎么了解,请看这里

梯度下降算法的三种变体

一般来说,梯度下降算法有三种变种,它们之间的区别是使用多少数据来计算目标函数的梯度。取决于数据的大小,我们在参数更新的精度和花费的时间进行平衡。

Batch gradient descent

批量梯度下降是一种对参数的update进行累积,然后批量更新的一种方式。这种算法很慢,并且对于大的数据集并不适用;并且使用这种算法,我们无法在线更新参数。

Stochastic gradient descent

随机梯度下降是一种对参数随着样本训练,一个一个的及时update的方式。这种方法迅速并且能够在线使用;但是它频繁的更新参数会使得目标函数波动很大。

Mini-batch gradient descent

吸取了BGD和SGD的优点,每次选择一小部分样本进行训练。

挑战

尽管Mini-batch gradient descent算法不错, 它也不能保证收敛到好的值,并且带来了新的挑战:

  • 很难选择合适的学习率。过小的学习率会使得收敛非常缓慢;多大的学习率会发生震荡甚至发散。
  • 学习率相关的参数只能提前设定,无法使用数据集的特性
  • 所有的参数更新都使用相同的学习率
  • 如何跳出局部最小

各种梯度下降优化算法

接下来,我们将会例举出一些被深度学习领域广泛使用的解决上文提到的挑战的算法。我们不会讨论那些在实际中不适用于高维数据的算法,比如诸如Newton的方法二阶方法。

Momentum

SGD方法的一个缺点是,其更新方向完全依赖于当前的batch,因而其更新十分不稳定。解决这一问题的一个简单的做法便是引入momentum。momentum即动量,它模拟的是物体运动时的惯性,即更新的时候在一定程度上保留之前更新的方向,同时利用当前batch的梯度微调最终的更新方向。这样一来,可以在一定程度上增加稳定性,从而学习地更快,并且还有一定摆脱局部最优的能力。
特点:

  • 下降初期时,使用上一次参数更新,下降方向一致,乘上较大的能够进行很好的加速
    • 下降中后期时,在局部最小值来回震荡的时候,,使得更新幅度增大,跳出陷阱
    • 在梯度改变方向的时候,能够减少更新 总而言之,momentum项能够在相关方向加速SGD,抑制振荡,从而加快收敛

    Nesterov Momentum

    这是对传统momentum方法的一项改进,由Ilya Sutskever(2012 unpublished)在Nesterov工作的启发下提出的。

    这里写图片描述

    首先,按照原来的更新方向更新一步(棕色线),然后在该位置计算梯度值(红色线),然后用这个梯度值修正最终的更新方向(绿色线)。上图中描述了两步的更新示意图,其中蓝色线是标准momentum更新路径。其实,momentum项和nesterov项都是为了使梯度更新更加灵活,对不同情况有针对性。但是,人工设置一些学习率总还是有些生硬,接下来介绍几种自适应学习率的方法

    Adagrad

    说明一:大多数方法对于所有参数都使用了同一个更新速率。但是同一个更新速率不一定适合所有参数,比如有的参数可能已经到了仅需要微调的阶段,但又有些参数由于对应样本少等原因,还需要较大幅度的调动。Adagrad就是针对这一问题提出的,自适应地为各个参数分配不同学习率的算法。

    说明二:AdaGrad是第一个自适应算法,通过每次除以根号下之前所有梯度值的平方和,从而使得步长单调递减。同时因为cache的变化与每个维度上的值有关,所以此方法可以解决各个维度梯度值相差较大的问题。对于每个参数,随着其更新的总距离增多,其学习速率也随之变慢。
    特点:

    • 前期较小的时候, regularizer较大,能够放大梯度
    • 后期较大的时候,regularizer较小,能够约束梯度
    • 适合处理稀疏梯度

    缺点:

    • 由公式可以看出,仍依赖于人工设置一个全局学习率
    • 设置过大的话,会使regularizer过于敏感,对梯度的调节太大
    • 中后期,分母上梯度平方的累加将会越来越大,使,使得训练提前结束

    Adadelta

    Adagrad算法存在三个问题:

    • 其学习率是单调递减的,训练后期学习率非常小
    • 其需要手工设置一个全局的初始学习率
    • 更新xt时,左右两边的单位不同一

    Adadelta是对Adagrad的扩展,最初方案依然是对学习率进行自适应约束,但是进行了计算上的简化。 Adagrad会累加之前所有的梯度平方,而Adadelta只累加固定大小的项,并且也不直接存储这些项,仅仅是近似计算对应的平均值。
    特点:

    • 训练初中期,加速效果不错,很快
    • 训练后期,反复在局部最小值附近抖动

    RMSprop

    简单的说,RMSProp对于AdaGrad的改进在于cache的更新方法。不同于不断的累加梯度的平方,RMSProp中引入了泄露机制,使得cache每次都损失一部分,从而使得步长不再是单调递减了。RMSprop可以算作Adadelta的一个特例
    特点:

    • 其实RMSprop依然依赖于全局学习率
    • RMSprop算是Adagrad的一种发展,和Adadelta的变体,效果趋于二者之间
    • 适合处理非平稳目标 - 对于RNN效果很好

    Adam

    Adam(Adaptive Moment Estimation)本质上是带有动量项的RMSprop,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。Adam的优点主要在于经过偏置校正后,每一次迭代学习率都有个确定范围,使得参数比较平稳。
    特点:

    • 结合了Adagrad善于处理稀疏梯度和RMSprop善于处理非平稳目标的优点
    • 对内存需求较小
    • 为不同的参数计算不同的自适应学习率
    • 也适用于大多非凸优化 - 适用于大数据集和高维空间

    Adamax

    Adamax是Adam的一种变体,此方法对学习率的上限提供了一个更简单的范围。Adamax学习率的边界范围更简单。

    Nadam

    Nadam类似于带有Nesterov动量项的Adam。Nadam对学习率有了更强的约束,同时对梯度的更新也有更直接的影响。一般而言,在想使用带动量的RMSprop,或者Adam的地方,大多可以使用Nadam取得更好的效果。
    #经验之谈

    • 对于稀疏数据,尽量使用学习率可自适应的优化方法,不用手动调节,而且最好采用默认值
    • SGD通常训练时间更长,但是在好的初始化和学习率调度方案的情况下,结果更可靠
    • 如果在意更快的收敛,并且需要训练较深较复杂的网络时,推荐使用学习率自适应的优化方法。
    • Adadelta,RMSprop,Adam是比较相近的算法,在相似的情况下表现差不多。
    • 在想使用带动量的RMSprop,或者Adam的地方,大多可以使用Nadam取得更好的效果