回归补充(三)梯度下降的改进
发布日期:2021-07-03 20:40:53 浏览次数:2 分类:技术文章

本文共 7465 字,大约阅读时间需要 24 分钟。

梯度下降的改进

文章目录

前言

在学习梯度下降的时候,提及过梯度下降仍然存在很多缺点。在这篇文章当中,我们有在3.3部分说道:

梯度下降,并不是没有缺点,比如说:

  • 当整个损失函数遇到了一个比较平缓的地方,那么这个地方的导数接近于0。而这个平缓的地方又不一定是极值点。那么就会造成停止下降,这样计算就有了偏差
  • 只能找到局部极值点,难以找到全局最小点。
  • 在鞍点(Saddle Point)处,梯度变化容易停滞

正因为存在这些问题,所以才会针对这些个问题,提出若干方法。

一.学习率预判

这个在英文资料当中称为:Learning Rate scheduling。即:优化学习率

优化学习率的方法,在下面讲述的SGD以及Adam当中都使用,具有一定的“普适性”

我们在的第7部分,已经演示了梯度下降以及梯度上升,从中提到了梯度失灵以及梯度爆炸的现象。这两个现象的出现都与学习率的调整有着直接关系。如果学习率调整的太大,就会出现这些现象。但是,如果学习率调整的太小,则大大增加运算时间,影响运算效率。所以,该如何设定这个学习率呢?

1.1 原版梯度下降

有一种思路是:最开始的时候,学习率可以设定的大一些,但是,随着迭代次数的增加,越来越逼近极值点,学习率就应该响应的减小。我们假设学习率是alpha,t代表迭代的次数。那么大可以这么设定:

α t = α t − 1 1 + t \alpha_{t} = \frac{\alpha_{t-1}}{\sqrt{1+t}} αt=1+t αt1
这样一来,迭代公式就变成了:

w t = w t − 1 + α t − 1 g t − 1 w_{t} = w_{t-1} + \alpha_{t-1}g_{t-1} wt=wt1+αt1gt1

其中,g为偏导的值:这个方法被称为:原版梯度下降(Vanilla Gradient descent)(香草这个单词的衍生意思有“原生的”意思)

1.2 自适应梯度下降

还有一种方法叫:自适应梯度算法(AdaGrad)

在这个算法当中,引入了均方根差(Root Mean Square),它的公式其实很简单。就是均方误差开根号:
δ t = R M S D ( g t ) = M S E ( g t ) \delta_{t} = RMSD(g_{t}) = \sqrt{MSE(g_{t})} δt=RMSD(gt)=MSE(gt)
g代表偏导的值

同时,结合原版梯度下降当中计算alpha的方法:

w t = w t − 1 + α t − 1 δ t − 1 g t − 1 w_{t} = w_{t-1} + \frac{ \alpha_{t-1}}{\delta_{t-1}}g_{t-1} wt=wt1+δt1αt1gt1
于是,就有了这样一个迭代方式:
在这里插入图片描述

1.3 RMSProp算法

英文全称: Root Mean Square Prop。中文有人翻译为:均方根传递算法

这个算法,其实承接了AdaGrad,在AdaGrad的基础上做了一定的微调。它的具体计算公式如下:
w t = w t − 1 − η v t g t − 1 v 1 = g 0 2 v t = α v t − 1 + ( 1 − α ) g t − 1 2 w_{t} = w_{t-1} - \frac{ \eta}{\sqrt{v_{t}}}g_{t-1}\\v_{1} = g_{0}^2\\v_{t}=\alpha v_{t-1} + (1-\alpha)g_{t-1}^2 wt=wt1vt ηgt1v1=g02vt=αvt1+(1α)gt12

1.4 其它

以上两个比较重要,随着时间的推移,越来越多的学习率优化方法被提了出来,比如说:

1.4.1 LR Range Test

这个算法可以帮助寻找合适的学习率区间。整体思路就是:模型和数据迭代几次,把学习率初始值设置得比较小,随着迭代次数的增加,学习率也要相应的增大。增大的结果就是:损失函数下降的速度开始加速。

但是,别忘了,我们之前已经有提到过“梯度爆炸”的概念。随着学习率的进一步增大,我们发现损失函数值竟然也开始增大了。这个时候,停止迭代。从梯度开始加速下降到开始上升的这个区间,就是合适的学习率区间。
下面这个图,记录了一个损失函数随着学习率的增加而变化的趋势。两条虚线之间就是合适的学习率区间。
在这里插入图片描述

1.4.2 循环学习率

英文名:Cyclical LR。这个其实基于LR Range Test,先用LR Range Test来确定学习率的变化范围,然后就在这范围之间周期性变化。

二.批量梯度下降(Batch gradient descent , 简称BGD)

如果,整体上只有一个局部最小值,那么这个事情就容易解决多了,批量梯度下降就是一个方式。批量梯度下降的思路就是:既然整体最小值也是局部最小值,那么不管从哪个方向开始下降,最终都会走到那个最小值,即:汇聚在了一起。批量梯度的伪代码如下:

在这里插入图片描述

即:对所有的点都进行梯度计算,直到所有的点都汇集到最低的那个点,这也意味着批量梯度下降一定能找到全局的最优点

三. 随机梯度下降(Stochastic gradient descent, 简称:SGD)

批量梯度下降需要不停的进行梯度下降,直到所有的点都能汇集到最小点,这也意味着他的计算量非常巨大,因此,如果数据量比较大,BGD费时费力。于是就有人提出了SGD。

随机梯度下降是每次迭代使用一个样本来对参数进行更新。比如说,我第一次迭代,得到了一个较低的值,我再往后迭代的时候,碰到了更低的值,那么就用这个更低的值去覆盖原来的值。以此类推,直到迭代结束。SGD的步骤如下:

  • step1:先随机选定一个theta0点
  • step2:计算损失函数在theta点的偏导数g
  • step3:利用梯度下降公式,求出一个新的theta点(g为偏导数)
    θ 1 = θ 0 − α g ( θ 0 ) \theta_{1} = \theta_{0} - \alpha g(\theta_{0}) θ1=θ0αg(θ0)
  • 不断重复上面的计算,知道g约为0为止

随机梯度的伪代码如下:

在这里插入图片描述

当然了,虽然熟读更快,运算量也比BGD减少不少,不过,由于只是经历了m次循环,二不像BGD那样把所有的可能性都走了一遍,这也意味着那个全局的最低点恐怕总也找不到。

于是,就有人想,能不能折中一下呢?

四.小批量梯度下降(Mini-Batch)

BGD与SGD的折中方案就是这个Mini-Batch。小批量梯度下降对随机梯度下降当中的for循环做了修改,它不像随机梯度算法那样,把i从1到m都跑一遍,而是从m个样本中随机抽取若干个进行迭代。而选出来的这几个进行BGD。

为了能够从m个样本当中随机抽取,小批量梯度下降搞出了一个batch_size, 其实就是一个参数,我们假设这个batch_size = 10。那么我们大概就可以写出Mini_batch的伪代码如下:

repeat until convergence{	for i = 1, 11,21,31……m,{		SGD	}}

五.SGD还有改进空间吗?

答案是肯定的,而且还很多。

5.1 SGDM

这个英文全称:SGD with Momentum。即:带有偏移量的SGD,从字面意思就很好理解,给损失函数加上一个偏移量。为什么要加这个偏移量呢?我们在前面说过,梯度下降的一个缺点就是:遇到比较平缓的,或者鞍点,由于此时导数近似是0,因此会导致下降停滞。加上这个偏移量,就能让平缓点,鞍点处重新“斜”起来,这样导数就不再是0,就可以继续运算下去。

SGDM,在SGD的基础上做了一些修改,引入了一个偏移量:v,他的算法步骤如下:

  • step1:先随机选定一个theta0点

  • step2:计算损失函数在theta点的偏导数g

  • step3:设定偏移量的初始值为v0 = 0

  • step4:对偏移量进行迭代:

    v 1 = λ v 0 − α g ( θ 0 ) v_{1} = \lambda v_{0} - \alpha g(\theta_{0}) v1=λv0αg(θ0)

  • step5:对theta进行迭代:

    θ 1 = θ 0 + v 1 \theta_{1} = \theta_{0} +v_{1} θ1=θ0+v1

  • step6:对偏移量进行迭代

    v 2 = λ v 1 − α g ( θ 1 ) v_{2} = \lambda v_{1} - \alpha g(\theta_{1}) v2=λv1αg(θ1)

  • step7:对theta进行迭代

    θ 2 = θ 1 + v 2 \theta_{2} = \theta_{1} +v_{2} θ2=θ1+v2
    ……

  • 不断重复上面的计算,知道g约为0为止

5.2 涅斯捷罗夫梯度加速(NAG)

英文全称:Nesterov accelerated gradient。提出人就是这个:尤里·涅斯捷罗夫(Yurii Nesterov)。因此,这个算法以他的名字命名。

NAG其实是SGDM的一个变种,在SGDM当中,如果我们把5.1部分的步骤稍微总结一下,其实迭代公式就是这个,其中g代表偏导:

θ t = θ t − 1 − v t v t = λ v t − 1 + α g ( θ t − 1 ) \theta_{t} = \theta_{t−1} − v_{t}\\ v_{t} = \lambda v_{t−1} + \alpha g(\theta_{t-1}) θt=θt1vtvt=λvt1+αg(θt1)

而NAG则对当中的偏导数g动了手脚,即:不再是对上一个theta点进行求导,而是对“下一个点”进行求导。于是就有了:

θ t = θ t − 1 − v t v t = λ v t − 1 + α g ( θ t − 1 − λ v t − 1 ) \theta_{t} = \theta_{t−1} − v_{t}\\ v_{t} = \lambda v_{t−1} + \alpha g(\theta_{t-1} -\lambda v_{t-1}) θt=θt1vtvt=λvt1+αg(θt1λvt1)

所以也有人戏称NAG是“超前执行”

关于SGD的这些变种,其实还有不少。这里只列举这几个,其他的都是在相关的算法基础上进行微调。

六.Adam

关于Adam,其实就是SGDM和RMSProp的结合体。我们可以翻看一下上面的公式。再来对比一下Adam到底是什么?

首先,在SGDM当中,我们令v迭代当中的两个参数alpha和lambda的加和是1。于是,SGDM的迭代公式,我们可以写成:
θ t = θ t − 1 − v t v t = α 1 v t − 1 + ( 1 − α 1 ) g t − 1 \theta_{t} = \theta_{t-1} - v_{t}\\ v_{t} =\alpha_{1} v_{t-1} + (1-\alpha_{1}) g_{t-1} θt=θt1vtvt=α1vt1+(1α1)gt1

然后我们再看看RMSProp。为了把参数进行区分和统一,我们这么写:

θ t = θ t − 1 − η v t g t − 1 v 1 = g 0 2 v t = α 2 v t − 1 + ( 1 − α 2 ) g t − 1 2 \theta_{t} = \theta_{t-1} - \frac{ \eta}{\sqrt{v_{t}}}g_{t-1}\\v_{1} = g_{0}^2\\v_{t}=\alpha_{2} v_{t-1} + (1-\alpha_{2})g_{t-1}^2 θt=θt1vt ηgt1v1=g02vt=α2vt1+(1α2)gt12

然后综合一下:

θ t = θ t − 1 − η v ^ t + ϵ g ^ t − 1 \theta_{t} = \theta_{t-1} - \frac{ \eta}{\sqrt{\hat{v}_{t}}+\epsilon}\hat{g}_{t-1} θt=θt1v^t +ϵηg^t1

其中:

v ^ t = v t 1 − α 2 t g ^ t = g t 1 − α 1 t \hat{v}_{t} =\frac{ v_{t}}{1-\alpha_{2}^t}\\ \hat{g}_{t} = \frac{g_{t}}{1-\alpha_{1}^t}\\ v^t=1α2tvtg^t=1α1tgt

关于Adam,其实也有很多个变种和改进,比如说:

6.1 AMSGrad

先看看Adam,关于Adam的这个公式,科学家们发现,收敛速度其实是很快的。也就是说,这个学习率值是偏大的,偏大就容易导致不收敛。

为了解决这个不收敛的问题。有大佬在2018年提出了这个AMSGrad,思路就是:通过单调地减小步长,来防止收敛速度过快。公式如下:
θ t = θ t − 1 − η v ^ t + ϵ g ^ t − 1 v ^ t = m a x ( v t , v ^ t − 1 ) \theta_{t} = \theta_{t-1} - \frac{ \eta}{\sqrt{\hat{v}_{t}}+\epsilon}\hat{g}_{t-1}\\ \hat{v}_{t} = max(v_{t},\hat{v}_{t-1}) θt=θt1v^t +ϵηg^t1v^t=max(vt,v^t1)

6.2 NAdam

在SGD当中,我们已经介绍了NAG,这个算法可以“超前执行”,而NAdam也具有超前执行的能力,这就使得收敛速度更快。原因在于,NAdm其实就是Adam和NAG的结合

θ t = θ t − 1 − η v ^ t + ϵ g ^ t − 1 v t = α 1 v t 1 − α 1 t + 1 + ( 1 − α 1 ) g t − 1 1 − α 1 t \theta_{t} = \theta_{t-1} - \frac{ \eta}{\sqrt{\hat{v}_{t}}+\epsilon}\hat{g}_{t-1}\\v_{t} = \frac{\alpha_{1}v_{t}}{1-\alpha_{1}^{t+1}}+\frac{(1-\alpha_{1})g_{t-1}}{1-\alpha_{1}^t} θt=θt1v^t +ϵηg^t1vt=1α1t+1α1vt+1α1t(1α1)gt1

6.3 AdamW

这个算法,引入了L2正则化的思想。之所以正则化,是为了防止过拟合。

g ^ t = α 1 g t − 1 + ( 1 − α 1 ) g ( θ t − 1 ) v ^ t = α 2 v t − 1 + ( 1 − α 2 ) g 2 ( θ t − 1 ) θ t = θ t − 1 − η ( 1 v t ^ + ϵ v ^ + γ θ t − 1 ) \hat{g}_{t} = \alpha_{1}g_{t-1} + (1-\alpha_{1})g(\theta_{t-1})\\ \hat{v}_{t} = \alpha_{2} v_{t-1} + (1-\alpha_{2})g^2(\theta_{t-1})\\ \theta_{t}=\theta_{t-1} -\eta (\frac{1}{\sqrt{\hat{v_{t}}}+\epsilon}\hat{v} + \gamma \theta_{t-1}) g^t=α1gt1+(1α1)g(θt1)v^t=α2vt1+(1α2)g2(θt1)θt=θt1η(vt^ +ϵ1v^+γθt1)

6.4 RAdam

RAdam的算法如下:

在这里插入图片描述
这当中,m就是前面所讲的g,而gamma_t则是一个参数,这个参数随着迭代次数增加而增加。所以说,RAdam多多少少引入了LR Range Test的思想,在最开始的时候,学习率较小,越往后学习率越大。这样做的目的,其实是为了尽快找到合适的学习率,减少学习率不合的影响。这种,最开始学习率较低,后来逐渐增大的方式,也叫:warm-up(预热)

我们再仔细看看后面的when,发现,当p<4的时候,其实使用的是SGDM,而后面的这个when部分,使用的是Adam。因此,RAdam其实是,SGDM到Adam的一个转换。

七.SWATS

7.1 SGDM与Adam的对比

整体来说,SGDM与ADAM有如下区别:

首先看SGDM:它收敛速度较慢,迭代步数较小,相对于Adam而言,更容易拟合,稳定性较强。
而Adam呢?收敛速度较快,迭代步数也比较大,但也相对容易出现‘“学习率失效,学习率爆炸”的现象(即:不一定拟合),稳定性不是很高。

于是就有人想:能不能把SGDM与Adam的优点相结合,来一个折中的方案呢?这个就是方案就是:SWATS

7.2 SWATS简介

从英文名就可以看出来这个算法的思路,这个算法的英文名:Switching from Adam to SGD。也就是说,在开始的时候,使用Adam来加速收敛,等到达到某个指标的时候,开始使用SGD减少收敛速度。整个算法流程如下:

在这里插入图片描述
其中,蓝色部分是Adam。

因此,这个SWATS几乎可以看成是RAdam的一个反向过程。那么这两个算法有什么区别和联系呢?

7.3 SWATS与RAdam的对比

在这里插入图片描述

八.总结

以上这些算法,很多其实都是很相近的,而且有些内容相互覆盖和交叉。因此,在这里需要厘清一下思路,有一个整体脉络。

8.1 以上这些算法都属于哪个簇?

以上的这些算法,其实往大了说,两大类,一个是SGD,一个是Adam。根据不同的基础,很多算法都是基于这两个大类别来进行细分的。只有一个SWATS,是脚踩SGD和Adam两条船,属于“中间派”

在这里插入图片描述

8.2 SGD与Adam的对比

这个其实在7.1部分已经说了。做成表格则如下所示:

在这里插入图片描述

转载地址:https://blog.csdn.net/johnny_love_1968/article/details/117535111 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:深度学习简介
下一篇:Sklearn的一些技巧

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年04月15日 19时03分34秒