👨🎓作者简介:一位即将上大四,正专攻机器学习的保研er
🌌上期文章:机器学习&&深度学习——Dropout
📚订阅专栏:机器学习&&深度学习
希望文章对你们有所帮助
这一部分包括了很多概率论和数学的知识,而书上的推导很少,这边会做个比较细致的讨论,数学基础不行就去补,不能拖,深入浅出的感觉是最让人感到心情愉悦的。
数值稳定性和模型初始化
- 梯度消失和梯度爆炸
- 梯度消失
- 梯度爆炸
- 让训练更加稳定
- 参数初始化
- 讨论(各种概率论思维推导)
- 默认初始化
- Xavier初始化
梯度消失和梯度爆炸
一个具有L层、输入x和输出o的深层网络。每一层l由f定义,变换的参数权重为W(l),其隐藏变量为h(l)(令h(0)=x)。则我们的网络可以定义为:
h
(
l
)
=
f
l
(
h
(
l
−
1
)
)
因此
o
=
f
L
○
.
.
.
○
f
1
(
x
)
h^{(l)}=f_l(h^{(l-1)})因此o=f_L○...○f_1(x)
h(l)=fl(h(l−1))因此o=fL○...○f1(x)
若所有隐藏向量和输入都是向量,我们可以将o关于任何一组参数W{(l)}的梯度写为:
∂
h
(
L
−
1
)
h
(
L
)
⋅
.
.
.
⋅
∂
h
(
l
)
h
(
l
+
1
)
∂
w
(
l
)
h
(
l
)
\partial_h(L-1)h^{(L)}·...·\partial_h(l)h^{(l+1)}\partial_w(l)h^{(l)}
∂h(L−1)h(L)⋅...⋅∂h(l)h(l+1)∂w(l)h(l)
换言之,该梯度是一个L-l个矩阵M(L)·…·M(l+1)与梯度向量v{l}的乘积。
这么多的乘积放在一起会出现严重的问题:可能会造成梯度的不稳定。要么是梯度爆炸:参数更新过大,破坏了模型的稳定收敛;要么是梯度消失:参数更新过小,在每次更新时几乎不会移动,导致模型无法学习。
梯度消失
sigmoid就是一个造成梯度消失的常见原因,我们可以绘制sigmoid函数以及它的导数函数观察:
import torch
from d2l import torch as d2l
x = torch.arange(-8.0, 8.0, 0.1, requires_grad=True)
y = torch.sigmoid(x)
y.backward(gradient=torch.ones_like(x)) # 参与的参数是非标量的时候,就需要指定gradient为和x形状相同的全1向量(矩阵)
d2l.plot(x.detach().numpy(), [y.detach().numpy(), x.grad.numpy()],
legend=['sigmoid', 'gradient'], figsize=(4.5, 2.5))
d2l.plt.show()
如上图,当sigmoid函数的输入很大或者很小时梯度会消失。此外,当反向传播通过许多层时,除非函数的输入接近于0,否则整个成绩的梯度都可能会消失。因此,更稳定的ReLU系列函数已经成为从业者的默认选择(虽然在神经科学的角度看起来不太合理)。
梯度爆炸
梯度爆炸可能同样令人烦恼。 为了更好地说明这一点,我们生成100个高斯随机矩阵,并将它们与某个初始矩阵相乘。 对于我们选择的尺度(方差σ2=1),矩阵乘积发生爆炸。当这种情况是由于深度网络的初始化所导致时,我们没有机会让梯度下降优化器收敛。
import torch
M = torch.normal(0, 1, size=(4, 4))
print('一个矩阵\n', M)
for i in range(100):
M = torch.mm(M, torch.normal(0, 1, size=(4, 4)))
print('乘以100个矩阵后\n', M)
一个矩阵
tensor([[ 2.2266, 0.1844, -0.1071, -0.7712],
[-0.1580, -0.3028, -0.9375, -0.2922],
[ 0.0616, -1.1593, 1.8516, 1.6285],
[ 0.2703, -0.5483, -0.6187, -1.2804]])
乘以100个矩阵后
tensor([[ 1.3260e+25, -6.2655e+25, 1.2841e+25, 1.5429e+25],
[ 1.5770e+24, -7.4518e+24, 1.5273e+24, 1.8351e+24],
[ 8.5330e+23, -4.0321e+24, 8.2638e+23, 9.9294e+23],
[ 5.7656e+24, -2.7244e+25, 5.5837e+24, 6.7091e+24]])
让训练更加稳定
而如何让我们的训练更加稳定呢?也就是要避免掉梯度消失和梯度爆炸问题。
目标:让梯度值在合理范围内,如[1e-6,1e3]
将乘法变加法:ResNet,LSTM
归一化:梯度归一化,梯度裁剪
合理的权重和激活函数(这是我们的重点)
参数初始化
减轻上面问题的一种方法就是进行参数初始化,优化期间的注意以及适当的正则化也可以使得训练更加的稳定。
讨论(各种概率论思维推导)
我们现在做一个假设:
(1)假设w都是独立同分布的,那么:
E
[
w
i
,
j
t
]
=
0
,
D
[
w
i
,
j
t
]
=
γ
t
2
E[w_{i,j}^t]=0,D[w_{i,j}^t]=γ_t^2
E[wi,jt]=0,D[wi,jt]=γt2
(2)ht-1独立于wt(也就是层的权重与输入是无关的)
我们大胆假设此时没有激活函数,那么
h
t
=
W
t
h
t
−
1
,这里
W
t
∈
R
n
t
×
n
t
−
1
h^t=W^th^{t-1},这里W^t∈R^{n_t×n_{t-1}}
ht=Wtht−1,这里Wt∈Rnt×nt−1
则容易推出:
E
[
h
i
t
]
=
E
[
∑
j
w
i
,
j
t
h
j
t
−
1
]
=
∑
j
E
[
w
i
,
j
]
E
[
h
j
t
−
1
]
=
0
(独立同分布的推广)
E[h_i^t]=E[\sum_jw_{i,j}^th_j^{t-1}]=\sum_jE[w_{i,j}]E[h_j^{t-1}]=0(独立同分布的推广)
E[hit]=E[j∑wi,jthjt−1]=j∑E[wi,j]E[hjt−1]=0(独立同分布的推广)
此时我们分别计算正向方差与反向方差,并且让他们都相同。
正向方差
D
[
h
i
t
]
=
E
[
(
h
i
t
)
2
]
−
E
[
h
i
t
]
2
=
E
[
(
∑
j
w
i
,
j
t
h
j
t
−
1
)
2
]
(前面假设过独立同分布那么
E
[
h
i
t
]
=
0
)
=
E
[
∑
j
(
w
i
,
j
t
)
2
(
h
j
t
−
1
)
2
+
∑
j
≠
k
w
i
,
j
t
w
i
,
k
t
h
j
t
−
1
h
k
t
−
1
]
(这里就是
(
a
+
b
+
c
+
.
.
.
)
2
的计算方式)
由于独立同分布,所以
∑
j
≠
k
w
i
,
j
t
w
i
,
k
t
h
j
t
−
1
h
k
t
−
1
=
0
,则
上式
=
∑
j
E
[
(
w
i
,
j
t
)
2
]
E
[
(
h
j
t
−
1
)
2
]
=
∑
j
(
E
[
(
w
i
,
j
t
)
2
]
−
E
[
w
i
,
j
t
]
2
)
(
E
[
(
h
j
t
−
1
)
2
]
−
E
[
h
j
t
−
1
]
2
)
(构造出
D
)
=
∑
j
D
[
w
i
,
j
t
]
D
[
h
j
t
−
1
]
=
n
t
−
1
γ
t
2
D
[
h
j
t
−
1
]
D[h_i^t]=E[(h_i^t)^2]-E[h_i^t]^2=E[(\sum_jw_{i,j}^th_j^{t-1})^2](前面假设过独立同分布那么E[h_i^t]=0)\\ =E[\sum_j(w_{i,j}^t)^2(h_j^{t-1})^2+\sum_{j≠k}w_{i,j}^tw_{i,k}^th_j^{t-1}h_k^{t-1}](这里就是(a+b+c+...)^2的计算方式)\\ 由于独立同分布,所以\sum_{j≠k}w_{i,j}^tw_{i,k}^th_j^{t-1}h_k^{t-1}=0,则\\ 上式=\sum_jE[(w_{i,j}^t)^2]E[(h_j^{t-1})^2]\\ =\sum_j(E[(w_{i,j}^t)^2]-E[w_{i,j}^t]^2)(E[(h_j^{t-1})^2]-E[h_j^{t-1}]^2)(构造出D)\\ =\sum_jD[w_{i,j}^t]D[h_j^{t-1}]=n_{t-1}γ_t^2D[h_j^{t-1}]
D[hit]=E[(hit)2]−E[hit]2=E[(j∑wi,jthjt−1)2](前面假设过独立同分布那么E[hit]=0)=E[j∑(wi,jt)2(hjt−1)2+j=k∑wi,jtwi,kthjt−1hkt−1](这里就是(a+b+c+...)2的计算方式)由于独立同分布,所以j=k∑wi,jtwi,kthjt−1hkt−1=0,则上式=j∑E[(wi,jt)2]E[(hjt−1)2]=j∑(E[(wi,jt)2]−E[wi,jt]2)(E[(hjt−1)2]−E[hjt−1]2)(构造出D)=j∑D[wi,jt]D[hjt−1]=nt−1γt2D[hjt−1]
我们让t层输入的反差与输出的方差都是相同的,那么可以推出:
n
t
−
1
γ
t
2
=
1
(其中
n
t
−
1
代表第
t
层输入的规模)
n_{t-1}γ_t^2=1(其中n_{t-1}代表第t层输入的规模)
nt−1γt2=1(其中nt−1代表第t层输入的规模)
其他层也是同理的。
反向方差
而反向和正向的情况就类似了,可以这么推导:
∂
l
∂
h
t
−
1
=
∂
l
∂
h
t
W
t
\frac{\partial l}{\partial h^{t-1}}=\frac{\partial l}{\partial h^t}W^t
∂ht−1∂l=∂ht∂lWt
分别取转置,得:
(
∂
l
∂
h
t
−
1
)
T
=
(
W
t
)
T
(
∂
l
∂
h
t
)
T
(\frac{\partial l}{\partial h^{t-1}})^T=(W^t)^T(\frac{\partial l}{\partial h^t})^T
(∂ht−1∂l)T=(Wt)T(∂ht∂l)T
依旧假设:
E
[
∂
l
∂
h
i
t
−
1
]
=
0
E[\frac{\partial l}{\partial h_i^{t-1}}]=0
E[∂hit−1∂l]=0
则
D
[
∂
l
∂
h
i
t
−
1
]
=
n
t
γ
t
2
D
[
∂
l
∂
h
j
t
]
D[\frac{\partial l}{\partial h_i^{t-1}}]=n_tγ_t^2D[\frac{\partial l}{\partial h_j^t}]
D[∂hit−1∂l]=ntγt2D[∂hjt∂l]
这时我们可以推出:
n
t
γ
t
2
=
1
(其中
n
t
代表第
t
层输出的规模)
n_tγ_t^2=1(其中n_t代表第t层输出的规模)
ntγt2=1(其中nt代表第t层输出的规模)
其他层也是同理的。
照着上面的方式推下去,我们最终整合起来的结论是
n
t
−
1
γ
t
2
=
1
和
n
t
γ
t
2
=
1
n_{t-1}γ_t^2=1和n_tγ_t^2=1
nt−1γt2=1和ntγt2=1
显然我们要满足上面的式子,当且仅当:
n
t
−
1
=
n
t
n_{t-1}=n_t
nt−1=nt
这并不容易满足,因为我们很难说对于一层中,我们的输入和输出的规模(神经元的数量)是相同的。
接下来就会谈到Xavier初始化,将会用另外一种方式来解决这一问题。
默认初始化
在前面的学习中,我们初始化权重值的方式都是使用正态分布来。而如果我们不指定初始化方法的话,框架会使用默认的随机初始化方法(比如Linear就会提供,具体原理可以自行去了解),简单问题用默认初始化还是很有效的。
Xavier初始化
回到之前的讨论,我们已知很难同时满足
n
t
−
1
γ
t
2
=
n
t
γ
t
2
=
1
n_{t-1}γ_t^2=n_tγ_t^2=1
nt−1γt2=ntγt2=1
我们推广到每一层,即为:
n
i
n
σ
2
=
n
o
u
t
σ
2
=
1
n_{in}\sigma^2=n_{out}\sigma^2=1
ninσ2=noutσ2=1
虽然难以满足输入和输出规模相同,但是我们可以先将两个式子相加并调整:
σ
2
(
n
i
n
+
n
o
u
t
)
/
2
=
1
→
σ
=
2
(
n
i
n
+
n
o
u
t
)
\sigma^2(n_{in}+n_{out})/2=1→\sigma=\sqrt\frac{2}{(n_{in}+n_{out})}
σ2(nin+nout)/2=1→σ=(nin+nout)2
对于上面的式子,我们就可以有两种采样方式:
(1)Xavier初始化从均值为0,方差为
σ
2
=
2
n
i
n
+
n
o
u
t
\sigma^2=\frac{2}{n_{in}+n_{out}}
σ2=nin+nout2
的高斯分布中采样权重,即为
正态分布
N
(
0
,
2
n
i
n
+
n
o
u
t
)
正态分布N(0,\sqrt\frac{2}{n_{in}+n_{out}})
正态分布N(0,nin+nout2)
(2)从均匀分布从抽取权重时的方差,我们先注意一个定理:
均匀分布
U
(
−
a
,
a
)
的方差为
a
2
3
均匀分布U(-a,a)的方差为\frac{a^2}{3}
均匀分布U(−a,a)的方差为3a2
此时我们将其带入到σ2的条件中,将得到初始化值域:
均匀分布
U
(
−
6
n
i
n
+
n
o
u
t
,
6
n
i
n
+
n
o
u
t
)
均匀分布U(-\sqrt\frac{6}{n_{in}+n_{out}},\sqrt\frac{6}{n_{in}+n_{out}})
均匀分布U(−nin+nout6,nin+nout6)