好的初始化可以加速收敛、避免梯度消失/爆炸。本课深入分析Xavier、Kaiming等初始化方法,理解它们为什么有效。
初始化太差 → 梯度消失/爆炸 → 训练失败
好的初始化 → 前向传播保持方差 → 反向传播梯度稳定 → 快速收敛
如果所有权重初始化为0,同一层的所有神经元输出相同,梯度也相同,对称性无法打破。
Var(y) = n_in · Var(w) · Var(x)
为保持方差不变:Var(w) = 1/n_in(Xavier)
考虑ReLU:Var(w) = 2/n_in(Kaiming He)
W ~ N(0, 2/(n_in + n_out))
或 W ~ U(-√(6/(n_in+n_out)), √(6/(n_in+n_out)))
适用于:Sigmoid、Tanh激活函数
W ~ N(0, 2/n_in) (fan_in模式)
专门为ReLU设计,考虑ReLU让一半输出归零
import torch
import torch.nn as nn
import math
# 不同初始化方法的对比
torch.manual_seed(42)
input_dim = 100
hidden_dims = [256, 256, 256, 256, 256]
def test_init(init_fn, name):
layers = []
prev_dim = input_dim
for h in hidden_dims:
linear = nn.Linear(prev_dim, h)
init_fn(linear.weight)
nn.zeros_(linear.bias)
layers.append(linear)
layers.append(nn.ReLU())
prev_dim = h
layers.append(nn.Linear(prev_dim, 10))
model = nn.Sequential(*layers)
x = torch.randn(32, input_dim)
with torch.no_grad():
output = model(x)
# 检查每层输出的方差
x_temp = x.clone()
variances = []
for layer in model[:-1]:
x_temp = layer(x_temp)
if isinstance(layer, nn.ReLU):
variances.append(x_temp.var().item())
print(f"{name:>25}: 输出方差={output.var().item():.6f}, 层方差={[f'{v:.4f}' for v in variances]}")
test_init(lambda w: nn.init.zeros_(w), "全零初始化")
test_init(lambda w: nn.init.normal_(w, std=0.01), "正态(0,0.01)")
test_init(lambda w: nn.init.xavier_normal_(w), "Xavier正态")
test_init(lambda w: nn.init.xavier_uniform_(w), "Xavier均匀")
test_init(lambda w: nn.init.kaiming_normal_(w, mode='fan_in'), "Kaiming(ReLU)")
test_init(lambda w: nn.init.kaiming_uniform_(w, mode='fan_in'), "Kaiming均匀(ReLU)")
# Kaiming初始化推导验证
print("\n=== Kaiming初始化方差验证 ===")
fan_in = 256
# ReLU: E[x²] = 0.5 * E[x²] (一半被置零)
# Var(y) = fan_in * Var(W) * 0.5 * Var(x)
# 令 Var(y) = Var(x): Var(W) = 2/fan_in
print(f"fan_in = {fan_in}")
print(f"Kaiming方差 = 2/{fan_in} = {2/fan_in:.6f}")
print(f"Kaiming标准差 = √(2/{fan_in}) = {math.sqrt(2/fan_in):.6f}")
w = torch.empty(256, 256)
nn.init.kaiming_normal_(w, mode='fan_in')
print(f"实际方差: {w.var().item():.6f}")
print(f"实际标准差: {w.std().item():.6f}")
假设:输入x和权重w独立同分布,均值为0
Var(y) = n_in × Var(w) × Var(x)
为使 Var(y) = Var(x):Var(w) = 1/n_in
考虑反向传播:Var(w) = 1/n_out
折中:Var(w) = 2/(n_in + n_out)
ReLU让一半输出归零:E[ReLU(x)²] = 0.5 × E[x²]
因此 Var(y) = 0.5 × n_in × Var(w) × Var(x)
为使 Var(y) = Var(x):Var(w) = 2/n_in
fan_in模式(默认):W ~ N(0, 2/n_in)
fan_out模式:W ~ N(0, 2/n_out)
⚠️ 常见的初始化错误:
💡 推荐资源:
对于GELU和Swish,应该用什么初始化?推导并验证。
实现Layer-Sequential Unit-Variance初始化,与Kaiming对比。
用预训练权重初始化,对比随机初始化的收敛速度。
一般规则:偏置初始化为0
特殊情况:
• 输出层偏置:用训练集的类别频率初始化(分类任务)
• LSTM遗忘门偏置:初始化为1-2(开始时允许信息流动)
• BatchNorm的β:初始化为0,γ初始化为1
最佳初始化 = 有人在相关任务上训练好的权重
好的初始化不仅加速收敛,还能让训练成为可能。深层网络尤其敏感:
理解本课内容需要将其置于更大的知识网络中。每个核心概念都不是孤立的,它们相互关联、相互支撑:
建立正确的直觉比记住公式更重要:
1. 维度直觉:高维空间中,数据分布与低维直觉截然不同(维度诅咒)
2. 信息瓶颈:神经网络逐层压缩信息,保留任务相关的、丢弃无关的
3. 流形假设:高维数据实际分布在低维流形上,学习即发现流形结构
4. 偏差-方差权衡:简单模型欠拟合(高偏差),复杂模型过拟合(高方差)
本课作为神经网络基础阶段的核心内容,与前后课程紧密关联:
| 关联课程 | 关联点 | 协同效应 |
|---|---|---|
| 前序课程 | 提供了本课的基础知识 | 循序渐进的理解 |
| 后续课程 | 本课内容是后续的基础 | 逐步构建能力 |
| 平行课程 | 同一阶段的互补知识 | 多角度深入理解 |
| 实战项目 | 综合运用所有知识 | 理论与实践结合 |
💡 准备面试时,确保能回答以下问题:
掌握本课内容后,可以通过以下方式继续深入:
将本课涉及的关键公式整理如下,方便回顾和记忆。理解每个公式背后的直觉比死记硬背更重要——试着用自然语言解释每个公式在做什么。
| 概念A | 概念B | 关键区别 |
|---|---|---|
| 参数 | 超参数 | 参数通过训练学习,超参数需要手动设定 |
| 训练误差 | 泛化误差 | 训练误差衡量拟合程度,泛化误差衡量预测能力 |
| 偏差 | 方差 | 偏差是系统性误差,方差是随机波动 |
| L1正则 | L2正则 | L1产生稀疏解,L2产生平滑解 |
| BatchNorm | LayerNorm | BN沿batch维度,LN沿特征维度 |
以下是本课核心概念的标准PyTorch实现模板,可以直接用于实际项目:
💡 调试建议:当结果不符合预期时,先检查数据,再检查损失函数,最后检查模型结构。90%的问题出在前两个环节。
好的开始是成功的一半!你懂得如何让训练有个好起点。