小批次梯度下降
该算法在之前也讨论过,对于数据量很大的训练集,我们将其拆分为若干小训练集,每次向前传播与向后传播都只用拆分出来的小集合,这样只需要遍历整个训练集一次,大大提高了训练速度。
一个小批次的大小通常选择2的幂次,如 64 , 128 , 512 , 1024 64,128,512,1024 64,128,512,1024,尽量让一个小批次的数据可以装进计算机内存中。
动量梯度下降
将每次我们计算出的梯度用指数加权平均变换一下,作为参数的更新量。具体来讲,设每次迭代求出的梯度为
d
W
i
,
d
b
i
dW_i,db_i
dWi,dbi,我们将更新值变为
V
d
W
=
β
1
V
d
W
+
(
1
−
β
1
)
d
W
i
V
d
b
=
β
1
V
d
b
+
(
1
−
β
1
)
d
b
i
V_{dW}=\beta_1 V_{dW}+(1-\beta_1)dW_i\\ V_{db}=\beta_1 V_{db}+(1-\beta_1)db_i
VdW=β1VdW+(1−β1)dWiVdb=β1Vdb+(1−β1)dbi然后让
W
=
W
−
α
V
d
W
,
b
=
b
−
α
V
d
b
W=W-\alpha V_{dW},b=b-\alpha V_{db}
W=W−αVdW,b=b−αVdb,完成一次更新。
从链接文章我们可以看到,指数加权平均近似于对前 1 1 − β \frac{1}{1-\beta} 1−β1个数据求平均,通过这种平均,可以让梯度中一些震荡相互抵消,而同向的部分不变,从而使得收敛速度更快。
一般来讲,取 β = 0.9 \beta=0.9 β=0.9为比较稳健的选择,也可以将其作为一个超参数在验证集里试验。而偏差修正并不常用,因为在 1 1 − β \frac{1}{1-\beta} 1−β1次训练以后加权平均值就已经没什么偏差了,而训练的迭代次数通常都是成百上千,额外增添一个只对前十几项有效的偏差修正没什么必要。
均方根传递
使用指数加权平均计算梯度的平方,在更新的时候除以该值的平方根。具体来讲,我们先用指数加权平均统计求得梯度的平方
S
d
W
=
β
2
S
d
W
+
(
1
−
β
2
)
d
W
i
2
S
d
b
=
β
2
S
d
b
+
(
1
−
β
2
)
d
b
i
2
S_{dW}=\beta_2S_{dW}+(1-\beta_2)dW_i^2\\ S_{db}=\beta_2S_{db}+(1-\beta_2)db_i^2\\
SdW=β2SdW+(1−β2)dWi2Sdb=β2Sdb+(1−β2)dbi2
然后令
W
=
W
−
α
d
W
S
d
W
+
ε
b
=
b
−
α
d
b
S
d
b
+
ε
W=W-\alpha\frac{dW}{\sqrt{S_{dW}}+\varepsilon}\\ b=b-\alpha\frac{db}{\sqrt{S_{db}}+\varepsilon}\\
W=W−αSdW+εdWb=b−αSdb+εdb就完成了一次更新,其中
ε
\varepsilon
ε是为了防止分母变成0而添加的微小常数,一般取
1
0
−
8
10^{-8}
10−8。
该算法的原理其实与归一化有些相似,除掉梯度的均方根后,原本较大的梯度变动会变小,而小的变动会放大,相当于将各个维度的梯度变化均衡了一下。
Adam优化
结合了小批次梯度下降、动量梯度下降与均方根传递的究极缝合怪!
对于每次反向传播后得到的梯度
d
W
i
,
d
b
i
dW_i,db_i
dWi,dbi,我们不仅把它们本身指数加权平均,还把平方指数加权平均,然后用一阶矩除以二阶矩的平方根作为更新值,即
V
d
W
=
β
1
V
d
W
+
(
1
−
β
1
)
d
W
i
,
V
d
b
=
β
1
V
d
b
+
(
1
−
β
1
)
d
b
i
S
d
W
=
β
2
S
d
W
+
(
1
−
β
2
)
d
W
i
2
,
S
d
b
=
β
2
S
d
b
+
(
1
−
β
2
)
d
b
i
2
V
d
W
=
V
d
W
/
(
1
−
β
1
t
)
,
V
d
b
=
V
d
b
/
(
1
−
β
1
t
)
S
d
W
=
S
d
W
/
(
1
−
β
2
t
)
,
S
d
b
=
S
d
b
/
(
1
−
β
2
t
)
W
=
W
−
α
V
d
W
S
d
W
+
ε
,
b
=
b
−
α
V
d
b
S
d
b
+
ε
V_{dW}=\beta_1 V_{dW}+(1-\beta_1)dW_i,V_{db}=\beta_1 V_{db}+(1-\beta_1)db_i\\ S_{dW}=\beta_2S_{dW}+(1-\beta_2)dW_i^2,S_{db}=\beta_2S_{db}+(1-\beta_2)db_i^2\\ V_{dW}=V_{dW}/(1-\beta_1^t),V_{db}=V_{db}/(1-\beta_1^t)\\ S_{dW}=S_{dW}/(1-\beta_2^t),S_{db}=S_{db}/(1-\beta_2^t)\\ W=W-\alpha\frac{V_{dW}}{\sqrt{S_{dW}}+\varepsilon},b=b-\alpha\frac{V_{db}}{\sqrt{S_{db}}+\varepsilon}
VdW=β1VdW+(1−β1)dWi,Vdb=β1Vdb+(1−β1)dbiSdW=β2SdW+(1−β2)dWi2,Sdb=β2Sdb+(1−β2)dbi2VdW=VdW/(1−β1t),Vdb=Vdb/(1−β1t)SdW=SdW/(1−β2t),Sdb=Sdb/(1−β2t)W=W−αSdW+εVdW,b=b−αSdb+εVdb
之前吴恩达还讲偏差修正没必要,转头就在这里加上了偏差修正,可能是因为两个优化结合起来以后对偏差的要求变高了?
有四个超参数,除了 α \alpha α以外,其他三个参数惯用的值为 β 1 = 0.9 , β 2 = 0.999 , ε = 1 0 − 8 \beta_1=0.9,\beta_2=0.999,\varepsilon=10^{-8} β1=0.9,β2=0.999,ε=10−8。
学习率衰减
在收敛过程中,可能会出现求解点在全局最优解附近持续徘徊的情况,这是因为步距太大导致求解点没法准确移动到最优解。一个可行的解决方法是让学习率逐渐衰减,在迭代的后期步距越来越小,从而能准确地踩到全局最优解上。使
α
\alpha
α衰减的方法有很多,我们可以令遍历整个数据集的次数为
epoch_num
\text{epoch\_num}
epoch_num,有众多可选的公式:
α
=
1
1
+
k
∗
epoch_num
α
0
α
=
k
epoch_num
α
0
α
=
k
epoch_num
α
0
\alpha=\frac{1}{1+k*\text{epoch\_num}}\alpha_0\\ \alpha=k^\text{epoch\_num}\alpha_0\\ \alpha=\frac{k}{\sqrt\text{epoch\_num}}\alpha_0
α=1+k∗epoch_num1α0α=kepoch_numα0α=epoch_numkα0其中
k
k
k为可调整的超参数。
或者令 α \alpha α随着训练时间递减,或者人工调整皆可。