“糟糕”的初始化会导致什么
在 Xavier 初始化被提出之前,人们通常使用非常简单的方法,比如从一个很小的正态分布(如 N(0, 0.01)
)中采样来初始化权重。这在浅层网络中或许可行,但在深度网络中会引发灾难性的梯度消失(Vanishing Gradients) 或梯度爆炸(Exploding Gradients) 问题。
让我们直观地理解一下:
- 信号的前向传播: 每一层的输出(激活值)是下一层的输入。如果权重过小,每次通过一层,信号的“能量”(用方差来衡量)就会衰减。经过很多层后,信号可能变得微乎其微,导致网络学不到东西。
- 梯度的反向传播: 梯度从后向前传播。如果权重过小,梯度每传播一层也会衰减。传到浅层网络时,梯度几乎为零,导致浅层参数无法更新。这就是梯度消失。
- 反之亦然: 如果权重过大,信号和梯度在逐层传播中会指数级增长,最终导致数值溢出,模型崩溃。这就是梯度爆炸。
初始化的核心目标:找到一种初始化权重的方法,使得信息(无论是前向的激活值还是反向的梯度)在网络中传播时,其统计特性(主要是均值和方差)能够保持稳定。我们希望每一层的输出方差和输入方差大致相同,每一层梯度的方差也和后一层梯度的方差大致相同。这是一个“刚刚好”的“金发姑娘问题”(Goldilocks problem)。
Xavier初始化的数学推导
Xavier初始化的全部推导,都围绕着这个核心目标:保持输入和输出的方差一致。
1. 建立模型和假设
我们来看一个没有激活函数的线性层:
- : 层的输入,有 个。
- : 权重。
- : 层的输出之一。
现在,我们做出几个关键且合理的假设:
- H1: 权重 和输入 是相互独立的。
- H2: 每一个权重 都从同一个分布中独立采样。这个分布的均值为0,方差为 。即 ,。
- H3: 每一个输入 也来自同一个分布,其均值为0,方差为 。即 ,。
- (为什么假设均值为0?这在实践中很常见,比如数据经过标准化处理,或前一层是
tanh
等零中心激活函数)。
- (为什么假设均值为0?这在实践中很常见,比如数据经过标准化处理,或前一层是
2. 推导前向传播的方差
我们的目标是计算输出 的方差 ,并让它等于输入的方差 。
第一步:计算 的均值
根据期望的线性性质,可以把求和与期望交换:
因为 和 相互独立(H1),所以 。
根据假设 H2 和 H3,我们知道 且 。
结论1: 如果输入和权重的均值都为0,那么输出的均值也为0。
第二步:计算 的方差 这是推导的核心。我们需要用到方差的两个关键性质:
- 对于独立变量 ,有 。
- 。
开始计算:
由于各个 项之间是相互独立的(因为 和 都是独立采样的),我们可以将方差的求和变为求和的方差:
现在,我们需要计算 。利用性质2:
因为 和 独立,所以 。
我们知道 ,当 时,。所以:
- (来自 H2)
- (来自 H3)
代入上式,得到:
最后,我们把它代回到 的求和式中:
结论2: 输出的方差是输入方差的 倍。
3. 得到前向传播的条件
我们的目标是保持方差不变,即 。
两边消去 ,得到前向传播的稳定条件:
4. 推导反向传播的方差
梯度也是信号,我们也希望它在反向传播时方差保持稳定。假设该层的输出是 维。反向传播时,层的输入梯度 是由输出梯度 计算得来的:
这个公式的结构和前向传播惊人地相似!我们可以用完全相同的逻辑进行推导,只是角色互换:
- 输入变成了 个输出梯度 。
- 输出是输入梯度 。
- 权重仍然是 。
直接套用我们刚刚得到的结论2的结构:
为了让反向传播的梯度方差也保持稳定,即 ,我们得到反向传播的稳定条件:
5. 正向传播与反向传播稳定的最终妥协:Xavier 初始化
现在我们面临一个困境:
- 为了前向传播稳定,需要 。
- 为了反向传播稳定,需要 。
当 时,这两个条件是矛盾的。Xavier 和 Bengio 提出,一个合理的妥协是使用这两者的调和平均数。
这就是 Xavier 初始化的核心思想和最终公式! 它试图同时兼顾前向和反向传播的稳定性。
实践与局限
如何使用这个方差?
我们已经知道了权重的理想方差,但如何生成符合这个方差的随机数呢?通常有两种方法:
-
Xavier 正态分布初始化 (Xavier Normal): 直接从一个均值为0,方差为 的正态分布中采样。
-
Xavier 均匀分布初始化 (Xavier Uniform): 从一个均匀分布 中采样。均匀分布的方差是 。 我们令这个方差等于我们想要的方差:
所以,我们从均匀分布 中采样。 这是 PyTorch 中
nn.init.xavier_uniform_
的默认实现。
Xavier 的局限性
我们整个推导是基于一个线性单元的,没有考虑激活函数。Xavier 的原论文分析了 tanh
和 sigmoid
这类“类线性”的激活函数(它们在0附近近似于线性函数 ),并发现这个初始化效果很好。
但是,对于现代神经网络中最常用的 ReLU 激活函数,Xavier 初始化就不再完美了。因为 ReLU 会将所有负数输入强制变为0,这会改变输出的分布,使其方差大约减半。为了解决这个问题,Kaiming He 等人提出了Kaiming (He) 初始化,它专门针对 ReLU 及其变体设计,其推导过程与 Xavier 类似,但考虑了 ReLU 的影响,最终得到 。