本文的目标是解释为什么现代LLM架构在前馈部分使用
SwiGLU
作为激活函数并且已经放弃了
ReLU
。
神经网络本质上是一系列矩阵乘法,如果我们堆叠线性层而不使用任何激活函数:
无论你堆叠多少层,它仍然只是一个线性变换,网络只能学习线性关系。
激活函数引入了非线性,使网络能够逼近复杂的非线性函数,这是深度学习表达能力的基础。
ReLU有什么问题?
ReLU
确实彻底改变了深度学习:
它简单、快速,并且解决了
sigmoid
或
tanh
等函数存在的梯度消失等问题。
虽然人们通常会列出使用
ReLU
时可能遇到的问题,比如神经元死亡等等,但这些问题要么是理论上的,要么在大多数情况下可以通过现代神经网络技术(批量归一化、自适应学习权重等)很好的避免。
不过在进入SwiGLU之前,我们先来看一个激活函数 Swish,它是 SwiGLU 的组成部分。
Swish是一个"自门控"激活函数:输入 (x) 乘以其自身的sigmoid σ(x),它充当一个门,控制有多少输入能够通过。
看看门的行为:
当x非常负时:σ(x) ≈ 0,所以门是关闭的(抑制输出)
当x非常正时:σ(x) ≈ 1,所以门是完全打开的(几乎原样通过输入)
尽管公式稍微复杂一些,
Swish
的行为与
ReLU
非常相似。
Swish比ReLU更好吗?
Swish
被发现比
ReLU
效果更好,但就像深度学习中的许多事情一样我们并不确切知道为什么
Swish
效果更好,不过倒是可以总结出以下的区别:
没有硬梯度截断
看上面的图,主要区别就是它们如何处理负输入:
ReLU:在零处硬截断
当x<0时:输出 = 0 且 梯度 = 0。这就是神经元死亡问题(尽管如前所述,通常可以通过BatchNorm等现代技术来避免)
Swish:平滑、渐进地趋近于零
对于负x:梯度渐近趋近于零,但对于有限值永远不会精确等于零/所以理论上神经元总是可以接收更新(尽管对于非常负的输入,更新可能可以忽略不计)
平滑性
ReLU
在x=0处有不连续性(导数从0跳到1)。
Swish
在任何地方都是无限可微的,这意味着梯度景观是平滑的。这种平滑性是否有助于
Swish
的性能还不是100%清楚但它可能有助于优化
什么是门控线性单元(GLU)?
下面就是
SwiGLU
的另外一个组件。让我们来谈谈 GLU。
其中:
x是输入
W 和 V 是权重矩阵
b和c是偏置向量
⊙ 是逐元素乘法
σ 是sigmoid函数
GLU
使用门控机制在这方面与
Swish
有些相似。而它们区别在于GLU不是对所有特征应用相同的变换(恒等变换)然后用固定函数(sigmoid)进行门控,而是使用两个独立的线性投影:
xW+ b 这只是取输入并对其进行变换。它通常被称为 内容路径
σ(xV + c):这第二部分说明每个特征的内容应该让多少通过,因此它被称为 门路径
所以GLU
实际上可以被认为是
Swish` 的泛化
逐元素乘法 ⊙ 允许门选择内容的哪些元素可以通过。当 σ(xV + c) 接近0时,门可以完全抑制某些特征,而当 σ(xV + c) 接近1时则完全让其他特征通过。
门控的具体示例
假设我们有一个4维向量 x = [1.0, -0.5, 2.0, 0.3]
GLU对同一个输入应用2个变换:
- 通过内容路径对内容进行变换:xW + b。假设它产生 [2.0, -1.5, 3.0, 0.5]1. 第2个变换应该扮演门的角色: σ(xV + c)。假设它产生 [0.9, 0.1, 0.95, 0.05]
GLU输出是它们的逐元素乘积:
GLU output = [2.0 × 0.9, -1.5 × 0.1, 3.0 × 0.95, 0.5 × 0.05] = [1.8, -0.15, 2.85, 0.025]
得到的结果如下:
特征1:内容为正(2.0),门值高(0.9)→ 强烈通过(1.8)
特征2:内容为负(-1.5),门值低(0.1)→ 被阻挡(-0.15)
特征3:内容为正(3.0),门值非常高(0.95)→ 完全通过(2.85)
特征4:内容较小(0.5),门值非常低(0.05)→ 被抑制(0.025)
这样网络学习了复杂的决策规则:"对于像x这样的输入,放大特征1和3,但抑制特征2和4。"
那么SwiGLU是什么?
现在我们有了所有的组成部分,
SwiGLU
(Swish门控线性单元)简单地结合了Swish和GLU:
它不是像GLU那样使用sigmoid作为门,而是使用Swish。这就是为什么它被称为 Swish + GLU。
那么公式的每个部分做什么呢?这与GLU的逻辑完全相同,改变的只是门控函数。
- Swish(xW):门——决定每个特征有多少可以通过
- xV:内容——正在传输的实际信息
- ⊙:逐元素乘法——将门应用于内容
为什么SwiGLU效果这么好?
从经验上看,SwiGLU在LLM中优于其他激活函数(尽管目前还不确定VLM的情况)。但为什么呢?
乘法交互创建特征组合
考虑每种架构计算的内容:
标准FFN(ReLU/GELU):
output = activation(xW₁) @ W₂
每个输出维度是激活特征的加权和,激活是逐元素应用的——特征在激活内部不会相互交互。
SwiGLU FFN:
output = (Swish(xW) ⊙ xV) @ W₂
逐元素乘法 ⊙ 在两条路径之间创建乘积。如果我们用 g = Swish(xW) 和 c = xV 表示,那么在最终投影之前的输出维度 i 是 gᵢ × cᵢ。
这就是为什么这很重要:gᵢ 和 cᵢ 都是输入特征的线性组合(在Swish之前)。它们的乘积包含像 xⱼ × xₖ 这样的交叉项。网络可以学习 W 和 V,使得某些输入特征组合被放大或抑制。
这类似于为什么注意力机制很强大,注意力计算 softmax(QKᵀ)V,其中 QKᵀ 乘积捕获查询和键特征之间的交互。SwiGLU为FFN带来了类似的乘法表达能力。
为什么不在门中使用sigmoid而是使用Swish?
GLU使用sigmoid:σ(xW) ⊙ xV。sigmoid的问题在于它会饱和。对于大的正或负输入,σ(x) ≈ 1 或 σ(x) ≈ 0,且梯度 ∂σ/∂x ≈ 0,门就会被“冻结”了。
Swish对于正输入不会饱和,它近似线性增长(就像
ReLU
)。这意味着:- 梯度通过门路径流动得更好 - 门可以调节而不仅仅是开/关切换
平滑性
另外就是SwiGLU是无限可微的,这种平滑性可能有助于优化稳定性。
总结
SwiGLU的强大来自于其门控机制和乘法交互。通过将输入分成两条路径并将它们相乘,网络可以学习哪些特征组合是重要的——类似于注意力机制如何通过 QKᵀ捕获交互。
结合Swish的非饱和梯度,这使得SwiGLU对于大型模型特别有效。
https://avoid.overfit.cn/post/3fa28c75fb0b4874aa297defa145ec4a
作者:Safouane Chergui