光宇
24.33M · 2026-03-31
如果神经网络只有线性变换(矩阵乘法 + 偏置),无论堆多少层,最终都等价于一层线性变换:y = W₃(W₂(W₁x + b₁) + b₂) + b₃ = Wx + b。这意味着多层网络没有意义。
激活函数在每层之间引入非线性"弯折",让神经网络能够拟合复杂的非线性模式。在 Transformer 的 FFN(Feed-Forward Network)中,激活函数决定了模型的表达能力、训练稳定性和计算效率。
本文深入讲解 FFN 中主流激活函数(ReLU、GELU、SiLU、SwiGLU)的原理、演进和选择策略。
在深入激活函数之前,先理解 FFN 在 Transformer 中的位置。
Transformer Block 包含两个核心组件:
每个组件后都有残差连接和层归一化(Add & Norm)。
FFN 包含三个步骤:
数学表达式:
FFN(x) = W₂ · σ(W₁ · x + b₁) + b₂
↑
激活函数 σ
其中:
W₁ ∈ ℝ^(d_ff × d_model):第一层权重(扩展)W₂ ∈ ℝ^(d_model × d_ff):第二层权重(压缩)σ:激活函数(决定 FFN 的非线性特性)关键洞察:
FFN 的结构很简单(两层全连接 + 激活函数),但它承担了 Transformer 中 70-80% 的参数量。
激活函数的选择,直接影响 FFN 的表达能力和训练效率。
在深入具体算法前,先理解一个好的激活函数需要满足什么条件。
要求: 必须是非线性函数,否则多层网络退化为单层。
反例:f(x) = ax + b(线性函数)
正例:f(x) = max(0, x)(ReLU,有折点)
要求: 至少几乎处处可微,否则无法用梯度下降训练。
部分可微的例子:ReLU 在 x=0 处不可微,但实际训练中可忽略(概率为 0)
完全可微的例子:GELU、SiLU(处处光滑)
要求: 避免梯度消失(gradient vanishing)或梯度爆炸(gradient exploding)。
问题示例:Sigmoid
σ(x) = 1 / (1 + e^(-x))
梯度:dσ/dx = σ(x) · (1 - σ(x))
当 x → +∞ 时,σ(x) → 1,梯度 → 0
当 x → -∞ 时,σ(x) → 0,梯度 → 0
结果:深层网络中,梯度会越乘越小(梯度消失)。
改进:ReLU 系列在 x > 0 时梯度恒为 1,避免了梯度消失。
要求: 计算快,占用 GPU 资源少。
对比:
| 激活函数 | 计算复杂度 | 原因 |
|---|---|---|
| ReLU | 极低 | 只需比较和取最大值 |
| GELU | 中等 | 需要计算误差函数 erf(x) 或 tanh 近似 |
| SwiGLU | 较高 | 需要额外的线性变换(参数量增加) |
| 实际影响: |
根据 Michael Brenndoerfer 的测试,激活函数的计算时间通常只占 FFN 总时间的 < 1%。但在超大规模模型(如 GPT-4 的 1.8T 参数)中,即使 1% 的差异也值得优化。
要求: 在极端输入下不会溢出或下溢。
问题示例:Softmax
softmax(x) = exp(x_i) / Σ exp(x_j)
当 x_i 很大(如 1000)时:
exp(1000) = 2.7 × 10^434 ← 数值溢出!
解决方案:Softmax 通常会减去 max(x) 来稳定。
ReLU(Rectified Linear Unit)定义为 ReLU(x) = max(0, x),即负数部分置零,正数部分保持不变。
ReLU 的核心优势是计算极快、梯度简单(x > 0 时梯度恒为 1),有效缓解了 Sigmoid/Tanh 的梯度消失问题,并且会产生稀疏激活(很多神经元输出 0)。
但 ReLU 有致命缺陷:死亡 ReLU 问题。如果神经元输入始终为负,则输出和梯度永远为 0,导致权重无法更新,神经元"死亡"。研究者提出了 Leaky ReLU、PReLU、ELU 等改进版本,在负数部分保留小的梯度,但增加了调参复杂度或计算成本。
现状(2026):主流 LLM 已不再使用 ReLU(GPT-3 之后),但在资源受限场景(边缘设备)和稀疏模型中仍有价值。
ReLU 的问题在于太"硬":在 x = 0 附近,微小的输入差异会导致截然不同的输出(-0.001 → 0,+0.001 → 0.001)。GELU 的思路是让激活函数"软"一点。
GELU(Gaussian Error Linear Unit)定义为 GELU(x) = x · Φ(x),其中 Φ(x) 是标准正态分布的累积分布函数(CDF)。直观理解:Φ(x) 表示"从 N(0,1) 采样的随机变量 ≤ x 的概率"。GELU 用概率来决定信号的激活程度:x 很大时 Φ(x) ≈ 1(几乎全部保留),x 很小时 Φ(x) ≈ 0(几乎全部抛弃),x 接近 0 时 Φ(x) ≈ 0.5(部分保留)。
GELU 处处可微(没有 ReLU 的折点),梯度为 dGELU/dx = Φ(x) + x · φ(x)(φ是概率密度函数)。梯度特点:x > 0 时梯度 > 1(略微放大),x ≈ 0 时梯度 ≈ 0.5,x < 0 时梯度 > 0(不会完全死亡)。
实践中,计算精确的 Φ(x) 需要误差函数 erf(x),可能较慢。常用近似方法包括 Tanh 近似(精度 99.9%)和 Sigmoid 近似(精度 98%)。PyTorch 默认使用 Tanh 近似作为精度和速度的平衡点。
对比实验(BERT 论文,2018):
| 激活函数 | GLUE 分数 | SQuAD F1 |
|---|---|---|
| ReLU | 80.1 | 88.2 |
| GELU | 82.3 | 90.1 |
| Swish | 81.7 | 89.5 |
| 关键结论: |
GELU 在 BERT 上显著优于 ReLU(+2.2 GLUE 分数)。
为什么 GELU 更好?
BERT(2018)首次在 Transformer 中使用 GELU,此后 GPT-2、GPT-3、T5 等模型延续使用。现状(2026):GELU 仍是 Encoder-Only 模型(如 BERT)和 Encoder-Decoder 模型(如 T5)的主流选择,但在 Decoder-Only 模型(如 GPT 系列、LLaMA)中正在被 SwiGLU 取代。
SiLU(Sigmoid Linear Unit)又称 Swish,是一个激活函数,定义为 SiLU(x) = x · sigmoid(x)。
先理解 sigmoid(x):
sigmoid 函数 sigmoid(x) = 1 / (1 + e^(-x)) 的输出值永远在 0 到 1 之间:
SiLU 的"自门控":
传统激活函数(如ReLU)只处理输入:ReLU(x) = max(0, x)
SiLU 不同:输入 x 既是"被处理的信号",又是"控制开关":
这就是"自门控":输入控制自己能通过多少。
关键:SiLU 是单路径的,只有一个输入 x,经过 SiLU 激活后输出。它替代了 ReLU/GELU,作为传统 FFN 的激活函数。
对比实验(LLaMA 论文,2023):
| 激活函数 | 困惑度(Perplexity) | 训练速度 |
|---|---|---|
| ReLU | 10.8 | 基线 |
| GELU | 10.2 | +5% 慢 |
| SiLU | 10.1 | +2% 慢 |
| 关键结论: |
SiLU 在性能上略优于 GELU,同时计算开销更小。
核心差异:SiLU 是激活函数,SwiGLU 是 FFN 架构。
输入 x (512维)
↓
W₁ 升维到 2048维
↓
SiLU 激活
↓
W₂ 降维回 512维
↓
输出 (512维)
输入 x (512维)
├─→ W₁ 升维到 2048维 → SiLU → 门控 g (2048维)
└─→ W₂ 升维到 2048维 ────→ 内容 v (2048维)
↓
g ⊙ v 逐元素相乘 (2048维)
↓
W₃ 降维回 512维
↓
输出 (512维)
SiLU(自门控):
SwiGLU(分离门控):
看到差别了吗?
SiLU:x 再怎么复杂,也只能"自己决定自己的命运" SwiGLU:路径A 可以学会"识别重要性",路径B 专注"提取内容",两者分工合作,表达能力更强。
举例:假设 x 包含了"重要信息"和"噪声"混在一起,
实验证明(GLU Variants Improve Transformer,2020):SwiGLU 比传统激活函数性能提升 +1.2 BLEU,代价是参数量增加 50%。
参数量权衡:PaLM 论文(2022)提出通过调整隐藏层维度保持参数量不变。关键公式:d_ff_swiglu = 2/3 × d_ff_standard。例如:
性能表现:PaLM 实验显示,在相同参数量下,SwiGLU 比 GELU 困惑度降低 3-4%。
LoRA(Low-Rank Adaptation)通过在原始权重旁添加低秩矩阵来微调模型。对于 SwiGLU 的三个矩阵:
理论上:三个矩阵都可以加 LoRA
实践建议:
| 策略 | LoRA 应用位置 | 参数量 | 适用场景 |
|---|---|---|---|
| 完整微调 | W₁ + W₂ + W₃ | 3 × rank × (d_model + d_ff) | 数据充足,追求最佳效果 |
| 重点微调 | W₁ + W₂ | 2 × rank × (d_model + d_ff) | 平衡效果和效率(推荐) |
| 极简微调 | W₁ 或 W₂ | 1 × rank × (d_model + d_ff) | 资源受限,快速实验 |
为什么 W₁ 和 W₂ 更重要?
W₃ 只是降维投影,相对通用;W₁ 和 W₂ 直接决定特征如何被提取和门控,对任务适应性影响更大。
对比传统 FFN 的 LoRA:
大多数开源实现(如 LLaMA 的 LoRA)默认对所有线性层(包括 W₁、W₂、W₃)应用 LoRA。
实际应用(2023-2026):LLaMA、Mistral、Gemma、Qwen 等主流大模型均采用 SwiGLU。现状(2026):SwiGLU 已成为 Decoder-Only 大模型的默认选择。
| 激活函数 | 计算速度 | 参数量 | 性能(困惑度) | 梯度稳定性 | 推荐场景 |
|---|---|---|---|---|---|
| ReLU | 基线 | 资源受限、稀疏模型 | |||
| GELU | 基线 | Encoder、小模型 | |||
| SiLU | 基线 | 通用 Decoder 模型 | |||
| SwiGLU | 基线 × 1.5 | 大规模 Decoder 模型 |
根据项目类型选择:
Encoder-Only(如 BERT)
Encoder-Decoder(如 T5)
Decoder-Only(如 GPT、LLaMA)
场景 1:从零训练大模型(> 7B)
→ 选择 SwiGLU
理由:
场景 2:微调预训练模型
→ 保持原模型的激活函数
理由:
场景 3:资源受限(边缘设备、移动端)
→ 选择 ReLU
理由:
场景 4:研究新架构
→ 尝试 GELU 或 SiLU
理由:
让激活函数的形状可以学习。例如 Adaptive Piecewise Linear (APL) 将激活函数表示为可学习参数 aᵢ 和 bᵢ 的分段线性组合。优势是可以自动调整到最适合数据的形状,缺点是参数量增加、计算开销大。
2025 年的 Spark Transformer 论文显示:只激活 8% 的 FFN 神经元就能达到接近原始性能,推理速度提升 3.2 倍。实现方式是只保留 top-k 的激活值,其余置零。
在不同层使用不同的激活函数。理由是不同深度的层承担的任务不同,或许需要不同的非线性特性。例如底层用 SwiGLU(表达能力强)、中层用 GELU(计算快)、顶层用 ReLU(稀疏性好)。
Apple 的 One Wide FFN 论文(2025)提出使用三层 FFN(x → W₁ → σ₁ → W₂ → σ₂ → W₃ → y),在相同总参数量下,训练 loss 更低、参数效率更高、训练速度相当。
激活函数的选择与模型架构(Encoder vs Decoder)、训练数据规模(小数据集上差异不大)、计算资源(SwiGLU 需要更多显存)、历史惯性(延续前代设计)等因素有关。建议:如果不确定,选择与参考模型相同的激活函数。
理论上可以,但实践中很少这么做。原因:激活函数是 FFN 的核心,切换相当于重新初始化,需要额外 warm-up 过程,可能导致训练不稳定。替代方案:从头开始用新激活函数重新训练一个分支对比性能。
来自实验调优,不是理论推导。PaLM 论文尝试了多个比例:1/2(困惑度 10.5)、2/3(10.1)、3/4(10.0)、1.0(9.9)。结论:2/3 是性能和参数量的最佳平衡点。
激活函数本身不占参数(只是计算逻辑),但 GLU 系列需要额外的权重矩阵。例如 d_model=4096, d_ff=16384 时:标准 FFN 参数量 134M,SwiGLU 原始版本 201M,2/3 调整后 134M。
梯度消失问题。在 x=10 时,Sigmoid 梯度 ≈ 0.00005,ReLU 梯度 = 1.0。在 24 层 Transformer 中,Sigmoid 梯度累乘后 ≈ 0(完全消失),ReLU 梯度保持 1.0(完美传递)。
2010-2015: ReLU 时代
2016-2019: GELU 时代
2020-2023: SiLU 时代
2023-至今: SwiGLU 时代
| 时代 | 核心思想 | 代表函数 |
|---|---|---|
| 第一代 | 简单有效 | ReLU |
| 第二代 | 平滑性 | GELU |
| 第三代 | 自门控 | SiLU |
| 第四代 | 选择性激活 | SwiGLU |
三大方向:
随着模型规模持续增长,激活函数的选择将更加注重:
激活函数看似是神经网络中的"小"组件,但它承载着引入非线性、控制信息流的核心功能。从 ReLU 到 SwiGLU 的演进,正是深度学习领域不断追求"更强表达能力"和"更高效计算"的缩影。
参考资料: