FFN 激活函数深度解析:从 ReLU 到 SwiGLU 的演进之路
引言:为什么需要激活函数?
如果神经网络只有线性变换(矩阵乘法 + 偏置),无论堆多少层,最终都等价于一层线性变换:y = W₃(W₂(W₁x + b₁) + b₂) + b₃ = Wx + b。这意味着多层网络没有意义。
激活函数在每层之间引入非线性"弯折",让神经网络能够拟合复杂的非线性模式。在 Transformer 的 FFN(Feed-Forward Network)中,激活函数决定了模型的表达能力、训练稳定性和计算效率。
本文深入讲解 FFN 中主流激活函数(ReLU、GELU、SiLU、SwiGLU)的原理、演进和选择策略。
FFN 的基本结构:激活函数在哪里?
在深入激活函数之前,先理解 FFN 在 Transformer 中的位置。
Transformer 的整体架构
Transformer Block 包含两个核心组件:
- Multi-Head Attention:建模序列关系
- Feed-Forward Network (FFN):本文重点!每个位置独立进行非线性特征变换
每个组件后都有残差连接和层归一化(Add & Norm)。
标准 FFN 的计算流程
FFN 包含三个步骤:
- 第一层线性变换(W₁):将输入 x (d_model = 512) 扩展到更高维度 h (d_ff = 2048)
- 激活函数(σ):对 h 进行非线性变换 → 本文重点!
- 第二层线性变换(W₂):将激活后的向量压缩回原维度 y (d_model = 512)
数学表达式:
scss
FFN(x) = W₂ · σ(W₁ · x + b₁) + b₂
↑
激活函数 σ
其中:
W₁∈ ℝ^(d_ff × d_model):第一层权重(扩展)W₂∈ ℝ^(d_model × d_ff):第二层权重(压缩)σ:激活函数(决定 FFN 的非线性特性)
关键洞察:
FFN 的结构很简单(两层全连接 + 激活函数),但它承担了 Transformer 中 70-80% 的参数量。
- Attention 负责"谁和谁相关"(序列建模)
- FFN 负责"每个位置的特征变换"(非线性表达)
激活函数的选择,直接影响 FFN 的表达能力和训练效率。
激活函数的核心要求
在深入具体算法前,先理解一个好的激活函数需要满足什么条件。
1. 非线性(Nonlinearity)
要求: 必须是非线性函数,否则多层网络退化为单层。
反例:f(x) = ax + b(线性函数)
正例:f(x) = max(0, x)(ReLU,有折点)
2. 可微性(Differentiability)
要求: 至少几乎处处可微,否则无法用梯度下降训练。
部分可微的例子:ReLU 在 x=0 处不可微,但实际训练中可忽略(概率为 0)
完全可微的例子:GELU、SiLU(处处光滑)
3. 梯度友好(Gradient-Friendly)
要求: 避免梯度消失(gradient vanishing)或梯度爆炸(gradient exploding)。
问题示例:Sigmoid
scss
σ(x) = 1 / (1 + e^(-x))
梯度:dσ/dx = σ(x) · (1 - σ(x))
当 x → +∞ 时,σ(x) → 1,梯度 → 0
当 x → -∞ 时,σ(x) → 0,梯度 → 0
结果:深层网络中,梯度会越乘越小(梯度消失)。
改进:ReLU 系列在 x > 0 时梯度恒为 1,避免了梯度消失。
4. 计算效率(Computational Efficiency)
要求: 计算快,占用 GPU 资源少。
对比:
| 激活函数 | 计算复杂度 | 原因 |
|---|---|---|
| ReLU | 极低 | 只需比较和取最大值 |
| GELU | 中等 | 需要计算误差函数 erf(x) 或 tanh 近似 |
| SwiGLU | 较高 | 需要额外的线性变换(参数量增加) |
| 实际影响: |
根据 Michael Brenndoerfer 的测试,激活函数的计算时间通常只占 FFN 总时间的 < 1%。但在超大规模模型(如 GPT-4 的 1.8T 参数)中,即使 1% 的差异也值得优化。
5. 数值稳定性(Numerical Stability)
要求: 在极端输入下不会溢出或下溢。
问题示例:Softmax
python
softmax(x) = exp(x_i) / Σ exp(x_j)
当 x_i 很大(如 1000)时:
exp(1000) = 2.7 × 10^434 ← 数值溢出!
解决方案:Softmax 通常会减去 max(x) 来稳定。
第一代:ReLU - 简单粗暴的开拓者
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 之后),但在资源受限场景(边缘设备)和稀疏模型中仍有价值。
第二代:GELU - 引入概率的平滑曲线
GELU 的设计动机与定义
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 的数学性质
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 近似作为精度和速度的平衡点。
GELU 的实际表现
对比实验(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 更好?
- 平滑性 → 梯度更稳定,训练更顺畅
- 非零负值 → 不会像 ReLU 那样完全"死亡"
- 概率性质 → 类似于"软门控"(soft gating),比硬切换更灵活
GELU 的应用案例
BERT(2018)首次在 Transformer 中使用 GELU,此后 GPT-2、GPT-3、T5 等模型延续使用。现状(2026):GELU 仍是 Encoder-Only 模型(如 BERT)和 Encoder-Decoder 模型(如 T5)的主流选择,但在 Decoder-Only 模型(如 GPT 系列、LLaMA)中正在被 SwiGLU 取代。
第三代:SiLU/Swish - 自门控的激活函数
SiLU(Sigmoid Linear Unit)又称 Swish,是一个激活函数 ,定义为 SiLU(x) = x · sigmoid(x)。
先理解 sigmoid(x):
sigmoid 函数 sigmoid(x) = 1 / (1 + e^(-x)) 的输出值永远在 0 到 1 之间:
- x 很大时 → sigmoid ≈ 1(完全打开)
- x 很小时 → sigmoid ≈ 0(完全关闭)
- x = 0 时 → sigmoid = 0.5(半开半闭)
SiLU 的"自门控":
传统激活函数(如ReLU)只处理输入:ReLU(x) = max(0, x)
SiLU 不同:输入 x 既是"被处理的信号",又是"控制开关":
- x=5 时:sigmoid(5)≈0.993,SiLU(5) = 5 × 0.993 ≈ 4.97(信号强,开关几乎全开,大部分通过)
- x=-5 时:sigmoid(-5)≈0.007,SiLU(-5) = -5 × 0.007 ≈ -0.03(信号弱,开关几乎全关,几乎阻断)
这就是"自门控":输入控制自己能通过多少。
关键:SiLU 是单路径的,只有一个输入 x,经过 SiLU 激活后输出。它替代了 ReLU/GELU,作为传统 FFN 的激活函数。
SiLU 的实际性能
对比实验(LLaMA 论文,2023):
| 激活函数 | 困惑度(Perplexity) | 训练速度 |
|---|---|---|
| ReLU | 10.8 | 基线 |
| GELU | 10.2 | +5% 慢 |
| SiLU | 10.1 | +2% 慢 |
| 关键结论: |
SiLU 在性能上略优于 GELU,同时计算开销更小。
第四代:SwiGLU - 从单路径到双路径的革命
核心差异:SiLU 是激活函数,SwiGLU 是 FFN 架构。
传统 FFN(使用 SiLU)
scss
输入 x (512维)
↓
W₁ 升维到 2048维
↓
SiLU 激活
↓
W₂ 降维回 512维
↓
输出 (512维)
- 2个权重矩阵:W₁(升维), W₂(降维)
- 单路径:一个输入,一次激活,一个输出
SwiGLU FFN(双路径门控)
scss
输入 x (512维)
├─→ W₁ 升维到 2048维 → SiLU → 门控 g (2048维)
└─→ W₂ 升维到 2048维 ────→ 内容 v (2048维)
↓
g ⊙ v 逐元素相乘 (2048维)
↓
W₃ 降维回 512维
↓
输出 (512维)
- 3个权重矩阵:W₁(门控升维), W₂(内容升维), W₃(降维聚合)
- 双路径:输入分两路,一路用SiLU激活作门控,一路作内容,最后相乘聚合
直观对比
SiLU(自门控):
- 输入:x = 5.0
- sigmoid(5) = 0.993(自己控制自己)
- 输出:5.0 × 0.993 = 4.97
SwiGLU(分离门控):
- 输入:x = [1.0, 2.0, 3.0]
- 路径A(门控):W₁·x → SiLU → g = [0.9, 0.3, 0.8]
- 路径B(内容):W₂·x → v = [5.0, 4.0, 6.0]
- 输出:g ⊙ v = [4.5, 1.2, 4.8]
看到差别了吗?
- SiLU:一个值控制自己(5.0 控制 5.0 能通过多少)
- SwiGLU:一路控制另一路(g[0]=0.9 控制 v[0]=5.0 能通过多少)
为什么 SwiGLU 更强?
SiLU:x 再怎么复杂,也只能"自己决定自己的命运" SwiGLU:路径A 可以学会"识别重要性",路径B 专注"提取内容",两者分工合作,表达能力更强。
举例:假设 x 包含了"重要信息"和"噪声"混在一起,
- SiLU:无法区分,只能整体缩放
- SwiGLU:路径A学会屏蔽噪声(给噪声位置的门控信号=0.1),只激活重要信息(给重要位置的门控信号=0.9)
实验证明(GLU Variants Improve Transformer,2020):SwiGLU 比传统激活函数性能提升 +1.2 BLEU,代价是参数量增加 50%。
参数量权衡:PaLM 论文(2022)提出通过调整隐藏层维度保持参数量不变。关键公式:d_ff_swiglu = 2/3 × d_ff_standard。例如:
- 传统 FFN:d_model=4096, d_ff=16384,参数量 134M
- SwiGLU(直接替换):参数量 201M(+50%)
- SwiGLU(2/3 调整):d_ff=10923,参数量 134M(持平)
性能表现:PaLM 实验显示,在相同参数量下,SwiGLU 比 GELU 困惑度降低 3-4%。
LoRA 微调时如何处理 SwiGLU?
LoRA(Low-Rank Adaptation)通过在原始权重旁添加低秩矩阵来微调模型。对于 SwiGLU 的三个矩阵:
理论上:三个矩阵都可以加 LoRA
- W₁(门控路径):影响"什么重要"的判断
- W₂(内容路径):影响特征的提取
- W₃(输出投影):影响最终的输出表示
实践建议:
| 策略 | 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:
- 传统 FFN(ReLU/GELU):只有 W₁ 和 W₂ 两个矩阵,通常都加 LoRA
- SwiGLU FFN:多了一个 W₂,可以选择性应用
大多数开源实现(如 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)
- 推荐:GELU
Encoder-Decoder(如 T5)
- 推荐:GELU 或 SwiGLU
Decoder-Only(如 GPT、LLaMA)
- 模型规模 < 1B → 推荐:GELU 或 SiLU
- 模型规模 ≥ 1B → 推荐:SwiGLU(2/3 规则)
实际选择建议
场景 1:从零训练大模型(> 7B)
→ 选择 SwiGLU
理由:
- 性能最佳(困惑度降低 3-4%)
- 业界验证充分(LLaMA、Mistral 等)
- 参数量可控(2/3 规则)
场景 2:微调预训练模型
→ 保持原模型的激活函数
理由:
- 改变激活函数需要重新初始化 FFN
- 微调时改动架构风险大
场景 3:资源受限(边缘设备、移动端)
→ 选择 ReLU
理由:
- 计算最快
- 可以利用稀疏性优化
场景 4:研究新架构
→ 尝试 GELU 或 SiLU
理由:
- 实现简单
- 调参容易
- 性能稳定
前沿趋势:激活函数的未来方向
1. 自适应激活函数
让激活函数的形状可以学习。例如 Adaptive Piecewise Linear (APL) 将激活函数表示为可学习参数 aᵢ 和 bᵢ 的分段线性组合。优势是可以自动调整到最适合数据的形状,缺点是参数量增加、计算开销大。
2. 稀疏激活
2025 年的 Spark Transformer 论文显示:只激活 8% 的 FFN 神经元就能达到接近原始性能,推理速度提升 3.2 倍。实现方式是只保留 top-k 的激活值,其余置零。
3. 混合激活函数
在不同层使用不同的激活函数。理由是不同深度的层承担的任务不同,或许需要不同的非线性特性。例如底层用 SwiGLU(表达能力强)、中层用 GELU(计算快)、顶层用 ReLU(稀疏性好)。
4. 三层 FFN
Apple 的 One Wide FFN 论文(2025)提出使用三层 FFN(x → W₁ → σ₁ → W₂ → σ₂ → W₃ → y),在相同总参数量下,训练 loss 更低、参数效率更高、训练速度相当。
常见问题解答
Q1: 为什么不同论文的激活函数选择不一样?
激活函数的选择与模型架构(Encoder vs Decoder)、训练数据规模(小数据集上差异不大)、计算资源(SwiGLU 需要更多显存)、历史惯性(延续前代设计)等因素有关。建议:如果不确定,选择与参考模型相同的激活函数。
Q2: 能否在训练中途切换激活函数?
理论上可以,但实践中很少这么做。原因:激活函数是 FFN 的核心,切换相当于重新初始化,需要额外 warm-up 过程,可能导致训练不稳定。替代方案:从头开始用新激活函数重新训练一个分支对比性能。
Q3: SwiGLU 的 2/3 规则是怎么来的?
来自实验调优,不是理论推导。PaLM 论文尝试了多个比例:1/2(困惑度 10.5)、2/3(10.1)、3/4(10.0)、1.0(9.9)。结论:2/3 是性能和参数量的最佳平衡点。
Q4: 激活函数对模型大小有什么影响?
激活函数本身不占参数(只是计算逻辑),但 GLU 系列需要额外的权重矩阵。例如 d_model=4096, d_ff=16384 时:标准 FFN 参数量 134M,SwiGLU 原始版本 201M,2/3 调整后 134M。
Q5: 为什么 Transformer 不用 Sigmoid 或 Tanh?
梯度消失问题。在 x=10 时,Sigmoid 梯度 ≈ 0.00005,ReLU 梯度 = 1.0。在 24 层 Transformer 中,Sigmoid 梯度累乘后 ≈ 0(完全消失),ReLU 梯度保持 1.0(完美传递)。
总结:激活函数的演进路径
历史演进
2010-2015: ReLU 时代
- 突破点:解决梯度消失
- 局限:死亡 ReLU、硬切换
2016-2019: GELU 时代
- 突破点:平滑激活、概率性质
- 局限:计算略慢
2020-2023: SiLU 时代
- 突破点:自门控、与 GELU 等效但更简单
- 局限:仍是单路径设计
2023-至今: SwiGLU 时代
- 突破点:双路径门控、选择性激活
- 权衡:参数量增加(但可通过 2/3 规则平衡)
核心设计原则的演变
| 时代 | 核心思想 | 代表函数 |
|---|---|---|
| 第一代 | 简单有效 | ReLU |
| 第二代 | 平滑性 | GELU |
| 第三代 | 自门控 | SiLU |
| 第四代 | 选择性激活 | SwiGLU |
未来展望
三大方向:
- 自适应激活:让激活函数的形状可学习
- 稀疏激活:只激活部分神经元以提升效率
- 架构融合:激活函数与网络结构深度结合(如三层 FFN)
随着模型规模持续增长,激活函数的选择将更加注重:
- 参数效率(同等性能下更少参数)
- 计算效率(推理速度和吞吐量)
- 可解释性(理解激活模式的含义)
激活函数看似是神经网络中的"小"组件,但它承载着引入非线性、控制信息流的核心功能。从 ReLU 到 SwiGLU 的演进,正是深度学习领域不断追求"更强表达能力"和"更高效计算"的缩影。
参考资料:
- FFN Activation Functions: ReLU, GELU, and SiLU for Transformer Models
- SwiGLU: The FFN Upgrade I Use to Get Free Performance
- GLU Variants Improve Transformer (2020)
- Activation function and GLU variants for Transformer models
- One Wide Feedforward is All You Need (Apple, 2025)
- Spark Transformer: Reactivating Sparsity in Transformer FFN (2025)