机器学习金典算法(二)–梯度下降法
本人上篇博文梯度下降法(1)解释了梯度下降法在机器学习中位置及思想,本文将继续讨论梯度下降法,梯度下降法存在的问题及改进思路,以及现有的几种流行的变种梯度下降法。
文章目录
1 普通梯度下降法
上篇博文中,我们用1个样本计算误差,然后反向传递,这不是普通梯度下降法,而是单样本梯度下降法;而普通梯度下降法是怎么做的呢??
它是先一次性计算所有样本误差,并求平均,再反向传播更新参数;当我们训练样本不多时,不会有感觉,而当我们样本很多时,如有上百万个样本,该方法就先计算这100万个样本误差,然后更新一次网络,每更新一次都要计算100万个前向计算;
说到这里就清楚了,这个速度比乌龟还慢;再者,当样本量大过一定程度,平均误差几乎不变,所以计算全部样本的平均误差也没有必要,只会浪费我们训练网络的时间;还有一般情况我们的显存也不够啊。
为了结合后面神经网络算法,本系列从现在开始规范化表示符号;其Loss Function为:
ℓ
(
y
^
i
,
y
i
)
\ell (\hat y_i,y_i)
ℓ(y^i,yi)
误差函数会根据任务不同而有不同形式;代价函数(目标函数):
J
(
w
,
b
)
=
1
m
∑
i
=
0
m
ℓ
(
y
^
i
,
y
i
)
J(w,b) = \frac{1}{m} \displaystyle\sum_{i=0}^m\ell (\hat y_i,y_i)
J(w,b)=m1i=0∑mℓ(y^i,yi)
这里的 m m m表示总样本个数。我们梯度下降最小化这个目标函数的一种优化方法;实际应用中,目标函数后面经常会加上一个正则化(Regularization)项。
正则化项又被称为目标函数的惩罚项,主要是对目标函数中的一些参数做一些限制,有利于防止过拟合,提高泛化能力,具体点开正则化链接。
L1正则化:
J
(
w
,
b
)
=
1
m
∑
i
=
0
m
ℓ
(
y
^
i
,
y
i
)
+
λ
2
m
∣
∣
w
∣
∣
1
J(w,b) = \frac{1}{m} \displaystyle\sum_{i=0}^m\ell (\hat y_i,y_i)+\frac{\lambda}{2m}||w|| _1
J(w,b)=m1i=0∑mℓ(y^i,yi)+2mλ∣∣w∣∣1
L2正则化:
J
(
w
,
b
)
=
1
m
∑
i
=
0
m
ℓ
(
y
^
i
,
y
i
)
+
λ
2
m
∣
∣
w
∣
∣
2
2
J(w,b) = \frac{1}{m} \displaystyle\sum_{i=0}^m\ell (\hat y_i,y_i)+\frac{\lambda}{2m}||w|| _2^2
J(w,b)=m1i=0∑mℓ(y^i,yi)+2mλ∣∣w∣∣22
式中** λ \lambda λ是一个超参数**,根据实际情况而定;当 λ \lambda λ过大时,它会导致部分 w w w衰减为0,则对应神经元不起作用,使得网络慢慢像简单网络,甚至是线性的;当 λ \lambda λ过小时,它几乎没有作用;所有当 λ \lambda λ合适时,适当干掉一些神经元,防止过拟合(这是不是和Dropout有点像呢);当然了防止过拟合,也可以通过增加样本等手段,总之,训练好一个网络,是多方面因素一起搞定的,而不是某一个参数完全控制的。
在Caffe训练中,超参数文件(solver)中常常看到的weight_decay就是这玩意。
实际中,L2被用得较多,也被称为权重衰减;在多层神经网络中,正则化范围为当前层的
w
w
w,也就是当前层
w
w
w更新值由当前层
w
w
w来正则化。
有人可能会问 b b b参数可不可以加正则化呢?答案是肯定的,但在神经网络模型中,由于 b b b参数占所有参数比重非常小,对其正则化,对网络影响极小,所有常常不加。
本人后面的博文大多数情况都会忽略正则化,但实际用时会加上,请熟知。
2 随机梯度下降法
针对普通梯度下降的问题,我们可以将样本集切分成多个子样本集**(Mini-batch),例如100w个样本,我们切分成100份,每份1万个样本(batch size)**;
我们在训练时,就可以循环调用这100个Mini-batch(循环完1次,即每个样本参与1次,称为1个epoch),也即每计算1万个样本就更新一次网络,这样将大大提高网络收敛的时间,这就是随机梯度下降法
简而言之,我们加上一个batch size参数来控制网络计算多少个样本就反向更新一次。而当batch size=1时,就是单样本梯度下降法;当batch size=m时,就是普通梯度下降法;
实际网络训练中,我们常常看到的batch size就是来控制这玩意的;要根据你的显存大小,训练速度、样本个数来确定,有时还可能与模型结构有关;常常为2的次方,一般情况只要显存允许,尽量大一点。
因此随机梯度下降法的目标函数为:
J
(
w
,
b
)
=
1
m
[
t
]
∑
i
=
0
m
[
t
]
ℓ
(
y
^
i
,
y
i
)
J(w,b) = \frac{1}{m^{[t]}} \displaystyle\sum_{i=0}^{m^{[t]}}\ell (\hat y_i,y_i)
J(w,b)=m[t]1i=0∑m[t]ℓ(y^i,yi)
其中 m [ t ] m^{[t]} m[t]表示一个Mini-batch的样本个数,也就是batch size大小。
3 标准梯度下降存在的问题
3.1 容易在最优值附近震荡
因为学习率是固定值,开始优化时表现不错,但到最优处附近时,即黄色点处,由于步幅较大,误差会在其左右来回震荡,而达不到最小值处。解决办法,见后面学习率衰减。
3.2 局部极小值
如图,我们常常遇到的目标函数并不只是拥有1个极小值的,然而B处极小值才是我们想要的;实际中,如果初始化不当,如图中红色点,优化就可能在A出结束。
解决办法可以是多次初始化,多训练几次,然后取最小的那个;也可采用一些改进梯度下降法,见后面。
3.3 参数调整缓慢
在实际应用中,我们的目标函数常常是高维的,这种情况下,鞍点(Saddle Point)要比局部极小值更容易遇到,所以我们面临的问题常常不是局部最小值,而是平稳段(Plateaus)减缓学习问题。
后面一些改进梯度下降法就是来加速学习及更好收敛的。
4 学习率衰减
学习率衰减的思想:在开始训练时采用相对较大的学习率,让模型快速下降到最优值附近,然后降低学习率,让模型更进一步逼近最优值。
因为在最优值附近,如果还用较大学习率,loss值就会呈现在某个值附近震荡,如4.1提到的问题。
在实际应用中,学习率衰减的方法有很多,我们拿Caffe训练来说,当然其他框架也是一样的,我们在超参数控制文件(solver)经常看到base_lr和lr_policy,前者表示基准学习率 η \eta η,后者表示学习率衰减策略,也就是采用什么样的策略衰减基准学习率,还有个**gamma( γ \gamma γ)**超参数。
常用衰减策略:
1)fixed:保持不变,即不衰减
2)step:根据迭代次数衰减
设置step,还要添加一个stepsize参数,具体如下:
η
=
η
∗
γ
f
l
o
o
r
(
i
t
e
r
/
s
t
e
p
s
i
z
e
)
\eta = \eta * \gamma^{floor(iter/stepsize)}
η=η∗γfloor(iter/stepsize)
其中iter表示迭代次数,下同。
3)exp:根据迭代次数指数衰减
η
=
η
∗
γ
i
t
e
r
\eta = \eta * \gamma^{iter}
η=η∗γiter
4)inv:
设置inv,还要添加一个power参数,具体如下:
η
=
η
∗
(
1
+
γ
∗
i
t
e
r
)
−
p
o
w
e
r
\eta = \eta * (1+\gamma * iter)^{-power}
η=η∗(1+γ∗iter)−power
5)multistep:
设置step,还要添加一个或多个stepvalue参数,当iter = stepvalue,学习率衰减10倍,具体如下:
η
=
0.1
∗
η
\eta =0.1*\eta
η=0.1∗η
6)ploy:多项式衰减
设置inv,还要添加一个power参数,具体如下:
η
=
η
∗
(
1
−
i
t
e
r
/
i
t
e
r
m
a
x
)
p
o
w
e
r
\eta = \eta * (1- iter/iter_{max})^{power}
η=η∗(1−iter/itermax)power
7)sigmoid:sigmoid衰减
设置step,还要添加一个stepsize参数,具体如下:
η
=
η
∗
(
1
/
(
1
+
e
−
γ
∗
(
i
t
e
r
−
s
t
e
p
s
i
z
e
)
)
)
\eta = \eta *(1/(1+e^{- \gamma*(iter-stepsize)}))
η=η∗(1/(1+e−γ∗(iter−stepsize)))
这么多方法,到底用那个,这就要看实际情况而定了,一般某个任务,其相关论文中会提到作者用的什么策略,超参数值等,自己也可以根据自己任务多尝试对比。
5 动量梯度下降法
动量(Momentum)梯度下降法常常要比标准梯度快得多,它的原理是用**梯度加权平均**来更新梯度,就像是给一个高处滚下的小球加上动量,使得它滚得更快。

动量梯度更新原理如下:
第1步:更新梯度(增加动量)
{
v
d
w
=
β
1
v
d
w
+
(
1
−
β
1
)
∗
d
w
v
d
b
=
β
1
v
d
b
+
(
1
−
β
1
)
∗
d
b
\begin{cases} v_{dw} = \beta_1 v_{dw} + (1-\beta_1)*dw\\ v_{db} = \beta_1 v_{db} + (1-\beta_1)*db \end{cases}
{vdw=β1vdw+(1−β1)∗dwvdb=β1vdb+(1−β1)∗db
第2步:更新权值
{
w
=
w
−
η
∗
v
d
w
b
=
b
−
η
∗
v
d
b
\begin{cases} w = w - \eta *v_{dw}\\ b = b - \eta *v_{db} \end{cases}
{w=w−η∗vdwb=b−η∗vdb
要弄懂其背后的原理,就要理解**指数加权平均**,这不是一两句话能说清楚,我们专门为其总结一个博文;使用动量梯度后,呈现效果如下:
上图中,蓝色线条是标准梯度下降法梯度震荡曲线,红色表示动量梯度下降法,它能更快收敛到最优值处。
在Caffe的超参数文件(solver)中的momentum参数就是这个
β
1
\beta_1
β1。
6 RMSprop
RMSprop(root mean square prob)也是一种加速梯度下降的方法,其原理如下:
第1步:更新梯度
{
s
d
w
=
β
2
s
d
w
+
(
1
−
β
2
)
∗
(
d
w
)
2
s
d
b
=
β
2
s
d
b
+
(
1
−
β
2
)
∗
(
d
b
)
2
\begin{cases} s_{dw} = \beta_2 s_{dw} + (1-\beta_2)*(dw)^2\\ s_{db} = \beta_2 s_{db} + (1-\beta_2)*(db)^2 \end{cases}
{sdw=β2sdw+(1−β2)∗(dw)2sdb=β2sdb+(1−β2)∗(db)2
第2步:更新权值
{
w
=
w
−
η
∗
d
w
s
d
w
+
ξ
b
=
b
−
η
∗
d
b
s
d
b
+
ξ
\begin{cases} w = w - \eta *\frac {dw}{\sqrt{ s_{dw}}+\xi}\\ b = b - \eta *\frac {db}{\sqrt{ s_{db}}+\xi} \end{cases}
{w=w−η∗sdw+ξdwb=b−η∗sdb+ξdb
其中,
ξ
\xi
ξ作用是防止分母数值太小,而引起更新量太大,一般
ξ
=
1
0
−
8
\xi = 10^{-8}
ξ=10−8,怎么理解这个RMSprop呢?
我们梯度前进时,如下图,我们希望纵轴上变化慢一点,而横轴变化快一点,这样就能快速收敛;对于RMSprop,我们可以将
w
w
w看成在横轴上起主要作用,
b
b
b在纵轴上起主要作用,实际中,
d
b
db
db较大,则使得纵轴更新较小,
d
w
dw
dw较小,横轴更新较大(这一解释个人也没完全理解,吴恩达是这么解释的)

如图所示,蓝色迭代折线表示标准梯度前进方向;而绿色折线标准RMSprop前进方向,明显会加速梯度下降。
7 Adam优化算法
Adam(Adaptive Momnet Estimation)是结合了动量和RMS的优化方法,效果很好,应用非常广泛,适用于多种结构的神经网络结构,其原理如下:
首先初始化
v
d
w
v_{dw}
vdw,
v
d
b
v_{db}
vdb,
s
d
w
s_{dw}
sdw,
s
d
b
s_{db}
sdb为0,在第
t
t
t次迭代时:
第1步:动量、RMS计算
{
v
d
w
=
β
1
v
d
w
+
(
1
−
β
1
)
∗
d
w
v
d
b
=
β
1
v
d
b
+
(
1
−
β
1
)
∗
d
b
\begin{cases} v_{dw} = \beta_1 v_{dw} + (1-\beta_1)*dw\\ v_{db} = \beta_1 v_{db} + (1-\beta_1)*db \end{cases}
{vdw=β1vdw+(1−β1)∗dwvdb=β1vdb+(1−β1)∗db
{
s
d
w
=
β
2
s
d
w
+
(
1
−
β
2
)
∗
(
d
w
)
2
s
d
b
=
β
2
s
d
b
+
(
1
−
β
2
)
∗
(
d
b
)
2
\begin{cases} s_{dw} = \beta_2 s_{dw} + (1-\beta_2)*(dw)^2\\ s_{db} = \beta_2 s_{db} + (1-\beta_2)*(db)^2 \end{cases}
{sdw=β2sdw+(1−β2)∗(dw)2sdb=β2sdb+(1−β2)∗(db)2
第2步:动量、RMS修正
{
v
d
w
c
=
v
d
w
1
−
β
1
t
v
d
b
c
=
v
d
b
1
−
β
1
t
\begin{cases} v^c_{dw} = \frac {v_{dw}}{1-\beta^t_1}\\ v^c_{db} = \frac {v_{db}}{1-\beta^t_1} \end{cases}
{vdwc=1−β1tvdwvdbc=1−β1tvdb
{
s
d
w
c
=
s
d
w
1
−
β
2
t
s
d
b
c
=
s
d
b
1
−
β
2
t
\begin{cases} s^c_{dw} = \frac {s_{dw}}{1-\beta^t_2}\\ s^c_{db} = \frac {s_{db}}{1-\beta^t_2} \end{cases}
{sdwc=1−β2tsdwsdbc=1−β2tsdb
第3步:Adam更新
{
w
=
w
−
η
∗
v
d
w
c
s
d
w
c
+
ξ
b
=
b
−
η
∗
v
d
b
c
s
d
b
c
+
ξ
\begin{cases} w = w - \eta *\frac {v^c_{dw}}{\sqrt{ s^c_{dw}}+\xi}\\ b = b - \eta *\frac {v^c_{db}}{\sqrt{ s^c_{db}}+\xi} \end{cases}
⎩⎨⎧w=w−η∗sdwc+ξvdwcb=b−η∗sdbc+ξvdbc
这里用到了多个超参数,但我们不必担心,这些超参数大多是有默认值,由大牛们证明有效的,所以大部分超参数我们不需要改变,只有少数需要根据具体情况而定,这里:
{
η
:
需
要
我
们
多
调
试
设
定
β
1
=
0.9
β
2
=
0.999
ξ
=
1
0
−
8
\begin{cases} \eta : 需要我们多调试设定\\ \beta_1 = 0.9 \\ \beta_2 = 0.999 \\ \xi = 10^{-8} \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧η:需要我们多调试设定β1=0.9β2=0.999ξ=10−8
8 总结
当然优化方法不只这几种,但这几种是常常用到的,其他就不多说了,下面用两幅动态图展示下各算法情况。
1)鞍点处速度表现

2)最优解及速度表现

9 参考文献
【1】机器学习中正则化项L1和L2的直观理解:https://blog.youkuaiyun.com/jinping_shi/article/details/52433975
【2】梯度下降法:https://blog.youkuaiyun.com/qq_42379006/article/details/80675704
【3】吴恩达DeepLearning.ai课程:https://mooc.study.163.com/smartSpec/detail/1001319001.htm
【4】深度学习最全优化方法总结比较:https://blog.youkuaiyun.com/u012759136/article/details/52302426