各种优化器SGD,AdaGrad,Adam,LBFGS都做了什么?
文章目录各种优化器SGD,AdaGrad,Adam,LBFGS都做了什么?1. SGD:2. SGD+Momentum:3. NAG(Nesterov Accelerated Gradient ):4. AdaGrad(Adaptive Gradient Algorithm):5. AdaDelta:6. RMSProp:7. Adam:8. [AdaMax](https://arxiv.org/
各种优化器SGD,AdaGrad,Adam,LBFGS都做了什么?
优化的目标是希望找到一组模型参数,使模型在所有训练数据上的平均损失最小。
1. SGD:
用单个训练样本的损失来近似平均损失,即每次随机采样一个样本来估计当前梯度,对模型参数进行一次更新。
θ
t
+
1
=
θ
t
−
η
∇
L
(
θ
t
;
x
i
,
y
i
)
=
g
t
θ
t
+
1
=
θ
t
−
η
g
t
\theta_{t+1}=\theta_t-\eta\nabla L(\theta_t;x_i,y_i)\\ \overset{\underset{g_t}{}}{=}\\ \theta_{t+1}=\theta_t-\eta g_t
θt+1=θt−η∇L(θt;xi,yi)=gtθt+1=θt−ηgt
优点:训练速度快,内存开销小。
缺点:SGD每步接受的信息有限,对梯度的估计准确性低,造成目标函数的收敛不稳定伴有震荡甚至出现不收敛。随机性大,并不保证全局最优化。
2. SGD+Momentum:
动量方法考虑了带衰减系数的前一步伐,可以加速SGD,抑制震荡。
m
t
=
β
1
m
t
−
1
+
η
∇
L
(
θ
t
)
θ
t
+
1
=
θ
t
−
m
t
m_{t}=\beta_1 m_{t-1}+\eta\nabla L(\theta_t)\\ \theta_{t+1}=\theta_t-m_t
mt=β1mt−1+η∇L(θt)θt+1=θt−mt
优点:比SGD收敛更快,目标函数的收敛更稳定,减少在鞍点等的震荡。
缺点:保持惯性,缺乏适应性。梯度方向不变的维度上速度变快,梯度方向有所改变的维度上的更新速度变慢 。
3. NAG(Nesterov Accelerated Gradient ):
在SGD+Momentum上增加“提前量”设计,在计算梯度时做了调整,用
θ
t
−
β
1
m
t
−
1
\theta_t-\beta_1 m_{t-1}
θt−β1mt−1来近似当作参数下一步会变成的值,计算未来可能位置处的梯度而非当前位置的梯度。
m
t
=
β
1
m
t
−
1
+
η
∇
L
(
θ
t
−
β
1
m
t
−
1
)
θ
t
+
1
=
θ
t
−
m
t
m_{t}=\beta_1 m_{t-1}+\eta\nabla L(\theta_t-\beta_1 m_{t-1})\\ \theta_{t+1}=\theta_t-m_t
mt=β1mt−1+η∇L(θt−β1mt−1)θt+1=θt−mt
优点:改进Momentum方法,防止按照惯性走的太快,会衡量一下梯度做出修正。
4. AdaGrad(Adaptive Gradient Algorithm):
自适应地确定参数的学习速度,对更新频率低的参数做较大的更新,对更新频率高的参数做较小的更新。采用“历史梯度平方和”来衡量不同参数的梯度的稀疏性,取值越小表明越稀疏。
θ
t
+
1
,
i
=
θ
t
,
i
−
η
∑
k
=
0
t
g
k
,
i
2
+
ϵ
g
t
,
i
\theta_{t+1,i}=\theta_{t,i}-\frac{\eta}{\sqrt{\sum_{k=0}^{t}g_{k,i}^2}+\epsilon}g_{t,i}
θt+1,i=θt,i−∑k=0tgk,i2+ϵηgt,i
优点:减少学习率的手动调整,更适用于稀疏数据,提高SGD的鲁棒性。
缺点:分母会不断累积,学习率衰减越来越快。
5. AdaDelta:
针对AdaGrad改进:因为AdaGrad采用所有历史梯度平方和的平方根做分母,分母随时间单调递增,产生的自适应学习速率随时间衰减的速度过于激进 。AdaDelta 采用指数衰减平均的计算方法,用过去梯度平方的衰减平均值代替他们的求和。 这个分母相当于梯度的均方根 root mean squared (RMS),在数据统计分析中,将所有值平方求和,求其均值,再开平方,就得到均方根值。
θ
t
+
1
=
θ
t
−
R
M
S
[
Δ
θ
]
t
−
1
R
M
S
[
g
]
t
g
t
E
[
g
2
]
t
=
γ
E
[
g
2
]
t
−
1
+
(
1
−
γ
)
g
t
2
E
[
Δ
θ
2
]
t
=
γ
E
[
Δ
θ
2
]
t
−
1
+
(
1
−
γ
)
Δ
θ
t
2
\theta_{t+1}=\theta_t-\frac{RMS[\Delta\theta]_{t-1}}{RMS[g]_t}g_t\quad \\ E[g^2]_t=\gamma E[g^2]_{t-1}+(1-\gamma)g_t^2\\ E[\Delta \theta^2]_t=\gamma E[\Delta \theta^2]_{t-1}+(1-\gamma)\Delta \theta_t^2
θt+1=θt−RMS[g]tRMS[Δθ]t−1gtE[g2]t=γE[g2]t−1+(1−γ)gt2E[Δθ2]t=γE[Δθ2]t−1+(1−γ)Δθt2
优点:不需要提取设定学习速率,使用指数衰减平均计算,防止学习速率衰减过快。
6. RMSProp:
是 Geoff Hinton 提出的一种自适应学习率方法。结合了Momentum的惯性原则,加上AdaGrad对错误方向的阻力。但是缺少了Momentum的一部分,因此后面Adam补上这个想法。
RMSprop 和 AdaDelta 都是为了解决 AdaGrad 学习率急剧下降问题的。
v
t
=
β
1
v
t
−
1
+
(
1
−
β
1
)
g
t
2
θ
t
+
1
=
θ
t
−
η
v
t
+
ϵ
g
t
v_t = \beta_1 v_{t-1}+(1-\beta_1)g_t^2\\ \theta_{t+1}=\theta_t-\frac{\eta}{\sqrt{v_t+\epsilon}}g_t\\
vt=β1vt−1+(1−β1)gt2θt+1=θt−vt+ϵηgt
优点:解决 AdaGrad 学习率急剧下降。
7. Adam:
结合Momentum和AdaGrad的优点,即考虑过去梯度的平方的指数衰减平均值,也保持过去梯度的指数衰减平均值。还包含了偏置修正,修正从0初始化的一阶矩和二阶矩的估计。
m
t
=
β
1
m
t
−
1
+
(
1
−
β
1
)
g
t
v
t
=
β
2
v
t
−
1
+
(
1
−
β
2
)
g
t
2
m
t
^
=
m
t
1
−
β
1
t
v
t
^
=
v
t
1
−
β
2
t
θ
t
+
1
=
θ
t
−
η
v
t
^
+
ϵ
m
t
^
m_t=\beta_1m_{t-1}+(1-\beta_1)g_t\\ v_t=\beta_2v_{t-1}+(1-\beta_2)g_t^2\\ \hat{m_t}=\frac{m_t}{1-\beta_1^t}\quad \hat{v_t}=\frac{v_t}{1-\beta_2^t}\\ \theta_{t+1}=\theta_t-\frac{\eta}{\sqrt{\hat{v_t}+\epsilon}}\hat{m_t}
mt=β1mt−1+(1−β1)gtvt=β2vt−1+(1−β2)gt2mt^=1−β1tmtvt^=1−β2tvtθt+1=θt−vt^+ϵηmt^
优点:为不同参数产生自适应的学习速率。
8. AdaMax:
Adamax优化器来自于Adam的论文的Section7,该方法是基于无穷范数的Adam方法的变体,对梯度平方的处理由指数衰减平均改为指数衰减求最大值。在Adam中,单个权重的更新规则是将其梯度与当前和过去梯度的
L
2
L^2
L2范数(标量)成反比例缩放。作者又将基于
L
2
L^2
L2范数的更新规则泛化到基于
L
p
L^p
Lp范数的更新规则中。
v
t
=
β
2
p
v
t
−
1
+
(
1
−
β
2
p
)
∣
g
t
∣
p
=
(
1
−
β
2
p
)
∑
i
t
β
2
p
(
t
−
i
)
⋅
∣
g
i
∣
p
\begin{aligned} v_t&=\beta_2^p v_{t-1}+(1-\beta_2^p)|g_t|^p\\ &=(1-\beta_2^p)\sum_{i}^{t} \beta_2^{p(t-i)}\cdot|g_i|^p \end{aligned}
vt=β2pvt−1+(1−β2p)∣gt∣p=(1−β2p)i∑tβ2p(t−i)⋅∣gi∣p
虽然这样的变体会因为
p
p
p的值较大而在数值上变得不稳定,但是在特例中,令
p
→
∞
p\rightarrow\infty
p→∞会得出一个极其稳定和简单的算法。
u
t
=
lim
p
→
∞
(
v
t
)
1
/
p
=
max
(
β
2
⋅
u
t
−
1
,
∣
g
t
∣
)
\begin{aligned} u_t&=\lim_{p\rightarrow\infty}(v_t)^{1/p}\\ &=\max(\beta_2\cdot u_{t-1},|g_t|) \end{aligned}
ut=p→∞lim(vt)1/p=max(β2⋅ut−1,∣gt∣)
由于
u
t
u_t
ut依赖于max操作,所以AdaMax不像在Adam中
m
t
m_t
mt和
v
t
v_t
vt的偏差趋向于0,所以不需要计算
u
t
u_t
ut的偏差校正(
u
0
=
0
u_0=0
u0=0)。
m
t
=
β
1
m
t
−
1
+
(
1
−
β
1
)
g
t
u
t
=
max
(
β
2
u
t
−
1
,
∣
g
t
∣
)
θ
t
+
1
=
θ
t
−
η
u
t
m
t
m_t=\beta_1m_{t-1}+(1-\beta_1)g_t\\ u_t=\max(\beta_2u_{t-1},|g_t|)\\ \theta_{t+1}=\theta_t-\frac{\eta }{u_t}m_t
mt=β1mt−1+(1−β1)gtut=max(β2ut−1,∣gt∣)θt+1=θt−utηmt
9. AdamW:
在Ilya Loshchilov & Frank Hutter 的论文Decoupled weight decay regularization中,把Adam中的权重衰减和基于损失的梯度更新解耦(AdamW)。发现在Adam这种自适应学习率算法中L2正则化不像在SGD中有效:
- L2正则化和Weight Decay并不等价,只有在标准的SGD下可以把两者等价。特别当与自适应梯度相结合时,L2正则化导致具有较大历史参数或梯度幅度的权重比使用权重衰减时更小。
- 使用Adam优化带L2正则的损失并不有效。如果引入L2正则化项,在计算梯度的时候会加上正则项求梯度的结果。正常的权重衰减是对所有的权重都采用相同的系数进行更新,本身比较大的一些权重对应的梯度也会比较大,惩罚也越大。但由于Adam计算步骤中减去项会有除以梯度平方的累积,使得梯度大的减去项偏小,从而具有大梯度的权重不会像解耦权重衰减那样得到正则化。 这导致自适应梯度算法的L2和解耦权重衰减正则化的不等价。
而在常见的深度学习库中只提供了L2正则,并没有提供权重衰减的实现。这可能就是导致Adam跑出来的很多效果相对SGD with Momentum有偏差的一个原因。大部分的模型都会有L2 regularization约束项,因此很有可能出现Adam的最终效果没有SGD的好。目前bert训练采用的优化方法就是AdamW,对除了layernorm,bias项之外的模型参数做weight decay。
Adam的weight decay发生在紫字部分,所以由于 g 2 g^2 g2作分母,会使得大的梯度得不到足够力度的正则化;而AdamW把weight decay放在了绿字部分,所以能有效的正则化。
10. SGDW:
和AdamW类似,是SGD+momentum使用解耦的weight decay(SGDW)。原始的SGD+momentum权重衰减发生在梯度的L2正则化,而SGDW是在更新参数 θ t \theta_t θt时使用解耦权重衰减。
11. AMSGrad:
偏置修正只是对训练的开始有用,先不考虑偏置修正。Adam中
η
v
t
+
ϵ
\frac{\eta}{\sqrt{{v_t}+\epsilon}}
vt+ϵη朝着平均梯度方向前进的步幅,随着训练会逐渐减少。由于学习率是恒定或递减的,作者提出的解决方法是通过添加另一个变量来跟踪梯度平方的指数衰减平均
v
t
v_t
vt的最大值,从而迫使
v
t
v_t
vt增加。
m
t
=
β
1
m
t
−
1
+
(
1
−
β
1
)
g
t
v
t
=
β
2
v
t
−
1
+
(
1
−
β
2
)
g
t
2
v
t
^
=
max
(
v
t
,
v
^
t
−
1
)
θ
t
+
1
=
θ
t
−
η
v
t
^
+
ϵ
m
t
m_t=\beta_1m_{t-1}+(1-\beta_1)g_t\\ v_t=\beta_2v_{t-1}+(1-\beta_2)g_t^2\\ \hat{v_t}=\max (v_t,\hat{v}_{t-1})\\ \theta_{t+1}=\theta_t-\frac{\eta}{\sqrt{\hat{v_t}+\epsilon}}m_t
mt=β1mt−1+(1−β1)gtvt=β2vt−1+(1−β2)gt2vt^=max(vt,v^t−1)θt+1=θt−vt^+ϵηmt
12. LBFGS:
经典的优化问题中迭代法的一阶法(梯度下降法),前面SGD、Adam等都是在一阶法的基础上进行改进,加快收敛速率。二阶法(牛顿法)的收敛速度是远快于一阶法的,但是Hessian矩阵求逆的计算复杂度很大,对于目标函数非凸时,二阶法有可能会收敛到鞍点。针对二阶法的这个问题,提出了BFGS算法,再是低存储的L-BFGS算法。简答说L-BFGS和梯度下降、SGD干的同样的事情。
牛顿法求根 f ( x ) = 0 f(x)=0 f(x)=0的思路:
- 已知 f ( x ) f(x) f(x)下,随机产生点 x 0 x_0 x0.
- 由已知的 x 0 x_0 x0按照 x k = x k − 1 − f ( x k − 1 ) f ′ ( x k − 1 ) x_k=x_{k-1}-\frac{f(x_{k-1})}{f'(x_{k-1})} xk=xk−1−f′(xk−1)f(xk−1)进行 k k k次迭代。
- 如果 x k x_k xk与上一次的迭代结果 x k − 1 x_{k-1} xk−1相同或相差小于阈值,那么 x k x_k xk就是函数 f ( x ) f(x) f(x)的根。
对于机器学习中的最优化问题,大部分要优化的是目标函数的导函数,即求导函数为0的点(驻点)。用牛顿法求导函数为0,转换迭代公式为: x k = x k − 1 − f ‘ ( x k − 1 ) f ′ ’ ( x k − 1 ) x_k=x_{k-1}-\frac{f‘(x_{k-1})}{f'’(x_{k-1})} xk=xk−1−f′’(xk−1)f‘(xk−1)。牛顿法求驻点本质是目标函数 f ( x ) f(x) f(x)的二阶泰勒展开: f ( x ) ≈ f ( x k ) + f ′ ( x k ) ( x − x k ) + 1 2 f ′ ′ ( x k ) ( x − x k ) 2 f(x)\approx f(x_k)+f'(x_k)(x-x_k)+\frac{1}{2}f''(x_k)(x-x_k)^2 f(x)≈f(xk)+f′(xk)(x−xk)+21f′′(xk)(x−xk)2。对目标函数求导即对近似式求导即 f ′ ( x k ) + f ′ ′ ( x k ) ( x − x k ) = 0 f'(x_k)+f''(x_k)(x-x_k)=0 f′(xk)+f′′(xk)(x−xk)=0,变换后就是上面的迭代公式。
机器学习中优化的目标函数是多元的,
x
,
f
′
(
x
)
x,f'(x)
x,f′(x)都是向量,
f
′
′
(
x
)
f''(x)
f′′(x)是Hessian矩阵,迭代公式变为下式,
g
k
g_k
gk就是
f
′
(
x
k
)
f'(x_k)
f′(xk),
H
k
−
1
H^{-1}_k
Hk−1是二阶导数的倒数:
x
k
+
1
=
x
k
−
H
k
−
1
⋅
g
k
,
k
=
0
,
1
,
…
x_{k+1}=x_k-H^{-1}_k\cdot g_k, \; k=0,1,\dots
xk+1=xk−Hk−1⋅gk,k=0,1,…
直接求
H
k
−
1
H^{-1}_k
Hk−1很困难,因此提出BFGS算法:通过迭代法来逼近
H
k
−
1
H^{-1}_k
Hk−1的算法。
D
k
+
1
=
(
I
−
s
k
y
k
T
y
k
T
s
k
)
D
k
(
I
−
y
k
s
k
T
y
k
T
s
k
)
+
s
k
s
k
T
y
k
T
s
k
D_{k+1}=(I-\frac{s_k y_k^T}{y_k^T s_k})D_k(I-\frac{y_k s_k^T}{y_k^T s_k})+\frac{s_k s_k^T}{y_k^T s_k}
Dk+1=(I−ykTskskykT)Dk(I−ykTskykskT)+ykTskskskT
其中
D
k
=
H
k
−
1
,
s
k
=
x
k
+
1
−
x
k
,
y
k
=
g
k
+
1
−
g
k
D_k=H_k^{-1},s_k=x_{k+1}-x_k,y_k=g_{k+1}-g_k
Dk=Hk−1,sk=xk+1−xk,yk=gk+1−gk。
D k D_k Dk的迭代公式也很复杂,利用单位矩阵( D 0 = I D_0=I D0=I)逐步逼近 H H H矩阵,每次计算要存储 D D D矩阵。如果数据集维度很大,迭代所需要的存储巨大。
因为无法保存巨大的 D D D矩阵,提出了L-BFGS算法:
时间换空间的方法:每次计算 D D D矩阵要迭代计算 s k s_k sk和 y k y_k yk,那存储所有的 s k s_k sk和 y k y_k yk就可以。如果要得到 D 10 D_{10} D10,用单位矩阵与存储的 s 1 , … , s 10 , y 1 , … , y 10 s_1,\dots,s_{10},y_1,\dots,y_{10} s1,…,s10,y1,…,y10计算即可。如果数据集是10000维,存储大小为 10000 × 10000 10000\times 10000 10000×10000的 D k D_k Dk,变成存储10个大小为 1 × 10000 1\times 10000 1×10000的向量 s k s_k sk和 y k y_k yk,有效节省了内容空间。
如果迭代次数很大,内存同样会不足。设定最大的存储向量数 N N N,如果 s k s_k sk和 y k y_k yk迭代超过 N N N,就丢弃第一组 s 1 , y 1 s_1,y_1 s1,y1,存储 s 2 , … , s N + 1 , y 2 , … , y N + 1 s_2,\dots, s_{N+1}, y_2,\dots, y_{N+1} s2,…,sN+1,y2,…,yN+1,每次丢弃最前边的 s k s_k sk和 y k y_k yk。虽然损失了精度,但可以保证使用有限的内存将函数的解通过BFGS算法求得到。
L-BFGS算法,可以看做是对BFGS算法的又一次近似。
优点:收敛速度快、内存开销少。
Reference
欢迎各位关注我的个人公众号:HsuDan,我将分享更多自己的学习心得、避坑总结、面试经验、AI最新技术资讯。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)