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
只堆注意力会怎样?注意力本质是对 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² # 对齐
也就是「用一个额外的门控矩阵,换掉一部分中间宽度」,在同等预算下拿到更好的效果。这是工程上很典型的「结构换性能」的等参数比较。
六、面试拆解算例
这类题最怕只讲术语,最好把它落成一次资源账。假设模型有 32 层、hidden size 为 4096、序列长度从 2K 增到 16K,标准注意力的相关度矩阵规模会从 2K × 2K 变成 16K × 16K,理论元素数量放大 64 倍。即使具体算子不会真的把所有中间矩阵都落到 HBM,复杂度曲线仍然决定了 prefill 延迟和显存压力会快速上升。
attention_scores_per_head = seq_len * seq_len
2K -> 2,048 * 2,048 ≈ 4.19M
16K -> 16,384 * 16,384 ≈ 268.44M
放大倍数 ≈ 64
| 观察维度 | 面试要说清的问题 | 工程判断 |
|---|---|---|
| 张量形状 | Q/K/V、hidden state 或路由权重怎样变化 | 能否解释实现差异 |
| 复杂度 | 随层数、序列长度、head 数怎样增长 | 谁先成为瓶颈 |
| 质量风险 | 是否改变训练分布或表达能力 | 会不会掉点 |
| 部署代价 | 算子、框架、缓存是否支持 | 能不能稳定上线 |
输入 token -> embedding -> 注意力/FFN/归一化模块 -> hidden state -> logits
| | |
位置/掩码 显存与吞吐 质量与稳定性
所以回答「Transformer 里的 FFN 有什么用?为什么现代大模型用 SwiGLU 激活?」时,推荐先讲结构变化,再讲这条变化怎样影响资源曲线,最后补一句质量和部署的边界。这样比单纯背「某某结构更快、更省」更像工程答案。
七、常见误区与追问
- 误区:FFN 会跨 token 混合信息。 不会,FFN 是逐位置独立作用于每个 token;跨 token 交互全靠注意力。
- 误区:SwiGLU 就是换了个激活函数。 它是门控结构(GLU)+ Swish,多了一个权重矩阵,不只是替换激活。
- 追问:FFN 中间维为什么是 4d? 经验上的容量/成本平衡;越大越强越贵。
- 追问:为什么说知识主要存在 FFN? 多项可解释性研究把 FFN 视为键值记忆,事实性知识、模式多编码在其权重中;编辑知识(如 ROME)也常作用于 FFN。
- 追问:SwiGLU 为什么把中间维改成 8/3 d? 为在增加一个矩阵后保持总参数量不变,做等参数对比才公平。
- 追问:GELU 和 Swish 什么关系? 都是平滑的、带门控直觉的激活;Swish=
x·sigmoid(βx),GELU≈x·Φ(x),形状相近,SwiGLU 用 Swish 是经验选择。
八、加强记忆
FFN 记「注意力管通信、FFN 管计算与记忆」:它逐 token 做「升维→激活→降维」的非线性加工,占了 Transformer 大半参数,被认为是知识的主要存放处。激活演进记一条线:ReLU(硬截断)→ GELU(平滑门控,BERT/GPT)→ SwiGLU(门控线性单元+Swish,Llama/PaLM)。SwiGLU 的精髓是「一路 Swish 当门、逐元素乘另一路线性内容」,表达力更强;因为多了一个矩阵,就把中间维从 4d 缩到 8/3 d 来对齐参数量。简要说抓本质:用自适应门控替代固定激活,等参数下换来更好效果。