写在开头:这里主要要记录在平时学习中遇到的一些问题与学习的一些东西,整体的风格按照参考文献的大佬进行。
内容介绍
今天主要对momentum、NesterovMomentum、AdaGrad、RMSprop以及Adam是什么进行讲解,并对这些和比较新的AdaBound算法结果进行对比,通常会使用梯度下降来得到神经网络的参数,但是有时为了加速优化收敛,需要使用优化方法。今天就将对笔者在最近学习深度学习中遇到的优化方法,进行一个分享。如果有感兴趣的朋友想了解这几种优化方法的一些基础核心内容,可以点击这里查看指数加权平均和带偏差修正的指数加权平均。
开始分享
1.momentum
当笔者第一次使用Torch框架的时候,在调用optim.SGD时意外发现了一个参数,没错这个参数就是momentum,在一度以为SGD就是我接触的最棒梯度下降时解决的办法时,笔者对momentum的出现产生了好奇,并在Torch实操案例MNIST中添加了关于momentum的说明,在使用SGD的时候我们不难发现下降的速度比较的慢,而且从理论上来看容易遇到鞍点,就是一个局部最小点,放在一个二维来说就是如下图一样,(图片来自李宏毅《一天搞懂深度学习》),
那么这个时候怎么办,加入动量,能够帮提高我们的效率,特别是对于高曲率、小但一致的梯度,或者噪声比较大的梯度能够很好的加快学习过程。动量就是一个对于之前的速度与当前的加速度加权考虑的一个综合平均值,能够有效的保持当前的一个速度,对冲当前加速度的影响。
比较好理解的解释就是,加入动量,能够保持原有趋势,在原有趋势上,调整更新的步幅。如果梯度方向与动量方向相同则加强这个方向的步幅,反之则进行削弱。其具体算法过程,如下(参考《deep learning》):
在更新速度的时候,对速度也就是动量减去负梯度,相当于就是负梯度更新与动量更新的均衡。从torch的源码中的解释可以看到,动量的SGD的定义,笔者会在文章的最后通过代码来展示各个方法不同的效果。
Considering the specific case of Momentum, the update can be written as
.. math::
v_{t+1} = \mu * v_{t} + g_{t+1} \\
p_{t+1} = p_{t} - lr * v_{t+1}
where p, g, v and :math:`\mu` denote the parameters, gradient,
velocity, and momentum respectively.
2.NesterovMomentum
既然有了Momentum的方法为什么还需要一个Nesterov的动量方法呢?我们给出一张示意图,从图上可以看到,左边就是我们的普通的动量学习法,右边就是Nesterov的方法,如果从结果出发我们可以理解为修正了动量的改进方向。再来看一看算法进行理解,
与动量算法不同的是,该方法先对参数进行一个临时的更新,也就是站在近似的更新点上来计算梯度,相当于就是跨了一步走。但并不能证明提高了收敛率。
在cs231n中告诉我们在实践中人们我那个网更习惯于使用参数只在最后进行更新,就像前面的动量一样,于是我们可以得到一个新的计算方法,
将上述公式展开写就是
w = w + β 2 V − ( 1 + β ) α d w w = w + \beta^2 V - (1+\beta)\alpha dw w=w+β2V−(1+β)αdw这个地方的证明是借鉴的这里,
首先有
V t + 1 = β V t − α ∇ w i L ( w t + β V t ) V_{t+1} = \beta V_t-\alpha\nabla_{w_i}L(w_t+\beta V_t) Vt+1=βVt−α∇wiL(wt+βVt) w t + 1 = w t + V t + 1 w_{t+1}=w_t+V_{t+1} wt+1=wt+Vt+1我们定义第一步的向量近似更新步骤,
w t ′ = w t + β V t w^{'}_t=w_t+\beta V_t wt