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
避坑提醒:我曾经在FPGA上直接用查找表实现sigmoid,结果发现精度不够。后来改用分段线性近似,才解决了资源与精度的平衡问题。

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则是一条平滑曲线。这个特性对梯度下降很有帮助,训练时不容易死神经元。

关键点:Swish的非单调性(在x负半轴先降后升)是它比ReLU表现更好的原因之一。我在做BERT模型加速时,把激活函数从ReLU换成Swish,精度提升了约0.3%。

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的非单调性给门控机制带来了更丰富的表达能力。

我的经验:实际部署时,SwiGLU需要三个矩阵乘法(两个用于生成A和B,一个用于后续处理),计算量比ReLU大不少。但精度提升值得这个代价。

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