SwiGLU:LLaMA 选择的激活函数,为什么比 GELU 效果好?门控机制的直觉理解

我最早以为,激活函数这种“小部件”,选个 ReLU 就完事了。直到读 LLaMA 技术报告,发现他们专门强调 FFN 里用的是 SwiGLU,而不是我当时以为的 GELU。更让我在意的是报告里那句 use the SwiGLU activation function。为什么一个激活函数也值得被写进论文?这背后到底是什么在起作用?

AI technology illustration

先把 FFN 拆开:它其实是在“展开再折叠”

Transformer 的每个 block 里,自注意力后面都跟着一个前馈网络 FFN。它做的事可以粗暴理解成:先把表示“展开”到更高维,再“折叠”回去。展开得越大,模型能表达的函数越复杂;而展开和折叠之间,需要激活函数来提供非线性。

最朴素的版本是 ReLU 的 FFN:FFN(x) = ReLU(xW1) W2。后来大家发现 GELU 更好,比如 GPT-2、BERT 都用的 GELU。

GELU 赢过 ReLU,靠的是两个细节

GELU 的公式是 GELU(x) = x * Φ(x),其中 Φ 是标准正态分布的累积分布函数。这个激活函数来自 2016 年的 GELU 论文。直观上,它是在拿“x 是正数的概率”给 x 本身做缩放:输入越大,放行越多;输入为负时,不是直接砍掉,而是留下一点软信号。

这个设计比 ReLU 平滑,梯度在零附近不会突变。另一个好处是,负值区域仍然有小梯度,训练时不容易死神经元。

Swish:激活函数里的“自门控”

2017 年,Google Brain 用自动搜索找激活函数,找到了 SwishSwish(x) = x * σ(x)。这里没有额外参数,单纯是 x 乘以它自己的 sigmoid。看上去和 GELU 有点像,但它的形状有自己的特点:有下界,无上界,像一条平滑的 ReLU。

如果只是把 GELU 换成 Swish,还不足以让模型大幅提升。真正的关键在于“门控”两个字。

门控线性单元:给信息装一个独立的水龙头

GLU(Gated Linear Unit)最早是语言建模中的门控机制。它有两个线性变换结果,其中一个用 sigmoid 当门,另一个当内容,然后逐元素相乘:GLU(x) = σ(xW1 + b) ⊗ (xW2 + c)

你可以把门想象成水龙头。左边是内容管道,右边是独立水管控制阀门开合。门不是由激活函数自带的,而是模型在训练中专门学出来的一整套“如何放行”的参数。这让信息流变得有选择。

Shazeer 在 GLU Variants Improve Transformer 里把 GLU 的门函数从 sigmoid 换成了 Swish,得到了 SwiGLU:SwiGLU(x) = Swish(xW1) ⊗ xW2。他对比了一堆 GLU 变体,结论很一致:带门控的变体都比不带门控的 ReLU/GELU 在翻译任务上强。

门控为什么有效?因为乘法比加法更容易表达“交互”

普通激活函数是逐元素的:每个神经元自己对输入做非线性变换,神经元之间互不相干。门控引入了“特征 × 特征”的交互。比如一个通道的内容是“苹果颜色”,另一个通道的门是“是否水果”,两者相乘之后,模型才真正获得“水果苹果”的信息。加法做不到这一点。

还有一个容易被忽略的梯度理由:GLU 的梯度里有一项正比于门的值 σ(x),这让模型可以在训练中动态调节某个特征的梯度大小。需要保留的特征梯度大,不需要的梯度趋近于零,这比固定激活函数灵活得多。

LLaMA 的真正操作:用参数量换表达力

SwiGLU 多了一个投影矩阵,所以 FFN 的参数量会膨胀。为了维持总参数预算,LLaMA 把 FFN 的中间维度从常见的 4 倍 d_model 缩减到约 2.67 倍。在 PyTorch 里,实现非常直白:

def swiglu_ffn(x, w_gate, w_up, w_down):
    gate = F.silu(F.linear(x, w_gate))
    up = F.linear(x, w_up)
    return F.linear(gate * up, w_down)

也就是说,SwiGLU 并不是“换了一个函数”,而是把 FFN 的结构本身改成了双分支门控。这也是为什么它能进入 LLaMA 及其后继者等一系列新一代大模型。

结构 公式 门控 中间维
ReLU FFN ReLU(xW1)W2 4d
GELU FFN GELU(xW1)W2 4d
SwiGLU FFN Swish(xW1) ⊗ xW3 · W2 ~2.67d

关于 SwiGLU,三个最常见的误解

误解一:Swish 和 SiLU 不是同一个东西?

它们是同一种函数。PyTorch 的 F.silu 就是 Swish。所以你在 LLaMA 代码里看到 F.silu(gate) * up,就是 SwiGLU。

误解二:SwiGLU 好是因为 Swish 代替了 GELU?

只换激活函数的提升非常有限。SwiGLU 的本质提升来自那个独立的门控投影,它多学了一组参数,给模型增加了一条“决策通道”。

误解三:门控就是 LSTM 那种随时间变化的记忆门?

完全不是。SwiGLU 的门是逐位置的,对同一个 token 的所有特征统一计算,不跨时间步,也没有记忆。它是特征选择器,不是序列状态管理器。

说实话,我最早也被“门控”这个词带着走,以为它像 LSTM 一样在控制“记忆”。后来自己动手写了一遍才发现,它其实只是两个线性变换的逐元素乘法。可是当我真的去训练一个小模型对比 GELU(xW)WSilu(xW1) 相乘时,后者的训练 loss 下降得更快。这个结果让我意识到,深度学习里很多巧妙的改进,本质上都是给信息流加了“可学习的路由”。

SwiGLU 的边界:它并不是免费的午餐

SwiGLU 的参数量和计算量都比单分支的 FFN 高。在推理时需要多次矩阵乘法,对显存和带宽要求更大。小模型上,它可能因为参数更多而需要更多的数据去拟合;而如果总参数预算有限,你必须像 LLaMA 那样压缩中间维度,这又会限制单分支的“宽度”。

我的判断是:SwiGLU 在当前大模型范式下是一个“便宜”的 win,因为它带来的表达力收益大于参数开销。但它不是不可替代的。已经有研究在探索更高效的门控形式,也有模型选择保留 GELU 但把 FFN 改成 MoE 结构。门控机制不会消失,但 SwiGLU 这个具体形态会不会被挤出舞台,还真不好说。

原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/423.html

(0)
上一篇 4天前
下一篇 4天前

相关推荐