深度学习中的优化算法

本文尝试通过一个框架来梳理深度学习中的常用优化算法,即从SGD到NAdam。

整体框架

我们设待学习参数为 w , 目标函数为 f(w), 初始学习率为α。第t时刻的梯度为g_t, 一阶动量为m_t, 二阶动量为v_t,更新步长为 n_t ,则有:





SGD

首先看看SGD,在SGD中没有动量,即m_t = g_t, v_t = I 。
所以n_t = α * g_t
SGD的问题是所以方向所有时刻使用固定的学习率,这就导致收敛慢;并且容易在沟壑的两边来回震荡;有时候会陷入局部最优点。

SGD with Momentum

为了解决sgd震荡问题,sgdm认为加入惯性(一阶动量),让他下坡时下的更快,改变方向变难,这样加速训练减少震荡。其中一阶动量m_t的定义为:



一阶动量是各个时刻梯度方向的指数移动平均值,约等于最近

个时刻的梯度向量和的平均值。
通常β取值在0.9-0.999之间。这样,梯度更新就不只与当前梯度有关,还与之前累积的梯度有关,这样就可以减少震荡加速下降了。

PS:指数移动平均值的概念在优化算法中会经常被提起,在本文最后给出这个概念的相关知识。

SGD with Nesterov Acceleration

SGD有一个问题是会陷入局部最优点,然后在局部最优附近来回震荡。SGD和SGDM中我们都是站在“当下”来判断未来,那何不“多走”一步,用“未来”帮助我们判断“未来”。
在SGDM中当前的更新不光由当前梯度决定,那我们可以进一步改进,即当前的梯度再进一步,用累计的梯度往前走一步,然后在决定当前的梯度方向,即:



用累计动量计算走一步后的梯度来决定当前的梯度更新。

Adagrad

上面的改进都是针对SGD的梯度进行改进,而SGD中所有时刻的学习率是固定的,导致下降缓慢的问题还是没有得到改善,同时,参数在更新时更新频率是不同的,典型的场景如Embedding,我们希望更新频繁的参数在每次更新时改动小一点而不至于忘记之前学到的,对于不频繁的,我们更希望更新时改动大些,尽可能多学到一些。
而如何度量更新频率呢?此时就要用到二阶动量了,即:


在回头看一下我们的更新梯度:



此时,本质上是对学习速率用梯度的累计做约束,动态自适应调整学习率。
在参数更新前期,g_t小,放大学习率,在后期,累计大,缩小学习率,即更新的越频繁学习率就越小。
但是由于v_t是单调递增的,所以,这也导致了一个问题:学习率可能会被缩小至0,而导致提前终止学习。

RMSProp

为了解决Adagrad提前终止学习的问题,我们对二阶动量的累计改为最近一段时间内的二阶动量累计,即指数移动平均,这样就可以避免提前终止学习了。


Adam

SGDM引入一阶动量m_t,RMSProp引入二阶动量,那集二者大成,就是我们的Adam了,即Adaptive + Momentum
其中:




β_1通常取0.9,β_2通常取0.99
而在迭代初期,m_t 和v_t很容易朝着0方向走,所以一般会引入一个bias correction(偏置纠正):




PS:一般的实现中都是会加偏置纠正,但也有人不加,比如Bert中的Adam。- - !

NAdam

而Adam还漏掉了Nesterov Acceleration,那在Adam的基础上引入Nesterov即是NAdam。


最后放两张非常直观的图



指数移动平均

指数移动平均(Exponential Moving Average)也叫权重移动平均(Weighted Moving Average),是一种给予近期数据更高权重的平均方法。

全局平均值求解:

EMA:


时,两种平均值的计算相等,而此时对应的n为

即EMA是过去1 / 1-β 个时刻的近似均值,n越大越近似。
将v_t展开,

其中



带人后

即1/1 - β之前时刻的值都被衰减了约1/e 倍。

ref:
https://zhuanlan.zhihu.com/p/68748778
https://zhuanlan.zhihu.com/p/32230623
https://zhuanlan.zhihu.com/p/32626442

你可能感兴趣的:(深度学习中的优化算法)