数学原理:SwiGLU的数学公式拆解

好,咱们直接进入正题。SwiGLU 这个名字,说白了就是 Swish 和 GLU 的合体。你可能会问:为什么要把两个东西拼在一起?嗯,我在调模型的时候也想过这个问题。后来发现,这其实是一次很聪明的「功能互补」。

咱们先拆开看,再合起来理解。

Swish 函数:不是简单的 ReLU 替代品

Swish 的公式长这样:

Swish(x) = x · σ(βx)

其中 σ 是 sigmoid 函数,β 是个可学习的参数(或者固定为 1)。

你可能会觉得:这不就是 x 乘上一个 sigmoid 吗?没错,但效果差很多。我刚开始用的时候也觉得这玩意儿多余,直到有一次在深层网络里,ReLU 把一堆负值直接砍成 0,梯度死活传不下去。换成 Swish 之后,负半轴保留了微小的负梯度,模型居然活过来了。

Swish 有几个关键特性:

  • 非单调性:在 x 为负时先降后升,这能引入一些非线性表达能力
  • 平滑性:处处可导,不像 ReLU 在 0 点有个尖角
  • 自门控:说白了就是 x 自己决定自己的「开关」程度

我个人习惯:在 Transformer 的 FFN 层里,Swish 比 GELU 收敛快 5%-10%。当然,这跟具体任务有关,但至少值得一试。

GLU 门控机制:信息流的阀门

GLU(Gated Linear Unit)的原始形式是:

GLU(x) = A ⊙ σ(B)

这里 A 和 B 是输入 x 经过两个不同线性变换得到的结果。⊙ 是逐元素乘法,σ 是 sigmoid。

说白了,B 经过 sigmoid 后变成一个 0 到 1 之间的「阀门」,控制着 A 的信息能通过多少。这个机制在语言模型里特别有用——它能让模型学会「哪些信息该放行,哪些该拦住」。

我记得有一次做序列标注任务,用普通 FFN 怎么调都过拟合。换成 GLU 之后,门控机制自动学会了过滤噪声,验证集 F1 直接涨了 2 个点。

SwiGLU:合体之后发生了什么?

SwiGLU 的公式是:

SwiGLU(x) = (xW₁) ⊙ Swish(xW₂)

对比一下原始 GLU:

组件 GLU SwiGLU
门控函数 σ (sigmoid) Swish
值路径 线性变换 A 线性变换 xW₁
门控路径 线性变换 B → sigmoid 线性变换 xW₂ → Swish

你发现没有?SwiGLU 其实就是把 GLU 里的 sigmoid 换成了 Swish。这个替换带来了两个好处:

  1. 门控更灵活:Swish 不是饱和在 0-1 之间,而是可以输出负值。这意味着门控不仅能「关小」,还能「反向」
  2. 梯度更健康:sigmoid 在两端梯度几乎为 0,容易造成门控路径梯度消失。Swish 的梯度在负半轴仍然存在

避坑指南:我曾经在训练一个 12 层 Transformer 时,直接用 SwiGLU 替换了 ReLU FFN。结果发现训练不稳定,loss 乱跳。后来排查发现是权重初始化没调——SwiGLU 的输出方差比 ReLU 大,需要把初始化 scale 调小一点。具体来说,W₁ 和 W₂ 的初始化标准差建议设为 sqrt(2 / d_model) 而不是默认的 sqrt(1 / d_model)。

核心逻辑:一张图看懂

下面这张 SVG 图展示了 SwiGLU 的数据流:

输入 x 线性变换 W₁ 线性变换 W₂ Swish 激活 输出 y 值路径 门控路径 逐元素相乘

你看,输入 x 兵分两路。一路直接做线性变换得到「值」,另一路先做线性变换再经过 Swish 得到「门控信号」。最后两者逐元素相乘,就是 SwiGLU 的输出。

这个结构的好处是:门控路径不是简单的 0/1 开关,而是通过 Swish 产生一个连续且可微的「软门控」。模型可以精细地控制每个维度上的信息流量。

注意:SwiGLU 的参数量比普通 FFN 多 50%。因为原来只需要一个权重矩阵 W,现在需要 W₁ 和 W₂ 两个。在资源受限的场景下,这个开销要考虑进去。我一般会在 1B 参数以上的模型里才用 SwiGLU,小模型用 GELU 就够了。

好了,数学原理就拆到这里。说白了,SwiGLU 就是用 Swish 替换了 GLU 里的 sigmoid,让门控更灵活、梯度更健康。下一节咱们聊聊它在 Transformer 里的具体位置和实现细节。


专注资料整理