动量法是传统梯度下降法(SGD)的一种扩展,它比SGD更高效。动量法又被称作基于动量的梯度下降法(SGD with momentum),是一种使梯度向量向相关方向加速变化、最终实现加速收敛的方法。动量法是一种非常受欢迎的优化算法,并被用于当下的很多模型中。
想象一个球从山上滚下来,刚开始速度为0,就会滚得磕磕碰碰(震荡)。经过一段时间动量(Momentum)的累加,震荡就会减少,径直往山下滚。表示为数学公式就是
g_t \leftarrow \nabla J(\theta_{t-1}) v_t \leftarrow \gamma v_{t-1} + \eta g_t \theta_t \leftarrow \theta_{t-1} - v_t
g_t 是梯度值,v_t表示了动量的累加。特点:
- 下降初期时,使用上一次参数更新,下降方向一致,乘上较大的能够进行很好的加速
- 下降中后期时,在局部最小值来回震荡的时候,,使得更新幅度增大,跳出陷阱
- 在梯度改变方向的时候,能够减少更新 总而言之,momentum项能够在相关方向加速SGD,抑制振荡,从而加快收敛。
[引用:https://zhuanlan.zhihu.com/p/22252270,作者:ycszen]
在进一步解释算法相关方程之前,我们先来看一些有关动量的基础数学知识。
指数加权平均
指数加权平均用于处理数字序列。假设我们有一些嘈杂的序列 S。在这个例子中,我绘制了余弦函数并添加了一些高斯噪声。如下图所示:
注意,尽管这些点看起来非常接近,但它们的 x 坐标是不同的。也就是说,对每个点而言,其 x 坐标是唯一的标识,因此这也是定义序列 S 中每个点的索引。
我们需要处理这些数据,而非直接使用它们。我们需要某种「移动」的平均值,这个平均值会使数据「去噪」从而使其更接近原始函数。指数加权平均值可以产生如下所示的图片:
[图片:动量——来自指数加权平均的数据]
如我们所见,这是一个相当不错的结果。与噪声很大的数据相比,我们得到了更平滑的曲线,这意味着与初始数据相比,我们得到了与原始函数更接近的结果。指数加权平均值用下面的公式定义了新的序列 V:
序列 V 是上面的散点图中的黄色部分。Beta 是取值为 0 到 1 的另一个超参数。在上述例子中,取 Beta = 0.9。0.9 是一个很好的值,经常用于具有动量的 SGD 方法。我们可以这样对 Beta 进行直观理解:我们对序列后面的 1 /(1- beta)的点进行近似平均。让我们看看 beta 的选择会对新序列 V 产生怎样的影响。
[图片:Beta 取值不同时的指数加权平均结果。]
如我们所见,Beta 取值越小,序列 V 波动越大。因为我们平均的例子更少,因此结果与噪声数据更「接近」。随着 Beta 值越大,比如当 Beta = 0.98 时,我们得到的曲线会更加圆滑,但是该曲线有点向右偏移,因为我们取平均值的范围变得更大(beta = 0.98 时取值约为 50)。Beta = 0.9 时,在这两个极端间取得了很好的平衡。
数学部分
这个部分对你在项目中使用动量而言不是必要的,所以可以跳过。但这部分更直观地解释了动量是如何工作的。
让我们对指数加权平均新序列 V 的三个连续元素的定义进行扩展。
[图片:V——新序列。S——原始序列。]
将其进行合并,我们可以得到:
再对其进行简化,可得:
从这个等式中可以看出,新序列的第 T 个值取决于原始序列 S 的所有先前的数值 1…t。来自 S 的所有数值被赋了一定的权重。这个权重是序列 S 的第(t-i)个值乘以(1- beta)得到的权重。因为 Beta 小于 1,所以当我们对某个正数的幂取 beta 时,值会变得更小。所以序列 S 的原始值的权重会小得多,也因此序列 S 对序列 V 产生的点积影响较小。从某些角度来说,该权重小到我们几乎可以说我们「忘记」了这个值,因为其影响小到几乎无法注意到。使用这个近似值的好处在于当权重小于 1 / e 时,更大的 beta 值会要求更多小于 1 / e 的权值。这就是为什么 beta 值越大,我们就要对更多的点积进行平均。下面的图表显示的是与 threshold = 1 / e 相比,随着序列 S 初始值变化,权重变小的速度,在此我们「忘记」了初始值。
最后要注意的是,第一次迭代得到的平均值会很差,因为我们没有足够的值进行平均。我们可以通过使用序列 V 的偏差修正版而不是直接使用序列 V 来解决这一问题。
式中 b = beta。当 t 值变大时,b 的 t 次幂与零无法进行区分,因此不会改变 V 值。但是当 t 取值较小时,这个方程会产生较好的结果。但是因为动量的存在使得机器学习过程稳定得很快,因此人们通常会懒得应用这一部分。
动量 SGD 法
我们已经定义了一种方法来获得一些序列的「移动」平均值,该值会与数据一起变化。我们该如何将其应用于神经网络的训练中呢?它可以平均我们的梯度。我将在下文中解释它是如何在动量中完成的这一工作,并将继续解释为什么它可能会得到更好的效果。
我将提供两个定义来定义具有动量的 SGD 方法,这几乎就是用两种不同的方式表达同一个方程。首先,是吴恩达在 Coursera 深度学习专业化(https://www.deeplearning.ai/)的课程中提出的定义。他解释的方式是,我们定义一个动量,这是我们梯度的移动平均值。然后我们用它来更新网络的权重。如下所示:
式中 L 是损失函数,三角形符号是梯度 w.r.t 权重,α 是学习率。另一种最流行的表达动量更新规则的方式不那么直观,只是省略了(1 - beta)项。
这与第一组方程式非常相似,唯一的区别是需要通过(1 - β)项来调整学习率。
Nesterov 加速渐变
Nesterov 动量是一个版本略有不同的动量更新,最近越来越受欢迎。在这个版本中,首先会得到一个当前动量指向的点,然后从这个点计算梯度。如下图所示:
Nesterov 动量可用下式定义:
动量工作原理
在这里我会解释为什么在绝大多数情况下动量法会比经典 SGD 法更好用。
使用随机梯度下降的方法,我们不会计算损失函数的确切导数。相反,我们是对一小批数据进行估算的。这意味着我们并不总是朝着最佳的方向前进,因为我们得到的结果是「嘈杂的」。正如我在上文中列出的图表。所以,指数的加权平均可以提供一个更好的估计值,该估计值比通过嘈杂计算得到的结果更接近实际值的导数。这就是动量法可能比传统 SGD 更好的原因之一。
另一个原因在于沟谷(ravine)。沟谷是一个区域,在其中,曲线在一个维度比另一个维度陡得多。在深度学习中,沟谷区可近似视为局部最低点,而这一特性无法用 SGD 方法得到。SGD 倾向于在狭窄的沟谷上摆动,因为负梯度将沿着陡峭的一侧下降,而非沿着沟谷向最优点前进。动量有助于加速梯度向正确的方向前进。如下图所示:
[图片:左图——没有动量的 SGD,右图——有动量的 SGD]
结论
希望本节会提供一些关于具有动量的 SGD 方法是如何起作用以及为什么会有用的想法。实际上它是深度学习中最流行的优化算法之一,与更高级的算法相比,这种方法通常被人们更频繁地使用。
[图片集描述来源:机器之心,Stochastic Gradient Descent with momentum:https://towardsdatascience.com/stochastic-gradient-descent-with-momentum-a84097641a5d]
发展历史
DNNs和RNNs是在处理图像和语言相关的复杂模式识别时十分强大的工具。然而对DNNs的训练直到近年来才逐渐变得简单。Hinton等人于2006年提出的贪婪层智慧预训练(greedy layerwise pre-training)让DNNs重新得到了大量关注。这一方法为之后的一系列算法提供了基础(Bengio等人,2007)。这些方法按顺序训练DNN中的每一层,之后用一些优化方法(如SGD)对整个网络进行微调。
动量法由Polyak于1964年提出,是一种用来加速梯度下降的技术,动量一词借鉴了物理中的概念。Nesterov于1983提出的Nesterov’s Accelerated Gradient(简称为NAG)备受凸规划(convex optimization)社区的关注。NAG类似动量法,也是一种在保证了高速的收敛速率的前提下一阶优化(first-order optimization)的方法。虽然NAG并不被看作是一种动量法,它与动量法仅在速度向量v的更新方式上有所不同。
虽然以上两种方法传统的收敛理论依赖于无噪声的梯度估计(noiseless gradient estimates),但它们都可经过改造适用于随机背景下。然而,Orr(1996)和Wiegerinck(1999)预测收敛的渐进局部速率(asymptotic local rate)带来的优势将会消失。由于这些原因,90年代时人们对于动量法的兴趣逐渐消退。很多当时的研究者不建议人们继续使用向量法,甚至一度忽视了它的优势(LeCun,1998)。
直到2011年,一种改进的SGD:AdaGrad(adaptive gradient algorithm) 问世。它加快了稀疏参数的训练速度。2012年出现的AdaDelta是AdaGrad的一种扩展,为了降低Adagrad中学习速率衰减过快问题,它进行了三处改动:一是使用了窗口(Math Processing Error)w;二是对于参数梯度历史窗口序列(不包括当前)不再使用平方和,而是使用均值代替;三是最终的均值是历史窗口序列均值与当前梯度的时间衰减加权平均。2012年,Geoff Hinton在Coursera上提出了RMSProp(Root Mean Square Propagation)。经验上,RMSProp被证明有效且实用的深度学习网络优化算法。相比于AdaGrad的历史梯度,RMSProp增加了一个衰减系数来控制历史信息的获取多少。后来经过升级,有了Adam(Adaptive Moment Estimation)。Adam算法可以看做是修正后的动量法和RMSProp的结合,动量直接并入梯度一阶矩估计中(指数加权)。与RMSprop区别在于,它计算历史梯度衰减方式不同,不使用历史平方衰减。
下图对比了上述各优化方法:
[图片:上:SGD各优化方法在损失曲面上的表现,下:SGD各优化方法在损失曲面鞍点处的表现]
主要事件
年份 | 事件 | 相关论文/Reference |
1964 | Boris T. POLYAK提出动量法 | Some methods of speeding up the convergence of iteration methods |
1983 | Yurii Nesterov提出NAG | A method for unconstrained convex minimization problem with the rate of convergence |
2011 | John Duchi等人提出AdaGrad | Adaptive Subgradient Methods for Online Learning and Stochastic Optimization |
2012 | Matthew D. Zeiler.提出AdaDelta | ADADELTA:An Adaptive Learning Rate Method |
2012 | Geoff Hinton提出了RMSProp | Coursera |
2015 | Diederik P. Kingma和Jimmy Lei Ba提出了Adam | Adam: a Method for Stochastic Optimization |
发展分析
瓶颈
虽然传统的SGD和动量法对于很多问题都能给出很好的结果,但相比其他自适应优化法,它们的收敛速度更慢,需要花费在调节超参数(hyperparameters)上的人工成本也更高。
未来发展方向
动量法的提出推动了上述其他SGD优化方法的发展。在实际应用中,并不能认为哪个方法一定是最好的,对于优化方法的选取,要视具体问题和参数设定的情况而定。在使用这些优化方法时,最重要的部分是参数的选取。一个非常有潜力的发展方向是研究各种方法中参数的预设定值,比如从过度拟合的角度入手。
Contributor: Xiaoxue Zhang