神经网络参数初始化详解:为什么重要、常用方法及其优缺点

神经网络参数初始化详解:为什么重要、常用方法及其优缺点

1. 引言

在神经网络中,模型结构、损失函数和优化器经常受到更多关注,但参数初始化同样会直接影响模型是否能够顺利训练。

所谓参数初始化,是指在正式训练开始之前,为神经网络中的权重和偏置指定初始数值。例如,一个全连接层可以写为:

z(l)=W(l)a(l−1)+b(l)\mathbf{z}^{(l)}=\mathbf{W}^{(l)}\mathbf{a}^{(l-1)}+\mathbf{b}^{(l)}z(l)=W(l)a(l−1)+b(l)

其中:

  • W(l)\mathbf{W}^{(l)}W(l) 是第 lll 层的权重矩阵;
  • b(l)\mathbf{b}^{(l)}b(l) 是第 lll 层的偏置向量;
  • a(l−1)\mathbf{a}^{(l-1)}a(l−1) 是上一层输出;
  • z(l)\mathbf{z}^{(l)}z(l) 是当前层进入激活函数之前的线性输出。

训练开始时,优化器并不是从"完全空白"的状态开始搜索,而是从初始化参数所在的位置开始调整。因此,初始化实际上决定了优化问题的起点。

初始化不合理时,模型可能出现:

  • 所有神经元学习相同内容;
  • 前向传播的数值迅速变大或变小;
  • 激活函数进入饱和区;
  • 梯度消失;
  • 梯度爆炸;
  • 收敛速度极慢;
  • 损失函数变成 NaN
  • 即使训练很久也难以达到较好结果。

初始化合理时,模型通常可以:

  • 打破神经元之间的对称性;
  • 保持各层激活值的合理尺度;
  • 保持梯度在深层网络中的稳定传播;
  • 提高训练速度;
  • 降低模型对学习率的敏感程度;
  • 提高训练过程的稳定性。

因此,参数初始化不是一个无关紧要的细节,而是深度神经网络能够被成功训练的重要条件。


2. 神经网络中有哪些参数需要初始化

神经网络中的主要可训练参数包括:

  1. 权重矩阵;
  2. 偏置向量;
  3. 归一化层的缩放参数与平移参数;
  4. 嵌入层参数;
  5. 循环神经网络中的门控参数;
  6. 注意力模块中的投影矩阵。

其中,最需要重点设计的是权重矩阵的初始化。

对于普通全连接层:

z=Wx+b\mathbf{z}=\mathbf{W}\mathbf{x}+\mathbf{b}z=Wx+b

通常需要初始化:

W∈Rnout×nin\mathbf{W}\in\mathbb{R}^{n_{\mathrm{out}}\times n_{\mathrm{in}}}W∈Rnout×nin

b∈Rnout\mathbf{b}\in\mathbb{R}^{n_{\mathrm{out}}}b∈Rnout

这里:

  • ninn_{\mathrm{in}}nin 表示输入神经元数量;
  • noutn_{\mathrm{out}}nout 表示输出神经元数量。

在初始化方法中,这两个数量通常称为:

fan_in=nin\mathrm{fan\in}=n{\mathrm{in}}fan_in=nin

fan_out=nout\mathrm{fan\out}=n{\mathrm{out}}fan_out=nout

对于卷积层,fan_infan_out 还需要考虑卷积核尺寸和通道数。


3. 参数初始化为什么重要

3.1 打破神经元之间的对称性

假设一个隐藏层中有两个神经元,并且它们的权重和偏置全部初始化为相同数值。

两个神经元的输出分别为:

z1=w1Tx+b1z_1=\mathbf{w}_1^{\mathrm{T}}\mathbf{x}+b_1z1=w1Tx+b1

z2=w2Tx+b2z_2=\mathbf{w}_2^{\mathrm{T}}\mathbf{x}+b_2z2=w2Tx+b2

如果:

w1=w2\mathbf{w}_1=\mathbf{w}_2w1=w2

b1=b2b_1=b_2b1=b2

那么对于任意输入,都有:

z1=z2z_1=z_2z1=z2

经过相同激活函数之后:

a1=a2a_1=a_2a1=a2

在反向传播过程中,两个神经元接收到的梯度也完全相同,因此它们的参数更新仍然相同。

这意味着两个神经元始终学习相同的特征,相当于浪费了一个神经元。

因此,神经网络的权重不能全部初始化为相同值,而需要通过随机初始化打破对称性。

3.2 控制前向传播的数值尺度

假设某一层包含 ninn_{\mathrm{in}}nin 个输入:

zj=∑i=1ninwjiaiz_j=\sum_{i=1}^{n_{\mathrm{in}}}w_{ji}a_izj=i=1∑ninwjiai

为了便于分析,假设:

  • wjiw_{ji}wji 与 aia_iai 相互独立;
  • 权重均值为 0;
  • 输入均值为 0;
  • 各个输入具有相同方差。

那么可以近似得到:

Var(zj)=ninVar(wji)Var(ai)\mathrm{Var}(z_j)=n_{\mathrm{in}}\mathrm{Var}(w_{ji})\mathrm{Var}(a_i)Var(zj)=ninVar(wji)Var(ai)

这个公式非常重要。

如果权重方差过大,则每经过一层,输出方差都会被放大,最终导致激活值爆炸。

如果权重方差过小,则每经过一层,输出方差都会缩小,最终导致激活值接近 0。

理想情况下,希望:

Var(zj)≈Var(ai)\mathrm{Var}(z_j)\approx\mathrm{Var}(a_i)Var(zj)≈Var(ai)

因此可以令:

ninVar(wji)≈1n_{\mathrm{in}}\mathrm{Var}(w_{ji})\approx1ninVar(wji)≈1

从而得到:

Var(wji)≈1nin\mathrm{Var}(w_{ji})\approx\frac{1}{n_{\mathrm{in}}}Var(wji)≈nin1

Xavier 初始化、He 初始化和 LeCun 初始化,本质上都围绕"保持各层数值尺度稳定"这一目标设计。

3.3 控制反向传播的梯度尺度

反向传播时,某层梯度会与权重矩阵和激活函数导数相乘。

对于第 lll 层,可以简化写为:

δ(l)=(W(l+1))Tδ(l+1)⊙ϕ′(z(l))\boldsymbol{\delta}^{(l)}=\left(\mathbf{W}^{(l+1)}\right)^{\mathrm{T}}\boldsymbol{\delta}^{(l+1)}\odot\phi'(\mathbf{z}^{(l)})δ(l)=(W(l+1))Tδ(l+1)⊙ϕ′(z(l))

其中:

  • δ(l)\boldsymbol{\delta}^{(l)}δ(l) 表示第 lll 层误差信号;
  • ϕ′(z(l))\phi'(\mathbf{z}^{(l)})ϕ′(z(l)) 表示激活函数导数;
  • ⊙\odot⊙ 表示逐元素乘法。

如果权重过小,或者激活函数导数长期小于 1,梯度会逐层衰减,产生梯度消失。

如果权重过大,梯度可能逐层放大,产生梯度爆炸。

因此,初始化不仅需要稳定前向传播,还要兼顾反向传播。

3.4 避免激活函数过早进入饱和区

对于 Sigmoid:

σ(x)=11+e−x\sigma(x)=\frac{1}{1+\mathrm{e}^{-x}}σ(x)=1+e−x1

其导数为:

σ′(x)=σ(x)(1−σ(x))\sigma'(x)=\sigma(x)(1-\sigma(x))σ′(x)=σ(x)(1−σ(x))

当输入绝对值较大时,Sigmoid 会接近 0 或 1,导数接近 0。

如果初始权重过大,则线性输出:

z=wTx+bz=\mathbf{w}^{\mathrm{T}}\mathbf{x}+bz=wTx+b

可能从训练一开始就具有很大的绝对值,使 Sigmoid 或 Tanh 进入饱和区。

这时即使损失较大,梯度也很小,模型难以从初始状态中恢复。

因此,使用 Sigmoid 或 Tanh 时,初始化需要特别注意控制权重尺度。


4. 错误初始化会造成什么问题

4.1 所有权重初始化为 0

一种直观但错误的方法是将所有权重设置为 0:

W=0\mathbf{W}=\mathbf{0}W=0

对于线性回归或逻辑回归,权重从 0 开始通常可以训练。

但对于包含隐藏层的神经网络,这会导致同一层所有神经元完全对称。

所有神经元:

  • 得到相同输出;
  • 接收相同梯度;
  • 执行相同更新;
  • 永远学习相同特征。

因此:

神经网络隐藏层权重不能全部初始化为 0。

但是,偏置通常可以初始化为 0,因为权重的随机性已经足以打破神经元之间的对称性。

4.2 所有权重初始化为相同常数

例如:

wij=0.01w_{ij}=0.01wij=0.01

虽然权重不再是 0,但同一层所有神经元仍然拥有完全相同的参数,因此仍然存在对称性问题。

所以问题不在于权重是否为 0,而在于:

同一层不同神经元不能从完全相同的权重状态开始。

4.3 随机值过小

假设使用:

wij∼N(0,10−6)w_{ij}\sim\mathcal{N}(0,10^{-6})wij∼N(0,10−6)

权重非常小时,每一层的输出都可能接近 0。

深层网络经过多层传播后,信号可能不断衰减,导致:

  • 激活值接近 0;
  • 梯度非常小;
  • 参数更新缓慢;
  • 模型长期停留在初始状态附近。

4.4 随机值过大

假设使用:

wij∼N(0,102)w_{ij}\sim\mathcal{N}(0,10^2)wij∼N(0,102)

权重非常大时,线性输出会迅速放大。

对于 Sigmoid 和 Tanh,大输入会导致函数饱和。

对于没有归一化和梯度裁剪的网络,大权重还可能导致:

  • 激活爆炸;
  • 梯度爆炸;
  • 损失震荡;
  • 数值溢出;
  • 出现 NaN

5. 最基础的随机初始化

5.1 随机正态分布初始化

随机正态初始化可以写为:

wij∼N(μ,σ2)w_{ij}\sim\mathcal{N}(\mu,\sigma^2)wij∼N(μ,σ2)

通常取:

μ=0\mu=0μ=0

例如:

wij∼N(0,0.012)w_{ij}\sim\mathcal{N}(0,0.01^2)wij∼N(0,0.012)

优点
  • 可以打破神经元之间的对称性;
  • 实现简单;
  • 适合小型或浅层网络的快速实验。
局限性
  • 标准差需要人工选择;
  • 没有考虑输入和输出维度;
  • 网络变深后容易出现激活或梯度尺度不稳定;
  • 对不同激活函数缺乏针对性。
适用场景
  • 教学示例;
  • 非常浅的网络;
  • 已知网络对初始尺度不敏感的情况。

5.2 随机均匀分布初始化

随机均匀初始化可以写为:

wij∼U(−a,a)w_{ij}\sim U(-a,a)wij∼U(−a,a)

其中,aaa 决定随机数范围。

优点
  • 计算和实现简单;
  • 可以打破参数对称性;
  • 所有权重被限制在有限区间内。
局限性
  • 区间范围需要人工选择;
  • 没有自动适应网络宽度;
  • 过大或过小都可能引发训练问题。

随机正态和随机均匀并不是完全错误的方法,关键是必须合理选择其方差或区间。Xavier、He 和 LeCun 初始化正是在此基础上给出了更科学的尺度选择方法。


6. Xavier 初始化

Xavier 初始化也称为 Glorot 初始化,主要用于 Sigmoid、Tanh 或近似对称激活函数。

6.1 核心思想

Xavier 初始化希望同时兼顾:

  • 前向传播的激活方差;
  • 反向传播的梯度方差。

如果只考虑前向传播,权重方差适合取:

Var(w)=1fan_in\mathrm{Var}(w)=\frac{1}{\mathrm{fan\_in}}Var(w)=fan_in1

如果只考虑反向传播,权重方差适合取:

Var(w)=1fan_out\mathrm{Var}(w)=\frac{1}{\mathrm{fan\_out}}Var(w)=fan_out1

Xavier 初始化对二者进行折中:

Var(w)=2fan_in+fan_out\mathrm{Var}(w)=\frac{2}{\mathrm{fan\_in}+\mathrm{fan\_out}}Var(w)=fan_in+fan_out2

6.2 Xavier 正态初始化

Xavier 正态初始化为:

wij∼N(0,2fan_in+fan_out)w_{ij}\sim\mathcal{N}\left(0,\frac{2}{\mathrm{fan\_in}+\mathrm{fan\_out}}\right)wij∼N(0,fan_in+fan_out2)

其标准差为:

σ=2fan_in+fan_out\sigma=\sqrt{\frac{2}{\mathrm{fan\_in}+\mathrm{fan\_out}}}σ=fan_in+fan_out2

6.3 Xavier 均匀初始化

Xavier 均匀初始化为:

wij∼U(−6fan_in+fan_out,6fan_in+fan_out)w_{ij}\sim U\left(-\sqrt{\frac{6}{\mathrm{fan\_in}+\mathrm{fan\_out}}},\sqrt{\frac{6}{\mathrm{fan\_in}+\mathrm{fan\_out}}}\right)wij∼U(−fan_in+fan_out6 ,fan_in+fan_out6 )

6.4 为什么适合 Tanh

Tanh 在 0 附近近似线性:

tanh⁡(x)≈x\tanh(x)\approx xtanh(x)≈x

如果初始化能够让大部分线性输出保持在 0 附近,就可以:

  • 避免 Tanh 进入饱和区;
  • 保持较大的导数;
  • 缓解梯度消失;
  • 稳定多层信号传播。

6.5 Xavier 初始化的优点

  • 同时考虑输入维度和输出维度;
  • 比固定标准差的随机初始化更加稳定;
  • 适用于 Tanh、Sigmoid 和线性层;
  • 能够较好地保持前向和反向传播的方差;
  • 广泛应用于全连接网络和注意力投影层。

6.6 Xavier 初始化的局限性

  • 假设激活函数近似线性或对称;
  • 对 ReLU 不够理想,因为 ReLU 会将约一半输入置零;
  • 在非常深的网络中,仅靠 Xavier 仍不一定能够完全避免梯度问题;
  • 对残差结构、归一化层和特殊网络结构没有进行专门建模。

6.7 适用场景

通常适用于:

  • Tanh 隐藏层;
  • Sigmoid 网络;
  • 线性激活;
  • Softmax 输出层之前的线性映射;
  • Transformer 中部分线性投影层;
  • 没有明确使用 ReLU 系列激活函数的普通全连接层。

7. He 初始化

He 初始化也称为 Kaiming 初始化,主要针对 ReLU 及其变体设计。

7.1 为什么 Xavier 对 ReLU 不够理想

ReLU 定义为:

ReLU(x)=max⁡(0,x)\mathrm{ReLU}(x)=\max(0,x)ReLU(x)=max(0,x)

当输入近似关于 0 对称时,大约一半输入会变为 0。

这意味着 ReLU 会降低激活方差。如果仍使用:

Var(w)=1fan_in\mathrm{Var}(w)=\frac{1}{\mathrm{fan\_in}}Var(w)=fan_in1

经过 ReLU 后,信号方差可能逐层缩小。

为了补偿 ReLU 丢弃一半信号的影响,He 初始化将权重方差放大为:

Var(w)=2fan_in\mathrm{Var}(w)=\frac{2}{\mathrm{fan\_in}}Var(w)=fan_in2

7.2 He 正态初始化

He 正态初始化为:

wij∼N(0,2fan_in)w_{ij}\sim\mathcal{N}\left(0,\frac{2}{\mathrm{fan\_in}}\right)wij∼N(0,fan_in2)

标准差为:

σ=2fan_in\sigma=\sqrt{\frac{2}{\mathrm{fan\_in}}}σ=fan_in2

7.3 He 均匀初始化

He 均匀初始化常写为:

wij∼U(−6fan_in,6fan_in)w_{ij}\sim U\left(-\sqrt{\frac{6}{\mathrm{fan\_in}}},\sqrt{\frac{6}{\mathrm{fan\_in}}}\right)wij∼U(−fan_in6 ,fan_in6 )

7.4 Leaky ReLU 对应的 He 初始化

对于 Leaky ReLU:

ϕ(x)={x,x>0ax,x≤0\phi(x)=\begin{cases}x,&x>0\\ax,&x\leq0\end{cases}ϕ(x)={x,ax,x>0x≤0

其推荐增益与负半轴斜率 aaa 有关:

gain=21+a2\mathrm{gain}=\sqrt{\frac{2}{1+a^2}}gain=1+a22

因此权重标准差可以写为:

σ=2(1+a2)fan_in\sigma=\sqrt{\frac{2}{(1+a^2)\mathrm{fan\_in}}}σ=(1+a2)fan_in2

如果 a=0a=0a=0,就退化为普通 ReLU 的 He 初始化。

7.5 He 初始化的优点

  • 专门适配 ReLU 及其变体;
  • 能够补偿 ReLU 丢弃负半轴信号造成的方差下降;
  • 适合深层全连接网络和卷积神经网络;
  • 通常比 Xavier 更适合 ReLU;
  • 实现简单且效果稳定。

7.6 He 初始化的局限性

  • 主要针对 ReLU 类激活函数;
  • 对 Sigmoid 和 Tanh 可能使初始权重偏大;
  • 在极深网络中仍可能需要配合残差连接和归一化;
  • 如果 fan_infan_out 或非线性参数配置错误,初始化效果会受到影响。

7.7 适用场景

通常适用于:

  • ReLU;
  • Leaky ReLU;
  • PReLU;
  • 深层卷积神经网络;
  • 使用 ReLU 系列激活函数的多层感知机。

8. LeCun 初始化

LeCun 初始化主要用于 SELU、自归一化网络,以及某些线性或 Tanh 风格网络。

8.1 LeCun 正态初始化

LeCun 正态初始化为:

wij∼N(0,1fan_in)w_{ij}\sim\mathcal{N}\left(0,\frac{1}{\mathrm{fan\_in}}\right)wij∼N(0,fan_in1)

其标准差为:

σ=1fan_in\sigma=\sqrt{\frac{1}{\mathrm{fan\_in}}}σ=fan_in1

8.2 LeCun 均匀初始化

LeCun 均匀初始化为:

wij∼U(−3fan_in,3fan_in)w_{ij}\sim U\left(-\sqrt{\frac{3}{\mathrm{fan\_in}}},\sqrt{\frac{3}{\mathrm{fan\_in}}}\right)wij∼U(−fan_in3 ,fan_in3 )

8.3 与 Xavier 和 He 的区别

三种初始化的核心方差分别为:

VarLeCun(w)=1fan_in\mathrm{Var}_{\mathrm{LeCun}}(w)=\frac{1}{\mathrm{fan\_in}}VarLeCun(w)=fan_in1

VarXavier(w)=2fan_in+fan_out\mathrm{Var}_{\mathrm{Xavier}}(w)=\frac{2}{\mathrm{fan\_in}+\mathrm{fan\_out}}VarXavier(w)=fan_in+fan_out2

VarHe(w)=2fan_in\mathrm{Var}_{\mathrm{He}}(w)=\frac{2}{\mathrm{fan\_in}}VarHe(w)=fan_in2

可以看到:

  • LeCun 主要考虑输入端方差;
  • Xavier 在输入和输出之间折中;
  • He 为 ReLU 的半截断特性增加了补偿系数 2。

8.4 LeCun 初始化的优点

  • 形式简单;
  • 适用于 SELU 和自归一化网络;
  • 有助于保持前向传播中的方差;
  • 比固定方差随机初始化更合理。

8.5 LeCun 初始化的局限性

  • 使用范围不如 Xavier 和 He 广;
  • 对 ReLU 通常不如 He 初始化;
  • 自归一化效果依赖网络结构、激活函数和 Dropout 类型等条件;
  • 不能简单理解为所有网络的通用最优方案。

8.6 适用场景

通常适用于:

  • SELU;
  • 自归一化神经网络;
  • 某些需要保持输入方差的线性层;
  • 明确遵循 SELU 网络设计约束的模型。

9. 正交初始化

正交初始化使权重矩阵的行或列近似相互正交。

对于方阵 Q\mathbf{Q}Q:

QTQ=I\mathbf{Q}^{\mathrm{T}}\mathbf{Q}=\mathbf{I}QTQ=I

初始化时通常先生成随机矩阵,再通过 QR 分解或奇异值分解获得正交矩阵。

最终权重可以写为:

W=gQ\mathbf{W}=g\mathbf{Q}W=gQ

其中,ggg 是缩放增益。

9.1 为什么正交矩阵有助于梯度传播

对于正交矩阵:

∥Qx∥2=∥x∥2\|\mathbf{Q}\mathbf{x}\|_2=\|\mathbf{x}\|_2∥Qx∥2=∥x∥2

这意味着在线性变换中,向量的二范数不会被任意放大或压缩。

因此,正交初始化能够在一定程度上:

  • 保持信号范数;
  • 保持梯度范数;
  • 缓解深层线性变换中的梯度消失和爆炸。

9.2 正交初始化的优点

  • 有助于保持向量范数;
  • 适合深层线性网络;
  • 常用于循环神经网络的隐藏状态矩阵;
  • 对控制长期梯度传播有一定帮助;
  • 可与适当增益结合适配不同激活函数。

9.3 正交初始化的局限性

  • 初始化计算比普通随机初始化复杂;
  • 对非方阵需要进行适当截取或扩展;
  • 经过非线性激活后,严格的范数保持不再成立;
  • 不一定适合所有卷积结构;
  • 不能替代门控结构、残差连接和归一化方法。

9.4 适用场景

通常适用于:

  • RNN 隐藏状态权重;
  • LSTM 或 GRU 中的循环权重;
  • 深层线性网络;
  • 需要保持信号方向和范数的特殊结构。

10. 稀疏初始化

稀疏初始化会让权重矩阵中的大部分元素为 0,只保留少量非零随机权重。

例如,每个神经元只与上一层少量神经元建立初始连接。

可以表示为:

wij=0for most i,jw_{ij}=0\quad\text{for most }i,jwij=0for most i,j

非零部分再从某个随机分布中采样。

10.1 稀疏初始化的优点

  • 减少初始连接数量;
  • 可能促进不同神经元学习不同特征;
  • 在某些超宽网络中可以减少初始干扰;
  • 对研究稀疏网络结构具有意义。

10.2 稀疏初始化的局限性

  • 不属于多数普通网络的默认选择;
  • 稀疏程度需要人工设定;
  • 过度稀疏可能降低信息传播能力;
  • 不一定能带来实际计算加速,因为训练框架可能仍使用稠密矩阵;
  • 对最终性能的收益具有任务依赖性。

10.3 适用场景

  • 稀疏神经网络研究;
  • 超宽网络;
  • 特殊结构实验;
  • 需要限制初始连接数量的模型。

11. 截断正态初始化

截断正态分布会先从正态分布采样,再丢弃距离均值过远的极端值。

普通正态初始化可能偶尔产生绝对值很大的权重,而截断正态可以减少这些异常初始值。

可以简单理解为:

w∼N(μ,σ2),w∈μ−kσ,μ+kσw\sim\mathcal{N}(\mu,\sigma^2),\quad w\in\\mu-k\\sigma,\\mu+k\\sigmaw∼N(μ,σ2),w∈μ−kσ,μ+kσ

11.1 优点

  • 减少极端大权重;
  • 初始数值更加集中;
  • 在 Transformer、视觉 Transformer 和大型模型中较常见;
  • 可以降低初始阶段数值异常的概率。

11.2 局限性

  • 仍然需要合理选择标准差;
  • 截断会改变原始正态分布的精确方差;
  • 不同框架对截断范围和重采样方式的实现可能不同;
  • 并不是所有网络都需要截断正态。

11.3 适用场景

  • Transformer;
  • Vision Transformer;
  • 大型嵌入层;
  • 明确采用较小标准差初始化的现代模型。

12. 常数初始化适用于哪些参数

"不能使用常数初始化"主要针对隐藏层权重,而不是所有参数。

12.1 偏置初始化为 0

普通全连接层和卷积层的偏置通常可以设置为:

b=0\mathbf{b}=\mathbf{0}b=0

原因是权重已经使用随机方式打破对称性,因此偏置不需要再随机化。

优点
  • 简单;
  • 稳定;
  • 不会额外引入初始偏移。
局限性
  • 某些特殊结构需要非零偏置;
  • 对所有模型机械地设为 0 可能忽略结构先验。

12.2 ReLU 偏置初始化为小正数

有时会将 ReLU 神经元的偏置初始化为小正值,例如:

b=0.01b=0.01b=0.01

其目标是让更多神经元在训练初期处于激活状态。

但这种方法并不是必须的,也不是所有任务都有效。

优点
  • 可能减少初始阶段的神经元失活;
  • 让部分 ReLU 更容易进入正区间。
局限性
  • 会引入整体正偏移;
  • 不一定优于零偏置;
  • 过大时可能导致激活均值偏离 0。

12.3 LSTM 遗忘门偏置

LSTM 中的遗忘门可以写为:

ft=σ(Wfxt+Ufht−1+bf)\mathbf{f}_t=\sigma(\mathbf{W}_f\mathbf{x}_t+\mathbf{U}f\mathbf{h}{t-1}+\mathbf{b}_f)ft=σ(Wfxt+Ufht−1+bf)

有时会将遗忘门偏置初始化为较大的正值,例如:

bf=1\mathbf{b}_f=\mathbf{1}bf=1

这样训练初期:

ft≈σ(1)>0.5\mathbf{f}_t\approx\sigma(1)>0.5ft≈σ(1)>0.5

模型更倾向于保留历史信息。

优点
  • 有助于保留长期状态;
  • 在部分序列任务中可以改善训练初期表现。
局限性
  • 不是所有实现和任务都必须这样设置;
  • 过大的遗忘门偏置可能使模型过度保留旧信息。

13. 归一化层的参数初始化

Batch Normalization 可以写为:

y=γx^+βy=\gamma\hat{x}+\betay=γx^+β

其中:

  • γ\gammaγ 是缩放参数;
  • β\betaβ 是平移参数。

常见初始化方式为:

γ=1\gamma=1γ=1

β=0\beta=0β=0

这样在训练初期,归一化层近似保持标准化后的输入不变。

13.1 残差网络中的特殊初始化

对于残差块:

y=x+F(x)\mathbf{y}=\mathbf{x}+F(\mathbf{x})y=x+F(x)

有时会将残差分支最后一个归一化层的缩放参数初始化为 0:

γlast=0\gamma_{\mathrm{last}}=0γlast=0

这样训练开始时:

F(x)≈0F(\mathbf{x})\approx0F(x)≈0

残差块初始状态近似为恒等映射:

y≈x\mathbf{y}\approx\mathbf{x}y≈x

这有助于非常深的残差网络从稳定状态开始训练。


14. 不同激活函数与初始化方法如何匹配

激活函数或网络结构 推荐初始化方法 原因
Sigmoid Xavier 控制初始输入尺度,减少饱和
Tanh Xavier 让输入尽量位于近似线性区域
ReLU He/Kaiming 补偿负半轴被截断造成的方差损失
Leaky ReLU 带斜率参数的 He 根据负半轴斜率调整增益
PReLU 带实际斜率的 He 与可学习负斜率匹配
SELU LeCun Normal 配合自归一化性质
GELU Xavier 或较小截断正态 保持初始尺度稳定,具体取决于架构
Swish Xavier 或 He 风格初始化 需要结合具体网络和框架验证
线性层 Xavier 或 LeCun 保持线性传播方差
RNN 循环权重 正交初始化 有助于保持长期梯度范数
Transformer 投影层 Xavier 或截断正态 常见于注意力和前馈线性层
卷积网络 ReLU 层 He/Kaiming 适配 ReLU 非线性
残差分支末端 零初始化最后缩放参数 使残差块初始近似恒等映射

需要注意:

初始化方法与激活函数之间不是完全独立的,选择初始化时必须考虑后续使用的非线性函数。


15. Xavier、He 和 LeCun 的统一理解

这三种初始化都在解决同一个问题:

如何让信号经过多层传播后,方差不要迅速变大或变小。

它们的差异主要来自对激活函数的不同假设。

LeCun

Var(w)=1fan_in\mathrm{Var}(w)=\frac{1}{\mathrm{fan\_in}}Var(w)=fan_in1

主要保持前向传播的输入方差。

Xavier

Var(w)=2fan_in+fan_out\mathrm{Var}(w)=\frac{2}{\mathrm{fan\_in}+\mathrm{fan\_out}}Var(w)=fan_in+fan_out2

在前向传播和反向传播之间折中。

He

Var(w)=2fan_in\mathrm{Var}(w)=\frac{2}{\mathrm{fan\_in}}Var(w)=fan_in2

针对 ReLU 会丢弃一半输入的情况进行补偿。

因此,它们并不是互相竞争的三个"固定答案",而是针对不同激活函数和方差传播假设得到的不同方案。


16. PyTorch 中的参数初始化

PyTorch 提供了 torch.nn.init 模块。

16.1 ReLU 网络使用 He 初始化

python 复制代码
import torch
import torch.nn as nn


class FeedforwardNN(nn.Module):
    def __init__(self, input_dim: int, output_dim: int) -> None:
        super().__init__()
        self.network = nn.Sequential(
            nn.Linear(input_dim, 128),
            nn.ReLU(),
            nn.Linear(128, 64),
            nn.ReLU(),
            nn.Linear(64, output_dim)
        )

        self.apply(self._initialize_weights)

    @staticmethod
    def _initialize_weights(module: nn.Module) -> None:
        if isinstance(module, nn.Linear):
            nn.init.kaiming_normal_(
                module.weight,
                mode="fan_in",
                nonlinearity="relu"
            )

            if module.bias is not None:
                nn.init.zeros_(module.bias)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        return self.network(x)

16.2 Tanh 网络使用 Xavier 初始化

python 复制代码
import torch
import torch.nn as nn


class TanhNetwork(nn.Module):
    def __init__(self, input_dim: int, output_dim: int) -> None:
        super().__init__()
        self.network = nn.Sequential(
            nn.Linear(input_dim, 64),
            nn.Tanh(),
            nn.Linear(64, 32),
            nn.Tanh(),
            nn.Linear(32, output_dim)
        )

        self.apply(self._initialize_weights)

    @staticmethod
    def _initialize_weights(module: nn.Module) -> None:
        if isinstance(module, nn.Linear):
            gain = nn.init.calculate_gain("tanh")
            nn.init.xavier_normal_(module.weight, gain=gain)

            if module.bias is not None:
                nn.init.zeros_(module.bias)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        return self.network(x)

16.3 Leaky ReLU 使用带斜率的 Kaiming 初始化

python 复制代码
import torch
import torch.nn as nn


class LeakyReLUNetwork(nn.Module):
    def __init__(
        self,
        input_dim: int,
        output_dim: int,
        negative_slope: float = 0.01
    ) -> None:
        super().__init__()
        self.negative_slope = negative_slope

        self.network = nn.Sequential(
            nn.Linear(input_dim, 128),
            nn.LeakyReLU(negative_slope),
            nn.Linear(128, 64),
            nn.LeakyReLU(negative_slope),
            nn.Linear(64, output_dim)
        )

        self.apply(self._initialize_weights)

    def _initialize_weights(self, module: nn.Module) -> None:
        if isinstance(module, nn.Linear):
            nn.init.kaiming_normal_(
                module.weight,
                a=self.negative_slope,
                mode="fan_in",
                nonlinearity="leaky_relu"
            )

            if module.bias is not None:
                nn.init.zeros_(module.bias)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        return self.network(x)

16.4 正交初始化循环权重

python 复制代码
import torch
import torch.nn as nn


def initialize_lstm(lstm: nn.LSTM) -> None:
    for name, parameter in lstm.named_parameters():
        if "weight_ih" in name:
            nn.init.xavier_uniform_(parameter)

        elif "weight_hh" in name:
            nn.init.orthogonal_(parameter)

        elif "bias" in name:
            nn.init.zeros_(parameter)

            hidden_size = parameter.shape[0] // 4

            with torch.no_grad():
                parameter[hidden_size:2 * hidden_size].fill_(1.0)

这里:

  • 输入到隐藏状态的权重使用 Xavier;
  • 隐藏状态到隐藏状态的权重使用正交初始化;
  • 偏置默认置 0;
  • 遗忘门偏置置为 1。

实际使用时,需要确认具体框架中 LSTM 四个门的参数排列顺序。


17. NumPy 手工实现常见初始化

python 复制代码
import numpy as np


def xavier_normal(
    fan_in: int,
    fan_out: int,
    rng: np.random.Generator
) -> np.ndarray:
    std = np.sqrt(2.0 / (fan_in + fan_out))
    return rng.normal(0.0, std, size=(fan_out, fan_in))


def he_normal(
    fan_in: int,
    fan_out: int,
    rng: np.random.Generator
) -> np.ndarray:
    std = np.sqrt(2.0 / fan_in)
    return rng.normal(0.0, std, size=(fan_out, fan_in))


def lecun_normal(
    fan_in: int,
    fan_out: int,
    rng: np.random.Generator
) -> np.ndarray:
    std = np.sqrt(1.0 / fan_in)
    return rng.normal(0.0, std, size=(fan_out, fan_in))


rng = np.random.default_rng(seed=42)

weight_xavier = xavier_normal(128, 64, rng)
weight_he = he_normal(128, 64, rng)
weight_lecun = lecun_normal(128, 64, rng)

print(weight_xavier.shape)
print(weight_he.shape)
print(weight_lecun.shape)

18. 如何检查初始化是否合理

仅仅调用某种初始化函数还不够,还应该观察网络实际产生的激活和梯度。

18.1 检查各层激活值

可以统计:

  • 均值;
  • 标准差;
  • 最大值;
  • 最小值;
  • 0 值比例;
  • 饱和比例。

理想情况下,各层激活不应:

  • 迅速趋近于 0;
  • 迅速增长到极大值;
  • 大量进入 Sigmoid/Tanh 饱和区;
  • 在 ReLU 中出现几乎全部为 0 的情况。

18.2 检查各层梯度

可以统计每层权重梯度范数:

∥∇W(l)L∥2\|\nabla_{\mathbf{W}^{(l)}}\mathcal{L}\|_2∥∇W(l)L∥2

如果靠近输入层的梯度远小于输出层,可能存在梯度消失。

如果梯度突然极大或出现无穷值,可能存在梯度爆炸。

18.3 PyTorch 中打印参数和梯度统计量

python 复制代码
def print_parameter_statistics(model: torch.nn.Module) -> None:
    for name, parameter in model.named_parameters():
        data = parameter.detach()

        print(
            f"{name:30s} "
            f"mean={data.mean().item(): .6f} "
            f"std={data.std().item(): .6f} "
            f"min={data.min().item(): .6f} "
            f"max={data.max().item(): .6f}"
        )


def print_gradient_statistics(model: torch.nn.Module) -> None:
    for name, parameter in model.named_parameters():
        if parameter.grad is None:
            continue

        gradient = parameter.grad.detach()

        print(
            f"{name:30s} "
            f"grad_mean={gradient.mean().item(): .6f} "
            f"grad_std={gradient.std().item(): .6f} "
            f"grad_norm={gradient.norm().item(): .6f}"
        )

19. 初始化与其他训练技术的关系

参数初始化非常重要,但它不是独立解决所有训练问题的万能方法。

现代深度网络通常同时依赖:

  • 合理初始化;
  • Batch Normalization 或 Layer Normalization;
  • 残差连接;
  • 合理学习率;
  • 学习率调度;
  • 梯度裁剪;
  • 合适激活函数;
  • 优化器;
  • 正则化方法。

例如,残差连接可以写为:

y=x+F(x)\mathbf{y}=\mathbf{x}+F(\mathbf{x})y=x+F(x)

即使 F(x)F(\mathbf{x})F(x) 的梯度传播不够稳定,恒等路径仍然允许梯度直接传播。

归一化层也可以动态控制训练过程中的激活尺度。

因此,现代神经网络的稳定训练通常是多种技术共同作用的结果。


20. 参数初始化与随机种子

随机初始化意味着每次训练的起点可能不同。

为了提高实验可复现性,通常需要固定随机种子。

python 复制代码
import random
import numpy as np
import torch


def set_random_seed(seed: int) -> None:
    random.seed(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)

    if torch.cuda.is_available():
        torch.cuda.manual_seed(seed)
        torch.cuda.manual_seed_all(seed)


set_random_seed(42)

但是,固定随机种子并不意味着不同环境下结果绝对一致,因为:

  • GPU 算法可能具有非确定性;
  • 框架版本可能不同;
  • 驱动和硬件可能不同;
  • 并行计算顺序可能不同。

随机种子的主要作用是降低由初始化和数据顺序造成的随机差异。


21. 参数初始化的常见误区

21.1 误区一:所有参数都不能初始化为 0

不准确。

  • 隐藏层权重不能全部为 0;
  • 普通偏置通常可以为 0;
  • BatchNorm 的平移参数通常为 0;
  • 某些残差分支最后的缩放参数也可以为 0。

21.2 误区二:He 初始化永远优于 Xavier

不准确。

He 初始化主要适用于 ReLU 系列,Xavier 更适合 Tanh、Sigmoid 和线性映射。

初始化方法需要与激活函数和网络结构匹配。

21.3 误区三:只要用了 BatchNorm,初始化就不重要

不准确。

BatchNorm 可以缓解激活尺度问题,但:

  • 第一轮前向传播仍由初始化决定;
  • 梯度传播仍会受到初始参数影响;
  • 不合理初始化仍可能导致数值异常;
  • 并非所有网络都使用 BatchNorm。

21.4 误区四:初始化只影响训练速度,不影响最终结果

不准确。

初始化不仅影响速度,还可能决定优化器最终进入哪个局部最优区域。

不同初始化可能导致:

  • 最终精度不同;
  • 泛化性能不同;
  • 收敛状态不同;
  • 是否出现训练失败不同。

因此,严谨实验通常应使用多个随机种子重复训练,并报告均值和标准差。

21.5 误区五:框架默认初始化一定最适合当前模型

深度学习框架的默认初始化通常是合理的通用选择,但不一定与自定义网络完全匹配。

例如:

  • 自定义激活函数可能需要特殊增益;
  • RNN 循环矩阵可能更适合正交初始化;
  • 残差网络可能需要特殊零初始化;
  • SELU 网络需要满足自归一化约束;
  • 输出层可能需要根据任务设置较小初始权重。

因此,需要了解框架默认值,而不是完全依赖默认行为。


22. 各初始化方法优缺点总结

初始化方法 核心公式或特点 主要优点 主要局限性 常见适用场景
全零初始化 所有权重为 0 简单 隐藏层无法打破对称性 普通偏置
相同常数初始化 所有权重相同 简单 仍然存在对称性 不推荐用于隐藏层权重
小随机正态 固定较小标准差 实现简单 不适应网络宽度 浅层教学模型
随机均匀 固定区间采样 范围可控 区间需人工设定 浅层实验
Xavier 2/(fan_in+fan_out)2/(\mathrm{fan\_in}+\mathrm{fan\_out})2/(fan_in+fan_out) 兼顾前向和反向方差 不专门适配 ReLU Tanh、Sigmoid、线性层
He/Kaiming 2/fan_in2/\mathrm{fan\_in}2/fan_in 适配 ReLU 系列 对饱和激活可能偏大 ReLU、Leaky ReLU、CNN
LeCun 1/fan_in1/\mathrm{fan\_in}1/fan_in 适合 SELU 通用性较弱 SELU、自归一化网络
正交初始化 权重矩阵近似正交 保持范数,利于长期梯度 构造更复杂 RNN、循环权重
稀疏初始化 大量权重为 0 限制初始连接 收益依赖任务 稀疏网络研究
截断正态 去除正态分布极端值 减少异常大权重 标准差仍需设计 Transformer、ViT
零缩放残差分支 末端缩放参数为 0 初始近似恒等映射 依赖残差结构 深层 ResNet

23. 实际选择建议

可以使用下面的经验规则。

普通多层感知机使用 ReLU

推荐:

text 复制代码
He Normal 或 He Uniform

普通卷积神经网络使用 ReLU

推荐:

text 复制代码
Kaiming Normal,mode="fan_out" 或根据实现选择 fan_in

具体模式需要结合目标是保持前向激活还是反向梯度。

隐藏层使用 Tanh

推荐:

text 复制代码
Xavier Normal 或 Xavier Uniform

隐藏层使用 Leaky ReLU

推荐:

text 复制代码
带 negative_slope 参数的 Kaiming 初始化

使用 SELU

推荐:

text 复制代码
LeCun Normal

同时需要尽量遵循自归一化网络的其他设计条件。

RNN、LSTM、GRU

推荐考虑:

text 复制代码
输入权重使用 Xavier
循环权重使用 Orthogonal
偏置通常为 0
LSTM 遗忘门偏置可设为 1

Transformer

常见方案包括:

text 复制代码
Xavier
较小标准差正态分布
截断正态分布

具体选择通常应遵循原始架构或官方实现。


24. 一个完整的初始化策略示例

假设网络结构为:

text 复制代码
输入层
→ Linear
→ ReLU
→ Linear
→ ReLU
→ Linear
→ 输出层

可以采用:

text 复制代码
隐藏层权重:He Normal
隐藏层偏置:0
输出层权重:Xavier Normal
输出层偏置:0

PyTorch 示例:

python 复制代码
import torch
import torch.nn as nn


class RegressionNetwork(nn.Module):
    def __init__(self, input_dim: int, output_dim: int) -> None:
        super().__init__()

        self.hidden_one = nn.Linear(input_dim, 128)
        self.hidden_two = nn.Linear(128, 64)
        self.output_layer = nn.Linear(64, output_dim)
        self.activation = nn.ReLU()

        self._initialize_parameters()

    def _initialize_parameters(self) -> None:
        nn.init.kaiming_normal_(
            self.hidden_one.weight,
            mode="fan_in",
            nonlinearity="relu"
        )
        nn.init.zeros_(self.hidden_one.bias)

        nn.init.kaiming_normal_(
            self.hidden_two.weight,
            mode="fan_in",
            nonlinearity="relu"
        )
        nn.init.zeros_(self.hidden_two.bias)

        nn.init.xavier_normal_(self.output_layer.weight)
        nn.init.zeros_(self.output_layer.bias)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        x = self.activation(self.hidden_one(x))
        x = self.activation(self.hidden_two(x))
        return self.output_layer(x)

这个例子体现了一个重要思想:

不同层可以根据其后续激活函数和功能使用不同的初始化方法。


25. 总结

神经网络参数初始化决定了模型从什么位置开始优化,也决定了训练初期各层激活值和梯度的数值尺度。

一个合理的初始化方法需要完成三个核心任务:

  1. 打破不同神经元之间的对称性;
  2. 保持前向传播中激活值的方差稳定;
  3. 保持反向传播中梯度的方差稳定。

最常见的初始化方法可以概括为:

  • Xavier 初始化:适合 Tanh、Sigmoid 和线性层;
  • He 初始化:适合 ReLU、Leaky ReLU 和卷积网络;
  • LeCun 初始化:适合 SELU 和自归一化网络;
  • 正交初始化:适合 RNN 循环权重和需要保持范数的结构;
  • 截断正态初始化:常见于 Transformer 和大型模型;
  • 零初始化:适合普通偏置和部分特殊缩放参数,但不适合隐藏层全部权重。

最重要的原则是:

参数初始化不能脱离激活函数和网络结构单独选择。

在实际开发中,不应该只机械地记住"Xavier、He、LeCun"三个名称,而应该理解它们背后的共同目标:让信号和梯度在多层网络中保持合理尺度。

只有当初始化、激活函数、归一化、残差连接、优化器和学习率共同匹配时,深层神经网络才能稳定而高效地完成训练。

相关推荐
qq_454245034 小时前
axioms prompt
人工智能·prompt
DFT计算杂谈5 小时前
扭转石墨烯中的高 Chern 数轨道磁体
人工智能
BerrySen1785 小时前
一个Java项目改成AI流程后,最难的部分完全变了
java·大数据·人工智能·可观测性·大模型应用开发·工程思维
LaughingZhu5 小时前
Product Hunt 每日热榜 | 2026-07-27
人工智能·深度学习·神经网络·搜索引擎·产品运营
水如烟5 小时前
孤能子视角:EIS是什么——回顾文明来时路,试构碳硅认知语法
人工智能
netho05 小时前
影刀多 table 组合定位,网页操作题怎么少踩坑
人工智能
核数聚5 小时前
【赛迪专访核数聚】深耕数据治理,打通数据孤岛夯实 AI 发展根基
大数据·人工智能·算法
丘丘用户思思澪5 小时前
AI Agent 工作模式完全指南:从执行逻辑到系统架构
人工智能·系统架构
无敌秋5 小时前
AI-RAN 完整详解
人工智能
万里鹏程转瞬至5 小时前
论文简读:Boogu-Image 图像生成与编辑模型
论文阅读·深度学习·aigc