观文听傑

返回

上一篇把损失沿计算图反传到了每一层,也看到深度会让局部 Jacobian 连乘。反向传播算法本身没有错,网络却可能在第一步更新前就已经“失声”:前向激活逐层缩成接近 0,或放大到溢出;反向梯度也会发生同样的指数级变化。

参数初始化(Parameter Initialization)不是随便给权重一点随机噪声。它要解决一个具体问题:在训练刚开始时,让信号和梯度穿过很多层后仍保持可用尺度,同时打破神经元之间的对称。 本文只追踪独立同分布近似下的方差,推导 Xavier 与 He 初始化,并把推导变成可执行的逐层体检。

01 全部设成 0 为什么不是最稳妥?#

考虑含两个隐单元的全连接层。若两个神经元的权重和偏置都相同,它们接收同一输入、输出同一激活、反传得到同一梯度,之后每一步也仍然相同。宽度为 2 的层实际只学出一个重复特征,这叫对称性(Symmetry)没有被打破。

随机初始化可以打破对称,但“随机”仍缺少尺度。设每层权重标准差都为 0.01,深层信号可能不断缩小;设为 1,又可能不断放大。初始化真正需要回答的是:权重方差应该怎样随输入连接数变化?

02 一层线性变换怎样改变方差?#

先看第 ll 层某个神经元的预激活:

zj(l)=i=1ninWji(l)ai(l1)+bj(l)z_j^{(l)}=\sum_{i=1}^{n_{\text{in}}}W_{ji}^{(l)}a_i^{(l-1)}+b_j^{(l)}

其中:

  • a(l1)Rnina^{(l-1)}\in\mathbb{R}^{n_{\text{in}}} 是上一层激活;
  • W(l)Rnout×ninW^{(l)}\in\mathbb{R}^{n_{\text{out}}\times n_{\text{in}}}
  • z(l),b(l)Rnoutz^{(l)},b^{(l)}\in\mathbb{R}^{n_{\text{out}}}
  • mini-batch 版本中,A(l1)[N,nin]A^{(l-1)}[N,n_{\text{in}}]W.T[n_in,n_out] 相乘,得到 Z(l)[N,nout]Z^{(l)}[N,n_{\text{out}}]

在初始化分析的近似里,假设权重与输入相互独立、均值为 0,各分量方差相同,偏置先设为 0。不同求和项的协方差于是近似为 0:

Var(zj(l))ninVar(Wji(l))Var(ai(l1))\operatorname{Var}(z_j^{(l)}) \approx n_{\text{in}}\operatorname{Var}(W_{ji}^{(l)}) \operatorname{Var}(a_i^{(l-1)})

这条式子揭示了危险:若 ninVar(W)=0.5n_{\text{in}}\operatorname{Var}(W)=0.5,线性信号每层约减半;若等于 2,则每层约翻倍。连续 20 层后,倍率分别是 0.5209.5×1070.5^{20}\approx9.5\times10^{-7}2201062^{20}\approx10^6

A⁽ˡ⁻¹⁾ [N,n_in]
   │  每个输出累加 n_in 项

Z⁽ˡ⁾ = A⁽ˡ⁻¹⁾ @ W⁽ˡ⁾ᵀ + b⁽ˡ⁾   [N,n_out]

   │  非线性还会截断或压缩分布

A⁽ˡ⁾ = φ(Z⁽ˡ⁾)                  [N,n_out]

目标:Var(A⁽ˡ⁾) 不随 l 指数消失或爆炸
text

03 用四个输入手算“尺度错误”#

设四个独立输入均值为 0、方差为 1,即 nin=4n_{\text{in}}=4

若权重方差为 11

Var(z)=4×1×1=4\operatorname{Var}(z)=4\times1\times1=4

一层后标准差从 1 变为 2。十个相同线性层后,标准差近似变为 210=10242^{10}=1024

若权重方差为 1/41/4

Var(z)=4×14×1=1\operatorname{Var}(z)=4\times\frac14\times1=1

线性层前后的方差保持不变。于是最直接的前向原则是:

Var(W)1nin\operatorname{Var}(W)\approx\frac{1}{n_{\text{in}}}

但神经网络在线性层后还有激活函数。上一篇使用的 ReLU 会把负值截成 0,不能继续沿用纯线性结论。

04 ReLU 为什么把 He 方差变成 2/fan_in?#

zz 的分布关于 0 对称,ReLU 输出 a=max(0,z)a=\max(0,z)。大约一半样本被置 0;在忽略非零均值带来的细微差别时,其二阶矩约保留一半:

E[a2]12E[z2]\mathbb{E}[a^2]\approx\frac12\mathbb{E}[z^2]

要让经过“线性层 + ReLU”后的二阶矩仍与输入接近,线性层应先放大约 2 倍:

Var(W)=2nin\operatorname{Var}(W)=\frac{2}{n_{\text{in}}}

这就是 He 初始化(He Initialization),在 PyTorch API 中也称 Kaiming 初始化(Kaiming Initialization)。若从均匀分布 U(a,a)U(-a,a) 采样,因为其方差为 a2/3a^2/3,需要:

a=6nina=\sqrt{\frac{6}{n_{\text{in}}}}

若从正态分布采样,则标准差为:

σ=2nin\sigma=\sqrt{\frac{2}{n_{\text{in}}}}

05 Xavier 为什么同时看 fan_in 与 fan_out?#

对 tanh 或近似线性的激活,前向保持方差希望:

Var(W)1nin\operatorname{Var}(W)\approx\frac{1}{n_{\text{in}}}

反向时,设流入本层的梯度为 δ(l)[N,nout]\delta^{(l)}[N,n_{\text{out}}],传向上一层的梯度为:

δ(l1)=δ(l)W(l)\delta^{(l-1)}=\delta^{(l)}W^{(l)}

每个输入方向累加 noutn_{\text{out}} 项,因此反向保持梯度方差希望:

Var(W)1nout\operatorname{Var}(W)\approx\frac{1}{n_{\text{out}}}

当扇入(Fan-in)与扇出(Fan-out)不同,两者无法同时精确满足。Xavier/Glorot 初始化取折中:

Var(W)=2nin+nout\operatorname{Var}(W)=\frac{2}{n_{\text{in}}+n_{\text{out}}}

正态版标准差为 2/(nin+nout)\sqrt{2/(n_{\text{in}}+n_{\text{out}})};均匀版边界为 6/(nin+nout)\sqrt{6/(n_{\text{in}}+n_{\text{out}})}。它通常适合 tanh、sigmoid 的近线性区域或无激活线性层;ReLU 隐层更常使用 He。

初始化权重方差(典型)主要匹配对象直觉
固定小高斯与宽度无关层越宽,累计方差越大
Xavier2/(fan_in+fan_out)2/(fan\_in+fan\_out)tanh / 近线性折中前向与反向
He/Kaiming2/fan_in2/fan\_inReLU 前向补偿约一半信号被截断
正交初始化由矩阵奇异值控制深线性/循环结构等尽量保持方向长度

06 完整初始化伪代码#

初始化必须与“这个权重后面接什么激活”匹配,而不是按层类名机械选择。输出层的尺度还取决于损失:二分类 logits、回归值和 softmax 前分数不应盲目套用同一 gain。

07 不依赖框架,验证方差公式#

下面用 NumPy 构造 20 层 ReLU 网络,不训练,只比较固定小方差、Xavier 与 He。代码显式写出 W[nout,nin]W[n_{out},n_{in}]x @ W.T

预期不是每层标准差精确等于 1,而是看数量级:small 很快接近 0;Xavier 在 ReLU 链中通常逐层衰减;He 在有限宽度的随机波动下更能维持可用尺度。若把激活换成 tanh,结论和合适 gain 也会变化。

08 用 PyTorch 2.13 正确初始化#

PyTorch 2.13 官方 torch.nn.init 提供 xavier_uniform_xavier_normal_kaiming_uniform_kaiming_normal_calculate_gain。这些函数会原地修改参数,并在 torch.no_grad() 语义下执行。

官方文档对 Kaiming 的一个关键提醒是:函数假设线性层按 x @ weight.T 使用,weight.shape=[fan_out,fan_in],这正是 nn.Linear 的约定。若你自己保存的是 [fan_in,fan_out] 且计算 x @ weight,应把 weight.T 传给初始化函数,否则 fan 方向会算反。

mode="fan_in" 更关注前向方差,mode="fan_out" 更关注反向方差。普通前馈网络常从 fan_in 开始;不要仅因为“梯度也重要”就给每层混用不同模式。

09 一次前向加反向,怎样定位第一层异常?#

前向钩子(Forward Hook)适合短期诊断,不应无界保存带计算图的输出;这里立即 detach() 并在结束时移除 handle。检查时重点找相邻层之间的突变,而不是迷信“std 必须等于 1”。

10 卷积层的 fan 怎样数?#

对二维卷积权重 W[out_channels,in_channels,k_h,k_w],每个输出位置累加的输入数是:

fan_in=in_channels×kh×kwfan\_in=in\_channels\times k_h\times k_w

每个输入方向影响的典型输出连接数是:

fan_out=out_channels×kh×kwfan\_out=out\_channels\times k_h\times k_w

因此不能只拿通道数计算初始化尺度。PyTorch 的初始化函数会根据张量形状处理常见线性与卷积权重;分组卷积、转置卷积或自定义张量布局则应额外核对 fan 的语义和真实乘法方向。

11 常见错误与最短调试路径#

  1. 每层复制同一组随机权重。 数值不是 0 也可能保留神经元对称;每个参数需要独立采样。
  2. ReLU 隐层使用过小固定标准差。 先打印每层激活 std,找到首次跌落一个数量级的层。
  3. fan_in 当成权重第 0 维。 nn.Linear.weight[fan_out,fan_in],先写出实际矩阵乘法。
  4. Leaky ReLU 忘记负斜率 a kaiming_*a 应与激活的 negative_slope 一致。
  5. 初始化后又被构造器或 checkpoint 覆盖。 在加载权重之后检查参数统计;恢复训练通常不应重新初始化。
  6. 只看参数分布,不看真实输入。 输入尺度、偏置、残差相加与归一化都会改变信号;至少用一批经过真实预处理的数据体检。
  7. 把随机波动误判为错误。 固定种子,多次初始化比较分布区间;宽度很小时理论近似本来就噪声更大。

一个实用的排查顺序是:输入均值/标准差 → 每层预激活 → 激活零比例 → loss 是否有限 → 每层梯度 → 一步更新比。第一个异常层比最后的 NaN 更有信息。

12 初始化解决不了什么?#

  • 极深网络中的相关性和 Jacobian 奇异值分布,不由逐层标量方差完全描述;
  • tanh/sigmoid 若被大偏置或异常输入推入饱和区,合适权重方差也救不回局部导数;
  • ReLU 神经元训练中可能长期落在负区,He 初始化只能降低起步时大面积死亡的风险;
  • 注意力、门控循环、残差分支和输出头常有架构特定初始化规则;
  • 混合精度下的溢出、错误损失缩放与过大学习率属于训练数值问题;
  • 初始化不能替代归一化、残差连接、合理优化器和数据标准化。

Xavier/He 关注的是分量方差。正交初始化进一步控制线性变换的奇异值,但经过非线性、宽度变化和训练后也不再精确等距。归一化则在运行时根据激活统计调整尺度,与只在训练开始执行一次的初始化完全不同。

13 今天真正需要记住什么?#

  1. 随机初始化同时承担打破对称与控制尺度;“不是 0”远远不够。
  2. 线性层近似满足 Var(z)fan_inVar(W)Var(a)\operatorname{Var}(z)\approx fan\_in\operatorname{Var}(W)\operatorname{Var}(a)
  3. Xavier 用 fan_infan\_infan_outfan\_out 折中前向和反向,He 用 2/fan_in2/fan\_in 补偿 ReLU 截断。
  4. 选择初始化时必须同时写出权重布局、真实矩阵乘法和后续激活。
  5. 最可靠的验收是一批真实输入上的逐层激活与梯度体检,而不是只打印首层权重标准差。

14 思考题与小练习#

  1. 一个 Linear(200, 50) 后接 ReLU。分别计算 He 正态初始化的标准差、He 均匀初始化的边界,以及 Xavier 正态初始化的标准差。为什么三者不同?
  2. 把 NumPy 实验中的 ReLU 改成纯线性和 tanh,分别比较三种初始化在 20 层后的标准差。tanh 的均值、饱和比例还应怎样记录?
  3. 构造一个宽度依次为 [64, 512, 32, 256] 的 MLP,故意把自定义权重保存为 [fan_in,fan_out]。先错误初始化,再按官方说明传入转置张量,比较逐层激活统计。

相关工作#

15 下一篇预告#

健康初始化让第一批信号能够穿过网络,但每一步仍可能沿狭长损失谷底左右振荡,或让不同参数因梯度尺度差异而进度悬殊。下一篇将把反传得到的梯度变成更新轨迹,手算 Momentum 的速度累积与 Adam 的一、二阶矩和偏差修正。

网络加深后信号为何消失?Xavier 与 He 初始化如何守住方差
https://zwjcode.cn/blog/xavier-he-initialization-signal-variance
作者
发布于 2026年9月1日
版权协议 CC BY-NC-SA 4.0
评论加载似乎遇到了问题,请尝试刷新页面。