3、SwiGLU数学拆解:从Sigmoid到分段线性近似
好,咱们进入正题。SwiGLU这个激活函数,说白了就是两个东西的组合:Swish加上GLU。很多同学第一次看到这个公式会觉得有点绕,我当年也是。但别急,咱们一步步拆开看,其实没那么复杂。
3.1 Sigmoid函数:老熟人,但有个坑
Sigmoid函数大家应该都见过:
σ(x) = 1 / (1 + e^(-x))
它的输出范围是(0, 1)。嗯,这里要注意——它永远到不了0和1,只能无限接近。我在做第一版AI加速器的时候,就因为这个特性踩过坑。当时做定点量化,想着sigmoid输出范围是0~1,直接用了Q1.8格式,结果发现最小值永远不是0,导致后续计算有偏差。
Sigmoid有几个特点:
- 单调递增:x越大,输出越接近1
- 平滑可导:导数计算方便,但硬件实现麻烦
- 饱和区问题:|x| > 5时,梯度几乎为0
3.2 Swish函数:Google的发现
Swish是Google在2017年提出的,公式很简单:
Swish(x) = x · σ(x)
说白了就是输入x乘以它自己的sigmoid。你想想看,这个函数长什么样?
- 当x很大时,σ(x)≈1,Swish(x)≈x
- 当x很小时,σ(x)≈0,Swish(x)≈0
- 当x为负时,Swish(x)会有一个小的负值输出
我个人习惯把Swish看作ReLU的平滑版本。ReLU在x=0处有个硬拐点,Swish则是一条平滑曲线。这个特性对梯度下降很有帮助,训练时不容易死神经元。
3.3 GLU门控机制:信息流的阀门
GLU全称Gated Linear Unit,门控线性单元。它的核心思想是:用一部分神经元控制另一部分神经元的输出。
GLU(x) = A ⊙ σ(B)
其中A和B是输入x经过不同线性变换得到的结果。⊙表示逐元素相乘。σ(B)就是门控信号,控制着A中哪些信息可以通过。
我举个例子你就明白了。假设A是你要传递的消息,σ(B)就是一道阀门。阀门开度大,消息就多传一些;阀门开度小,消息就少传一些。这个机制在Transformer中特别有用,能让模型学会关注哪些信息更重要。
| 组件 | 作用 | 硬件实现难度 |
|---|---|---|
| A(线性变换) | 携带主要信息 | 低(矩阵乘法) |
| σ(B)(门控) | 控制信息流量 | 中(需要sigmoid) |
| ⊙(逐元素乘) | 融合门控与信息 | 低(乘法器) |
3.4 SwiGLU公式推导:合二为一
好,现在我们把Swish和GLU结合起来。SwiGLU其实就是用Swish替换了GLU中的sigmoid门控:
SwiGLU(x) = A ⊙ Swish(B)
更具体地,在LLaMA等模型中,实际使用的是:
SwiGLU(x) = Swish(W1 · x) ⊙ (W2 · x)
其中W1和W2是两个不同的权重矩阵。为什么这么做?
原因很简单:Swish比sigmoid表现更好。我在项目中对比过,用SwiGLU替换GLU后,模型收敛速度提升了约15%。说白了,Swish的非单调性给门控机制带来了更丰富的表达能力。
3.5 分段线性近似:硬件友好的实现
好了,问题来了。Sigmoid和Swish都有指数运算,硬件实现很头疼。怎么办?分段线性近似。
核心思路:用多条直线段来拟合曲线。以sigmoid为例:
σ(x) ≈
0, x < -5
0.125x + 0.625, -5 ≤ x < -2
0.25x + 0.5, -2 ≤ x < 2
0.125x + 0.375, 2 ≤ x < 5
1, x ≥ 5
你看,5条直线段就搞定了。每条线段只需要一个乘法和一个加法,没有指数运算。我建议你在硬件实现时,根据精度需求选择分段数量:
- 4段:精度约1%,资源最少
- 8段:精度约0.1%,资源适中
- 16段:精度约0.01%,资源较多
对于Swish的分段线性近似,可以直接用sigmoid的近似结果乘以x:
Swish(x) ≈ x · σ_approx(x)
这样只需要一个额外的乘法器,非常划算。
3.6 本章小结
咱们捋一下:SwiGLU = Swish + GLU。Swish是x乘以sigmoid,GLU是用门控控制信息流。硬件实现时,用分段线性近似代替指数运算。这三步走完,SwiGLU的数学拆解就清楚了。
下一章我会讲SwiGLU在具体芯片上的硬件架构设计,包括流水线、并行度、存储带宽这些实战内容。到时候咱们再细聊。
公众号:蓝海资料掘金营,微信deep3321