Gradient Descent
梯度下降算法是通过沿着目标函数 J(θ) 的梯度(一阶导数)相反方向来不断更新模型参数来到达目标函数的极小值点(收敛),学习率为η。当目标函数具有多个参数,则使用相应的偏导
若
目
标
函
数
为
J
(
Θ
)
且
Θ
=
(
θ
1
,
θ
2
,
.
.
.
,
θ
i
)
,
则
第
j
个
参
数
的
梯
度
为
∂
J
(
Θ
)
∂
θ
j
若目标函数为 J(\Theta)且\Theta = (\theta_1, \theta_2, ..., \theta_i),则第j个参数的梯度为\ \frac{\partial J(\Theta)}{\partial \theta_j}
若目标函数为J(Θ)且Θ=(θ1,θ2,...,θi),则第j个参数的梯度为 ∂θj∂J(Θ)
在 pytorch 中可使用以下代码选择梯度下降算法
import torch
# TODO
# 其中,model 为前面的网络模型实例,Adam 为梯度下降算法,可以替换为其他方法
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
# ----------------------------------------------------------------------
optimizer.zero_grad() # 清空之前的梯度,避免累加梯度
optimizer.step() # 更新参数
批量梯度下降(BGD)
每次使用全部的训练样本来更新参数,当训练集过大时,该算法会变得十分缓慢。其优点在于每次更新都会朝着正确的方向进行,最后能够保证收敛于极值点(凸函数收敛于全局极值点,非凸函数可能会收敛于局部极值点),但是其缺点在于每次学习时间过长,不能进行在线模型参数更新,如果训练集很大则需要消耗大量的内存。其参数更新如下
θ
=
θ
−
η
⋅
∇
θ
J
(
θ
)
\theta = \theta - \eta\cdot \nabla_\theta J(\theta)
θ=θ−η⋅∇θJ(θ)
随机梯度下降(SGD)
每次从训练集中随机选取一个样本来更新参数,其训练速度较快,且能较快到达“最优点”附近,如果不设置迭代次数,SGD会不停游走于该点附近。SGD 最大的缺点在于每次更新可能并不会按照正确的方向进行,因此可以带来优化波动。不过从另一个方面来看,对于类似盆地区域这个波动可能会使优化的方向从当前的局部极小值点跳到另一个更好的局部极小值点,从而可能使非凸函数收敛于一个较好的局部极值点,甚至全局极值点。其参数更新如下
θ
=
θ
−
η
⋅
∇
θ
J
(
θ
;
x
i
;
y
i
)
\theta = \theta - \eta\cdot \nabla_\theta J(\theta;x_i;y_i)
θ=θ−η⋅∇θJ(θ;xi;yi)
小批量梯度下降(MBGD)
MBGD 综合了 BGD 与 SGD 的优点,在每次更新速度与更新次数中间取得一个平衡,其每次更新从训练集中随机选择 m 个样本进行学习,从而更新参数。对于 SGD,MBGD 降低了收敛波动性,即降低了参数更新的方差,使得更新更加稳定;相对于 BGD,其提高了每次学习的速度。其参数更新如下
θ
=
θ
−
η
⋅
∇
θ
J
(
θ
;
x
i
:
i
+
m
;
y
i
:
i
+
m
)
\theta = \theta - \eta\cdot\nabla_\theta J(\theta;x_{i:i+m};y_{i:i+m})
θ=θ−η⋅∇θJ(θ;xi:i+m;yi:i+m)
小结
- 上面三种梯度下降算法均存在一个超参数 η,而选择一个合理的学习速率很难。如果学习速率过小,则会导致收敛速度很慢;如果学习速率过大,可能会难以收敛,导致训练失败
- 学习率在训练过程中适当调整可能会更好。一开始选择较大的学习率,加快收敛速度;后期调整为一个较小的学习率,使提高收敛精度
- 对于非凸目标函数,容易陷入 critical points 中
Momentum
SGD 方法中的高方差振荡使得网络很难稳定收敛,所以有研究者提出了一种称为动量(Momentum)的技术,通过优化相关方向的训练和弱化无关方向的振荡。算法主要思想为计算梯度的指数加权平均,然后使用这个梯度来更新权重
v
t
=
γ
v
t
−
1
+
η
∇
θ
J
(
θ
)
θ
=
θ
−
v
t
o
r
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
−
o
r
v
t
=
β
v
t
−
1
+
(
1
−
β
)
∇
θ
J
(
θ
)
θ
=
θ
−
α
v
t
v_t = \gamma v_{t-1}+\eta\nabla_\theta J(\theta)\\ \theta = \theta - v_t\\ or--------------------------------or\\ v_t = \beta v_{t-1}+(1-\beta)\nabla_\theta J(\theta)\\ \theta = \theta - \alpha v_t\\
vt=γvt−1+η∇θJ(θ)θ=θ−vtor−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−orvt=βvt−1+(1−β)∇θJ(θ)θ=θ−αvt
注:其中动量项超参数 γ 、 β \gamma、\beta γ、β,一般等于 0.9
NAG
NAG不仅增加了动量项,并且在计算参数的梯度时,在损失函数中减去了动量项,这种方式预估了下一次参数所在的位置,每次学习过程中能够根据损失函数的斜率做到自适应更新来加速 SGD 的收敛
v
t
=
γ
v
t
−
1
+
η
⋅
∇
θ
J
(
θ
−
γ
v
t
−
1
)
θ
=
θ
−
v
t
\begin{aligned} &v_t = \gamma v_{t-1} + \eta\cdot\nabla_\theta J(\theta - \gamma v_{t-1})\\ &\theta = \theta - v_t \end{aligned}
vt=γvt−1+η⋅∇θJ(θ−γvt−1)θ=θ−vt
Adagrad
Adagrad 能够对每个参数自适应不同的学习速率,对稀疏特征,得到大的学习更新,对非稀疏特征,得到较小的学习更新,因此该优化算法适合处理稀疏特征数据。在前述中,每个模型参数使用相同的学习速率,而 Adagrad 在每一个更新步骤中对于每一个模型参数使用不同的学习速率
设
第
t
次
更
新
步
骤
中
,
目
标
函
数
的
参
数
θ
i
梯
度
为
g
t
,
i
,
即
:
g
t
,
i
=
∇
θ
J
(
θ
i
)
那
么
S
G
D
更
新
方
程
为
:
θ
t
+
1
,
i
=
θ
t
,
i
−
η
⋅
g
t
,
i
而
A
d
a
g
r
a
d
对
每
一
个
参
数
使
用
不
同
的
学
习
速
率
,
其
更
新
方
程
为
:
θ
t
+
1
,
i
=
θ
t
,
i
−
η
G
t
,
i
i
+
ϵ
其
中
,
G
t
∈
R
d
×
d
是
一
个
对
角
矩
阵
,
其
中
第
i
行
的
对
角
元
素
e
i
i
为
过
去
到
当
前
第
i
个
参
数
θ
i
的
梯
度
的
平
方
和
ϵ
是
一
个
平
滑
参
数
,
为
了
使
得
分
母
不
为
0
(
通
常
ϵ
=
1
e
−
8
)
,
另
外
如
果
分
母
不
开
根
号
,
算
法
性
可
能
会
很
糟
糕
。
进
一
步
,
将
所
有
G
t
,
i
i
,
g
t
,
i
的
元
素
写
成
向
量
G
t
,
g
t
,
这
样
便
可
以
使
用
向
量
点
乘
操
作
:
θ
t
+
1
=
θ
t
−
η
G
t
+
ϵ
⨀
g
t
o
r
θ
t
+
1
=
θ
t
−
η
∑
1
t
g
t
2
+
ϵ
⨀
g
t
\begin{aligned} &设第 t 次更新步骤中,目标函数的参数 \theta_i 梯度为 g_{t,i},即:g_{t, i} = \nabla_\theta J(\theta_i)\\ &那么 SGD 更新方程为:\theta_{t+1, i} = \theta_{t, i} - \eta\cdot g_{t, i}\\ &而 Adagrad 对每一个参数使用不同的学习速率,其更新方程为:\theta_{t+1, i} = \theta_{t, i} - \frac{\eta}{\sqrt{G_{t, ii} + \epsilon}}\\ &其中, G_t∈R^{d×d}是一个对角矩阵,其中第 i行的对角元素e_{ii}为过去到当前第i个参数θ_i的梯度的平方和\\ &\epsilon是一个平滑参数,为了使得分母不为0(通常 ϵ=1e−8),另外如果分母不开根号,算法性可能会很糟糕。\\ &进一步,将所有 G_{t,ii},g_{t,i} 的元素写成向量 G_t,g_t,这样便可以使用向量点乘操作:\\ &\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{G_t + \epsilon}}\bigodot g_t \quad or \quad \theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{\sum_1^tg_t^2 + \epsilon}}\bigodot g_t \end{aligned}
设第t次更新步骤中,目标函数的参数θi梯度为gt,i,即:gt,i=∇θJ(θi)那么SGD更新方程为:θt+1,i=θt,i−η⋅gt,i而Adagrad对每一个参数使用不同的学习速率,其更新方程为:θt+1,i=θt,i−Gt,ii+ϵη其中,Gt∈Rd×d是一个对角矩阵,其中第i行的对角元素eii为过去到当前第i个参数θi的梯度的平方和ϵ是一个平滑参数,为了使得分母不为0(通常ϵ=1e−8),另外如果分母不开根号,算法性可能会很糟糕。进一步,将所有Gt,ii,gt,i的元素写成向量Gt,gt,这样便可以使用向量点乘操作:θt+1=θt−Gt+ϵη⨀gtorθt+1=θt−∑1tgt2+ϵη⨀gt
注:Adagrad 主要优势在于它能够为每个参数自适应不同的学习速率,而一般的人工都是设定为 0.01。同时其缺点在于需要计算参数梯度序列平方和,随之时间地增加,分母项越来越大,最终导致学习率太小而无法进行有效更新
Adadelta
Adadelta 是 Adagrad 的一种扩展,为了降低 Adagrad 中学习速率衰减过快问题,其改进了三处:1、使用了窗口 w; 2、是对于参数梯度历史窗口序列(不包括当前)不再使用平方和,而是使用均值代替; 3、是最终的均值是历史窗口序列均值与当前梯度的时间衰减加权平均
记
R
M
S
[
g
]
t
=
∑
1
t
g
t
2
+
ϵ
t
,
表
示
梯
度
的
均
方
根
误
差
,
用
R
M
S
[
Δ
θ
]
t
−
1
代
替
学
习
率
η
则
得
到
A
d
a
d
e
l
t
a
更
新
规
则
:
Δ
θ
t
=
−
R
M
S
[
Δ
θ
]
t
−
1
R
M
S
[
g
]
t
g
t
θ
t
+
1
=
θ
t
+
Δ
θ
t
\begin{aligned} &记 RMS[g]_t = \sqrt{\frac{\sum_1^tg_t^2+\epsilon}{t}},表示梯度的均方根误差,用 RMS[\Deltaθ]_{t−1}代替学习率 \eta\\ &则得到 Adadelta 更新规则:\Delta\theta_t = -\frac{RMS[\Delta\theta]_{t-1}}{RMS[g]_t}g_t \qquad \theta_{t+1} = \theta_t+\Delta\theta_t \end{aligned}
记RMS[g]t=t∑1tgt2+ϵ,表示梯度的均方根误差,用RMS[Δθ]t−1代替学习率η则得到Adadelta更新规则:Δθt=−RMS[g]tRMS[Δθ]t−1gtθt+1=θt+Δθt
RMSprop
均方根传递(Root Mean Square prop), 其实 RMSprop 是 Adadelta 的中间形式,也是为了降低Adagrad中学习速率衰减过快问题,其参数更新如下
E
[
g
2
]
t
=
γ
E
[
g
2
]
t
−
1
+
(
1
−
γ
)
g
t
2
θ
t
+
1
=
θ
t
−
η
E
[
g
2
]
t
+
ϵ
⨀
g
t
\begin{aligned} &E[g^2]_t = \gamma E[g^2]_{t-1} + (1-\gamma)g_t^2\\ &\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{E[g^2]_t+\epsilon}}\bigodot g_t \end{aligned}
E[g2]t=γE[g2]t−1+(1−γ)gt2θt+1=θt−E[g2]t+ϵη⨀gt
Adam
Adaptive Moment Estimation(Adam) 也是一种不同参数自适应不同学习速率方法,与 Adadelta 与 RMSprop 区别在于,它计算历史梯度衰减方式不同,不使用历史平方衰减,其衰减方式类似动量,如下:
m
t
=
β
1
m
t
−
1
+
(
1
−
β
1
)
g
t
v
t
=
β
2
v
t
−
1
+
(
1
−
β
2
)
g
t
2
m
t
与
v
t
分
别
是
梯
度
的
带
权
平
均
和
带
权
有
偏
方
差
,
初
始
为
0
向
量
,
A
d
a
m
的
作
者
发
现
他
们
倾
向
于
0
向
量
,
特
别
是
在
衰
减
因
子
β
1
,
β
2
接
近
于
1
时
。
为
了
改
进
这
个
问
题
,
对
m
t
与
v
t
进
行
偏
差
修
正
(
b
i
a
s
−
c
o
r
r
e
c
t
e
d
)
:
m
t
^
=
m
t
1
−
β
1
t
v
t
^
=
v
t
1
−
β
2
t
最
终
,
A
d
a
m
的
更
新
方
程
为
:
θ
t
+
1
=
θ
t
−
η
v
t
^
+
ϵ
m
t
^
\begin{aligned} &m_t = \beta_1m_{t-1} + (1-\beta_1)g_t \qquad v_t = \beta_2v_{t-1} + (1 - \beta_2)g_t^2\\ &m_t与 v_t分别是梯度的带权平均和带权有偏方差,初始为0向量,Adam的作者发现他们倾向于 0 向量,特别是在衰减因子β_1, β_2接近于1时。\\ &为了改进这个问题,对 m_t与 v_t进行偏差修正(bias-corrected):\quad \hat{m_t} = \frac{m_t}{1-\beta_1^t}\quad \hat{v_t} = \frac{v_t}{1 - \beta_2^t}\\ &最终,Adam的更新方程为:\quad \theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{\hat{v_t}} + \epsilon}\hat{m_t} \end{aligned}
mt=β1mt−1+(1−β1)gtvt=β2vt−1+(1−β2)gt2mt与vt分别是梯度的带权平均和带权有偏方差,初始为0向量,Adam的作者发现他们倾向于0向量,特别是在衰减因子β1,β2接近于1时。为了改进这个问题,对mt与vt进行偏差修正(bias−corrected):mt^=1−β1tmtvt^=1−β2tvt最终,Adam的更新方程为:θt+1=θt−vt^+ϵηmt^