考虑一个具有 L L L层、输入 x \mathbf{x} x和输出 o \mathbf{o} o的深层网络。每一层 l l l由变换 f l f_l fl定义,该变换的参数为权重 W ( l ) \mathbf{W}^{(l)} W(l),其隐藏变量是 h ( l ) \mathbf{h}^{(l)} h(l)(令 h ( 0 ) = x \mathbf{h}^{(0)} = \mathbf{x} h(0)=x)。
考虑有L层的网络可以表示为:
h ( l ) = f l ( h ( l − 1 ) ) 因此 o = l o s s ∗ f L ∗ … ∗ f 1 ( x ) . \mathbf{h}^{(l)} = f_l (\mathbf{h}^{(l-1)}) \text{ 因此 } \mathbf{o} = loss * f_L * \ldots * f_1(\mathbf{x}). h(l)=fl(h(l−1)) 因此 o=loss∗fL∗…∗f1(x).
计算损失loss关于任何一组参数 W ( l ) \mathbf{W}^{(l)} W(l)的梯度写为下式:
∂ l o s s ∂ w l = ∂ l o s s ∂ h L ∂ h L ∂ h L − 1 . . . ∂ h l + 1 ∂ h l ∂ h l ∂ w l \frac{\partial loss}{\partial w^l} = \frac{\partial loss}{\partial h^L} \frac{\partial h^L}{\partial h^{L-1}} ... \frac{\partial h_{l+1}}{\partial h^l} \frac{\partial h^l}{\partial w^l} ∂wl∂loss=∂hL∂loss∂hL−1∂hL...∂hl∂hl+1∂wl∂hl
换言之,该梯度是 L − l L-l L−l个矩阵 M ( L ) ⋅ … ⋅ M ( l + 1 ) \mathbf{M}^{(L)} \cdot \ldots \cdot \mathbf{M}^{(l+1)} M(L)⋅…⋅M(l+1)与梯度向量 v ( l ) \mathbf{v}^{(l)} v(l)的乘积。因此,我们容易受到数值下溢问题的影响,当将太多的概率乘在一起时,这些问题经常会出现。在处理概率时,一个常见的技巧是切换到对数空间,即将数值表示的压力从尾数转移到指数。不幸的是,我们上面的问题更为严重:最初,矩阵 M ( l ) \mathbf{M}^{(l)} M(l) 可能具有各种各样的特征值。他们可能很小,也可能很大,他们的乘积可能非常大,也可能非常小。
不稳定梯度带来的风险不止在于数值表示。不稳定梯度也威胁到我们优化算法的稳定性。我们可能面临一些问题:
f l ( h l − 1 ) = σ ( W l h l − 1 ) (1) f_l(h^{l-1}) = \sigma(W^lh^{l-1}) \tag{1} fl(hl−1)=σ(Wlhl−1)(1) σ \sigma σ 是激活函数
∂ h l ∂ h l − 1 = d i a g ( σ ′ ( W l h l − 1 ) ) ( W l ) T (2) \frac{\partial h^l}{\partial h^{l-1}} = diag(\sigma '(W^lh^{l-1}))(W^l)^T \tag{2} ∂hl−1∂hl=diag(σ′(Wlhl−1))(Wl)T(2)
∏ i = l L − 1 ∂ h i + 1 ∂ h i = ∏ i = l L − 1 d i a g ( σ ′ ( W l h l − 1 ) ) ( W l ) T (3) \prod_{i=l}^{L-1}\frac{\partial h^{i+1}}{\partial h^{i}} = \prod_{i=l}^{L-1}diag(\sigma '(W^lh^{l-1}))(W^l)^T \tag{3} i=l∏L−1∂hi∂hi+1=i=l∏L−1diag(σ′(Wlhl−1))(Wl)T(3)
使用relu作为激活函数
σ ( x ) = m a x ( 0 , x ) a n d σ ′ ( x ) = { 1 , x > 0 0 , o t h e r w i s e (4) \sigma(x) = max(0,x) \quad and \quad \sigma '(x) = \begin{cases} 1,\quad x>0\\ 0, \quad otherwise \end{cases} \tag{4} σ(x)=max(0,x)andσ′(x)={1,x>00,otherwise(4)
L-l
很大,最终得到的梯度的值非常大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)
使用sigmoid作为激活函数:
σ ( x ) = 1 1 − e x (5) \sigma (x) = \frac{1}{1-e^x} \tag{5} σ(x)=1−ex1(5)
sigmoid激活函数的导数为:
σ ′ ( x ) = σ ( x ) ( 1 − σ ( x ) ) (6) \sigma '(x) = \sigma (x)(1-\sigma(x)) \tag{6} σ′(x)=σ(x)(1−σ(x))(6)
∏ i = l L − 1 ∂ h i + 1 ∂ h i = ∏ i = l L − 1 d i a g ( σ ′ ( W l h l − 1 ) ) ( W l ) T \prod_{i=l}^{L-1}\frac{\partial h^{i+1}}{\partial h^{i}} = \prod_{i=l}^{L-1}diag(\sigma '(W^lh^{l-1}))(W^l)^T ∏i=lL−1∂hi∂hi+1=∏i=lL−1diag(σ′(Wlhl−1))(Wl)T 的元素是L-l
个小数值进行乘 0. 8 100 ≈ 2 × 1 0 − 10 0.8^{100} \approx 2 \times 10^{-10} 0.8100≈2×10−10
# 下面这是sigmoid激活函数的图像和其导数图像,可以看到sigmoid函数的导数在输入较大的时候输出接近于0
%matplotlib inline
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(torch.ones_like(x))
d2l.plot(x.detach().numpy(), [y.detach().numpy(), x.grad.numpy()],
legend=['sigmoid', 'gradient'], figsize=(4.5, 2.5))
目前为止,模型的参数都是根据某种预先指定的分布设计的,我们认为是理所当然的,却忽略了如何作出这些选择的细节。
但是,初始化方案的选择在神经网络学习中起着非常重要的作用,其对保持数值稳定性至关重要。
初始化方案的选择和非线性激活函数的选择相结合,决定了优化算收敛的速度有多块,糟糕的选择会导致我们在训练时遇到梯度爆炸或者梯度消失。
在合理值的区间随机初始化参数
在训练开始的时候更容易有数值不稳定
使用 N ( 0 , 0.01 ) N(0,0.01) N(0,0.01)初始化小网络没有问题,但是不能保证深度神经网络
正向
E [ h i l ] = 0 V a r [ h i l ] = a (3.1) E[h_{i}^{l}] = 0 \quad Var[h_{i}^{l}] = a \tag{3.1} E[hil]=0Var[hil]=a(3.1)
反向
E [ ∂ L o s s h i l ] = 0 V a r [ ∂ L o s s h i l ] = b (3.2) E[\frac{\partial{Loss}}{h_{i}^{l}}] = 0 \quad Var[\frac{\partial{Loss}}{h_{i}^{l}}] = b \tag{3.2} E[hil∂Loss]=0Var[hil∂Loss]=b(3.2)
如果不加上非线性全连接层:该层 n i n n_\mathrm{in} nin输入 x j x_j xj及其相关权重 w i j w_{ij} wij,输出由下式给出
o i = ∑ j = 1 n i n w i j x j (3.3) o_{i} = \sum_{j=1}^{n_\mathrm{in}} w_{ij} x_j \tag{3.3} oi=j=1∑ninwijxj(3.3)
权重 w i j w_{ij} wij都是从同一分布中独立抽取的。此外,让我们假设该分布具有零均值和方差 σ 2 \sigma^2 σ2。请注意,这并不意味着分布必须是高斯的,只是均值和方差需要存在。现在,让我们假设层 x j x_j xj的输入也具有零均值和方差 γ 2 \gamma^2 γ2,并且它们独立于 w i j w_{ij} wij并且彼此独立。在这种情况下,我们可以按如下方式计算 o i o_i oi的平均值和方差:
E [ o i ] = ∑ j = 1 n i n E [ w i j x j ] = ∑ j = 1 n i n E [ w i j ] E [ x j ] = 0 , V a r [ o i ] = E [ o i 2 ] − ( E [ o i ] ) 2 = ∑ j = 1 n i n E [ w i j 2 x j 2 ] − 0 = ∑ j = 1 n i n E [ w i j 2 ] E [ x j 2 ] = n i n σ 2 γ 2 . (3.4) \begin{aligned} E[o_i] & = \sum_{j=1}^{n_\mathrm{in}} E[w_{ij} x_j] \\&= \sum_{j=1}^{n_\mathrm{in}} E[w_{ij}] E[x_j] \\&= 0,\tag{3.4} \\ \mathrm{Var}[o_i] & = E[o_i^2] - (E[o_i])^2 \\ & = \sum_{j=1}^{n_\mathrm{in}} E[w^2_{ij} x^2_j] - 0 \\ & = \sum_{j=1}^{n_\mathrm{in}} E[w^2_{ij}] E[x^2_j] \\ & = n_\mathrm{in} \sigma^2 \gamma^2. \end{aligned} E[oi]Var[oi]=j=1∑ninE[wijxj]=j=1∑ninE[wij]E[xj]=0,=E[oi2]−(E[oi])2=j=1∑ninE[wij2xj2]−0=j=1∑ninE[wij2]E[xj2]=ninσ2γ2.(3.4)
保持方差不变的一种方法是设置 n i n σ 2 = 1 n_\mathrm{in} \sigma^2 = 1 ninσ2=1。现在考虑反向传播过程,我们面临着类似的问题,尽管梯度是从更靠近输出的层传播的。使用与正向传播相同的推理,我们可以看到,除非 n o u t σ 2 = 1 n_\mathrm{out} \sigma^2 = 1 noutσ2=1,否则梯度的方差可能会增大,其中 n o u t n_\mathrm{out} nout是该层的输出的数量。这使我们进退两难:我们不可能同时满足这两个条件。相反,我们只需满足:
1 2 ( n i n + n o u t ) σ 2 = 1 或等价于 σ = 2 n i n + n o u t . (3.5) \begin{aligned} \frac{1}{2} (n_\mathrm{in} + n_\mathrm{out}) \sigma^2 = 1 \text{ 或等价于 } \sigma = \sqrt{\frac{2}{n_\mathrm{in} + n_\mathrm{out}}}. \end{aligned} \tag{3.5} 21(nin+nout)σ2=1 或等价于 σ=nin+nout2.(3.5)
这就是现在标准且实用的Xavier初始化的基础,它以其提出者Glorot.Bengio.2010
第一作者的名字命名。通常,Xavier初始化从均值为零,方差 σ 2 = 2 n i n + n o u t \sigma^2 = \frac{2}{n_\mathrm{in} + n_\mathrm{out}} σ2=nin+nout2的高斯分布中采样权重。我们也可以利用Xavier的直觉来选择从均匀分布中抽取权重时的方差。注意均匀分布 U ( − a , a ) U(-a, a) U(−a,a)的方差为 a 2 3 \frac{a^2}{3} 3a2。将 a 2 3 \frac{a^2}{3} 3a2代入到 σ 2 \sigma^2 σ2的条件中,将得到初始化的建议:
U ( − 6 n i n + n o u t , 6 n i n + n o u t ) (3.6) U\left(-\sqrt{\frac{6}{n_\mathrm{in} + n_\mathrm{out}}}, \sqrt{\frac{6}{n_\mathrm{in} + n_\mathrm{out}}}\right) \tag{3.6} U(−nin+nout6,nin+nout6)(3.6)
尽管上述数学推理中,不存在非线性的假设在神经网络中很容易被违反,但Xavier初始化方法在实践中被证明是有效的。
假设 σ ( x ) = α x + β (3.7) \sigma(x) = \alpha x + \beta \tag{3.7} σ(x)=αx+β(3.7)
h ′ = W l h l − 1 a n d h l = σ ( h ′ ) (3.8) h' = W^lh^{l-1} \quad and \quad h^l = \sigma(h') \tag{3.8} h′=Wlhl−1andhl=σ(h′)(3.8)
那么此层输出的均值和方差可以表示为:
E [ h i l ] = E [ α h i ′ + β ] = β (3.9) E[h_{i}^{l}] = E[\alpha h_i'+\beta] = \beta \tag{3.9} E[hil]=E[αhi′+β]=β(3.9)
V a r [ h i l ] = E [ ( h i l ) 2 ] − E [ ( h i l ) ] 2 = E [ ( α h i ′ + β ) 2 ] − β 2 = E [ α 2 ( h i ′ ) 2 + 2 α β h i ′ + β 2 ] − β 2 = α 2 V a r [ h i ′ ] (3.10) \begin{aligned} Var[h_{i}^{l}] &= E[(h_{i}^{l})^2] - E[(h_{i}^{l})]^2\\ & = E[(\alpha h_i' +\beta)^2] - \beta ^2\\ & = E[\alpha ^2(h_i')^2 + 2\alpha \beta h_i' + \beta^2] - \beta^2\\ & = \alpha^2Var[h_i'] \end{aligned} \tag{3.10} Var[hil]=E[(hil)2]−E[(hil)]2=E[(αhi′+β)2]−β2=E[α2(hi′)2+2αβhi′+β2]−β2=α2Var[hi′](3.10)
如果说要让激活函数不改变均值和方差,那么: β = 0 α = 1 \beta = 0 \quad \alpha = 1 β=0α=1
那么激活函数就等于本身了
反向一下看看
假设 σ ( x ) = α x + β (3.7) \sigma(x) = \alpha x + \beta \tag{3.7} σ(x)=αx+β(3.7)
h ′ = W l h l − 1 a n d h l = σ ( h ′ ) (3.8) h' = W^lh^{l-1} \quad and \quad h^l = \sigma(h') \tag{3.8} h′=Wlhl−1andhl=σ(h′)(3.8)
∂ l o s s ∂ h ′ = ∂ l o s s ∂ h l ( W l ) T a n d ∂ l o s s ∂ h l − 1 = α ∂ l o s s ∂ h ′ (3.11) \frac{\partial loss}{\partial{h'}} = \frac{\partial loss}{\partial{h^l}}(W^l)^T \quad and \quad \frac{\partial loss}{\partial{h^{l-1}}} = \alpha \frac{\partial loss}{\partial{h'}} \tag{3.11} ∂h′∂loss=∂hl∂loss(Wl)Tand∂hl−1∂loss=α∂h′∂loss(3.11)
E [ ∂ l o s s ∂ h i l − 1 ] = 0 (3.12) E[\frac{\partial{loss}}{\partial h_i^{l-1}}] = 0 \tag{3.12} E[∂hil−1∂loss]=0(3.12)
V a r [ ∂ l o s s ∂ h i l − 1 ] = α 2 V a r [ ∂ l o s s ∂ h j ′ ] (3.13) Var[\frac{\partial{loss}}{\partial h_i^{l-1}}] = \alpha^2Var[\frac{\partial loss}{\partial h_j'}] \tag{3.13} Var[∂hil−1∂loss]=α2Var[∂hj′∂loss](3.13)
那么 β = 0 α = 1 \beta = 0 \quad \alpha = 1 β=0α=1