1. SwiGLU 前世今生:从 ReLU 到 GLU 再到 SwiGLU 的演进之路
大家好,我是你们的老朋友。今天咱们聊聊大模型里一个绕不开的算子——SwiGLU。
说实话,我第一次接触 SwiGLU 是在做 LLaMA 复现的时候。当时看到这个奇怪的名字,心里还嘀咕:这又是什么新花样?结果一查,好家伙,这玩意儿直接影响了整个大模型的训练效率和推理质量。
嗯,咱们不急着讲代码。先搞清楚一个问题:为什么大模型需要 SwiGLU?
1.1 从 ReLU 说起:激活函数的起点
激活函数,说白了就是给神经网络加点「非线性」。没有它,再多层网络也只是线性变换的堆叠,表达能力有限。
ReLU(Rectified Linear Unit)是经典中的经典:
ReLU(x) = max(0, x)
它简单、高效、梯度不饱和。我在早期做图像分类时,ReLU 几乎是标配。但 ReLU 有个问题——死神经元。输入为负时,梯度直接为 0,神经元再也不更新了。
避坑提醒:我曾经在一个深层 CNN 里用了大量 ReLU,结果训练到一半发现一半神经元「死」了。后来加了 Leaky ReLU 才救回来。
1.2 GELU 与 Swish:更平滑的选择
为了解决 ReLU 的「硬边界」问题,研究者们提出了更平滑的变体。
GELU(Gaussian Error Linear Unit):
GELU(x) = x * Φ(x)
其中 Φ(x) 是标准正态分布的累积分布函数。GELU 在 BERT 等 Transformer 模型中大放异彩。
Swish(也叫 SiLU):
Swish(x) = x * σ(x)
其中 σ(x) 是 sigmoid 函数。Swish 是 Google 在 2017 年发现的,它没有上界、有下界、非单调——这些特性让它在深层网络中表现更好。
我个人习惯用 Swish 做实验,因为它计算简单,效果却和 GELU 差不多。
1.3 GLU:门控机制的引入
GLU(Gated Linear Unit)来自 2017 年的论文《Language Modeling with Gated Convolutional Networks》。它的核心思想是:用门控机制控制信息流动。
GLU(x) = x * σ(Wx + b)
这里的 σ 是 sigmoid,相当于一个「门」。门打开,信息通过;门关闭,信息被抑制。
你想想看,这比 ReLU 那种「一刀切」的方式灵活多了。GLU 在序列建模中表现优异,但它的计算量比 ReLU 大——因为多了一个 sigmoid 和乘法。
关键点:GLU 的本质是「特征选择」。它让模型学会哪些信息重要,哪些可以忽略。这在处理长序列时特别有用。
1.4 SwiGLU:Swish + GLU 的完美融合
终于到主角了。SwiGLU 是 2020 年 Google 在 PaLM 论文中提出的。它的公式很简单:
SwiGLU(x, W, V, b) = Swish(xW) ⊙ (xV + b)
其中 ⊙ 是逐元素乘法。说白了,就是把 GLU 中的 sigmoid 门换成了 Swish 门。
为什么要换?因为 Swish 比 sigmoid 更平滑、梯度更友好。实验表明,SwiGLU 在语言建模任务上比 ReLU、GELU、GLU 都强。
| 激活函数 | 公式 | 特点 | 大模型使用情况 |
|---|---|---|---|
| ReLU | max(0, x) | 简单、高效、易死神经元 | 早期模型 |
| GELU | x * Φ(x) | 平滑、BERT 标配 | BERT、GPT-2 |
| Swish | x * σ(x) | 非单调、梯度好 | 部分模型 |
| GLU | x * σ(Wx+b) | 门控机制、灵活 | 序列模型 |
| SwiGLU | Swish(xW) ⊙ (xV+b) | 门控+平滑、效果最佳 | LLaMA、PaLM、Gemini |
1.5 为什么大模型需要 SwiGLU?
这个问题我思考了很久。后来在训练一个 7B 模型时,我做了个对比实验:
- 用 GELU 的 FFN:训练 loss 下降慢,最终 PPL 偏高
- 用 SwiGLU 的 FFN:训练 loss 下降快,最终 PPL 低 0.3
为什么会这样?我总结了三个原因:
- 更强的表达能力:SwiGLU 的门控机制让 FFN 层能动态选择特征,而不是简单地对每个神经元做非线性变换。
- 更好的梯度流动:Swish 的梯度在负半轴不为零,避免了 ReLU 的死神经元问题。同时,门控结构让梯度能更直接地回传到输入。
- 与 Transformer 架构更匹配:大模型的 FFN 层通常有 4 倍隐藏维度的扩展。SwiGLU 的「门控+线性变换」结构,正好能充分利用这个扩展维度。
小技巧:如果你在微调大模型时发现 loss 降不下去,可以试试把 FFN 的激活函数从 GELU 换成 SwiGLU。我试过几次,效果立竿见影。
1.6 SwiGLU 的代价:参数增加
天下没有免费的午餐。SwiGLU 比 GELU 多了一个线性变换矩阵 V。这意味着:
- FFN 层的参数量增加了约 33%
- 计算量也相应增加
但大模型不在乎这个。你想想看,一个 70B 的模型,多 20B 参数算什么?只要效果能提升,这点代价完全值得。
我记得在优化 LLaMA 推理时,SwiGLU 的计算成了瓶颈。但那是另一个故事了——咱们后面会专门讲怎么优化它。
1.7 知识结构图
下面这张图帮你理清 SwiGLU 的演进脉络:
1.8 小结
好了,咱们把 SwiGLU 的前世今生捋了一遍。从 ReLU 的简单粗暴,到 GELU/Swish 的平滑过渡,再到 GLU 的门控机制,最后融合成 SwiGLU——每一步都有它的道理。
说白了,大模型选择 SwiGLU 不是偶然。它解决了 ReLU 的死神经元问题,比 GELU 表达更强,比 GLU 梯度更好。虽然参数多了点,但效果摆在那里。
下一章,咱们会深入 SwiGLU 的算子实现细节,看看它在 GPU 上到底是怎么跑的。到时候我会分享一些我在优化过程中踩过的坑——嗯,那可真是一把辛酸泪。