深度学习中的优化器原理总结(经典+前沿)
2024-05-26
[摘要] 目录前言一、梯度下降的思想与批梯度下降法1.随机梯度下降法2.标准梯度下降法3.批梯度下降法二、经典的五类优化器1.SGD2.SGDM(SGDwithmomentum)3.Adagrad4.RMSProp5.Adam三、前沿方法1.A

目录

前言

一、梯度下降的思想与批梯度下降法

1.随机梯度下降法

2.标准梯度下降法

3.批梯度下降法

二、经典的五类优化器

1.SGD

2.SGDM(SGD with momentum)

3.Adagrad

4.RMSProp

5.Adam

三、前沿方法

1.AMSGrad

2.AdaBound

3.SWAT

4.Cyclical LR/SGDR/One-cycle LR

5.RAdam

6.Lookahead

7.SGDWM/AdamW

8.一些帮助优化的方法

四、总结


本文介绍了经典和前沿的深度学习中的优化器(优化算法)。文章整体思路、图片、公式均源自李宏毅2020机器学习深度学习(完整版)国语_哔哩哔哩_bilibili。Optimization部分在网课中是由课程助教讲解的选学课程,难度较大(我在第一次学习的时候甚至连Adam算法都没有理解,就匆匆跳过了课程)。之所以整理出该文章,一方面用于以后自己经常回顾,一方面希望可以帮助向曾经的我一样被直接劝退的朋友们。视频中Adagrad、RMSProp等算法等讲解得过快,我在文中写入了自己对不同算法的理解、思考以及直观上的分析,如果能恰好帮助你理解,并与网课视频相互补充,那我将十分荣幸。

本文分为三个部分,第一个部分介绍梯度下降的思想及实际训练模型常用的批梯度下降法,第二部分介绍了五种经典的算法,第三部分介绍了一些前沿算法。在第二三部分的介绍中,每种算法在介绍时以算法的优势、步骤和直观理解为主,不讨论其理论性质的证明。

无论是DNN还是CNN,都追求模型预测值和真实值间的差异最小化,通常构造损失函数来度量这种差异(如回归问题中的平方损失,分类问题中的交叉熵损失),损失函数是模型参数的函数。因此,我们一定会面临一个最小化问题,目标函数是损失函数,决策变量是模型参数。于是,我们需要优化算法来求解这个最小化问题,梯度下降法或者说它的思想贯穿着深度学习优化算法的始终。


梯度下降是经典的优化算法,它的思想是:参数在更新时始终朝着目标函数(最小化问题)下降最快的方向移动,而这个方向就是梯度(梯度是上升最快的方向)的反方向,用公式可以表达为

	heta _{t}=	heta _{t-1}-\eta 	riangledown{L(	heta _{t-1})}

\small 	riangledown{L(	heta _{t-1})}是损失函数\small L对第\small t-1时刻的参数\small 	heta _{t-1}的梯度,\small \eta学习率是一个超参数,需要人为设定,通常设为0.001、0.01等。

算法的流程非常简单:初始化参数向量\small 	heta _{0},然后根据该公式不断更新梯度,使得损失函数收敛到较低水平时停止。

基于梯度下降优化算法的思想,通常有三种不同的模式来训练模型,分别是:随机梯度下降,标准梯度下降法,和批梯度下降法:

每次只使用一个训练集样本来更新参数。该方法的不足是参数更新不够稳定,收敛速度较慢,这是因为一个样本很难代表整体,每次更新只是减小了该样本的损失函数值,却可能造成在其他样本上损失函数值的增大。

每次利用全部训练集样本来更新参数。该方法虽然直观上解决了上述问题,但通常深度学习问题的数据量庞大,一次性将全部数据丢计算机进行训练几乎是不可能的。其次,由于包括了所有样本,不同样本对参数更新的影响可能会相互抵消,使得参数每轮更新值都很小。

批梯度下降法是对上述两种方法的集中,明显规避了两种方法的缺点,成为现在几乎一定会使用的方法。该方法就是将数据集分成几个批(batch),每个batch的数据量根据实际数据量的大小由自己定义,每次丢进一个batch进入模型进行训练。


见一,1。(虽然算法名叫随机梯度下降,但实际上,仍然采用的是mini-batch gradient descent,批梯度下降法。无论采用什么优化器,都需要用用mini-batch的方式训练。)

随机梯度下降法虽然有效,但容易陷入局部最小值点,甚至在驻点附近以及梯度值非常小的点附近时参数更新极为缓慢。为了改进这个缺点,引入物理中动量的概念,参数更新量\small m _{t},是当前梯度的方向\small g_{t},和上一次参数更新方向\small m _{t-1}的线性组合。算法如下:

①初始化参数\small 	heta = 	heta _{0}, m _{0} =0, \eta ,t=0

②计算当前梯度:\small g_{t}= 	riangledown{L(	heta _{t})}

③更新参数移动量:


u _{t+1}=\lambda m _{t}+\eta g_{t}

④更新参数:\small 	heta _{t+1}=	heta _{t}-m _{t+1}

\small t=t+1,返回步骤②,直到达到某终止条件。

下图是参数是以一维的情况下,动量法的直观示意。可以看到在局部最小值点时,虽然真实的梯度为0,但由于惯性(上一时刻的动量方向)存在,参数仍然会朝着原有方向更新,也就有了冲出局部最小值的可能。

?Adagrad算法的公式如下:

①初始化参数\small 	heta = 	heta _{0}, \eta, t=0;?

②计算当前梯度:\small g_{t}= 	riangledown{L(	heta _{t})};更新参数:

	heta _{t+1}=	heta _{t}-\frac{\eta }{\sqrt{\sum_{i=1}^{t}g_{i}^{2}}} g_{t}

\small t=t+1,返回步骤②,直到达到某终止条件。

观察步骤二参数更新公式中的式子

\small \frac{g_{t}}{\sqrt{\sum_{i=1}^{t}g_{i}^{2}}}\eta

可以发现,除了第一次更新时的更新量为\small \eta,其余时刻的更新量都小于\small \eta,是一个介于0到\small \eta之间的数。如果新的梯度很大,则更新量大(接近\small \eta),否则更新量小(接近0)。

直观上来讲,更新量是新的梯度的平方占累积梯度平方和的比例开根号乘以\small \eta,它的意义在于使得不同参数的更新处于同一维度之下,从下图可以体现出来。

可以看出,在给定的参数点上,在\small \omega _{1}方向上的导数大于\small \omega _{2}方向的导数。如果采用传统的SGD方法,参数更新的方向将是橙色线的方向。而如果是采用Adagrad算法,由于?\small \omega _{1}方向上的累积导数和也很大,这使得两个参数方向对最终的更新方向的贡献几乎相等,此时更新的方向大概是红色线的方向,这是更符合我们直观想法的。

Adagrad算法和RMSProp算法都称为自适应算法。自适应算法的意思就是,学习率随着更新次数而改变。Adagrad算法虽然在上述简单的例子中有直观解释,但实际的损失函数通常很复杂。且发现当t很大时,Adagrad下参数将几乎不再更新。可以假设,对任意t,\small g_{t}相同,此时参数的更新量将以\small O(\sqrt{1/t})阶减小。为了改变这一劣势,提出RMSProp算法。RMSProp算法如下:

①初始化参数\small 	heta = 	heta _{0}, \eta, 
u _{0}=0,t=0

②计算:\small g _{t}= 	riangledown{L(	heta _{t})} ,?\small 
u _{_{t+1}}=\alpha 
u _{_{t}}+(1-\alpha )g _{_{t}}^{2};

③更新参数:

	heta _{t+1}=	heta _{t}-\frac{\eta }{\sqrt{^{
u _{t+1}}}} g_{t}

\small t=t+1,返回步骤②,直到达到某终止条件。?

将步骤二中的\small 
u _{_{t+1}}展开得到:

\small 
u _{t+1}=\alpha ^{t}(1-\alpha)g_{0}^{2}+\alpha ^{t-1}(1-\alpha)g_{1}^{2}+...+\alpha ^{1}(1-\alpha)g_{t-1}^{2}+(1-\alpha)g_{t}^{2}

可以看到,与Adagrad相比,分母中过去的梯度值平方的权重已经由等权(权重均为1),变为指数加权。此时参,参数更新量的上界为\small \eta \sqrt{1/(1-\alpha) }。随着更新次数的增加,对于相同的\small t,g_{1},g_{2},...,g_{t},RMSProp算法的参数更新量\small \eta g_{t}/\sqrt{v_{t+1}}大于Adagrad算法,解决了过快收敛的问题。

Adam算法是RMSProp算法与SGDM算法的结合,其既是有着自适应学习率,又能引入了动量机制在一定程度上减小参数陷入局部最有点的可能性。其是应用最为广泛的深度学习优化器之一,算法步骤如下:

①初始化参数:\small 	heta = 	heta _{0}, \eta, 
u _{0}=0,m _{t}=0,t=0

②计算梯度:\small g _{t}= 	riangledown{L(	heta _{t})}

③更新\small m _{t+1}

\small m _{t+1}=\beta _{1}m _{t}+(1-\beta _{1})g _{t}

④更新\small 
u _{t+1}

\small 
u _{t+1}=\beta _{2}
u _{t}+(1-\beta _{2})g _{t}^{2}

⑤更新参数

	heta _{t+1}=	heta _{t}-\frac{\eta }{\sqrt{\hat{
u}_{t+1}} +\varepsilon }\hat{m}_{t+1}

其中,

\hat{m}_{t+1}=\frac{m_{t+1}}{1-\beta _{1}^{t}}

\hat{
u} _{t+1}=\frac{
u_{t+1}}{1-\beta _{2}^{t}}

\small t=t+1,返回步骤二,直到满足某终止条件。?

步骤④中的\hat{m}_{t+1},\hat{
u} _{t+1}{m}_{t+1},{
u} _{t+1}的估计量,其修正了偏差,以得到更好的理论性质;\varepsilon是为了防止前几次计算梯度为0时,参数更新量的分母为0。通常设置:\small \beta _{1}=0.9,\beta _{2}=0.999,\varepsilon =1e-8.?


一些前沿方法相继被提出,大部分是以上经典算法的改进、组合等。

算法步骤上,在ADAM算法基础上进行了改进:

①初始化参数:\small 	heta = 	heta _{0}, \eta, 
u _{0}=0,m _{t}=0,t=0

②计算梯度:\small g _{t}= 	riangledown{L(	heta _{t})}

③更新\small m _{t+1}

\small m _{t+1}=\beta _{1}m _{t}+(1-\beta _{1})g _{t}

④更新\small 
u _{t+1}

\small 
u _{t+1}=\beta _{2}
u _{t}+(1-\beta _{2})g _{t}^{2}

⑤更新参数

	heta _{t+1}=	heta _{t}-\frac{\eta }{\sqrt{\hat{
u}_{t+1}} +\varepsilon }{m}_{t+1}

其中,

\hat{
u} _{t+1}=max(\hat{
u} _{t},{
u} _{t+1}).

该算法的改进点在于\hat
u _{t+1}。可以看出AMSGrad法的\hat
u _{t+1}随着t的增加一直在递增,而Adam法中的\hat
u _{t+1}是有可能减小的。若\small \hat{
u} _{t+1}={
u} _{t+1},则参数更新量约等于ADAM算法;若\hat{
u} _{t+1}=\hat{
u} _{t},则参数更新量小于ADAM算法。

到后期,梯度值较小时,\hat
u _{t+1}将保持不变,\eta/(\sqrt{\hat{
u}_{t+1}}+\varepsilon )是常数,此时更新量的大小只取决于{m}_{t+1}的大小。

方法提出者在测试Adam算法时发现在更新参数时,更新量要么很大要么很小,因此提出了一个Bound的方法,控制每次的更新量不超过某个范围。

关键步骤为:

	heta _{t+1}=	heta _{t}-Clip(\frac{\eta }{\sqrt{\hat{
u}_{t+1}+\varepsilon} })\hat{?{m}}_{t+1}

Clip(x)=Clip(x,0.1-\frac{0.1}{(1-\beta _{2})t+1},0.1+\frac{0.1}{(1-\beta _{2})t+1})

一些研究发现,通常SGDM算法收敛速度较慢但稳定,ADAM算法收敛速度快但较不稳定,同时SGDM算法的收敛结果要好于ADAM。也就是SGDM算法虽然收敛得慢,但能够得到更低得损失函数值。

因此,想到可以结合二者得优点。训练时,先用ADAM算法使得损失函数快速下降,再使用SGDM法寻找更低的损失函数,这就是SWAT法。但该方法并没有给出一种通用的准则来决定:①何时切换两种方法②切换到SGDM时,学习率如何设置。因此,该方法更多是一种思路,对于不同问题需要不断尝试,且尝试成本较大。

这一类方法的思想是,SGDM之所以更新参数速度较慢,是因为学习率恒定,因此尝试在SGDM方法上加上一个人为的动态的学习率。典型的三种方法是Cyclical LR、SGDR和One-cycle LR,它们的学习率随着迭代次数的变化的形状依次见以下三幅图。

前两种方法的学习率变化具有周期性,而最后一种不具有周期性,因此称为One-cycle。

有研究发现Adam算法在前几代,所有参数的梯度值的方差较大,而在中后期梯度值的分布逐渐趋于稳定。为了防止梯度值比较散乱时,参数在错误的方向上更新量过大,采用一种热身(warm-up)的方法,在更新初期采用小的学习率,在后期采用大的学习率(One-cycle LR方法学习率图像中前期线性增长的部分就可以看作是一种warm-up)。

RAdam方法的warm-up通过r_{t}来控制,r_{t}逐渐从0增加到1。

r_{t}的公式和图像分别为:

\rho _{t}=\rho _{\infty }-\frac{2t\beta _{2}^{t}}{1-\beta _{2}^{t}}

\rho _{\infty }=\frac{2}{1-\beta _{2}}-1

r_{t}=\sqrt{\frac{(\rho _{t}-4)(\rho _{t}-2)\rho _{\infty }}{(\rho _{\infty }-4)(\rho _{\infty }-2)\rho _{t}}}

?

?参数更新的公式为:

  • \rho _{t}\leq 4时,

	heta _{t+1}=	heta _{t}-\eta\hat{m}_{t}

  • \rho _{t}> 4时,

	heta _{t+1}=	heta _{t}-\frac{r_{t+1}\eta }{\sqrt{\hat{
u}_{t+1}} +\varepsilon }

?因为只有当\rho _{t}> 4时,r_{t}才存在,因此当\rho _{t}\leq 4r_{t}不存在时,先采用SGDM法更新参数。

?对比一下RADAM和SWAT方法:

  • 提出动机:RADAM的提出动机是,ADAM更新参数初期,\small g _{t}估计不准,导致{
u}_{t+1}估计不准,因此采用warm-up的方法,用r_{t}乘原本的更新量,r_{t}逐渐从0增加到1;而SWAT提出动机是ADAM前期训练效率高,损失函数降的快,SGDM训练效率慢,但收敛效果好。
  • 具体做法:RADAM是先用SGDM(因为前期r_{t}不存在),再用warm-up的ADAM;SWAT是先用ADAM,再用SGDM。
  • 切换点:RADAM算法中,当r_{t}存在时,从SGDM切换到warm-up的ADAM;SWAT算法中,人为凭经验给定一个切换时刻,从ADAM切换至SGDM。

Lookahead方法是一种优化策略,可以与以上提出的任何一种优化方法相结合。该策略的思想是:向前走k步,向后退一步(k step?forward,1step back)。

正如同下面第一张图的公式。首先,在外层循环中设置快参数	heta _{t,0}和慢参数\phi _{t-1}的初始值相同,然后利用某种优化算法比如SGD算法更新快参数k步(对应下面图二中蓝色虚线从左下到右上的路径),接着更新慢参数,取慢参数为慢参数起始点和快参数终止点连线的中间某一点(对应下面图二从左下到右上的红色直线上的红色三角)。

下图是训练后期测试集准确率随训练代数更新的变化,纵轴是测试集准确率,横轴是训练代数。可以看到每个周期前k步,测试集准确率将快速下降(在数据量较少的情况下,如果一直训练,会过拟合的现象,到训练后期时,虽然训练集准确率可能不降低,但测试集准确率会下降,如图中每条蓝线所示),而第k+1步由于回退,测试集准确率保持在较高水平。

因此,我认为这个方法能很大程度延缓过拟合的到来,在与过拟合的“抗争"与“拉扯”中,试图找到更好的参数值。

通常为了防止过拟合,我们会在原来的损失函数L(	heta)的基础上加上二范数正则项1/2\gamma \left \| 	heta \right \|^{2}:

L_2(	heta)=L(	heta)+1/2\gamma \left \| 	heta \right \|^{2}

此时,参数在	heta _{t-1}处的梯度由	riangledown L(	heta _{t-1})变为	riangledown L(	heta _{t-1})+\gamma 	heta _{t-1}

因此,在基于梯度下降法更新参数时,自然要利用新的梯度进行更新,但对于SGDM法和Adam法来说,m _{t}
u _{t}的更新是否需要使用新的梯度呢?如果按照公式来讲,理论上就应该是使用新的梯度。但2017年,有学者表明,在SGDM算法更新m _{t},以及Adam算法更新m _{t}
u _{t}的过程中使用原梯度	riangledown L(	heta _{t-1})(即不加正则项的梯度)效果会更好。

?于是便有了SGDWM和AdamW算法,如下图所示:

  • Shuffling:做mini-batch时每次打乱数据顺序,保证batch样本的随机性,从而保证梯度更新的随机性。
  • Dropout:DNN中,使得一部分神经元随机失活。
  • Gradient noise:给梯度增加独立的随机正太噪声,噪声方差随时间t的增加而减小。

g_{t,i}=g_{t,i}+N(0,\sigma _{t}^{2})

\sigma _{t}=\frac{c}{(1+t)^{\gamma }}

  • Warm-up:学习率逐渐增加。
  • Curriculum learning:先用干净数据训练模型,再用复杂数据(有噪声数据)训练模型。
  • Fine-tuning:用训练好的参数(可以从已训练好的模型中获得)初始化自己的网络,然后用自己的数据接着训练,参数的调整方法与from scratch训练过程一样(梯度下降)。
  • Normalization:批归一化等。

以上方法总结为下图(NAG方法数学推导实在过于复杂,没有进行介绍):

应用最为广泛的两种方法SGDM和Adam的不同应用领域:



平台注册入口