1. SwiGLU激活函数原理:从GLU到SwiGLU的演进

说起SwiGLU,我得先坦白一件事。几年前我第一次在论文里看到它时,心里想的是:「又来个新激活函数?ReLU不够用吗?」结果后来在部署大模型时,发现几乎所有主流模型都在用SwiGLU。嗯,真香。

这一节,咱们就把它彻底搞明白。从GLU开始,一步步推到SwiGLU,再跟ReLU、GELU做个对比。你想想看,搞懂这些,后面做算子融合心里才有底。

1.1 从GLU说起:门控机制的直觉

GLU的全称是Gated Linear Unit,门控线性单元。它最早在NLP领域被提出,核心思想很简单:让网络自己决定「哪些信息该通过,哪些该过滤掉」

数学上,GLU的定义是这样的:

GLU(x) = (x * W1 + b1) ⊗ σ(x * W2 + b2)

其中⊗是逐元素乘法,σ是sigmoid函数。你看,它把输入分成两路:一路做线性变换,另一路经过sigmoid变成0到1之间的门控信号。两路相乘,门控信号决定了信息保留多少。

核心直觉:GLU相当于给神经网络装了个「智能阀门」。sigmoid输出的值接近1时,信息几乎无损通过;接近0时,信息被阻断。这种动态调节能力,比固定激活函数灵活得多。

我在项目中遇到过一个问题:用GLU做语言模型时,训练收敛确实快,但推理时sigmoid的计算开销不小。尤其端侧芯片上,sigmoid的指数运算是个瓶颈。这就引出了后面的改进。

1.2 SwiGLU的诞生:用Swish替换Sigmoid

2020年,Google在PaLM论文里提出了SwiGLU。说白了,就是把GLU里的sigmoid换成了Swish激活函数。

Swish长这样:

Swish(x) = x * σ(βx)

其中β是可学习的参数,通常设为1。当β=1时,Swish(x) = x * sigmoid(x)。

那么SwiGLU的公式就是:

SwiGLU(x) = (x * W1 + b1) ⊗ Swish(x * W2 + b2)

为什么这么改?我个人习惯从两个角度理解:

  • 梯度特性更好:Swish在负半轴不是完全饱和的,梯度不会像sigmoid那样趋近于0。这意味着深层网络的梯度消失问题得到缓解。
  • 表达能力更强:Swish的非线性比sigmoid更丰富。它保留了sigmoid的「软门控」特性,同时增加了负值区域的微小响应——这有点像给阀门加了「微调旋钮」。

我的经验:在实际部署中,SwiGLU相比GLU通常能提升0.5-1个百分点的准确率。代价是计算量略有增加,但端侧推理引擎可以通过算子融合来弥补。

1.3 数学公式的直观推导

咱们把SwiGLU拆开来看。假设输入是x,经过两个线性层得到a和b:

a = x * W1 + b1
b = x * W2 + b2

然后:

output = a ⊗ Swish(b) = a ⊗ (b * sigmoid(b))

写成完整形式:

SwiGLU(x) = (xW1 + b1) ⊗ [(xW2 + b2) * σ(xW2 + b2)]

你发现没有?这里其实隐含了一个「门控+非线性」的组合。a是线性变换后的主信号,b经过Swish后变成门控信号。两者相乘,既保留了GLU的门控机制,又引入了Swish的平滑非线性。

关键点:SwiGLU的参数量是普通激活函数的两倍(因为需要两个线性层),但换来的是更强的表达能力。在端侧部署时,这个「参数量翻倍」的问题需要通过算子融合来缓解。

1.4 与ReLU的对比:非线性与门控

ReLU太经典了,但它的局限性也很明显:

特性 ReLU SwiGLU
非线性形式 分段线性 门控+平滑非线性
负半轴响应 完全抑制(0) 微小负响应(通过Swish)
参数量 无额外参数 2个线性层参数
梯度特性 负半轴梯度为0 负半轴有非零梯度
端侧部署 极简单,零开销 需算子融合优化

我曾经在部署一个语音识别模型时,把SwiGLU换成ReLU,结果WER(词错误率)直接涨了3%。这说明在某些任务上,SwiGLU的门控机制确实不可或缺。

1.5 与GELU的对比:相似但不同

GELU(Gaussian Error Linear Unit)是另一种流行的激活函数,公式是:

GELU(x) = x * Φ(x)

其中Φ(x)是标准正态分布的累积分布函数。近似计算时常用:

GELU(x) ≈ 0.5x * (1 + tanh(√(2/π) * (x + 0.044715x³)))

GELU和SwiGLU看起来有点像——都是「输入乘以一个门控值」。但区别在于:

  • GELU的门控是输入本身的函数:Φ(x)只依赖于x本身。
  • SwiGLU的门控来自另一个线性变换:Swish(b)中的b是x经过独立线性层得到的。

说白了,SwiGLU多了一个「可学习的门控分支」,而GELU的门控是固定的(只依赖输入值)。这意味着SwiGLU能学到更复杂的门控策略。

避坑指南:我曾经在端侧芯片上直接使用GELU的精确公式,结果发现tanh和幂运算在定点推理时精度损失严重。后来改用近似公式,精度损失控制在0.1%以内。SwiGLU也有类似问题——Swish中的sigmoid在低比特量化时容易出问题,需要做校准。

1.6 知识体系结构图

下面这张图帮你理清SwiGLU在整个激活函数家族中的位置:

激活函数演进与SwiGLU定位 ReLU (2010) Sigmoid / Tanh Leaky ReLU (2013) ELU (2015) GELU (2016) Swish (2017) GLU (2017) SwiGLU (2020) GeGLU (2020) 端侧推理引擎:算子融合优化 门控机制 门控+高斯 替换sigmoid

从图中你能看到,SwiGLU站在两个「巨人」的肩膀上:GLU提供了门控框架,Swish提供了更好的非线性。最终在端侧部署时,我们需要通过算子融合来弥补它参数量翻倍带来的开销。

1.7 小结:为什么端侧需要关注SwiGLU

总结一下这节的核心:

  • SwiGLU = GLU + Swish,用Swish替换sigmoid,梯度更好、表达更强
  • 相比ReLU:SwiGLU有门控机制,负半轴有响应,但参数量翻倍
  • 相比GELU:SwiGLU的门控来自独立分支,更灵活,但计算更重
  • 端侧挑战:两个线性层 + sigmoid/Swish,计算量和内存访问都是瓶颈

我个人觉得,SwiGLU是「用计算换精度」的典型代表。在服务器端这不是问题,但在端侧,我们必须想办法把多出来的计算「藏」起来。下一节我会详细讲怎么通过算子融合做到这一点。

一句话记住:SwiGLU就是给GLU换了个更聪明的门控函数,让模型学得更好,但让端侧工程师更忙了。

专注资料整理