本文主要讲解各种优化器
,对应的PyTorch
实现放在下篇torch.optim
一、GD
GD(gradient descent)梯度下降,在机器学习中对模型进行更新,更新如下所示
d
f
(
x
)
d
x
=
lim
x
→
0
f
(
x
+
h
)
−
f
(
x
)
h
θ
t
+
1
=
θ
t
−
η
t
▽
f
(
θ
t
)
\begin{aligned} \frac{df(x)}{dx} &= \lim_{x\rightarrow 0} \frac{f(x+h)-f(x)}{h} \\ ~~ \\ \theta_{t+1} &= \theta_{t}-\eta_{t}\bigtriangledown f(\theta_{t}) \end{aligned}
dxdf(x) θt+1=x→0limhf(x+h)−f(x)=θt−ηt▽f(θt)
这是最原始的剃度下降方法,每次计算梯度
▽
f
(
θ
t
)
\bigtriangledown f(\theta_{t})
▽f(θt)时都需要对整个训练集进行遍历,即需要训练集的全部数据。当我们的数据集非常大时对整个数据集进行计算是很麻烦的,而且每次更新参数
θ
\theta
θ的数值时都很慢,也就是说我们需要迭代无数多次而每次都需要对整个数据集进行计算梯度,耗时很长,而且当参数移动到局部最优点(鞍点,梯度为0)时,就会陷入其中,参数停止更新
由于本文主要讲解SGD及其改进,所以对GD不做详细介绍
二、SGD及其改进
与GD不同,SGD每次从数据集中取出部分mini-batch
,求部分数据集的loss,即用部分数据的梯度来近似整体的梯度,首先和GD一样,我们需要了解梯度更新的过程
θ t + 1 = θ t − η t ▽ f ( θ t ) \begin{aligned} \theta_{t+1} &= \theta_{t}-\eta_{t}\bigtriangledown f(\theta_{t}) \end{aligned} θt+1=θt−ηt▽f(θt)
其中
- η t \eta_{t} ηt:学习率
- θ t \theta_{t} θt:在t时刻的参数值
- ▽ f ( θ t ) \bigtriangledown f(\theta_{t}) ▽f(θt):在 t t t时刻的梯度
计算与更新过程如图所示
1. SGD
SGD与GD不同的地方就在于SGD使用的是mini batch
,如下图所示,SGD一共分为如下几步
- 计算 θ \theta θ处的梯度:首先我们在位置 θ 0 \theta^{0} θ0处,计算 θ 0 \theta^{0} θ0处的梯度 ▽ L ( θ 0 ) \bigtriangledown L(\theta^{0}) ▽L(θ0),注意红色的箭头代表梯度的方法,我们的目的是减小 L L L,而梯度的方向是函数增加的方向,所以下一步更新 θ \theta θ时需要加负号
- 更新 θ \theta θ:更新 θ \theta θ到 θ 1 = θ 0 − η ▽ L ( θ 0 ) \theta^{1} = \theta^{0}-\eta \bigtriangledown L(\theta^{0}) θ1=θ0−η▽L(θ0)
- 计算在 θ 1 \theta^{1} θ1处的梯度并重复上述过程,直到 ▽ L ( θ t ) = 0 \bigtriangledown L(\theta^{t}) = 0 ▽L(θt)=0
2. SGDM
SGDM是上述SGD的改进加入了动量,假设在SGD的优化过程中梯度 ▽ L ( θ t ) = 0 \bigtriangledown L(\theta^{t}) = 0 ▽L(θt)=0,此时参数 θ \theta θ的值不会继续改变,如下图所示,但是当我们加入momentum以后,即使梯度为0,动量也会告诉参数要继续变化
那究竟什么是动量呢,这个动量和物理上的动量相似,想象一个场景我们在滑滑梯,当我们在滑梯上准备下滑时,滑梯是有一个斜度,我们在上面就有一个沿着滑梯下滑的力(也就是梯度),我们开始下滑,当我们到滑梯中间的某一处时,由于有梯度+在上一秒我们的初速度
,我们不会停下,即使我们到了滑梯底部滑梯变平了我们失去了向前的力(梯度),我们依然具有之前积累的速度,所以我们会继续向前运动,SGDM就是应用了这个道理
接下来看一下SGDM的具体执行过程
第一次更新------------------>
- 计算 θ 0 \theta^{0} θ0处的梯度: ▽ L ( θ 0 ) \bigtriangledown L(\theta^{0}) ▽L(θ0),这一步和上面的SGD一样。但是需要注意我们这里还有一个参数 v 0 v^{0} v0,这个参数就是我们的动量,记录上一步梯度的反方向,也就是上一步移动的方向,由于参数是第一次变化,没有之前的记录,所以一开始 v 0 = 0 v^{0}=0 v0=0
- 计算需要移动的距离: v 1 = λ v 0 − η ▽ L ( θ 0 ) = − η ▽ L ( θ 0 ) v^{1}=\lambda v^{0} \pmb{- \eta \bigtriangledown L(\theta^{0})} = \pmb{-\eta \bigtriangledown L(\theta^{0})} v1=λv0−η▽L(θ0)−η▽L(θ0)−η▽L(θ0)=−η▽L(θ0)−η▽L(θ0)−η▽L(θ0)
- 更新 θ 0 \theta^{0} θ0: θ 1 = θ 0 + v 1 \theta^{1} = \theta^{0} + v^{1} θ1=θ0+v1
第二次更新------------------>
- 计算 θ 1 \theta^{1} θ1处的梯度: ▽ L ( θ 1 ) \bigtriangledown L(\theta^{1}) ▽L(θ1)
- 计算需要移动的距离: v 2 = λ v 1 − η ▽ L ( θ 1 ) v^{2}=\lambda v^{1}\pmb{ - \eta \bigtriangledown L(\theta^{1})} v2=λv1−η▽L(θ1)−η▽L(θ1)−η▽L(θ1)
- 更新 θ 1 \theta^{1} θ1: θ 2 = θ 1 + v 2 = θ 1 + λ [ λ v 0 − η ▽ L ( θ 0 ) ] − η ▽ L ( θ 1 ) \theta^{2} = \theta^{1}+v^{2} = \theta^{1}+ \lambda [\lambda v^{0}-\eta \bigtriangledown L(\theta^{0})] \pmb{ - \eta \bigtriangledown L(\theta^{1})} θ2=θ1+v2=θ1+λ[λv0−η▽L(θ0)]−η▽L(θ1)−η▽L(θ1)−η▽L(θ1)
重复上述过程---------------->
通过上述计算可以发现,每次移动的距离不仅取决于所在点的梯度,还取决于上一步的移动,而上一步的移动与之前所有计算过的梯度都有关
- v 0 = 0 v^{0} = 0 v0=0
- v 1 = − η ▽ L ( θ 0 ) v^{1} = -\eta \bigtriangledown L(\theta^{0}) v1=−η▽L(θ0)
- v 2 = − λ η ▽ L ( θ 0 ) − η ▽ L ( θ 1 ) v^{2} = -\lambda \eta \bigtriangledown L(\theta^{0}) -\eta \bigtriangledown L(\theta^{1}) v2=−λη▽L(θ0)−η▽L(θ1)
- …
- v t + 1 = λ v t − η ▽ L ( θ t ) v^{t+1} = \lambda v^{t} -\eta \bigtriangledown L(\theta^{t}) vt+1=λvt−η▽L(θt)
3. Adagrad
与SGD不同的地方是,Adagrad在学习率上作了文章,如下公式所示
θ t + 1 = θ t − η ∑ i = 0 t ( ▽ L ( θ i ) ) 2 ▽ L ( θ t ) \theta_{t+1} = \theta_{t} - \frac{\eta}{\sqrt{\sum_{i=0}^{t}(\bigtriangledown L(\theta_{i}))^2}} \bigtriangledown L(\theta_{t}) θt+1=θt−∑i=0t(▽L(θi))2η▽L(θt)
这样做的意义是什么呢?有两点
- 假设一开始梯度较大:此时学习率的分母会变大,整体的学习率减小,这样梯度下降的速度就会变慢,这是为了避免错过最低点。相当于下滑梯时如果滑梯很陡,那就慢慢滑,避免滑到最下面的时候速度过快停不下来(错过最低点)
- 假设一开始梯度较小:此时学习率的分母会变小,整体的学习率减大,这样梯度下降的速度就会变快,这是为了快速进行梯度下降。相当于下滑梯时如果滑梯很缓,那就快速滑,以尽快达到最低点,而且当剃度下降到最低点时已经进行了很多次优化,分母经过累加已经变大,学习率也会降低,剃度下降也比较平缓,不会错过最低点
4. RMSProp
上述Adagrad有一个缺点,当一开始梯度较大时学习率会变得很小,我们希望在最优解的地方梯度下降变慢,但现在我们适得其反,在一开始的时候参数更新的就非常慢,而且学习率的分母是累加的梯度,导致学习率会越来越低,为了改变这个缺点,出现了RMSProp
θ t + 1 = θ t − η v t + 1 ▽ L ( θ t ) v 1 = ▽ L ( θ 0 ) 2 v t + 1 = α v t + ( 1 − α ) ( ▽ L ( θ t ) ) 2 \begin{aligned} \theta_{t+1} &= \theta_{t} - \frac{\eta}{\sqrt{v_{t+1}}} \bigtriangledown L(\theta_{t}) \\ v_{1} & = \bigtriangledown L(\theta_{0})^2 \\ v_{t+1} & = \alpha v_{t} + (1-\alpha)(\bigtriangledown L(\theta_{t}))^{2} \\ \end{aligned} θt+1v1vt+1=θt−vt+1η▽L(θt)=▽L(θ0)2=αvt+(1−α)(▽L(θt))2
虽然 v t v_{t} vt与之前的梯度也有关,但是 α \alpha α的存在使得分母不会像Adagrad那样累加,让我们看一下 v v v的变化情况
- v 1 = ▽ L ( θ 0 ) 2 v_{1} = \bigtriangledown L(\theta_{0})^2 v1=▽L(θ0)2
- v 2 = α ▽ L ( θ 0 ) 2 + ( 1 − α ) ▽ L ( θ 1 ) 2 v_{2} = \alpha \bigtriangledown L(\theta_{0})^2+ (1-\alpha) \bigtriangledown L(\theta_{1})^2 v2=α▽L(θ0)2+(1−α)▽L(θ1)2
- v 3 = α [ α ▽ L ( θ 0 ) 2 + ( 1 − α ) ▽ L ( θ 1 ) 2 ] + ( 1 − α ) ▽ L ( θ 2 ) 2 v_{3} = \alpha [\alpha \bigtriangledown L(\theta_{0})^2+ (1-\alpha) \bigtriangledown L(\theta_{1})^2]+ (1-\alpha) \bigtriangledown L(\theta_{2})^2 v3=α[α▽L(θ0)2+(1−α)▽L(θ1)2]+(1−α)▽L(θ2)2
- …
- v t + 1 = α v t 2 + ( 1 − α ) ▽ L ( θ t ) 2 v_{t+1} = \alpha v_{t}^2+ (1-\alpha) \bigtriangledown L(\theta_{t})^2 vt+1=αvt2+(1−α)▽L(θt)2
5. Adam
到这里我们梳理一下,我们现在讲了GD,SGD,SGDM,Adagrad以及RMSProp
- 其中SGD是GD的改进,SGDM是SGD的改进,所以前三个算法中最优的是SGDM
- RMSProp是Adagrad的改进,所以后两个算法最优的是RMSProp
θ t + 1 = θ t − η m t + 1 S G D M : m t + 1 = β 1 m t + ( 1 − β 1 ) ▽ L ( θ t ) 2 \begin{aligned} \theta_{t+1} &= \theta_{t} - \eta m_{t+1} \\ SGDM:~~~~~ m_{t+1} & = \beta_{1}m_{t} + (1-\beta_{1}) \bigtriangledown L(\theta_{t})^2 \end{aligned} θt+1SGDM: mt+1=θt−ηmt+1=β1mt+(1−β1)▽L(θt)2
θ t + 1 = θ t − η v t + 1 ▽ L ( θ t ) R M S P r o p : v 1 = ▽ L ( θ 0 ) 2 v t + 1 = α v t + ( 1 − α ) ( ▽ L ( θ t ) ) 2 \begin{aligned} \theta_{t+1} &= \theta_{t} - \frac{\eta}{\sqrt{v_{t+1}}} \bigtriangledown L(\theta_{t}) \\ RMSProp:~~~~~ v_{1} & = \bigtriangledown L(\theta_{0})^2 \\ v_{t+1} & = \alpha v_{t} + (1-\alpha)(\bigtriangledown L(\theta_{t}))^{2} \\ \end{aligned} θt+1RMSProp: v1vt+1=θt−vt+1η▽L(θt)=▽L(θ0)2=αvt+(1−α)(▽L(θt))2
SGDM是对加入了动量,是对梯度进行了变化;RMSProp是对学习率进行了改进,而Adam结合了两者的优点,可以理解为:Adam = SGDM+RMSProp
θ t + 1 = θ t − η v t ^ + ϵ m t ^ m t ^ = m t 1 − β 1 t v t ^ = v t 1 − β 2 t β 1 = 0.9 β 2 = 0.999 ϵ = 1 0 − 8 \begin{aligned} \theta_{t+1} &= \theta_{t} - \frac{\eta}{\sqrt{\hat{v_{t}}}+\epsilon} \hat{m_{t}} \\ \hat{m_{t}} &= \frac{m_{t}}{1-\beta_{1}^{t}} \\ \hat{v_{t}} &= \frac{v_{t}}{1-\beta_{2}^{t}} \\ \beta_{1} = 0.9 ~~ &\beta_{2} = 0.999 ~~ \epsilon = 10^{-8} \end{aligned} θt+1mt^vt^β1=0.9 =θt−vt^+ϵηmt^=1−β1tmt=1−β2tvtβ2=0.999 ϵ=10−8