门控:为什么现代 FFN 有三个矩阵,注意力的 q_proj 还要多输出一倍?
本课一问:门控:为什么现代 FFN 有三个矩阵,注意力的 q_proj 还要多输出一倍?
这一课先不碰:给门控加「软封顶」的 SiTU-GLU 与各家的激活截断(C15)、48 层 Gated DeltaNet 自带的输出门(C11)、这些门一共占多少参数(岔路 B1)。
② 从已有出发
L1 的 FFN 有两个矩阵:W_up 读、W_down 写,中间一个 GELU。C3 的注意力里,q_proj 把 5,120 维投影成 24 个头 × 256 维 = 6,144 维。可 Qwen3.8 的权重里是这样的(safetensors 头里读出的真实形状):
| 张量 | 形状 | 按 L1 / C3 的理解应该是 |
|---|---|---|
mlp.gate_proj | [17,408, 5,120] | (没有这个矩阵) |
mlp.up_proj | [17,408, 5,120] | W_up |
mlp.down_proj | [5,120, 17,408] | W_down |
self_attn.q_proj | [12,288, 5,120] | [6,144, 5,120] |
贯穿例句「小明把苹果给了小王」的 5 个 token,每一层都要各自穿过这三个 FFN 矩阵,每一个全注意力层都要经过这个加宽了的 q_proj(下面张量图里的 T = 5 就是它)。多出来的 gate_proj,和 q_proj 多出来的那一半,是同一个想法的两个用法:门。
③ 先自己设计:多出来的矩阵,是不是只是「多了参数」?
最省事的解释:gate_proj 就是多加的一份参数,三矩阵的 FFN 更好,只因为它更大。检验这个解释的办法是拿 GELU FFN 和 SwiGLU FFN 比一比——关键在于怎么比。
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
| 方案 | 中间维 | 矩阵个数 | 单层 FFN 参数 |
|---|
| 模型 | d | 中间维 I(config) | I ÷ d | 单层 FFN 参数 | 等价 GELU 宽度 | 8d/3 规则现算 |
|---|
对齐之后,Shazeer 2020 在 T5-base(编码器-解码器,d = 768,在 C4 语料上做完形填空式预训练)上比较了 8 种 FFN。65,536 步:ReLU 1.997、GELU 1.983、SwiGLU 1.944(4 次运行的标准差 0.010);524,288 步:1.677、1.679、1.636 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条GLU Variants Improve Transformer, Table 1:参数与计算量对齐;任务是 span 填空(不是 decoder-only 的下一个词预测),模型是 T5-base。换任务、换规模要重新验证。 出处Shazeer 2020 Table 1 ↗需联网 。
差距不大,但参数一样多时它站得住。那多出来的矩阵到底在做什么?作者自己在结论里坦白没有解释,把成功归于「divine benevolence」(Shazeer 2020 结论)——这正是对话样本里那句话:「为什么 SwiGLU 比普通 ReLU MLP 好?也不是证明」。我们能做的,是把它在做什么看清楚。
④ 改进到现代做法
第 1 步:门——把「放多少」和「放什么」拆开
回到 L1 的神经元:第 i 个神经元的输出是 act(x · w_i),写回时乘 W_down 的第 i 行。「亮不亮」和「亮多少」是同一个数算出来的——x 在读取方向 w_i 上的投影,过一次 GELU。
门控的做法是给每个神经元两个读取方向:
- 门前值 g = x · W_gate 的第 i 列,过激活后决定「放行多少」;
- 上投影 u = x · W_up 的第 i 列,提供「放行什么」;
- 输出 h = act(g) × u。
这就是 GLU 家族(Dauphin 等 2016 提出 GLU,act 是 sigmoid;Shazeer 2020 换成别的激活,act = SiLU 时叫 SwiGLU)。一个门控神经元只取决于 (g, u) 两个数,所以可以把它整个画在一张平面上:
试三件事:① 在平面左半边(g 为负)随便点:SiLU(g) 很小,不管 u 多大输出都接近 0——门关着;② 点 g = 0 附近:门的值是 0,可 ∂h/∂g 不是 0,门随时能被梯度「推开」——切到 ReGLU(门是 ReLU)再点 g 为负的地方,∂h/∂g 恰好为 0;③ 点 g = −3、u = −2:门的值是 −0.142,输出变成 +0.285——SiLU 门可以是负数,它不是 0 到 1 的开关;切到 GLU,门变回 sigmoid,取值只在 (0, 1) 之间。
门控神经元自带乘法(回扣 L1)。 把「好吃 / 不好吃 / 难吃 / 不难吃」的两个特征改用 ±1 编码(是 = +1,否 = −1),目标「偏正面」恰好是 −p × n:好吃 −(+1)(−1) = +1,不好吃 −(+1)(+1) = −1,难吃 −(−1)(−1) = −1,不难吃 −(−1)(+1) = +1。一个不带激活的门控神经元(Bilinear:h = g × u,g 读 p、u 读 −n)一个就够,而 L1 用 ReLU 要两个 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条±1 编码下 XOR 等于 −p·n;双线性单元 h = (x·a)(x·b) 取 a = e_p、b = −e_n 即得。这说明门控单元能直接表示乘法交互,不说明它在语言模型里一定更好。 出处待补 。乘法交互,加上「值分支的梯度只被门缩放」,是门控被认为可能有效的两个理由——都是理论动机,不是证明。
第 2 步:SwiGLU 的完整形状
| 维度 | 含义 | 数值 |
|---|---|---|
| T | 序列长度(「小明把苹果给了小王」在 Qwen3.8 分词器下是 5 个 token) | 5 |
| d | 隐藏维 hidden_size | 5120 |
| I | FFN 中间维 intermediate_size(= 3.4 × d) | 17,408 |
第 3 步:注意力的输出门——q_proj 为什么多输出一倍
朴素方案在哪失败:注意力「必须分出 100%」。
C3 的岔路课讲过 attention sink:softmax 的权重和恒为 1,一个头在当前位置没有合适的对象可看时,也必须把 100% 的注意力分出去,于是常常倒在第 1 个 token 上。Qwen 团队在一个 15B 参数(激活 2.54B)的 MoE 模型上量过:没有门时,各层平均有 46.7% 的注意力分给了第 1 个 token,某一层高达 83% 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条Qiu et al. 2025 Fig. 2 与 Table 4:15A2B MoE、400B token、测试集困惑度数据;F-Attn 列 = 第 1 个 token 的注意力占比。 出处Qiu et al. 2025 Table 4 ↗需联网 。
还有第二个结构问题:值投影 W_V 与输出投影 W_O 之间什么都没有。一个头里 W_V 把 5,120 维压到 256 维,W_O 再展回 5,120 维,两次线性变换合起来仍是一个线性映射,而且秩不超过 256 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条rank(W_V · W_O) ≤ min(rank W_V, rank W_O) ≤ head_dim = 256;softmax 权重只改变「取谁」,不改变这条线性通路的秩。 出处待补 。
改进:在 SDPA 输出上乘一个 sigmoid 门。
| 维度 | 含义 | 数值 |
|---|---|---|
| T | 序列长度(示例 5) | 5 |
| d | 隐藏维 | 5120 |
| Hd | 24 个 Q 头 × head_dim 256 | 6144 |
门由当前 token 自己的输入算出,逐头、逐元素地决定这个头这次取回的东西放行多少:一个头没什么可看时,它可以把 softmax 分出去的 100% 整个关掉。这也在 W_V 与 W_O 之间插进了一个非线性。论文在 30 多种位置与形式里比较,SDPA 输出后、逐头逐元素的 sigmoid 门最好:首 token 注意力占比 46.7% → 4.8%,各层最大隐藏激活 1053 → 94,困惑度 6.026 → 5.761,门的平均取值只有 0.116(大多数时候接近关闭) 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条Qiu et al. 2025 Table 4 第 (1)(2) 行,同一个 15A2B MoE 设置;另有 1.7B 稠密模型 3.5T token 的训练曲线显示 loss 尖峰明显减少。都是 Qwen 团队自报,其解释(非线性 + 稀疏)是事后分析。 出处Qiu et al. 2025 ↗需联网 。这一项确实是 Qwen 首创,Qwen3-Next 起用于量产模型。
「门」这个说法的精确映射与失效点。
- 精确映射:门 = 一个由当前输入算出来的逐元素系数;「放行多少」= 这个系数的大小;「关门」= 系数接近 0,对应的那一维几乎不写入残差流。
- 失效点:① SwiGLU 的「门」SiLU(g) 可以是负数,也可以远大于 1,它会翻转符号、放大,不只是开关;只有 sigmoid 门(原始 GLU、注意力输出门)才在 (0, 1) 里;② 门不是固定的开关,每个 token、每一维都不一样;③ 门和值都是学出来的,「哪个分支是门」只是命名习惯——SwiGLU 里把激活放在哪个分支上,两个分支就在做不同的事。
演进图:本课在第几代
门控在 2019 年之前的 Transformer 里没有;GLU 在 2016 年已经有了,2020 年才被放进 FFN,2025 年又被放到注意力的输出上。
门控本身已经是共识;分歧在它周边:SwiGLU 的输出没有上界(g = u = 10 时 SiLU(10) × 10 = 99.995),在低精度算术下有溢出风险,于是 2025–2026 年的前沿模型都在给它「封顶」,只是封法不同 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条R3 §3.6:gpt-oss swiglu_limit = 7;DeepSeek V4 / V4.1、GLM-5.3-Flash 截断为 10;MiniMax-M3 limit 7;Kimi K3 的 SiTU-GLU β₁ = 4、β₂ = 25,|f| ≤ 100。截断后激活有界是数学事实,截断改善训练是各家自报(DeepSeek 报告明说机理不明)。 出处待补 ——这是 C15 的内容。
⑤ 极小真数字算一次
一个 SwiGLU 神经元,g = 1.5、u = −2:σ(1.5) = 0.8176,SiLU(1.5) = 1.5 × 0.8176 = 1.2264,h = 1.2264 × (−2) = −2.453;∂h/∂u = 1.2264(值分支的梯度只被门缩放,不经过激活函数的导数),∂h/∂g = σ(g)(1 + g(1 − σ(g))) × u = −2.083。换成 g = −3:σ(−3) = 0.0474,门的值 SiLU(−3) = −0.142,h = +0.285——门是负的,输出的符号被翻了过来。这几个数在上面的门控平面上点对应位置就能读到。
注意力输出门:取 SDPA 输出的某一维为 0.8(随手取的输入,只为演示乘法),门前值 −2.0 时 σ(−2.0) = 0.119,放行 0.8 × 0.119 = 0.095;门前值 +2.0 时 σ = 0.881,放行 0.705。论文里门的平均取值只有 0.116——大多数时候,一个头取回的东西只放行一成左右。
基线用 SwiGLU(中间维 688),对照组 c4_gelu 只把 FFN 换成 GELU(中间维 1024),单层参数 528,384 对 524,288。差异小于 0.02 时,页面会标「在噪声内」——这是 C14 实验课用同配置 5 次重跑定的噪声底线(标准差 0.0066、极差 0.016;差距小于 3σ ≈ 0.020 不下结论)。
读图(2026-09-26 导出的数据,以组件显示为准): 单种子时 SwiGLU 4.6263、GELU 4.6410,差 0.015,小于同配置 5 次重跑的极差 0.016(C14 实验课),下不了结论。于是每组再补 4 个种子(种子 1337–1341):SwiGLU 4.6218 ± 0.0060,GELU 4.6657 ± 0.0206,GELU 差 0.044,超过 3σ 阈值 0.020,约是种子波动标准误的 4.6 倍——在参数对齐的前提下,这个项目上可以说 SwiGLU 更好,方向与 Shazeer 2020 一致 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条5 个种子、3.7M 参数、400 步;只在这个规模上成立。单种子的 0.015 恰好是差距被低估的一次。 出处c04-block.json › seed_summary(2026-09-26 导出) ↗ 。上面门控平面里的黑点是同一个基线模型第 2 层的 688 个神经元在「曰」字上的真实 (g, u):61.9% 的门前值为负,19.0% 的门几乎关闭(|SiLU(g)| < 0.1);同一层同一个字,GELU 版模型 1,024 个神经元里有 92.9% 的输入为负。
⑥ ⚠ 常见误解
「SwiGLU 的门是 0 到 1 之间的开关」✗ —— SiLU(g) 的值域是 [−0.278, +∞)。0 到 1 之间的只有 sigmoid 门:原始 GLU 和注意力输出门。
「SwiGLU 更好,是因为它多了一个矩阵、参数更多」✗ —— 公平的对比都把中间维乘了 2/3,参数一样多;真实模型的中间维是按预算另取的(Qwen3.8 取 3.4d)。
「门控被证明更好」✗ —— 乘法交互、线性梯度通路是理论动机;「更好」来自对照实验,原作者明说无法解释。
「注意力输出门是一个固定的开关 / 一种 dropout」✗ —— 门由当前 token 的输入算出,每个 token、每个头、每一维都不同;dropout 是训练时随机置零,推理时关掉。
⑦ 证据三问
- 它解决什么问题? FFN:让一个神经元把「放多少」和「放什么」分开,能直接表示乘法交互。注意力:让一个头可以「看了也不用」,并在 W_V 与 W_O 之间加进非线性。
- 数学上为什么可能有效? ∂h/∂u = act(g) 让值分支的梯度不经过激活函数的导数 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条h = act(g)·u 对 u 求导即得。 出处待补 ;双线性单元一个就能表示 XOR 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条±1 编码下 XOR = −p·n。 出处待补 ;这些只说明「可能有效」 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条Dauphin 2016 的线性梯度通路论证;Qiu 2025 的非线性 + 稀疏解释。都不是「一定更好」的证明。 出处Dauphin et al. 2016 ↗需联网 。
- 实验上为什么最后选了它? Shazeer 2020 在参数对齐下的 T5 对照 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条65,536 步:1.997 / 1.983 / 1.944(ReLU / GELU / SwiGLU)。 出处Shazeer 2020 Table 1 ↗需联网 ,Qiu 2025 在 15B MoE 与 1.7B 稠密模型上的对照 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条首 token 注意力 46.7% → 4.8%,PPL 6.026 → 5.761。 出处Qiu et al. 2025 ↗需联网 ,以及此后大量模型的选择;我们项目里参数对齐后 SwiGLU 比 GELU 低 0.015,仍在重跑噪声之内(单种子;C14:5 次重跑极差 0.016),这个规模上不能据此说它更好。
⑧ 一句话
门控 = 两条投影逐元素相乘:一条决定放行多少,一条提供内容;它更好是实验选出来的,不是证明出来的。
⑨ 下一个缺口
一个块的零件到这里全齐了:两个 zero-centered RMSNorm、一个带输出门的注意力(或 Gated DeltaNet)、一个 SwiGLU FFN、两次残差相加。零件的参数加起来是多少?FFN 真的占了六成吗?去岔路课 参数到底花在哪 算清总账;主线接着进入 C5 优化:块搭好了,参数怎么更新得又快又稳?
⑩ 你可能会问
- 「门占多少参数?」 —— FFN 的 gate_proj 每层 89,128,960 个;注意力输出门每层 31,457,280 个,16 层共 503,316,480 个。完整账本见岔路 B1。
- 「Qwen3.8 另外 48 层 Gated DeltaNet 也有门吗?」 —— 有,它的输出门用 swish(SiLU),Qwen3.8-Flash-Next 换成了 sigmoid;这些在 C11 第 4 课 Gated DeltaNet 的公式解剖里讲(「输出门」那一项)。
🔍 先看一眼形状
Qwen3.8 每层 GDN 有一个 in_proj_z,形状 [6144, 5120],就是它的输出门(R2 §1.3.1)。和注意力输出门一样,它由当前 token 的输入算出,逐元素乘在输出上。 - 「SiTU-GLU 是什么?」 —— Kimi K3 给 SwiGLU 的两个分支各套一个 β·tanh(x/β) 的软封顶,近原点几乎不变、远处被封在 β₁β₂ = 100 以内。它以本课的 SwiGLU 为前提,放到 C15 讲。