权重初始化需匹配层的fan_in和激活函数特性:ReLU用HeNormal(stddev=√(2/fan_in)),tanh/sigmoid用GlorotUniform;卷积层fan_in为核尺寸与输入通道乘积;初始化不当会导致信号爆炸/衰减、梯度异常,影响收敛。

权重初始化直接决定前向信号的尺度稳定性
训练刚开始时,如果某一层的 kernel 初始方差过大,比如用 tf.random.normal(stddev=1.0) 初始化一个输入维度为 784 的全连接层,那么该层输出的方差会接近 784 × 1.0² = 784 —— 这意味着激活值动辄上千,ReLU 后大量神经元饱和,梯度瞬间归零。反之,若 stddev=0.01,输出方差仅约 0.078,信号在几层后就衰减到几乎不可见。这两种情况都会让优化器“看不见路”,收敛自然极慢甚至卡死。
真正起作用的不是随机性本身,而是方差是否匹配当前层的 fan_in(输入节点数)和激活函数特性。TensorFlow 的 HeNormal 和 GlorotUniform 等初始化器,会在创建变量时自动计算并应用对应方差,让第一轮前向传播的激活值标准差稳定在 ~1 左右。
不同激活函数必须配不同初始化策略
ReLU 及其变体(LeakyReLU、ELU)只保留正半轴,前向传播中信息单向放大,因此需要更大的初始方差来补偿——HeNormal 就是为此设计:它设 stddev = sqrt(2.0 / fan_in),恰好抵消 ReLU 的“截断效应”。而 tanh 或 sigmoid 在原点附近近似线性且对称,用同样方差会导致输出迅速饱和,这时 GlorotUniform(limit = sqrt(6.0 / (fan_in + fan_out)))才合适。
常见错误:
立即学习“Python免费学习笔记(深入)”;
- 用
HeNormal初始化带tanh的层 → 前几轮 loss 就震荡剧烈,验证准确率不上升 - 用
GlorotUniform初始化 ResNet 的残差块 → 深层梯度衰减明显,50 层后训练停滞 - 自定义层里忘了传
kernel_initializer,退化为框架默认的glorot_uniform→ 在 ReLU 网络中表现尚可,但收敛比显式指定HeNormal慢 30%+
卷积层的 fan_in 计算容易被忽略
全连接层的 fan_in 就是输入特征数,但卷积层不是。例如 Conv2D(filters=64, kernel_size=(3, 3), input_shape=(224, 224, 3)),它的 fan_in = 3 × 3 × 3 = 27(即每个输出通道的权重总数),不是 224×224×3。TensorFlow 内部会自动算这个值,但如果你手动用 tf.keras.initializers.RandomNormal 并硬编码 stddev,就极易出错。
实操建议:
- 永远优先用
tf.keras.initializers.HeNormal或GlorotUniform,而不是手写分布参数 - 检查模型 summary 中每层的
kernel: (..., ..., ..., filters)形状,确认fan_in是前三个维度乘积 - 在自定义
Layer的build()方法里,显式调用self.add_weight(..., initializer=tf.keras.initializers.HeNormal()),别依赖__init__里的默认值
初始化影响梯度回传路径的有效性
反向传播时,梯度要穿过每一层的 Jacobian 矩阵。如果某层权重初始范数太大,其 Jacobian 的奇异值就会严重偏斜,导致某些方向梯度极大、某些方向极小——优化器(如 Adam)的二阶矩估计会被这些异常值污染,参数更新变得不稳定。这不是学习率能解决的问题。
He 初始化在推导时不仅考虑前向方差,还保证反向传播中梯度的方差也大致恒定。实验表明,在相同学习率下,用 HeNormal 初始化的 ResNet-50,第 10 个 batch 的梯度 norm 标准差比随机初始化低 4.2 倍,这意味着优化路径更平滑,收敛更快。
容易被忽略的一点:初始化不是“设一次就完事”。当你 freeze 部分层、新增分支、或做迁移学习时,新引入的权重仍需按其所在层的 fan_in 和激活函数重新初始化——否则新加的头(head)可能拖慢整个模型的收敛节奏。


















