
LSTM & GRU —— 门控循环神经网络
系统讲解LSTM与GRU的门控机制设计哲学与数学原理。从LSTM的“双轨”架构(细胞状态+隐藏状态)与三门结构(遗忘门、输入门、输出门)出发,推导细胞状态更新公式如何通过按元素加法路径缓解梯度消失,并深入剖析GRU的两大简化及其参数量优势。附带讨论双向LSTM与深层堆叠LSTM的应用场景。
阅读文章ZHY's Blog
A UNIVERSE OF IDEAS · BY ZHANG HAOYI
让好奇心 点亮知识宇宙
在代码、模型与思想之间自由漫游。这里持续记录人工智能、机器学习、软件工程与成长实践,让每次阅读都成为一次新的发现。
ARTICLE NOTE
在上一篇博客中,我们确立了深度学习的优化目标 —— 通过最大化似然(MLE)来定义损失函数,为模型指明了“学什么”的方向。然而,一个更现实的问题随之浮现:有了目标,梯度也计算出来了,但反向传播时,它真的能一路顺畅地传回底层吗?
本篇博客正是解决这一“梯度可达性”问题的关键章节。如果说前两篇构建了数据的“骨架”与目标的“标尺”,那么本篇将赋予模型“可训练”的生命力。我们从Sigmoid与Tanh优雅但致命的梯度饱和出发 —— 其导数峰值仅0.25,这意味着10层网络反向传播时梯度会衰减百万倍,这也是深度学习在2010年前后陷入困境的根源。
随后,我们将系统梳理ReLU及其变体(LeakyReLU、PReLU、ELU、GELU、Swish) 的演进逻辑。您将看到,ReLU在正区间导数为1的简洁设计,如何彻底打开梯度通道,使训练数十层网络成为可能;而GELU与Swish如何通过平滑非线性进一步优化Transformer等现代架构的训练稳定性。
然而,激活函数只是故事的一半。权重初始化若与激活函数不匹配,即使ReLU也无法避免梯度爆炸 —— 我们将深入推导Xavier初始化(适用于Sigmoid/Tanh的方差守恒)与Kaiming初始化(专为ReLU设计的“信号补偿”机制)的数学原理,揭示二者在方差层面的协同关系。
值得注意的是,本篇对梯度流动的深刻理解,将直接服务于后续自动微分与计算图中关于“梯度累积”的实现细节,以及MLP中反向传播公式的逐层推导。现在,请带着“如何让梯度在每一层都稳得住”的问题进入正文——理解了本篇,您就掌握了让深度学习模型真正“跑起来”的两把核心钥匙。
Sigmoid函数的定义为:
σ(x)=1+e−x1值域为 (0,1),在零点处取最大值 σ(0)=0.5。
Sigmoid有一个非常优美的导数公式:
σ′(x)=σ(x)(1−σ(x))证明:用商法则,
σ′(x)=(1+e−x)2e−x而
σ(x)(1−σ(x))=1+e−x1⋅1+e−xe−x=(1+e−x)2e−x因此 σ′(x)=σ(x)(1−σ(x))。这个公式的优雅之处在于:只要知道函数值,就能直接算出导数值。
然而,致命的缺陷隐藏在这个导数公式中:
当 x→+∞ 时,σ(x)→1,σ′(x)→0; 当 x→−∞ 时,σ(x)→0,σ′(x)→0。
在 x=0 处导数取最大值:
σ′(0)=σ(0)(1−σ(0))=21⋅21=41也就是说,Sigmoid的导数最大也只有0.25。
这意味着什么?假设一个10层的网络,每层都使用Sigmoid激活函数,在最优情况下(每层输入都在0附近),反向传播的梯度每经过一层就乘以0.25。10层之后:
0.2510≈9.5×10−7梯度衰减了一百万倍!这就是梯度消失的数学根源。
📌 实验数据:当输入绝对值大于5时,Sigmoid输出已接近饱和区,梯度接近零。在10层以上的网络中,反向传播时梯度会以指数级衰减。
Tanh函数的定义为:
tanh(x)=ex+e−xex−e−x它与Sigmoid的关系为:tanh(x)=2σ(2x)−1。
Tanh的导数公式为:
tanh′(x)=1−tanh2(x)Tanh相比Sigmoid的改进:输出是零中心(zero-centered) 的,值域为 (−1,1)。这缓解了Sigmoid非零中心导致的”锯齿形”(zigzag)梯度更新问题。
但Tanh仍然存在梯度饱和问题:当输入绝对值较大时,tanh(x)→±1,导数 tanh′(x)→0。虽然Tanh在零点处的导数最大值为1(比Sigmoid的0.25大),但在饱和区的梯度同样趋近于零。
| 缺陷 | Sigmoid | Tanh |
|---|---|---|
| 梯度饱和 | 最大导数仅0.25,极易梯度消失 | 仍存在饱和区,梯度趋近于零 |
| 非零中心 | 输出恒为正,导致zigzag更新 | ✅ 已解决,输出零中心 |
| 计算开销 | 需要exp运算,较慢 | 需要exp运算,较慢 |
ReLU(Rectified Linear Unit)的定义极为简单:
ReLU(x)=max(0,x)其导数为:
ReLU′(x)={1,0,x>0x≤0ReLU的革命性优势:
正区间无梯度饱和:当 x>0 时,导数为1,梯度可以完整地向前传播。这意味着在正区间,梯度不会衰减!
计算简单:不需要指数运算,只是简单的比较和取零。
稀疏激活:负值被置零,产生稀疏表示,有助于特征选择。
然而,ReLU并非完美。当神经元的输入持续为负时,该神经元的输出恒为0,梯度也为0,权重再也无法更新——这个神经元就”死”了。
数学上,若对于某神经元,在训练过程中 w⊤x+b<0 始终成立,则:
∂w∂L=∂ReLU∂L⋅ReLU′(w⊤x+b)=0权重永远无法更新。
死亡ReLU的严重后果:在深度超过20层的网络中,未经特殊处理的ReLU可能导致30%-50%的神经元死亡,显著降低模型的有效容量。
LeakyReLU在负区间引入一个小的斜率 α(通常取0.01):
LeakyReLU(x)={x,αx,x>0x≤0导数为:
LeakyReLU′(x)={1,α,x>0x≤0负区间梯度不再是0,神经元不会”死亡”。实验表明,α=0.01 时神经元死亡率可降低至5%以下。
PReLU将负区间的斜率 α 变为可学习的参数:
f(x)=max(x,αx)其中 α 通过反向传播与权重一起更新。在ImageNet分类任务中,PReLU较ReLU可提升约1.2%的Top-1准确率。
ELU在负区间使用指数函数:
ELU(x)={x,α(ex−1),x>0x≤0ELU具有ReLU的优势,且输出均值接近零,同时对噪声有一定鲁棒性。但需要计算exp,计算量稍大。
GELU是Transformer等现代架构的首选激活函数。其定义为:
GELU(x)=x⋅Φ(x)其中 Φ(x) 是标准正态分布的累积分布函数。
实际计算中常用近似公式:
GELU(x)≈0.5x(1+tanh(π2(x+0.044715x3)))GELU的核心思想是:根据输入的大小”软性”地决定激活程度——输入值大时接近完全激活,输入值小时部分激活,负值大时接近零但不完全为零。
GELU的平滑性和非零曲率提供了更丰富的梯度信息,使深度网络的训练更加稳定。
Swish由Google Brain团队通过自动搜索发现,定义为:
Swish(x)=x⋅σ(βx)=1+e−βxx其中 β 可以是常数(通常为1)或可训练参数。
Swish被称为**“自门控”(self-gated)激活函数**:输入 x 乘以其自身的Sigmoid函数 σ(x),Sigmoid充当一个”门”,控制有多少输入能够通过。
当 x 很大时,σ(x)≈1,Swish ≈x(近似线性); 当 x 很小时,σ(x)≈0,Swish ≈0(但梯度非零)。
Swish在负区间保持非零梯度,同时保留正区间的线性特性,避免了死亡ReLU问题。
| 激活函数 | 梯度饱和 | 零中心 | 计算开销 | 死亡神经元 | 适用场景 |
|---|---|---|---|---|---|
| Sigmoid | ✅ 严重 | ❌ | 高 | - | 二分类输出层 |
| Tanh | ✅ 存在 | ✅ | 高 | - | 传统RNN |
| ReLU | ❌ 正区间无 | ❌ | 低 | ✅ 有 | CNN通用 |
| LeakyReLU | ❌ | ❌ | 低 | ⚠️ 极少 | 防止死亡ReLU |
| PReLU | ❌ | ❌ | 低 | ⚠️ 极少 | 可学习负斜率 |
| ELU | ❌ | ✅ | 中 | ❌ | 需零中心输出 |
| GELU | ❌ | ❌ | 中 | ❌ | Transformer |
| Swish | ❌ | ❌ | 中 | ❌ | 深层网络 |
选择合适的激活函数只是解决梯度问题的一半。即使使用了ReLU,如果权重初始化不当,梯度仍然可能爆炸或消失。
考虑一个全连接层:z=∑i=1nwixi。
如果权重 wi 初始值太大,z 会很大,可能将激活函数推入饱和区(对Sigmoid/Tanh而言)。
如果权重 wi 初始值太小,z 会很小,梯度在反向传播时会逐层衰减。
理想情况是:每一层输出的方差保持稳定,既不放大也不衰减。
Xavier初始化由Glorot & Bengio在2010年提出,主要适用于 Sigmoid和Tanh 等饱和激活函数。
对于线性层 z=∑i=1ninwixi,根据方差的性质(独立变量和的方差等于方差之和):
Var(z)=i=1∑ninVar(wixi)=nin⋅Var(w)⋅Var(x)为了保持方差一致(Var(z)=Var(x)),需要:
nin⋅Var(w)=1⟹Var(w)=nin1反向传播时,梯度 ∂xi∂L 与权重的转置相关:
∂xi∂L=j=1∑noutwij⋅∂zj∂L同理,为保持梯度方差一致,需要:
nout⋅Var(w)=1⟹Var(w)=nout1前向和反向传播对方差的要求不同(1/nin vs 1/nout),Xavier取两者的调和平均:
Var(w)=nin+nout2正态分布:w∼N(0,nin+nout2)
均匀分布:若 w∼U(−a,a),则 Var(w)=3a2。令其等于 nin+nout2,得:
a=nin+nout6即 w∼U(−nin+nout6,nin+nout6)
Xavier初始化在ReLU上表现不佳,因为ReLU会将大约一半的神经元输出置为零,相当于砍掉了一半的信号。
何恺明在2015年的论文《Delving Deep into Rectifiers》中提出了专门针对ReLU的Kaiming初始化。
ReLU的负值全部被截断为零,导致输出的方差大约只有输入方差的一半。为了补偿这个损失,权重的方差需要翻倍。
设第 l 层的输入为 x(已经过ReLU激活),输出为 y=∑i=1nwixi(线性变换后,尚未激活)。
由于 x 是ReLU的输出,x≥0 且均值为0(假设权重均值为0,输入在0附近对称分布)。
关键步骤:ReLU将输入方差减半
对于零均值的对称分布 u,经过ReLU后:
E[x2]=E[(ReLU(u))2]=21E[u2]即 Var(x)=21Var(u)。
因此:
Var(y)=n⋅Var(w)⋅Var(x)=n⋅Var(w)⋅21Var(u)为了保持方差一致(Var(y)=Var(u)):
n⋅Var(w)⋅21=1⟹Var(w)=n2Kaiming初始化的权重方差为:
Var(w)=nin2正态分布:w∼N(0,nin2)
均匀分布:w∼U(−nin6,nin6)
💡 关键区别:Xavier用的是 nin+nout2,Kaiming用的是 nin2。对于ReLU,Kaiming初始化保证每层方差守恒。
1import numpy as np2
3def xavier_uniform(input_dim, output_dim):4 """Xavier均匀初始化,适用于Sigmoid/Tanh"""5 limit = np.sqrt(6 / (input_dim + output_dim))6 return np.random.uniform(-limit, limit, (output_dim, input_dim))7
8def xavier_normal(input_dim, output_dim):9 """Xavier正态初始化,适用于Sigmoid/Tanh"""10 std = np.sqrt(2 / (input_dim + output_dim))11 return np.random.normal(0, std, (output_dim, input_dim))12
13def kaiming_uniform(input_dim, output_dim):14 """Kaiming均匀初始化,适用于ReLU"""15 limit = np.sqrt(6 / input_dim)16 return np.random.uniform(-limit, limit, (output_dim, input_dim))17
18def kaiming_normal(input_dim, output_dim):19 """Kaiming正态初始化,适用于ReLU"""20 std = np.sqrt(2 / input_dim)21 return np.random.normal(0, std, (output_dim, input_dim))22
23# 示例:创建一个3层MLP的权重24d, h1, h2, q = 784, 256, 128, 1025
26# 使用Kaiming初始化(ReLU网络)27W1 = kaiming_normal(d, h1) # 方差 = 2/784 ≈ 0.0025528W2 = kaiming_normal(h1, h2) # 方差 = 2/256 ≈ 0.0078129W3 = kaiming_normal(h2, q) # 方差 = 2/128 ≈ 0.01563| 激活函数 | 推荐初始化 | 方差公式 |
|---|---|---|
| Sigmoid | Xavier | 2/(nin+nout) |
| Tanh | Xavier | 2/(nin+nout) |
| ReLU | Kaiming | 2/nin |
| LeakyReLU | Kaiming(Leaky版) | 2/(1+α2)nin |
| GELU | 近似Kaiming | 2/nin |
| Swish | 近似Kaiming | 2/nin |
回顾整个发展历程,我们可以看到一条清晰的脉络:
第一代(Sigmoid) :提出了可微的非线性激活,但梯度饱和严重,最大导数仅0.25,深层网络几乎无法训练。
第二代(Tanh) :解决了零中心问题,但饱和问题依然存在。
第三代(ReLU) :正区间导数为1,彻底解决了正区间的梯度消失问题,使训练深层网络成为可能。但引入了死亡ReLU的新问题。
第四代(LeakyReLU/PReLU/ELU/GELU/Swish) :在保留ReLU优势的同时,通过给负区间赋予非零梯度来解决死亡ReLU问题。
而权重初始化与激活函数相辅相成:
一个经验法则:
使用ReLU及其变体 → 用Kaiming初始化 使用Sigmoid或Tanh → 用Xavier初始化
理解这些原理,你就掌握了深度学习训练稳定性的两个关键杠杆。下一篇文章,我们将深入探讨卷积神经网络(CNN) 的数学原理与反向传播。
延伸阅读:
按顺序完成这组文章,循序渐进地掌握主题
发现错误、内容过时或有改进想法?欢迎告诉我
根据本文分类与标签,为你推荐可能感兴趣的内容

系统讲解LSTM与GRU的门控机制设计哲学与数学原理。从LSTM的“双轨”架构(细胞状态+隐藏状态)与三门结构(遗忘门、输入门、输出门)出发,推导细胞状态更新公式如何通过按元素加法路径缓解梯度消失,并深入剖析GRU的两大简化及其参数量优势。附带讨论双向LSTM与深层堆叠LSTM的应用场景。
阅读文章
系统讲解循环神经网络(RNN)的数学原理与随时间反向传播(BPTT)算法。从RNN的循环结构与共享参数出发,推导BPTT的梯度表达式,揭示梯度消失与梯度爆炸的数学根源,并介绍梯度裁剪作为应对梯度爆炸的工程解法。附带讨论LSTM如何通过门控机制缓解梯度消失。
阅读文章
系统讲解ResNet残差网络的设计哲学与数学原理:从退化问题的本质出发,推导残差块F(x)+x如何通过恒等映射直通路径缓解梯度消失,详解Bottleneck块如何将参数量减少约94%,并对比ResNet(加法融合)与DenseNet(拼接融合)的梯度流动差异。
阅读文章请使用微信扫描二维码分享
当前文章会保持在原页面