🌟 大背景:训练神经网络 = 下山寻宝
训练神经网络就像你蒙着眼在一座大山里,想找最低点(最小损失)。你只能靠脚下的坡度(梯度)来决定往哪儿走。
- 你的位置 = 模型参数(权重 www)
- 坡度 = 梯度 ∇J∇J∇J
- 走一步的大小 = 学习率 ηηη
- 山的结构 = 神经网络的结构
现在,我们看看路上会遇到哪些坑。
1. 参数初始化:你一开始站哪儿?
💬 大白话:
你不能随便往地上一站就开始走。
如果一开始站的位置太差(比如平地或悬崖),可能一辈子都找不到宝藏。
在神经网络里,参数初始化就是决定模型一开始的“姿势”。
❌ 常见错误:全0初始化
w = 0 # 所有权重都设为0
问题:所有神经元“长得一模一样”,更新也一样 → 对称性问题,学不到东西。
✅ 正确做法:用随机小数初始化
但随机也不能乱来!太小 → 信号传着传着没了;太大 → 信号爆炸。
于是,大神们提出了科学初始化方法:
1.1 Lecun Initialization(1998)
适用:tanh
激活函数 + 线性激活(如MLP)
核心思想:让前向传播时,信号的方差保持稳定。
数学公式:
权重 www 从均值为 0、方差为 1nin\frac{1}{n_{in}}nin1 的正态分布中采样:
w∼N(0,1nin)
w ∼ N(0, \frac{1}{n_{in}})
w∼N(0,nin1)
其中 ninn_{in}nin 是前一层的神经元数量。
例子:
前一层有 512 个神经元 → Var(w)=1512≈0.00195→w∼N(0,0.00195)Var(w) = \frac{1}{512} ≈ 0.00195 → w ∼ N(0, 0.00195)Var(w)=5121≈0.00195→w∼N(0,0.00195)
1.2 Xavier (Glorot) Initialization(2010)
适用:tanh
或 sigmoid
激活函数
核心思想:同时考虑前向和反向传播,让梯度也不爆炸不消失。
数学公式:
权重 www 从均值为 0、方差为 2nin+nout\frac{2}{n_{in} + n_{out}}nin+nout2 的正态分布中采样:
w∼N(0,2nin+nout) w ∼ N(0, \frac{2}{n_{in} + n_{out}}) w∼N(0,nin+nout2)
其中:
- ninn_{in}nin:前一层神经元数
- noutn_{out}nout:后一层神经元数
例子:
nin=512,nout=256→Var(w)=2512+256=2768≈0.0026→w∼N(0,0.0026)n_{in}=512, n_{out}=256 → Var(w) = \frac{2}{512+256} = \frac{2}{768} ≈ 0.0026 → w ∼ N(0, 0.0026)nin=512,nout=256→Var(w)=512+2562=7682≈0.0026→w∼N(0,0.0026)
✅ 比 Lecun 更“平衡”,兼顾前后向。
1.3 Kaiming (He) Initialization(2015)
适用:ReLU
及其变体(如 Leaky ReLU
)激活函数
为什么需要它?
因为 ReLU(x)=max(0,x)ReLU(x) = \max(0,x)ReLU(x)=max(0,x) 会“杀死”一半的神经元(负数变0),所以信号会衰减。
核心思想:补偿 ReLU
的“死亡率”,让信号方差稳定。
数学公式:
权重 www 从均值为 0、方差为 2nin\frac{2}{n_{in}}nin2 的正态分布中采样:
w∼N(0,2nin) w ∼ N(0, \frac{2}{n_{in}}) w∼N(0,nin2)
例子:
nin=512→Var(w)=2/512=0.0039→w∼N(0,0.0039)n_{in}=512 → Var(w) = 2/512 = 0.0039 → w ∼ N(0, 0.0039)nin=512→Var(w)=2/512=0.0039→w∼N(0,0.0039)
✅ 现代深度学习(如ResNet)几乎都用 Kaiming 初始化。
📊 总结对比
方法 | 适用激活函数 | 方差公式 |
---|---|---|
Lecun | tanh , 线性 | 1/nin1 / n_{in}1/nin |
Xavier | tanh , sigmoid | 2/(nin+nout)2 / (n_{in} + n_{out})2/(nin+nout) |
Kaiming | ReLU , Leaky ReLU | 2/nin2 / n_{in}2/nin |
2. 梯度消失 & 梯度爆炸
💬 大白话:
你走着走着,发现:
- 梯度消失:坡度太小,几乎感觉不到方向,走不动了。
- 梯度爆炸:坡度太大,一步迈过头,直接飞出山外。
📌 根源:链式法则的“连乘效应”
假设一个3层网络,损失 J
对第一层权重 w1
的梯度:
∂J/∂w1=(∂J/∂a3)×(∂a3/∂z3)×(∂z3/∂a2)×(∂a2/∂z2)×(∂z2/∂a1)×(∂a1/∂z1)×(∂z1/∂w1) ∂J/∂w_1 = (∂J/∂a_3) × (∂a_3/∂z_3) × (∂z_3/∂a_2) × (∂a_2/∂z_2) × (∂z_2/∂a_1) × (∂a_1/∂z_1) × (∂z_1/∂w_1) ∂J/∂w1=(∂J/∂a3)×(∂a3/∂z3)×(∂z3/∂a2)×(∂a2/∂z2)×(∂z2/∂a1)×(∂a1/∂z1)×(∂z1/∂w1)
其中 a=σ(z)a = σ(z)a=σ(z),σσσ 是激活函数。
📐 例子:Sigmoid 激活函数
Sigmoid 导数:σ′(z)=σ(z)(1−σ(z))σ'(z) = σ(z)(1-σ(z))σ′(z)=σ(z)(1−σ(z)),最大值 0.25
假设每层梯度都被乘以 0.25:
- 3层:0.253=0.01560.25^3 = 0.01560.253=0.0156
- 10层:0.2510≈9.5e−70.25^{10} ≈ 9.5e-70.2510≈9.5e−7 → 几乎为0 → 梯度消失!
📐 例子:权重太大
如果 www 初始化太大,比如 w=5w=5w=5,那 z=w×az = w×az=w×a 会很大 → σ(z)≈1σ(z) ≈ 1σ(z)≈1 → σ′(z)≈0σ'(z) ≈ 0σ′(z)≈0 → 同样梯度消失。
或者 w=10w=10w=10,zzz 超大 → 梯度超大 → 一步更新 w=w−η×∇Jw = w - η×∇Jw=w−η×∇J,直接飞出合理范围 → 梯度爆炸。
✅ 解决方案
- 换激活函数:用
ReLU
,它的导数在正区间是 1,不会让梯度变小。 - 用 Kaiming 初始化:专门针对
ReLU
设计。 - 加 Batch Normalization:让每层输入保持稳定分布。
- 残差连接:见下文。
3. 残差连接(Residual Connection)
💬 大白话:
梯度消失是因为路太长,梯度传不回去。
那怎么办?修条“捷径”!
让信息和梯度可以“抄近道”直接传回去。
📐 数学公式(ResNet)
普通层:
a[l]=σ(w[l]×a[l−1]+b[l])
a[l] = σ( w[l] × a[l-1] + b[l] )
a[l]=σ(w[l]×a[l−1]+b[l])
残差块:
a[l]=σ(F(a[l−1])+a[l−1])
a[l] = σ( F(a[l-1]) + a[l-1] )
a[l]=σ(F(a[l−1])+a[l−1])
其中 F(a[l−1])F(a[l-1])F(a[l−1]) 是“主路”(比如两层卷积),a[l−1]a[l-1]a[l−1] 是“捷径”。
📐 为什么能解决梯度消失?
看梯度 ∂J/∂a[l−1]∂J/∂a[l-1]∂J/∂a[l−1]:
∂J/∂a[l−1]=∂J/∂a[l]×∂a[l]/∂a[l−1] ∂J/∂a[l-1] = ∂J/∂a[l] × ∂a[l]/∂a[l-1] ∂J/∂a[l−1]=∂J/∂a[l]×∂a[l]/∂a[l−1]
而:
∂a[l]/∂a[l−1]=∂/∂a[l−1][F(a[l−1])+a[l−1]]=F′+I
∂a[l]/∂a[l-1] = ∂/∂a[l-1] [ F(a[l-1]) + a[l-1] ] = F' + I
∂a[l]/∂a[l−1]=∂/∂a[l−1][F(a[l−1])+a[l−1]]=F′+I
其中 III 是单位矩阵(来自 a[l−1]a[l-1]a[l−1] 的导数)。
关键:即使 F′≈0F' ≈ 0F′≈0(主路梯度消失),F′+IF' + IF′+I 的最小特征值也有 1!
所以梯度至少能以 111 的比例传回去,不会消失。
🖼️ 就像你下山,主路被雪埋了,但旁边有条水泥小路(+1),你还能走回去。
✅ 效果:
ResNet 可以轻松训练 100层、1000层 的网络!
4. 学习率与训练不稳定性
💬 大白话:
你走一步的大小(学习率 η
)得合适。
η
太小:走得慢,天黑了还没到底。η
太大:容易迈过头,来回震荡,甚至飞出山外(发散)。
📐 数学公式(梯度下降)
wt+1=wt−η×∇J(wt) w_{t+1} = w_t - η × ∇J(w_t) wt+1=wt−η×∇J(wt)
📌 例子:J(w)=w2J(w) = w²J(w)=w2(抛物线,最小值在 w=0w=0w=0)
- 梯度:∇J(w)=2w∇J(w) = 2w∇J(w)=2w
- 从 w=3w=3w=3 开始
学习率 ηηη | 更新过程 | 结果 |
---|---|---|
η=0.1η=0.1η=0.1 | 3→2.4→1.92→...3 → 2.4 → 1.92 → ...3→2.4→1.92→... | 慢慢收敛 |
η=0.6η=0.6η=0.6 | 3→−0.6→0.12→−0.024→...3 → -0.6 → 0.12 → -0.024 → ...3→−0.6→0.12→−0.024→... | 震荡收敛 |
η=1.1η=1.1η=1.1 | 3→−3.6→4.32→...3 → -3.6 → 4.32 → ...3→−3.6→4.32→... | 发散! |
🎯 训练不稳定性表现:
- 损失函数上蹿下跳
- 损失变成 NaNNaNNaN(数值溢出)
✅ 解决方案
- 调小学习率:最直接。
- 学习率预热(Warm-up):开始用小学习率,等稳定了再加大。
- 学习率衰减:训练后期逐渐减小 ηηη。
- 用自适应优化器:如 Adam,它会自动调每个参数的“步子”。
📊 总结对比表
问题 | 原因 | 数学关键 | 解决方案 |
---|---|---|---|
初始化不当 | 信号爆炸/消失 | Var(w)Var(w)Var(w) 不合理 | Lecun/Xavier/Kaiming |
梯度消失 | 链式法则连乘 | ∏σ′(z)≈0∏ σ'(z) ≈ 0∏σ′(z)≈0 | ReLU + Kaiming + BN + Residual |
残差连接 | 深网络梯度传不回 | ∂a[l]/∂a[l−1]=F′+I∂a[l]/∂a[l-1] = F' + I∂a[l]/∂a[l−1]=F′+I | 加“捷径” |
学习率太大 | 更新步子太大 | w=w−η×∇Jw = w - η×∇Jw=w−η×∇J 爆炸 | 调 ηηη,用 Adam |
💡 一句话记住
- 初始化:别乱站,按激活函数选“科学站位”。
- 梯度消失:路太长,坡没了 → 修“捷径”(残差)。
- 学习率:步子太大扯着蛋,太小半天到不了。