Transformer 里的 FFN 有什么用?为什么现代大模型用 SwiGLU 激活?
简化版
Transformer 每个块里,注意力负责「让 token 之间交换信息」,而 FFN(前馈网络) 负责「对每个 token 单独做非线性变换、加工特征」,是模型存放知识、增强表达力的主要部分。标准 FFN 是「升维 → 激活 → 降维」两层结构,中间维度约为 4 倍隐藏维。激活函数从早期 ReLU 演进到 GELU(GPT/BERT),再到 SwiGLU(Llama、PaLM)——它是一种门控线性单元(GLU),用一路 Swish 激活去「门控」另一路线性输出,表达力更强、效果更好,代价是多一个权重矩阵(通常把中间维缩到约 8/3 倍以保持参数量不变)。
详细版
FFN 在 Transformer 里的角色
一个 Transformer 块 = 注意力子层 + FFN 子层。分工明确:
- 注意力:跨 token 混合信息(谁该关注谁)。
- FFN:逐位置(position-wise)对每个 token 独立做非线性映射,不跨 token。
标准 FFN:
FFN(x) = W₂ · act( W₁·x + b₁ ) + b₂
W₁把维度从 d 升到约 4d(升维,扩大表达空间);- 激活函数引入非线性;
W₂再降回 d。- FFN 通常占 Transformer 参数量的大头(约 2/3)。
激活函数的演进
| 激活 | 特点 | 代表 |
|---|---|---|
| ReLU | 简单,max(0,x),负半轴硬截断 | 原始 Transformer |
| GELU | 平滑、按概率门控,负值不硬截断 | BERT、GPT-2/3 |
| SwiGLU | 门控线性单元 + Swish,表达力最强 | Llama、PaLM、Qwen |
SwiGLU 长什么样
SwiGLU-FFN(x) = W₂ · ( Swish(W₁·x) ⊙ (W₃·x) )
Swish(x) = x · sigmoid(βx)
- 有三个权重矩阵 W₁、W₂、W₃(比普通 FFN 多一个 W₃)。
- 一路
Swish(W₁x)当「门」,逐元素乘另一路W₃x,实现自适应门控。 - 为保持总参数量不变,中间维度从 4d 缩到约 8/3·d ≈ 2.67d。
完整版教学
记忆钩子:FFN 负责逐 token 非线性变换;SwiGLU 用“内容分支 × 门控分支”提升表达,等参数时中间维度不能照搬 4d。
一、为什么光有注意力还不够,必须有 FFN
只堆注意力会怎样?注意力本质是对 V 的加权平均(线性组合),即便多层堆叠,跨 token 的混合仍偏线性,缺乏对单个 token 特征的深度非线性加工。语言模型要存储和运用大量「知识」(词的含义、事实、模式),需要强非线性变换能力——这正是 FFN 提供的。
分工可以这样理解:
- 注意力是”通信层”:决定信息怎么在 token 之间流动。
- FFN 是”计算/记忆层”:对汇集来的信息做非线性加工,很多研究认为事实性知识主要存在 FFN 的权重里(FFN 像一个巨大的键值记忆库)。
两者交替堆叠,才让 Transformer 既能建模长程依赖,又有强表达和记忆力。
二、为什么 FFN 要先升维再降维
标准 FFN 中间维取 ~4d,是「先扩张后压缩」的瓶颈结构:
- 升维(d→4d):把特征投影到更高维空间,给非线性激活更大的施展空间,能表达更复杂的函数(类似 SVM 升维后更易分)。
- 激活:在高维空间施加非线性。
- 降维(4d→d):压回原维度,方便和残差相加、进入下一层。
4 倍是经验上的质量/成本平衡点。中间维越大,模型容量越大、知识越多,但参数和算力也越贵。
三、激活函数为什么从 ReLU 走到 GELU
ReLU max(0,x):简单高效,但负半轴直接归零(硬截断),会「杀死」部分神经元,且在 0 点不可导,信息利用不够平滑。
GELU(Gaussian Error Linear Unit):GELU(x) = x·Φ(x),Φ 是标准正态的累积分布。直觉是「按输入的大小、以概率方式决定保留多少」——大正值几乎全保留,大负值几乎全抑制,但过渡是平滑的,负值也保留一点点信息。这种平滑门控在实践中比 ReLU 更利于优化,BERT、GPT 系列都用它。
四、SwiGLU:把”门控”引入 FFN
SwiGLU 属于门控线性单元(GLU)家族。GLU 的核心思想是:不要用一个固定的激活直接作用于输出,而是用一路信号去”门控”(逐元素相乘)另一路信号,让网络自适应地决定「每个维度放行多少」。
SwiGLU 用 Swish 作为门:
SwiGLU-FFN(x) = W₂ · ( Swish(W₁·x) ⊙ (W₃·x) )
W₃·x是「内容」路(线性)。Swish(W₁·x)是「门」路,逐元素乘上去,动态调节内容路每个维度的强度。- 相比「单路激活」,门控让 FFN 的输入-输出关系更灵活、表达力更强。
Noam Shazeer 的实验(“GLU Variants Improve Transformer”)显示 SwiGLU/GeGLU 在同等条件下稳定优于 ReLU/GELU,于是被 PaLM、Llama 等采纳。
五、多一个矩阵,参数量怎么办
普通 FFN 有 2 个矩阵(W₁: d→4d,W₂: 4d→d);SwiGLU 有 3 个(W₁、W₃: d→h,W₂: h→d)。若中间维 h 仍取 4d,参数量会多 50%。为保持参数量和算力大致不变,SwiGLU 把中间维缩小到约 8/3·d ≈ 2.67d:
普通 FFN 参数 ≈ 2 × d × 4d = 8d²
SwiGLU 参数 ≈ 3 × d × (8/3·d) = 8d² # 对齐
也就是「用一个额外的门控矩阵,换掉一部分中间宽度」,在同等预算下拿到更好的效果。这是工程上很典型的「结构换性能」的等参数比较。
六、算清 SwiGLU 为什么常用较小中间维度
普通两层 FFN 的主矩阵参数量约为 2 × d_model × d_ff;SwiGLU 有 gate、value、output 三个投影,约为 3 × d_model × d_ff。若普通 FFN 取 d_ff=4d,为了保持相近参数预算,SwiGLU 可取 d_ff≈8d/3,因为 3×d×(8d/3)=8d²,恰好接近普通 FFN 的 2×d×4d=8d²。
以 d_model=4096 为例,普通 4 倍 FFN 的中间维度是 16384;等参数的 SwiGLU 理论值约为 10923,工程上会向硬件友好的倍数取整。门控提升表达力并非免费:它增加一个输入投影,实际速度还取决于融合 kernel、张量并行切分和对齐后的维度。
普通 FFN: 2 * 4096 * 16384 ≈ 134.2M 参数
SwiGLU: 3 * 4096 * 11008 ≈ 135.3M 参数
| 结构 | 输入投影 | 中间非线性 | 等预算时的中间维度 |
|---|---|---|---|
| GELU FFN | 1 个 | GELU(xW1) | 约 4d |
| SwiGLU | 2 个 | SiLU(xWg) ⊙ (xWv) | 约 8d/3 |
七、常见误区与追问
- 误区:注意力已经做了非线性变换,所以 FFN 可有可无。 注意力主要混合 token 间信息,FFN 在每个位置上提供大容量非线性特征变换,两者职责不同。
- 追问:SwiGLU 为什么有三个权重矩阵? 两个输入投影分别产生门值与内容并逐元素相乘,第三个投影把中间表示映回隐藏维。
- 误区:SwiGLU 仍应机械使用 4 倍中间维度。 三矩阵结构会显著增加参数,等预算比较时通常把中间维度降到约
8d/3并做硬件对齐。 - 追问:门控比 GELU 好在哪里? 内容分支可被输入相关的平滑门值选择性放大或抑制,表达更灵活;收益仍需在同预算实验中验证。
- 追问:参数量相近为何速度仍可能不同? 投影次数、融合 kernel、维度对齐、张量并行通信和中间激活读写都会影响实际吞吐。
八、加强记忆
FFN 记「注意力管通信、FFN 管计算与记忆」:它逐 token 做「升维→激活→降维」的非线性加工,占了 Transformer 大半参数,被认为是知识的主要存放处。激活演进记一条线:ReLU(硬截断)→ GELU(平滑门控,BERT/GPT)→ SwiGLU(门控线性单元+Swish,Llama/PaLM)。SwiGLU 的精髓是「一路 Swish 当门、逐元素乘另一路线性内容」,表达力更强;因为多了一个矩阵,就把中间维从 4d 缩到 8/3 d 来对齐参数量。简要说抓本质:用自适应门控替代固定激活,等参数下换来更好效果。