什么是 FFN(SwiGLU)?
如果说 Attention 负责“信息交换”,那么 FFN(Feed Forward Network,前馈网络)负责“信息加工”。
在现代大模型(LLaMA、Qwen、Gemma、Mistral、DeepSeek 等)里,Transformer Block 基本都是:
输入 │ ▼ Attention │ ▼ FFN(SwiGLU) │ ▼ 输出很多人会把 Attention 当成 Transformer 的核心,但实际上:
模型参数的大头往往在 FFN 里,而不是 Attention。
在 LLaMA 系列中,大约 60%~70% 的参数都在 FFN 中。
1. 先看原始 Transformer 的 FFN
2017 年《Attention Is All You Need》中的 FFN 非常简单:
FFN(x)=W2(ReLU(W1x)) FFN(x)=W_2(ReLU(W_1x))FFN(x)=W2(ReLU(W1x))
流程:
x │ ▼ Linear(W1) │ ▼ ReLU │ ▼ Linear(W2) │ ▼ 输出如果模型维度:
d_model = 4096则:
4096 ↓ 16384 (扩张4倍) ↓ 4096因此 FFN 又叫:
Expansion → Activation → Compression
即:
扩张 ↓ 非线性变换 ↓ 压缩2. 为什么要改进 FFN?
研究人员发现:
ReLU虽然简单,
但:
- 信息利用率不高
- 梯度不够平滑
- 表达能力有限
后来出现:
ReLU ↓ GELU ↓ GLU ↓ GEGLU ↓ SwiGLU2020 年 Noam Shazeer(Transformer 原作者之一)发表论文:
GLU Variants Improve Transformer
专门研究:
FFN 中的激活函数能不能换掉?
结果发现:
GEGLU SwiGLU效果明显优于:
ReLU GELU3. 什么是 GLU?
理解 SwiGLU 前必须先理解 GLU。
普通 FFN
普通 FFN:
h=ReLU(xW1) h = ReLU(xW_1)h=ReLU(xW1)
本质上:
输入 ↓ 激活 ↓ 输出只有一条路。
GLU
GLU(Gated Linear Unit)增加了一条门控路径:
GLU(x)=(xW)⊗σ(xV) GLU(x)= (xW)\otimes \sigma(xV)GLU(x)=(xW)⊗σ(xV)
其中:
⊗ \otimes⊗
表示逐元素相乘。
流程:
┌────► Linear(V) │ x ────────┤ │ └────► Linear(W) │ ▼ Sigmoid │ ▼ Element-wise *可以理解成:
Value × Gate即:
真正的信息 × 通过比例类似:
水流 × 阀门开度4. SwiGLU 做了什么?
SwiGLU 把 GLU 中的 Sigmoid 换成了 Swish(SiLU)。
原始 GLU:
GLU(x)=(xW)⊗σ(xV) GLU(x)= (xW) \otimes \sigma(xV)GLU(x)=(xW)⊗σ(xV)
SwiGLU:
SwiGLU(x)=(xV)⊗SiLU(xW) SwiGLU(x)= (xV) \otimes SiLU(xW)SwiGLU(x)=(xV)⊗SiLU(xW)
其中:
SiLU(z)=zσ(z) SiLU(z)=z\sigma(z)SiLU(z)=zσ(z)
5. 为什么叫 SwiGLU?
因为:
Swish + GLU合起来:
SwiGLU而:
Swish ≈ SiLU所以代码里经常看到:
F.silu(...)实际上就是 SwiGLU 的一部分。
6. 现代大模型里的 SwiGLU
LLaMA 的 FFN:
不是
y=down_proj(silu(up_proj(x)))而是:
y=down_proj(silu(gate_proj(x))*up_proj(x))对应:
gate_proj │ ▼ x ─────────────────► SiLU │ ▼ Gate x ──► up_proj ─────► Value Gate * Value │ ▼ down_proj │ ▼ 输出因此你会看到:
gate_proj up_proj down_proj三个矩阵。
而传统 FFN 只有:
up_proj down_proj两个矩阵。
7. 为什么 SwiGLU 更强?
这是很多人最关心的问题。
实际上论文作者自己都承认:
他们也没有严格理论解释,只知道实验效果更好。
但从直觉上理解:
普通 FFN
y = GELU(Wx)对于所有特征:
统一处理SwiGLU
y = Value × GateGate 可以动态决定:
哪些维度保留 哪些维度抑制 哪些维度放大类似:
注意力里的权重但是发生在 FFN 内部。
因此表达能力更强。
8. 参数为什么变成 8/3 倍?
原始 FFN:
4096 ↓ 16384 ↓ 4096中间层:
4d 4d4d
SwiGLU 有三组矩阵:
gate_proj up_proj down_proj如果仍然用:
4d 4d4d
参数会暴涨。
于是论文采用:
83d \frac{8}{3}d38d
代替:
4d 4d4d
这样总参数量和原 FFN 基本一致。
9. 为什么 LLaMA 的 hidden_dim 是 11008?
例如:
dim=4096理论上:
83×4096=10922 \frac{8}{3}\times4096= 1092238×4096=10922
再对齐到:
256倍数得到:
11008所以你会看到:
gate_proj:4096→11008up_proj:4096→11008down_proj:11008→4096这正是 LLaMA 的实现。
10. 一句话理解 SwiGLU
如果说:
Attention = 让不同Token交流那么:
FFN = 对每个Token进行加工而:
普通FFN = 加工一次SwiGLU = 先生成一个“阀门(Gate)” 再决定哪些信息该通过即:
输出 = 信息(Value) × 门控(Gate)这相当于给 FFN 增加了一个可学习的信息筛选器,因此在几乎相同参数量下,通常比 ReLU/GELU FFN 具有更好的表达能力和训练效果。
对于学习大模型源码,可以记住一个最核心的公式:
FFNSwiGLU(x)=(SiLU(xWg)⊙(xWu))Wd FFN_{SwiGLU}(x)= \bigl( SiLU(xW_g) \odot (xW_u) \bigr) W_dFFNSwiGLU(x)=(SiLU(xWg)⊙(xWu))Wd
对应代码:
gate=F.silu(gate_proj(x))up=up_proj(x)hidden=gate*up out=down_proj(hidden)这就是今天几乎所有主流 LLM(LLaMA、Qwen、Gemma、Mistral、DeepSeek)的 FFN 核心实现。