在TensorFlow中,Gradient Descent vs Adagrad vs Momentum

Kyr*_*rol 68 deep-learning tensorflow

我正在研究TensorFlow以及如何使用它,即使我不是神经网络和深度学习(只是基础知识)的专家.

以下教程中,我不理解三个优化器之间的实际差异.我看看API,我理解原则,但我的问题是:

1.何时优先使用一个而不是其他一个?

2.知道有重要的区别吗?

Sal*_*ali 182

以下是基于我的理解的简要说明:

  • 动量 有助于 SGD沿着相关方向导航并减轻无关紧要的振荡.它只是将前一步骤的一部分方向添加到当前步骤.这实现了在正确方向上的速度放大并且在错误的方向上软化振荡.该分数通常在(0,1)范围内.使用自适应动量也是有意义的.在学习开始时,一个巨大的动力只会阻碍你的进步,所以使用像0.01这样的东西是有意义的,一旦所有的高梯度消失,你就可以使用更大的动力.动量存在一个问题:当我们非常接近目标时,我们在大多数情况下的势头非常高,并且不知道它应该减速.这可能导致它在最小值周围错过或振荡
  • nesterov加速梯度通过开始减速来克服这个问题.在动量中,我们首先计算梯度,然后在那个方向上跳跃,放大我们之前的动量.NAG做了同样的事情,但是按照另一种顺序:首先我们根据存储的信息进行大跳,然后我们计算渐变并进行小的修正.这种看似无关紧要的变化带来了显着的实际加速.
  • AdaGrad或自适应梯度允许学习速率基于参数进行调整.它为不频繁的参数执行更大的更新,为频繁的参数执行更小的更新.因此,它非常适合稀疏数据(NLP或图像识别).另一个优点是它基本上消除了调整学习速率的需要.每个参数都有自己的学习速率,并且由于算法的特殊性,学习速率是单调递减的.这导致了最大的问题:在某些时间点,学习速度很小,系统停止学习.
  • AdaDelta 解决AdaGrad单调降低学习率的问题.在AdaGrad中,学习率大致计算为1除以平方根的总和.在每个阶段,您将另一个平方根添加到总和,这会导致分母不断增加.在AdaDelta中,它不是对所有过去的平方根求和,而是使用滑动窗口,允许总和减少.RMSprop与AdaDelta非常相似
  • Adam或自适应动量是一种类似于AdaDelta的算法.但除了存储每个参数的学习率之外,它还分别存储每个参数的动量变化.

    一个几可视化: 在此输入图像描述 在此输入图像描述

我会说SGD,Momentum和Nesterov都不如过去3.

  • "SGD,Momentum和Nesterov都不如最后3个" - 他们不是**低**,他们**慢**.人们使用SGD + Momentum进行论文培训是有原因的.新元+动能有更高的机会达到持平的最低点. (6认同)
  • @minerals如果我们要学究的话,那么我们也不能使用更慢的词。因为从理论上讲,始终可以找到任何算法都能发挥最佳性能的表面和起点。但是实际上这没有什么用。 (3认同)
  • 根据您在链接中提供的有关AdaDelta的评论:“没有一个明确的结论来决定选择哪种算法以及何时选择。根据问题和参数化的不同,所有算法的表现都不同。可以得出的结论是“选择最适合您的问题的方法” –恐怕” (2认同)
  • 这篇论文 (https://arxiv.org/abs/1705.08292) 讨论了 SGD 如何获得比自适应方法更好的解决方案。在更好的验证损失/准确性(即模型更好地概括)而不是快速训练时间的意义上更好 (2认同)

Ore*_*man 14

Salvador Dali的答案已经解释了一些流行方法(即优化器)之间的差异,但我会尝试更详细地阐述它们.
(请注意,我们的答案在某些方面存在分歧,特别是关于ADAGRAD.)

经典动量(CM)与Nesterov的加速梯度(NAG)

(主要基于论文中关于初始化和动力学在深度学习中的重要性的第2部分.)

CM和NAG中的每个步骤实际上由两个子步骤组成:

  • 动量子步骤 - 这只是[0.9,1)最后一步的一小部分(通常在范围内).
  • 梯度相关子步骤 - 这类似于SGD中的常规步骤- 它是学习速率和与梯度相反的向量的乘积,而梯度是在此子步骤开始的位置计算的.

CM首先采用梯度子步骤,而NAG首先采用动量子步骤.

以下是关于CM和NAG直觉的答案的演示:

CM与NAG的例子

所以NAG似乎更好(至少在图像中),但为什么呢?

需要注意的重要一点是,动量子步骤何时到来并不重要 - 两种方式都是相同的.因此,如果已经采取动量子步骤,我们可能表现得很好.

因此,问题实际上是:假设在动量子步骤之后采用梯度子步骤,我们是否应该计算梯度子步骤,就好像它是在动量子步骤之前或之后的位置开始的?

"它之后"似乎是正确的答案,通常情况下,某些点的渐变?大致指向从?最小的方向(具有相对正确的幅度),而在某个其他点的渐变不太可能指向您方向从?最小到最小(具有相对正确的幅度).

这是一个演示(来自下面的gif):

CM与NAG在令人敬畏的GIF中的特定时刻

  • 最小值是恒星的位置,曲线是等高线.(有关轮廓线及其垂直于渐变的原因的解释,请参阅传奇的3Blue1Brown的视频12.)
  • (长)紫色箭头是动量子步骤.
  • 如果它在动量子步骤之前开始,则透明红色箭头是梯度子步骤.
  • 如果在动量子步骤之后开始,则黑色箭头是梯度子步骤.
  • CM最终将成为暗红色箭头的目标.
  • NAG最终将成为黑箭的目标.

请注意,为什么NA​​G更好的这个论点与算法是否接近最小值无关.
一般来说,NAG和CM都存在积累更多动量而不是对它们有利的问题,因此每当它们改变方向时,它们就会有一个令人尴尬的"响应时间".我们解释的NAG优于CM的优势并不能解决问题,但只会使NAG的"响应时间"变得不那么尴尬(但仍然令人尴尬).

这个"响应时间"问题在Alec Radford(出现在Salvador Dali的答案中)的gif中得到了很好的证明:
两种动量方法令人尴尬的响应时间的一个例子

ADAGRAD

(主要基于ADADELTA中的第2.2.2 节:自适应学习率方法(原始的ADADELTA论文),因为我发现它比在线学习和随机优化的自适应子梯度方法(原始的ADAGRAD论文)更容易获得.)

SGD中,步骤由以下参数给出- learning_rate * gradient,同时learning_rate是超参数.
ADAGRAD也有一个learning_rate超参数,但梯度的每个分量的实际学习率是单独计算的.-th步骤
i第 - 个组件由下式t给出:

              learning_rate 
- --------------------------------------- * gradient_i_t
  norm((gradient_i_1, ..., gradient_i_t))
Run Code Online (Sandbox Code Playgroud)

而:

  • gradient_i_k是-th步骤中i渐变的k第 - 个组件
  • (gradient_i_1, ..., gradient_i_t)是一个带有t组件的向量.这对于构造这样的向量是不合理的(至少对我而言)是有意义的,但这就是算法所做的(概念上).
  • norm(vector)Eucldiean规范(又名l2规范)vector,这是我们直观的长度概念vector.
  • 令人困惑的是,在ADAGRAD(以及其他一些方法)中,乘以gradient_i_t(在这种情况下)的表达式learning_rate / norm(...)通常被称为"学习率"(事实上,我称之为前一段中的"实际学习率") ).我想这是因为在SGD中,learning_rate超参数和这个表达式是同一个.
  • 在实际实现中,将一些常量添加到分母,以防止除以零.

例如,如果:

  • i第一步中渐变的第 - 个组成部分是1.15
  • i第二步中渐变的第 - 个分量是1.35
  • i第三步中渐变的第 - 个分量是0.9

那么规范(1.15, 1.35, 0.9)就是黄线的长度,即:
sqrt(1.15^2 + 1.35^2 + 0.9^2) = 1.989.
所以i第三步的第一部分是:- learning_rate / 1.989 * 0.9

l2规范的例子

请注意有关i该步骤的-th组件的两件事:

  1. 它与...成正比learning_rate.
  2. 在计算中,规范正在增加,因此学习率正在下降.

这意味着ADAGRAD对超参数的选择很敏感learning_rate.
此外,可能是在一段时间之后步骤变得如此之小,以至于ADAGRAD几乎陷入困境.

ADADELTA和RMSProp

来自ADADELTA论文:

本文提出的想法来自ADAGRAD,以改进该方法的两个主要缺点:1)整个训练过程中学习率的持续衰减,以及2)手动选择的全球学习率的需要.

然后,本文解释了旨在解决第一个缺点的改进:

我们不是在所有时间累积平方梯度的总和,而是将累积的过去梯度的窗口限制为某个固定大小w[...].这确保即使在完成多次迭代迭代之后,学习仍在继续进行.
由于存储w先前的平方梯度是低效的,因此我们的方法将该累积实现为平方梯度的指数衰减平均值.

通过"指数衰减平方梯度的平均值",本文意味着对于每个i我们计算所计算i的所有梯度的所有平方分量的加权平均值.
每个平方i分量的权i重大于前一步骤中平方分量的权重.

这是一个大小窗口的近似值,w因为前面步骤中的权重非常小.

(当我想到一个指数衰减的平均值时,我喜欢想象一个彗星的踪迹,当它从彗星越来越远时变得更暗和更暗:

彗星的踪迹是对移动平均线的直觉)

如果您只对ADAGRAD进行此更改,那么您将获得RMSProp,这是Geoff Hinton在其Coursera类的第6讲中提出的方法.

所以在RMSProp中,-th步骤的i-th组件由下式t给出:

                   learning_rate
- ------------------------------------------------ * gradient_i_t
  sqrt(exp_decay_avg_of_squared_grads_i + epsilon)
Run Code Online (Sandbox Code Playgroud)

而:

  • epsilon 是一个超参数,可以防止除零.
  • exp_decay_avg_of_squared_grads_ii计算的所有梯度(包括gradient_i_t)的平方分量的指数衰减平均值.

但如前所述,ADADELTA也旨在摆脱learning_rate超参数,因此必须有更多的东西在其中.

在ADADELTA中,it- 步的第 - 个组件由下式给出:

  sqrt(exp_decay_avg_of_squared_steps_i + epsilon)
- ------------------------------------------------ * gradient_i_t
  sqrt(exp_decay_avg_of_squared_grads_i + epsilon) 
Run Code Online (Sandbox Code Playgroud)

while exp_decay_avg_of_squared_steps_ii计算的所有步骤的平方分量的指数衰减平均值(直到t-1第 - 步).
sqrt(exp_decay_avg_of_squared_steps_i + epsilon)有点类似于动量,根据论文,它"充当加速术语".(该文件还说明了为什么添加它的另一个原因,但我的答案已经太长了,所以如果你很好奇,请查看3.2节.)

亚当

(主要基于亚当:随机优化的方法,原始的亚当论文.)

Adam是自适应力矩估计的缩写(有关该名称的解释,请参阅此答案).-th步骤
i第 - 个组件由下式t给出:

                   learning_rate
- ------------------------------------------------ * exp_decay_avg_of_grads_i
  sqrt(exp_decay_avg_of_squared_grads_i) + epsilon
Run Code Online (Sandbox Code Playgroud)

而:

  • exp_decay_avg_of_grads_ii计算的所有梯度(包括gradient_i_t)的第 - 个分量的指数衰减平均值.
  • 其实,无论是exp_decay_avg_of_grads_iexp_decay_avg_of_squared_grads_i也被修正,以考虑向偏置0(更多有关,请参阅第3节的文件,并且还以stats.stackexchange答案).

请注意,Adam使用i渐变的第th个分量的指数衰减平均值,其中大多数SGD方法使用i当前渐变的第n个分量.这导致亚当表现得像"一个带有摩擦力的重球",正如在两个时间尺度更新规则收敛到局部纳什均衡训练的论文中所解释的那样.
有关亚当的动量行为与通常的动量行为有何不同,请参阅此答案.

  • 优秀的答案! (3认同)

y.s*_*hyk 5

让我们将其归结为几个简单的问题:

哪个优化程序可以给我最好的结果/准确性?

没有银弹。一些针对您的任务的优化器可能会比其他优化器更好。没有办法事先告诉您,您必须尝试一些才能找到最好的。好消息是,不同优化器的结果可能彼此接近。但是,您必须为所选的任何单个优化程序找到最佳的超参数。

我现在应该使用哪个优化程序?

也许,使用AdamOptimizer并以learning_rate 0.001和0.0001运行它。如果您想要更好的结果,请尝试以其他学习速度运行。或尝试其他优化器并调整其超参数。

很长的故事

选择优化器时,需要考虑以下几个方面:

  • 易于使用(即找到适合您的参数的速度);
  • 收敛速度(基本为SGD或更快。
  • 内存占用量(通常在模型的0到x2大小之间);
  • 与培训过程其他部分的关系。

普通SGD是可以做到的最低要求:只需将梯度乘以学习率,然后将结果加到权重即可。SGD具有许多出色的品质:只有1个超参数;它不需要任何额外的内存;它对训练的其他部分影响很小。它也有两个缺点:它可能对学习速率的选择过于敏感,并且培训可能比其他方法花费更长的时间。

从普通SGD的这些缺点中,我们可以看到更复杂的更新规则(优化程序)有什么用:我们牺牲了一部分内存来实现更快的训练,并可能简化了超参数的选择。

内存开销通常不重要,可以忽略。除非模型非常大,或者您正在使用GTX760进行培训,或者正在争取ImageNet的领导地位。动量或Nesterov加速梯度等较简单的方法需要模型大小(模型超参数的大小)为1.0或更小。二阶方法(亚当,可能需要两倍的内存和计算量。

收敛速度 -几乎任何东西都比SGD更好,其他任何东西都很难比较。一个注意事项可能是AdamOptimizer擅长几乎立即开始训练,而无需热身。

在选择优化器时,我认为易于使用是最重要的。不同的优化器具有不同数量的超参数,并且对它们的敏感性不同。我认为亚当是所有现有的最简单的。通常,您需要检查2-4个之间的learning_rates 0.0010.0001确定模型是否收敛良好。为了比较SGD(和动力),我通常尝试[0.1, 0.01, ... 10e-5]。亚当还有另外2个无需更改的超参数。

优化器与培训其他部分的关系。超参数调整通常涉及{learning_rate, weight_decay, batch_size, droupout_rate}同时选择。它们都是相互关联的,每个都可以看作是模型正则化的一种形式。例如,如果正好使用weight_decay或L2-norm并可能选择AdamWOptimizer而不是,则必须密切注意AdamOptimizer