吴恩达改善深层神经网络章节笔记(二)——优化算法)
视频课程链接:
https://www.bilibili.com/video/BV1FT4y1E74V?
笔记参考链接:
https://blog.csdn.net/weixin_36815313/article/details/105728919
1. Mini-batch梯度下降 (Mini-batch Gradient Descent)
机器学习的应用是一个高度依赖经验的过程,伴随着大量迭代的过程,你需要训练诸多模型,才能找到最合适的那一个,所以优化算法能够帮助你快速训练模型。
但是深度学习没有在大数据领域发挥最大的效果,我们可以利用一个巨大的数据集来训练神经网络,而在巨大的数据集基础上进行训练,训练速度很慢。因此你会发现,使用快速好用的优化算法能够大大提高你和团队的效率。那么,我们首先来谈谈mini-batch梯度下降法。
1.1 什么是mini-batch?
向量化能够有效地对所有
m
m
m个样本进行计算,允许你处理整个训练集,而无需某个明确的公式。所以我们要把所有的训练样本放大一个巨大的矩阵
X
X
X当中去,即
X
=
[
x
(
1
)
x
(
2
)
x
(
3
)
⋯
x
(
m
)
]
X=[x^{(1)}x^{(2)}x^{(3)}\cdots x^{(m)}]
X=[x(1)x(2)x(3)⋯x(m)]。输出
Y
Y
Y也是如此,即
Y
=
[
y
(
1
)
y
(
2
)
y
(
3
)
⋯
y
(
m
)
]
Y=[y^{(1)}y^{(2)}y^{(3)}\cdots y^{(m)}]
Y=[y(1)y(2)y(3)⋯y(m)]。所以
X
X
X的维数是
(
n
x
,
m
)
(n_x,m)
(nx,m),
Y
Y
Y的维数是
(
1
,
m
)
(1,m)
(1,m),向量化能够让你相对较快地处理所有
m
m
m个样本。
但是如果
m
m
m很大的话,处理速度仍然缓慢。举例来说,如果
m
m
m是500万,在对整个训练集执行梯度下降法时,你需要做的是处理这500万个训练样本,然后才能进行一步梯度下降法。接着你需要再重新处理这500万个训练样本,才能进行下一步梯度下降法。所以如果你在处理完500万个样本的训练集之前,先让梯度下降法处理一部分,你的算法速度会更快。
你可以把训练集分割为小一点的子集训练,这些子集被取名为mini-batch。假设每一个子集中只有1000个样本,把其中的
x
(
1
)
x^{(1)}
x(1)到
x
(
1000
)
x^{(1000)}
x(1000)取出来,将其称为第一个子训练集,记作
X
{
1
}
X^{\{1\}}
X{1},然后你再取出接下来1000个样本,即从
x
(
1001
)
x^{(1001)}
x(1001)到
x
(
2000
)
x^{(2000)}
x(2000),记作
X
{
2
}
X^{\{2\}}
X{2},然后再取1000个样本,以此类推,最后一个mini-batch记作
X
{
5000
}
X^{\{5000\}}
X{5000}。如果你的训练样本一共有500万个,那么每个mini-batch都有1000个样本,也就是说,你有5000个mini-batch。
对
Y
Y
Y也要进行相同处理,相应地拆分
Y
Y
Y的训练集,从
y
(
1
)
y^{(1)}
y(1)到
y
(
1000
)
y^{(1000)}
y(1000)为第一个子集,记作
Y
{
1
}
Y^{\{1\}}
Y{1},然后从
y
(
1001
)
y^{(1001)}
y(1001)到
y
(
2000
)
y^{(2000)}
y(2000)记作
Y
{
2
}
Y^{\{2\}}
Y{2},以此类推,直到
Y
{
5000
}
Y^{\{5000\}}
Y{5000}。
mini-batch的数量
t
t
t组成了
X
(
t
)
X^{(t)}
X(t)和
Y
(
t
)
Y^{(t)}
Y(t),这就是1000个训练样本,包含相应的输入输出对。如果
X
{
1
}
X^{\{1\}}
X{1}是一个有1000个样本的训练集,或者说是1000个
x
x
x值,所以维数应该是
(
n
x
,
1000
)
(n_x,1000)
(nx,1000),同理,
X
{
2
}
X^{\{2\}}
X{2}的维数应该是
(
n
x
,
1000
)
(n_x,1000)
(nx,1000)。以此类推,所有的子集维数都是
(
n
x
,
1000
)
(n_x,1000)
(nx,1000),而
Y
{
t
}
Y^{\{t\}}
Y{t}的维数都是
(
1
,
1000
)
(1,1000)
(1,1000)。
mini-batch梯度下降法,指的是每次同时处理的单个的mini-batch,即
X
{
t
}
X^{\{t\}}
X{t}和
Y
{
t
}
Y^{\{t\}}
Y{t},而不是同时处理全部的
X
X
X和
Y
Y
Y训练集。
1.2 Mini-batch梯度下降法的实现流程
假设训练集中500万个样本,划分成5000个mini-batch,即每个mini-batch中包含1000个训练样本。在训练集上运行mini-batch梯度下降法,因为我们有5000个mini-batch,其中各有1000个样本,因此使用for循环for t in range(1,5000),对5000个mini-batch
X
{
t
}
X^{\{t\}}
X{t}和
Y
{
t
}
Y^{\{t\}}
Y{t}执行一步梯度下降法。
首先,对输入
X
{
t
}
X^{\{t\}}
X{t}执行前向传播(Forward propagation)。因为现在你需要处理一个mini-batch,而不是一个样本集,因此前向传播过程中的输入
X
X
X变成了
X
{
t
}
X^{\{t\}}
X{t},即
Z
[
1
]
=
W
[
1
]
X
{
t
}
+
b
[
1
]
Z^{[1]}=W^{[1]}X^{\{t\}}+b^{[1]}
Z[1]=W[1]X{t}+b[1]
A
[
1
]
=
g
[
1
]
(
Z
[
1
]
)
A^{[1]}=g^{[1]}(Z^{[1]})
A[1]=g[1](Z[1]) 之所以用大写的
Z
Z
Z,是因为这是一个向量,以此类推,直到得到最终的预测值
y
^
\hat{y}
y^。
y
^
=
A
[
L
]
=
g
[
L
]
(
Z
[
L
]
)
\hat{y}=A^{[L]}=g^{[L]}(Z^{[L]})
y^=A[L]=g[L](Z[L]) 注意这里你需要用到一个向量化的执行命令,这个向量化的执行命令,一次性处理1000个而不是500万个样本。
接下来需要计算损失成本函数
J
J
J,因为子集规模是1000,因此
J
{
t
}
=
1
1000
∑
i
=
1
l
L
(
y
^
(
i
)
,
y
(
i
)
)
J^{\{t\}}=\frac1{1000}\sum_{i=1}^lL(\hat{y}^{(i)},y^{(i)})
J{t}=10001i=1∑lL(y^(i),y(i)) 说明一下,
L
(
y
^
(
i
)
,
y
(
i
)
)
L(\hat{y}^{(i)},y^{(i)})
L(y^(i),y(i))指的是来自于某一项mini-batch
X
{
t
}
X^{\{t\}}
X{t}和
Y
{
t
}
Y^{\{t\}}
Y{t}中的样本。
如果你用到了正则化,也可以添加正则化项,即
J
{
t
}
=
1
1000
∑
i
=
1
l
L
(
y
^
(
i
)
,
y
(
i
)
)
+
λ
2
∗
1000
∑
l
∣
∣
w
[
l
]
∣
∣
F
2
J^{\{t\}}=\frac1{1000}\sum_{i=1}^lL(\hat{y}^{(i)},y^{(i)})+\frac{\lambda}{2*1000}\sum_l||w^{[l]}||^2_F
J{t}=10001i=1∑lL(y^(i),y(i))+2∗1000λl∑∣∣w[l]∣∣F2 接下来执行反向传播(Back propagation)来计算
J
{
t
}
J^{\{t\}}
J{t}的梯度,这里使用
X
{
t
}
X^{\{t\}}
X{t}和
Y
{
t
}
Y^{\{t\}}
Y{t}。然后根据
d
W
dW
dW和
d
b
db
db更新
W
W
W和
b
b
b,即
W
[
l
]
:
=
W
[
l
]
−
α
d
W
[
l
]
W^{[l]}:=W^{[l]}-\alpha dW^{[l]}
W[l]:=W[l]−αdW[l]
b
[
l
]
:
=
b
[
l
]
−
α
d
b
[
l
]
b^{[l]}:=b^{[l]}-\alpha db^{[l]}
b[l]:=b[l]−αdb[l] 上述过程是使用mini-batch梯度下降法训练样本的一步,也可被称为进行一代(1 epoch)的训练。一代意味着遍历了一次训练集,也就是说,所有训练样本在神经网络中都进行了一次正向传播和一次反向传播。
使用batch梯度下降法,一次遍历训练集只能让你做一个梯度下降,而使用mini-batch梯度下降法,遍历一次训练集能让你做5000个梯度下降。
1.3 Batch vs. Mini-batch梯度下降法
使用batch梯度下降法时,每次迭代你都需要遍历整个训练集,并且每次迭代成本函数
J
J
J都会下降。如果成本函数
J
J
J在某次迭代中增加了,那肯定出了问题,也许是你的学习率(Learning rate)太大。
使用mini-batch梯度下降法时,成本函数
J
J
J并不是在整个过程中每次迭代都是下降的,特别是在每次迭代中,你需要处理的是
X
{
t
}
X^{\{t\}}
X{t}和
Y
{
t
}
Y^{\{t\}}
Y{t},而成本函数
J
{
t
}
J^{\{t\}}
J{t}只和
X
{
t
}
X^{\{t\}}
X{t},
Y
{
t
}
Y^{\{t\}}
Y{t}有关,也就是每次迭代下你都在训练不同的mini-batch或者说训练不同的样本集。因此在训练mini-batch梯度下降法时,经过多代,你可能会看到上图这样的曲线,走向朝下,但有更多的噪声。如果没有每次迭代都下降,这是不要紧的,但整体走势应该向下。
噪声产生的原因在于每次迭代下你都在训练不同的mini-batch或者说是样本集,也许
X
{
1
}
X^{\{1\}}
X{1}和
Y
{
1
}
Y^{\{1\}}
Y{1}是比较容易计算的mini-batch,因此成本会低一些。不过也许出于偶然,
X
{
2
}
X^{\{2\}}
X{2}和
Y
{
2
}
Y^{\{2\}}
Y{2}是比较难运算的mini-batch,或许你需要一些残缺的样本,这样一来,成本会更高一些,所以才会出现这些摆动。
1.4 如何选择mini-batch大小?
使用mini-batch梯度下降法的过程中,你需要决定的变量之一是mini-batch的大小,另外
m
m
m是训练集的大小。
第一种极端情况,假设mini-batch的大小等于
m
m
m,也就是batch梯度下降法,在这种极端情况下,你就有了mini-batch
X
{
1
}
X^{\{1\}}
X{1}和
Y
{
1
}
Y^{\{1\}}
Y{1},并且该mini-batch等于整个训练集,即
(
X
{
1
}
,
Y
{
1
}
)
=
(
X
,
Y
)
(X^{\{1\}},Y^{\{1\}})=(X,Y)
(X{1},Y{1})=(X,Y),所以把mini-batch大小设为
m
m
m,也就等于batch梯度下降法。
另一种极端情况,假设mini-batch大小为1,此时每个样本都是独立的mini-batch,这种新的算法,叫做随机梯度下降法。对于第一个mini-batch,也就是
X
{
1
}
X^{\{1\}}
X{1}和
Y
{
1
}
Y^{\{1\}}
Y{1},如果mini-batch大小为1,实际上它就是你的第一个训练样本,即
(
X
{
1
}
,
Y
{
1
}
)
=
(
X
(
1
)
,
Y
(
1
)
)
(X^{\{1\}},Y^{\{1\}})=(X^{(1)},Y^{(1)})
(X{1},Y{1})=(X(1),Y(1))。接着再看第二个mini-batch,也就是第二个训练样本,即
(
X
{
2
}
,
Y
{
2
}
)
=
(
X
(
2
)
,
Y
(
2
)
)
(X^{\{2\}},Y^{\{2\}})=(X^{(2)},Y^{(2)})
(X{2},Y{2})=(X(2),Y(2)),然后是第三个训练样本,以此类推,直到最后一个样本,而每一次梯度下降只处理一个样本。
接下来在上述两种极端下看一下成本函数的优化情况,如果上图是你想要最小化的成本函数的轮廓。batch梯度下降法(蓝色曲线)从某处开始,相对噪声低些,幅度也大一些,并最终找到最小值。
相反,在随机梯度下降法(紫色曲线)中,从某一点开始,每次迭代只对一个样本进行梯度下降,其大部分时候向着全局最小值靠近,有时候也会远离最小值,因为可能那个样本恰好给你指的方向不对,因此随机梯度下降法是有很多噪声的。平均来看,它最终会靠近最小值,不过有时候也会方向错误,因为随机梯度下降法永远不会收敛,而是会一直在最小值附近波动,并不会在达到最小值并停留在此。
而如果使用mini-batch梯度下降法(绿色曲线)的话,它不会总朝向最小值靠近,但它比随机梯度下降要更持续地靠近最小值的方向,它也不一定在很小的范围内收敛或者波动,如果出现这个问题,可以慢慢减少学习率。
如果使用batch梯度下降法,即mini-batch的大小为
m
m
m,每次迭代需要处理大量训练样本,该算法的主要弊端在于如果训练样本数量巨大,单次迭代耗时太长。如果训练样本不大,那么batch梯度下降法可以运行地很好。
使用随机梯度下降法的话,即mini-batch的大小为1,如果你只要处理一个样本,那这个方法很好,通过减小学习率,噪声会被改善或有所减小,但随机梯度下降法的一大缺点是,你会失去所有向量化带给你的加速,因为一次性只处理了一个训练样本,这样效率过于低下。
所以实践中最好选择不大不小的mini-batch尺寸,这样子学习率可以达到最快。你会发现两个好处,一方面,你得到了大量的向量化操作,上个视频我们用过的例子中,如果mini-batch大小为1000个样本,你就可以对1000个样本向量化,比你一次性处理多个样本快得多。另一方面,你不需要等待整个训练集被处理完就可以开始进行后续工作,同样在上个视频我们用过的例子中,每次训练集允许我们执行5000个梯度下降,所以实际上一些位于中间的mini-batch大小效果最好。
而位于中间的mini-batch大小应该如何选择,指导原则如下:
- 如果训练集较小,即样本数目小于2000个样本,直接使用batch梯度下降法即可。样本数目较小就没必要使用mini-batch梯度下降法,因为你可以快速处理整个训练集。如果样本数目较大的话,一般mini-batch大小设置为64到512,考虑到电脑内存设置和使用的方式,如果mini-batch大小是2的 n n n次方,代码会运行地快一些,比如64就是2的6次方,128是2的7次方,以此类推,256是2的8次方,512是2的9次方。所以我经常把mini-batch大小设成2的 n n n次方。在上一章节里,mini-batch大小设为了1000,你可以试一下1024,也就是2的10次方。
- 最后需要注意的是,在你的mini-batch中,要确保 X { t } X^{\{t\}} X{t}和 Y { t } Y^{\{t\}} Y{t}符合CPU/GPU内存,取决于你的应用方向以及训练集的大小。如果你处理的mini-batch和CPU/GPU内存不相符,不管用什么方法处理数据,你会发现算法的表现急转直下,变得惨不忍睹,所以我希望你对一般的mini-batch大小有一个直观了解。事实上mini-batch大小是一个重要的变量,你需要做一个快速尝试,才能找到能够最有效地减少成本函数的那个,我一般会尝试几个不同的值,几个不同的2的 n n n次方,然后看能否找到一个让梯度下降优化算法最高效的mini-batch大小。
2. 指数加权平均 (Exponentially Weighted Averages)
2.1 基本原理
上图是天气与日期的变化关系,横轴表示的是一年中的第几天,纵轴表示的是该天的温度。1月份和12月份的温度相对于年中(6、7月份)的温度要低一些。
下面我们通过温度的局部平均值(移动平均值)来描述温度的变化趋势。
v
0
=
0
v_0=0
v0=0
v
1
=
0.9
∗
v
0
+
0.1
∗
θ
1
v_1=0.9*v_0+0.1*\theta_1
v1=0.9∗v0+0.1∗θ1
v
2
=
0.9
∗
v
1
+
0.1
∗
θ
2
v_2=0.9*v_1+0.1*\theta_2
v2=0.9∗v1+0.1∗θ2
v
3
=
0.9
∗
v
2
+
0.1
∗
θ
3
v_3=0.9*v_2+0.1*\theta_3
v3=0.9∗v2+0.1∗θ3
⋯
⋯
\cdots \cdots
⋯⋯ 以此类推,我们可以用如下公式来计算局部平均值。
v
t
=
β
∗
v
t
−
1
+
(
1
−
β
)
∗
θ
t
v_t=\beta*v_{t-1}+(1-\beta)*\theta_t
vt=β∗vt−1+(1−β)∗θt 其中
v
t
v_t
vt表示到第
t
t
t天的局部平均温度值,
θ
t
\theta_t
θt表示第
t
t
t天的温度,
β
\beta
β表示可调节的超参数。
在计算时可将
v
t
v_t
vt看作是
1
(
1
−
β
)
\frac 1{(1-\beta)}
(1−β)1天内的平均温度。假设
β
\beta
β是0.9,即
1
(
1
−
β
)
=
1
(
1
−
0.9
)
=
10
\frac{1}{(1-\beta)}=\frac{1}{(1-0.9)}=10
(1−β)1=(1−0.9)1=10天内的平均温度,如下图中的红线部分。
假设将
β
\beta
β设置为一个接近1的值,比如0.98,即
1
(
1
−
0.98
)
=
50
\frac1{(1-0.98)}=50
(1−0.98)1=50,这就是粗略平均了一下过去50天的温度,如下图中的绿线部分。
相对于红线来说,得到的曲线要平坦一些,原因在于多平均了几天的温度,所以这个曲线,波动更小,更加平坦,但缺点是曲线进一步右移,产生了延迟。
假设
β
\beta
β取另一个极端值,比如说0.5,根据公式
1
(
1
−
β
)
\frac1{(1-\beta)}
(1−β)1可知这是平均了两天的温度,如下图中的黄线部分。
相对于红线来说,它抖动的更加厉害,因为它只平均了两天的温度,所以对于温度的趋势反馈能够更加的及时,更快的适应温度的变化,同时它也会带来更多的噪声(平均的天数太少)。
2.2 本质作用
对于这个计算指数加权平均的方程
v
t
=
β
∗
v
t
−
1
+
(
1
−
β
)
∗
θ
t
v_t=\beta*v_{t-1}+(1-\beta)*\theta_t
vt=β∗vt−1+(1−β)∗θt 假设
β
=
0.9
\beta=0.9
β=0.9,
t
t
t从100到1逐级递减,写下如下公式
v
100
=
0.9
∗
v
99
+
0.1
∗
θ
100
v_{100}=0.9*v_{99}+0.1*\theta_{100}
v100=0.9∗v99+0.1∗θ100
v
99
=
0.9
∗
v
98
+
0.1
∗
θ
99
v_{99}=0.9*v_{98}+0.1*\theta_{99}
v99=0.9∗v98+0.1∗θ99
v
98
=
0.9
∗
v
97
+
0.1
∗
θ
98
v_{98}=0.9*v_{97}+0.1*\theta_{98}
v98=0.9∗v97+0.1∗θ98
v
97
=
0.9
∗
v
96
+
0.1
∗
θ
97
v_{97}=0.9*v_{96}+0.1*\theta_{97}
v97=0.9∗v96+0.1∗θ97
⋯
⋯
\cdots \cdots
⋯⋯
v
1
=
0.9
∗
v
0
+
0.1
∗
θ
1
v_1=0.9*v_0+0.1*\theta_1
v1=0.9∗v0+0.1∗θ1将
v
99
v_{99}
v99代入到
v
100
v_{100}
v100中,可得:
v
100
=
0.1
∗
θ
100
+
0.9
∗
(
0.1
∗
θ
99
+
0.9
∗
v
98
)
v_{100}=0.1*\theta_{100}+0.9*(0.1*\theta_{99}+0.9*v_{98})
v100=0.1∗θ100+0.9∗(0.1∗θ99+0.9∗v98) 再将
v
98
v_{98}
v98代入到
v
99
v_{99}
v99中,可得:
v
100
=
0.1
∗
θ
100
+
0.9
∗
(
0.1
∗
θ
99
+
0.9
∗
(
0.1
∗
θ
98
+
0.9
∗
v
97
)
)
v_{100}=0.1*\theta_{100}+0.9*(0.1*\theta_{99}+0.9*(0.1*\theta_{98}+0.9*v_{97}))
v100=0.1∗θ100+0.9∗(0.1∗θ99+0.9∗(0.1∗θ98+0.9∗v97)) 以此类推,将这些括号里面的内容展开,可得:
v
100
=
0.1
∗
θ
100
+
0.1
∗
0.9
∗
θ
99
+
0.1
∗
0.
9
2
∗
θ
98
+
0.1
∗
0.
9
3
∗
θ
97
+
⋯
+
0.1
∗
0.
9
99
∗
θ
1
=
0.1
∗
∑
i
=
1
100
0.
9
(
100
−
i
)
∗
θ
i
\begin{aligned} v_{100}&=0.1*\theta_{100}+0.1*0.9*\theta_{99}+0.1*0.9^2*\theta_{98}+0.1*0.9^3*\theta_{97}+\cdots+0.1*0.9^{99}*\theta_1\\ &=0.1*\sum_{i=1}^{100} 0.9^{(100-i)}*\theta_i \\ \end{aligned}
v100=0.1∗θ100+0.1∗0.9∗θ99+0.1∗0.92∗θ98+0.1∗0.93∗θ97+⋯+0.1∗0.999∗θ1=0.1∗i=1∑1000.9(100−i)∗θi 由此可知,上面的式子就是一个指数加权平均。
取
ϵ
=
1
−
β
=
0.1
\epsilon=1-\beta=0.1
ϵ=1−β=0.1,即
β
=
0.9
\beta=0.9
β=0.9。当
(
1
−
ϵ
)
1
ϵ
=
1
e
(1-\epsilon)^{\frac{1}{\epsilon}}=\frac{1}{e}
(1−ϵ)ϵ1=e1时,即
(
0.9
)
10
=
1
e
≈
0.37
(0.9)^{10}=\frac{1}{e}\approx0.37
(0.9)10=e1≈0.37(
e
e
e为自然对数,
e
=
2.71828
e=2.71828
e=2.71828),也就是当曲线的高度下降到峰值的
1
3
\frac13
31,权重下降到峰值权重的
1
e
\frac{1}{e}
e1时,我们就说它平均了
1
ϵ
\frac{1}{\epsilon}
ϵ1=
1
1
−
β
\frac{1}{1-\beta}
1−β1天的数据。
2.3 算法实现
你要做的是,一开始先将 v v v初始化为0
v = 0
然后在第一天使 v : = β v + ( 1 − β ) θ 1 v:=\beta v+(1-\beta)\theta_1 v:=βv+(1−β)θ1
v = beta * v + (1 - beta) * theta_1
第二天继续更新 v v v值,使 v : = β v + ( 1 − β ) θ 2 v:=\beta v+(1-\beta)\theta_2 v:=βv+(1−β)θ2
v = beta * v + (1 - beta) * theta_2
以此类推,接下来每一天根据第
t
t
t天的数据,把
v
v
v更新为
v
t
=
β
v
θ
+
(
1
−
β
)
θ
t
v_t=\beta v_{\theta}+(1-\beta)\theta_t
vt=βvθ+(1−β)θt。
指数加权平均公式的好处之一在于,它占用极少内存,电脑内存中只占用一行数字而已,然后把最新数据代入公式,不断覆盖就可以了。但缺点是,如果保存所有最近的温度数据和过去10天的总和,必须占用更多的内存,执行更加复杂,计算成本也更加高昂。
2.4 偏差修正
2.4.1 偏差来源
在之前的章节中讲到,红色曲线对应的
β
\beta
β值为0.9,绿色曲线对应的
β
\beta
β值为0.98。但实际上,如果你执行公式
v
t
=
β
v
t
−
1
+
(
1
−
β
)
θ
t
v_t=\beta v_{t-1}+(1-\beta)\theta_t
vt=βvt−1+(1−β)θt,在
β
\beta
β等于0.98的时候,得到的并不是绿色曲线,而是紫色曲线,可以注意到紫色曲线的起点较低。
计算移动平均数的时候,首先初始化
v
0
v_0
v0
v
0
=
0
v_0=0
v0=0 因为
v
0
=
0
v_0=0
v0=0,所以
v
1
=
0.98
v
0
+
0.02
θ
1
=
0.02
θ
1
v_1=0.98v_0+0.02\theta_1=0.02\theta_1
v1=0.98v0+0.02θ1=0.02θ1 如果第一天的温度是40华氏度,那么
v
1
=
0.02
θ
1
=
0.02
∗
40
=
8
v_1=0.02\theta_1=0.02*40=8
v1=0.02θ1=0.02∗40=8,得到的值会比实际值小很多,所以第一天的温度估计不准确。
v
2
=
0.98
v
1
+
0.02
θ
2
v_2=0.98v_1+0.02θ_2
v2=0.98v1+0.02θ2 将
v
1
v_1
v1代入到
v
2
v_2
v2中
v
2
=
0.98
∗
0.02
θ
1
+
0.02
θ
2
=
0.0196
θ
1
+
0.02
θ
2
v_2=0.98*0.02\theta_1+0.02\theta_2=0.0196\theta_1+0.02\theta_2
v2=0.98∗0.02θ1+0.02θ2=0.0196θ1+0.02θ2 假设
θ
1
\theta_1
θ1和
θ
2
\theta_2
θ2都是正数,计算后
v
2
v_2
v2要远小于
θ
1
\theta_1
θ1和
θ
2
\theta_2
θ2,所以
v
2
v_2
v2不能很好地估算出这一年前两天的温度。
2.4.2 修正方法
在估测初期,不使用
v
t
v_t
vt,而是用
v
t
1
−
β
t
\frac{v_t}{1-\beta^t}
1−βtvt,其中
t
t
t是现在的天数。
举例来说,假设
t
=
2
t=2
t=2时,那么
1
−
β
t
=
1
−
0.9
8
2
=
0.0396
1-\beta^t=1-0.98^2=0.0396
1−βt=1−0.982=0.0396,因此对第二天温度的估测变成了
v
2
0.0396
=
0.0196
θ
1
+
0.02
θ
2
0.0396
\frac{v_2}{0.0396}=\frac{0.0196\theta_1+0.02\theta_2}{0.0396}
0.0396v2=0.03960.0196θ1+0.02θ2,也就是
θ
1
\theta_1
θ1和
θ
2
\theta_2
θ2的加权平均数,并且去除了偏差。随着
t
t
t增加,
β
t
\beta^t
βt接近于0,所以当
t
t
t很大的时候,偏差修正几乎没有作用,因此当
t
t
t较大的时候,紫线基本和绿线重合了。
3. 动量梯度下降法 (Gradient Descent with Momentum)
还有一种优化算法叫做Momentum,或者叫做动量梯度下降法,运行速度几乎总是快于标准的梯度下降算法,其基本的思路就是计算梯度的指数加权平均数,并利用该梯度更新你的权重。
3.1 案例说明
以优化成本函数为例,成本函数的形状如上图,红点代表最小值的位置。
以优化成本函数为例,假设从蓝点位置开始执行梯度下降,如果进行梯度下降的一次迭代,你会发现,无论是batch或mini-batch下降法,都会从起始点开始在这个椭圆范围内来回波动,然后一步一步梯度计算下去,慢慢摆动到最小值,这种上下波动减慢了梯度下降法的速度,你就无法使用更大的学习率(紫色曲线),如果你要用较大的学习率,结果可能会偏离函数的范围,因此为了避免摆动过大,你要用一个较小的学习率。
另一个看待问题的角度是,在纵轴上,你希望学习慢一点,因为你不想要这些摆动,但是在横轴上,你希望加快学习,能够快速从左向右移动,移向最小值。
3.2 算法实现
使用动量梯度下降法,你需要做的是,在每次迭代中,或者说在第
t
t
t次迭代的过程中,首先使用现有的mini-batch或batch来计算微分
d
W
dW
dW和
d
b
db
db,这里省略上标
[
l
]
[l]
[l]。
其次你要做的是通过指数加权平均来计算
v
d
W
v_{dW}
vdW和
v
d
b
v_{db}
vdb
v
d
W
=
β
v
d
W
+
(
1
−
β
)
d
W
v_{dW}=\beta v_{dW}+(1-\beta)dW
vdW=βvdW+(1−β)dW
v
d
b
=
β
v
d
b
+
(
1
−
β
)
d
b
v_{db}=\beta v_{db}+(1-\beta)db
vdb=βvdb+(1−β)db 然后重新赋值权重
W
:
=
W
−
α
v
d
W
W:=W-\alpha v_{dW}
W:=W−αvdW
b
:
=
b
−
α
v
d
b
b:=b-\alpha v_{db}
b:=b−αvdb 这样就可以减缓梯度下降的幅度。
这个算法中有两个超参数,即学习率
α
\alpha
α和参数
β
\beta
β,其中
β
\beta
β控制着指数加权平均数。
β
\beta
β最常用的值是0.9,我们之前平均了过去十天的温度,所以这里是平均了前十次迭代的梯度。
关于偏差修正,按照之前的公式,这里应该使用
v
d
W
1
−
β
t
\frac{v_{dW}}{1-\beta^t}
1−βtvdW和
v
d
b
1
−
β
t
\frac{v_{db}}{1-\beta^t}
1−βtvdb,但实际上人们不这么做,因为经过10次迭代之后,移动平均已经过了初始阶段,所以不会受到偏差修正的困扰。
v
d
W
v_{dW}
vdW的初始值是0,这是和
d
W
dW
dW以及
W
W
W拥有相同维数的零矩阵。同样的,
v
d
b
v_{db}
vdb的初始值也是向量零,并且和
d
b
db
db以及
b
b
b拥有相同的维数。
使用动量梯度下降法时,还会遇到另一种表达公式,即
1
−
β
1-\beta
1−β被删除了。
v
d
W
=
β
v
d
W
+
d
W
v_{dW}=\beta v_{dW}+dW
vdW=βvdW+dW 所以
v
d
W
v_{dW}
vdW缩小了
1
−
β
1-\beta
1−β倍,相当于乘以
1
1
−
β
\frac1{1-\beta}
1−β1,因此当你要使用梯度下降最新值的话,
α
\alpha
α也要根据
1
1
−
β
\frac1{1-\beta}
1−β1相应变化。实际上,二者效果都不错,只会影响到学习率
α
\alpha
α的最佳值。但是第二个公式使用起来没那么自然,它会有一个影响,如果最后要调整超参数
β
\beta
β,就会影响到
v
d
W
v_{dW}
vdW和
v
d
b
v_{db}
vdb,也许还要修改学习率
α
\alpha
α,因此更倾向于使用第一个公式。
3.3 本质理解
如果你要最小化的函数是碗状函数,微分项 d W dW dW和 d b db db相当于加速度,Momentum项 v d W v_{dW} vdW和 v d b v_{db} vdb相当于速度。假设你有一个碗,把一个球从碗的某个位置放下,微分项给了这个球一个加速度,此时球向下滚动,因为加速度的作用越滚越快,而因为 β \beta β稍小于1,相当于摩擦力作用,所以球不会无限加速下去,不像梯度下降法那样,每一步都独立于之前的步骤,你的球可以向下滚,从而获得动量。
4. RMSprop (Root Mean Square Rrop)
4.1 算法实现
在每一次迭代中,或者说在第
t
t
t次迭代中,首先RMSprop算法会计算当下mini-batch的微分
d
W
dW
dW和
d
b
db
db。
接着RMSprop会通过指数加权平均的方式计算
S
d
W
S_{dW}
SdW和
S
d
b
S_{db}
Sdb
S
d
W
=
β
S
d
W
+
(
1
−
β
)
(
d
W
)
2
S_{dW}=\beta S_{dW}+(1-\beta)(dW)^2
SdW=βSdW+(1−β)(dW)2
S
d
b
=
β
S
d
b
+
(
1
−
β
)
(
d
b
)
2
S_{db}=\beta S_{db}+(1-\beta)(db)^2
Sdb=βSdb+(1−β)(db)2 需要注意的是,这里的平方是针对整个符号的操作,这样做能够保留微分平方的加权平均数。
最后更新参数值
W
W
W和
b
b
b
W
:
=
W
−
α
d
W
S
d
W
+
ϵ
W:=W-\alpha \frac{dW}{\sqrt{S_{dW}}+\epsilon}
W:=W−αSdW+ϵdW
b
:
=
b
−
α
d
b
S
d
b
+
ϵ
b:=b-\alpha \frac{db}{\sqrt{S_{db}}+\epsilon}
b:=b−αSdb+ϵdb 为了确保这里不会除以0,在实际应用中,需要在分母上加上一个很小很小的
ϵ
\epsilon
ϵ,
ϵ
\epsilon
ϵ一般取
1
0
−
8
10^{−8}
10−8。
4.2 原理解释
以优化成本函数为例,假设纵轴代表参数
b
b
b,横轴代表参数
W
W
W。
在横轴方向或者说在例子中的
W
W
W方向,我们希望学习速度快,即希望
α
d
W
S
d
W
\alpha \frac{dW}{\sqrt{S_{dW}}}
αSdWdW较大,因此
S
d
W
S_{dW}
SdW会相对较小。
而在垂直方向,也就是例子中的
b
b
b方向,我们希望减缓纵轴上的摆动,也就是希望
b
b
b的浮动较小,即
α
d
b
S
d
b
\alpha \frac{db}{\sqrt{S_{db}}}
αSdbdb的值较小,所以需要分母上的
S
d
b
S_{db}
Sdb相对较大。
从上图中可以看到函数的倾斜程度,在纵轴上,也就是
b
b
b方向上的斜率要大于在横轴上的斜率,也就是
d
b
db
db较大,
d
W
dW
dW较小。
d
b
db
db的平方较大,所以
S
d
b
S_{db}
Sdb也会较大,而相比之下,
d
W
dW
dW会小一些,亦或
d
W
dW
dW平方会小一些,因此
S
d
W
S_{dW}
SdW会小一些,结果就是纵轴上的更新要被一个较大的数相除,就能消除摆动,而水平方向的更新则被较小的数相除,就能加快学习。
注:这里把纵轴和横轴方向分别称为
b
b
b和
W
W
W,只是为了方便展示而已。实际上,你会处于参数的高维度空间,可能是参数
W
1
W1
W1、
W
2
W2
W2、
W
3
W3
W3等的合集。同样的,
d
W
dW
dW和
d
b
db
db也是一个高维度的参数向量。
5. Adam优化算法 (Adam Optimization Algorithm)
5.1 算法实现
使用Adam算法,首先需要初始化
v
d
W
=
0
,
S
d
W
=
0
,
v
d
b
=
0
,
S
d
b
=
0
v_{dW}=0,S_{dW}=0,v_{db}=0,S_{db}=0
vdW=0,SdW=0,vdb=0,Sdb=0 接下来需要在第
t
t
t次迭代中计算微分,用当前的mini-batch计算
d
W
dW
dW和
d
b
db
db,一般会用mini-batch梯度下降法。
然后计算Momentum指数加权平均数
v
d
W
=
β
1
v
d
W
+
(
1
−
β
1
)
d
W
v_{dW}=\beta_1v_{dW}+(1-\beta_1)dW
vdW=β1vdW+(1−β1)dW
v
d
b
=
β
1
v
d
b
+
(
1
−
β
1
)
d
b
v_{db}=\beta_1v_{db}+(1-\beta_1)db
vdb=β1vdb+(1−β1)db 接着使用RMSprop进行更新,即使用不同的超参数
β
2
\beta_2
β2
S
d
W
=
β
2
S
d
W
+
(
1
−
β
2
)
(
d
W
)
2
S_{dW}=\beta_2S_{dW}+(1-\beta_2)(dW)^2
SdW=β2SdW+(1−β2)(dW)2
S
d
b
=
β
2
S
d
b
+
(
1
−
β
2
)
(
d
b
)
2
S_{db}=\beta_2S_{db}+(1-\beta_2)(db)^2
Sdb=β2Sdb+(1−β2)(db)2 相当于Momentum更新了超参数
β
1
\beta_1
β1,RMSprop更新了超参数
β
2
\beta_2
β2。
一般使用Adam算法的时候,要计算偏差修正
v
d
W
c
o
r
r
e
c
t
e
d
=
v
d
W
1
−
β
1
t
v_{dW}^{corrected}=\frac{v_{dW}}{1-\beta_1^t}
vdWcorrected=1−β1tvdW
v
d
b
c
o
r
r
e
c
t
e
d
=
v
d
b
1
−
β
1
t
v_{db}^{corrected}=\frac{v_{db}}{1-\beta_1^t}
vdbcorrected=1−β1tvdb
S
S
S也使用偏差修正,也就是
S
d
W
c
o
r
r
e
c
t
e
d
=
S
d
W
1
−
β
2
t
S_{dW}^{corrected}=\frac{S_{dW}}{1-\beta_2^t}
SdWcorrected=1−β2tSdW
S
d
b
c
o
r
r
e
c
t
e
d
=
S
d
b
1
−
β
2
t
S_{db}^{corrected}=\frac{S_{db}}{1-\beta_2^t}
Sdbcorrected=1−β2tSdb 最后更新参数值
W
:
=
W
−
α
v
d
W
c
o
r
r
e
c
t
e
d
S
d
W
c
o
r
r
e
c
t
e
d
+
ϵ
W:=W-\frac{\alpha v_{dW}^{corrected}}{\sqrt{S_{dW}^{corrected}}+\epsilon}
W:=W−SdWcorrected+ϵαvdWcorrected
b
:
=
b
−
α
v
d
b
c
o
r
r
e
c
t
e
d
S
d
b
c
o
r
r
e
c
t
e
d
+
ϵ
b:=b-\frac{\alpha v_{db}^{corrected}}{\sqrt{S_{db}^{corrected}}+\epsilon}
b:=b−Sdbcorrected+ϵαvdbcorrected 所以Adam算法结合了Momentum和RMSprop梯度下降法,并且是一种极其常用的学习算法,被证明能有效适用于不同神经网络以及适用于广泛的结构。
5.2 超参数的选择
(1) 学习率
α
\alpha
α:学习率
α
\alpha
α很重要,经常需要调试,你可以尝试一系列值,然后看哪个更有效。
(2) 移动加权平均系数
β
1
\beta_1
β1:常用的缺省值为0.9,这是
d
W
dW
dW的移动平均数,也就是
d
W
dW
dW的加权平均数,这是Momentum涉及的项。
(3) 移动加权平均系数
β
2
\beta_2
β2:Adam算法的发明者推荐使用0.999,这是在计算
(
d
W
)
2
(dW)^2
(dW)2以及
(
d
b
)
2
(db)^2
(db)2的移动加权平均值。
(4) 偏置项
ϵ
\epsilon
ϵ:
ϵ
\epsilon
ϵ的选择其实没那么重要,Adam论文的作者建议
ϵ
\epsilon
ϵ为
1
0
−
8
10^{-8}
10−8,但你并不需要设置它,因为它并不会影响算法表现。
6. 学习率衰减 (Learning Rate Decay)
6.1 概念解释
加快学习算法的一个办法就是随时间慢慢减少学习率。
假设你要使用mini-batch梯度下降法,mini-batch数量不大,大约是64或者128个样本,在迭代过程中会有噪音(蓝色曲线),下降朝向最小值,但是不会精确地收敛,所以最后会在最小值附近摆动,并不会真正收敛,因为使用的学习率
α
\alpha
α是固定值,不同的mini-batch中有噪音。
但要慢慢减少学习率
α
\alpha
α的话,在初期的时候,学习率
α
\alpha
α还较大,学习还是相对较快,但随着
α
\alpha
α变小,步伐也会变慢变小,所以最后会在最小值附近的一小块区域里摆动(绿色曲线),而不是在训练过程中,大幅度在最小值附近摆动。
所以慢慢减少
α
\alpha
α的本质在于,在学习初期,学习率大一些,能以较大的步伐向最小值下降,但当开始收敛的时候,小一些的学习率能让步伐小一些。
6.2 学习率衰减的方法
方法 | 备注 |
---|---|
α = 1 1 + d e c a y r a t e ∗ e p o c h _ n u m α 0 \alpha=\frac{1}{1\ +\ decay\ rate\ *\ epoch\_num}\alpha_0 α=1 + decay rate ∗ epoch_num1α0 | decay-rate为衰减率,epoch-num为代数,即遍历训练集的次数, α 0 \pmb{\alpha_0} α0α0α0为初始学习率 |
α = 0.9 5 e p o c h _ n u m α 0 \alpha=0.95^{epoch\_num}\alpha_0 α=0.95epoch_numα0 | 学习率呈指数下降 |
α = k e p o c h _ n u m α 0 \alpha=\frac{k}{\sqrt{epoch\_num}}\alpha_0 α=epoch_numkα0或 α = k t α 0 \alpha=\frac{k}{\sqrt{t}}\alpha_0 α=tkα0 | t t t为mini-batch的数字 |
离散下降(discrete stair cease) |
7. 局部最优的问题 (The Problem of Local Optima)
在深度学习研究早期,人们总是担心优化算法会困在极差的局部最优,不过随着深度学习理论不断发展,我们对局部最优的理解也发生了改变。
上图是曾经人们在想到局部最优时脑海里会出现的图,在图中似乎各处都分布着局部最优。梯度下降法或者某个算法可能困在一个局部最优中,而不会抵达全局最优。如果你要作图计算一个数字,比如在上图的两个维度中,就容易出现有多个不同局部最优的图,而这些低维的图曾经影响了我们的理解,但是这些理解并不正确。事实上,如果你要创建一个神经网络,通常梯度为零的点并不是这个图中的局部最优点,实际上成本函数的零梯度点,通常是鞍点。
但是一个具有高维度空间的函数,如果梯度为0,那么在每个方向,它可能是凸函数,也可能是凹函数。假设你在一个2万维空间中,想要得到局部最优,那么所有的2万个方向都需要是凹函数或者都是凸函数,但这样子发生的机率也许很小,大概只有
1
2
20000
\frac{1}{2^{20000}}
2200001,而更有可能遇到有些方向的曲线会向上弯曲,另一些方向曲线向下弯曲,而不是所有的都向上弯曲,因此在高维度空间,你更可能碰到鞍点,而不会碰到局部最优。
而另一个问题是在平稳段会减缓学习,平稳段是一块区域,其中导数长时间接近于0,如果你在此处,梯度会从曲面自上而下地下降,因为梯度等于或接近0,曲面很平坦,你得花上很长时间慢慢抵达平稳段的这个点(蓝色曲线),然后因为左边或右边的随机扰动,你的算法能够走出平稳段(红色曲线)。
总结一下这部分的要点:
第一,你不太可能困在极差的局部最优中,除非是在训练较大的神经网络,存在大量参数,并且成本函数
J
J
J被定义在较高的维度空间。
第二,平稳段是一个问题,这会使得学习十分缓慢,在这种情况下,使用更成熟的优化算法,如Adam算法,能够加快速度,让你尽早往下走出平稳段。