十、权值初始化
1、梯度消失与爆炸
上图中,
H
2
=
H
1
×
W
2
H_2 = H_1 \times W_2
H2=H1×W2,则
W
2
W_2
W2的梯度为:
Δ
W
2
=
∂
L
o
s
s
∂
W
2
=
∂
L
o
s
s
∂
o
u
t
×
∂
o
u
t
∂
H
2
×
∂
H
2
∂
W
2
=
∂
L
o
s
s
∂
o
u
t
×
∂
o
u
t
∂
H
2
×
H
1
\Delta W_2 = \frac{\partial{Loss}}{\partial{W_2}} = \frac{\partial{Loss}}{\partial{out}}\times\frac{\partial{out}}{\partial{H_2}}\times \frac{\partial{H_2}}{\partial{W_2}} = \frac{\partial{Loss}}{\partial{out}}\times\frac{\partial{out}}{\partial{H_2}}\times H_1
ΔW2=∂W2∂Loss=∂out∂Loss×∂H2∂out×∂W2∂H2=∂out∂Loss×∂H2∂out×H1
可以看到,
W
2
W_2
W2的梯度是与
H
1
H_1
H1相关的,而
H
1
H_1
H1是第一层神经元的输出,因此:
梯度消失:
H
1
→
0
⇒
Δ
W
2
→
0
梯度爆炸
:
H
1
→
∞
⇒
Δ
W
2
→
∞
\begin{array}{l} \text { 梯度消失: } \mathrm{H}_{1} \rightarrow \mathbf{0} \qquad \Rightarrow \qquad \Delta \mathrm{W}_{2} \rightarrow \mathbf{0} \\ \text { 梯度爆炸 }: \mathrm{H}_{1} \rightarrow \infty \qquad \Rightarrow \qquad \Delta \mathrm{W}_{2} \rightarrow \infty \end{array}
梯度消失: H1→0⇒ΔW2→0 梯度爆炸 :H1→∞⇒ΔW2→∞
以
H
1
H_1
H1中的第一个为例
H
11
H_{11}
H11为例,显然,
H
11
=
∑
i
=
0
n
X
i
×
W
1
i
\mathrm{H}_{11}=\sum_{i=0}^{n} X_{i} \times W_{1 i}
H11=∑i=0nXi×W1i,则:
V
a
r
(
H
11
)
=
∑
i
=
0
n
V
a
r
(
X
i
)
×
V
a
r
(
W
1
i
)
这里必须有独立性假设和零均值假设
=
n
×
(
1
×
1
)
=
n
这里认为方差均为1
\begin{array}{l}Var(H_{11}) = \sum_{i=0}^{n}Var(X_i)\times Var(W_{1i}) \qquad \text{这里必须有独立性假设和零均值假设}\\ = n \times (1 \times 1) = n \qquad \qquad \qquad \qquad \qquad \qquad \text{这里认为方差均为1} \end{array}
Var(H11)=∑i=0nVar(Xi)×Var(W1i)这里必须有独立性假设和零均值假设=n×(1×1)=n这里认为方差均为1
从这里可以看出,输入的数据的方差为1,但仅仅经过了一个前向传播,方差变为了
n
n
n,标准差就变为了
n
\sqrt{n}
n,同理,如果传播到
H
2
H_2
H2,则标准差就变为
n
n
n,因此越往后面传播,标准差越大,数据的范围也越来越大,最终超过数据可表示的范围,引发nan
。如何控制神经网络中的方差呢?很简单,我们只需要让
V
a
r
(
H
1
)
=
n
×
V
a
r
(
X
)
V
a
r
(
W
)
=
1
Var(H_1) = n\times Var(X)Var(W)=1
Var(H1)=n×Var(X)Var(W)=1即可,那么就需要
V
a
r
(
W
)
=
1
n
Var(W) = \frac{1}{n}
Var(W)=n1,即每一层传播的方差均为
1
n
\frac{1}{n}
n1,这样就能使整个神经元的方差稳定下来。
2、Xavier方法与Kaiming方法
- 方差一致性:保持数据尺度维持在恰当范围,通常方差为1
- 针对神经网络中存在激活函数的情况,应该如何初始化以满足方差一致性?这里介绍两种初始化方法:Xavier初始化和Kaiming初始化
(1)Xavier
方法
Xavier初始化方法是针对于饱和函数例如Sigmoid函数或者Tanh函数使用的
对于某一层神经网络,同时考虑前向传播和后向传播,则必须满足下面两个等式:
n
i
×
V
a
r
(
W
)
=
1
n
i
+
1
×
V
a
r
(
W
)
=
1
\begin{aligned} n_i \times Var(W) = 1 \\ n_{i+1} \times Var(W ) = 1 \end{aligned}
ni×Var(W)=1ni+1×Var(W)=1
n
i
n_i
ni为输入层神经元个数,
n
i
+
1
为
输
出
层
神
经
元
个
数
;
n_{i+1}为输出层神经元个数;
ni+1为输出层神经元个数;因此,
V
a
r
(
W
)
=
2
n
i
+
n
i
+
1
Var(W) = \frac{2}{n_i+n_{i+1} }
Var(W)=ni+ni+12,通常
X
a
v
i
e
r
Xavier
Xavier采用的是均匀分布,则设
W
∼
[
−
a
,
a
]
W \sim [-a,a]
W∼[−a,a],根据:
V
a
r
(
W
)
=
a
2
3
=
2
n
i
+
n
i
+
1
⇒
a
=
6
n
i
+
n
i
+
1
Var(W) = \frac{a^2}{3} = \frac{2}{n_i+n_{i+1} } \Rightarrow a = \frac{\sqrt{6}}{\sqrt{n_i+n_{i+1}}}
Var(W)=3a2=ni+ni+12⇒a=ni+ni+16
因此我们得到
W
W
W的分布为:
W
∼
U
[
−
6
n
i
+
n
i
+
1
,
6
n
i
+
n
i
+
1
]
W \sim U \left[-\frac{\sqrt{6}}{\sqrt{n_i+n_{i+1}}}, \frac{\sqrt{6}}{\sqrt{n_i+n_{i+1}}} \right]
W∼U[−ni+ni+16,ni+ni+16]
代码实例:
(2) Kaiming
方法
Xavier初始化方法是针对于ReLU
函数及其变种
对于ReLU
激活函数:
V
a
r
(
W
)
=
2
n
i
Var(W) = \frac{2}{n_i}
Var(W)=ni2
对于ReLU
变种:
V
a
r
(
W
)
=
2
(
1
+
a
2
)
×
n
i
Var(W) = \frac{2}{(1 + a^2)\times n_i}
Var(W)=(1+a2)×ni2,
a
a
a为负半轴斜率
代码实例:
3、常用初始化方法
不良的初始化会引起输出值过大或过小,从而引发梯度爆炸或梯度消失,导致模型无法正常训练,PyTorch
中提供了十种初始化方法,可分为四大类:
-
Xavier
方法: -
Xavier均匀分布
-
Xavier正态分布
-
Kaiming
方法: -
Kaiming均匀分布
-
Kaiming正态分布
-
常见分布初始化:
-
均匀分布
-
正态分布
-
常数分布
-
特殊矩阵初始化:
-
正交矩阵初始化
-
单位矩阵初始化
-
稀疏矩阵初始化
函数:nn.init.calculate_gain(nonlinearity, param=None)
:
- 功能:计算激活函数的方差变化尺度
- 主要参数:
nonlinearity
:激活函数名称param
:激活函数的参数,如Leaky ReLU的negative_slop
- 实例:
x = torch.randn(10000)
out = torch.tanh(x)
gain = x.std() / out.std()
print('gain:{}'.format(gain))
tanh_gain = nn.init.calculate_gain('tanh')
print('tanh_gain in PyTorch:', tanh_gain)
# gain:1.5982500314712524
# tanh_gain in PyTorch: 1.6666666666666667