第 2 章 第一部分:基础篇

Transformer 架构详解

从 Self-Attention 的数学推导到 GQA、MoE、MLA、NSA 等现代架构变体

Transformer Attention MoE 架构 NSA MTP

从 Attention 说起

2017 年 Vaswani et al. 发表 “Attention Is All You Need”,提出了 Transformer 架构。这篇论文的核心贡献是用 纯注意力机制 替代了 RNN/LSTM 中的循环结构,实现了完全并行化的序列建模。

Scaled Dot-Product Attention

Attention 的核心计算如下:

Attention(Q,K,V)=softmax(QKTdk)V\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V

其中:

  • Q∈Rn×dkQ \in \mathbb{R}^{n \times d_k}:Query 矩阵,代表”我要查询什么信息”
  • K∈Rm×dkK \in \mathbb{R}^{m \times d_k}:Key 矩阵,代表”我有什么信息可供查询”
  • V∈Rm×dvV \in \mathbb{R}^{m \times d_v}:Value 矩阵,代表”查到后返回什么信息”
  • dk\sqrt{d_k}:缩放因子,防止点积值过大导致 softmax 梯度消失

直觉理解:想象你在图书馆找书。QQ 是你的查询需求,KK 是每本书的标签,VV 是书的内容。QKTQK^T 计算的是你的需求与每本书的匹配程度,softmax 将匹配度归一化为概率分布,最后加权求和得到你需要的信息。

为什么需要缩放?

不加缩放因子会怎样?假设 QQ 和 KK 的每个元素都是均值为 0、方差为 1 的随机变量,则 QKTQ K^T 的每个元素的方差为 dkd_k。当 dkd_k 较大时(如 128),点积的值会非常大,导致 softmax 输出接近 one-hot 分布,梯度几乎为零。

除以 dk\sqrt{d_k} 后,点积的方差被规范化为 1,softmax 可以正常工作。

Multi-Head Attention

单头 Attention 只能捕捉一种类型的关系。Multi-Head Attention (MHA) 通过并行运行多个 Attention Head,让模型同时关注不同方面的信息:

MHA(Q,K,V)=Concat(head1,…,headh)WO\text{MHA}(Q, K, V) = \text{Concat}(\text{head}_1, \ldots, \text{head}_h) W^O

其中每个 head:

headi=Attention(QWiQ,KWiK,VWiV)\text{head}_i = \text{Attention}(Q W_i^Q, K W_i^K, V W_i^V)

假设模型维度 dmodel=4096d_{model} = 4096,头数 h=32h = 32,则每个头的维度 dk=dv=128d_k = d_v = 128。

参数量计算(一个 MHA 层):

4×dmodel2=4×40962=67,108,864≈67M4 \times d_{model}^2 = 4 \times 4096^2 = 67,108,864 \approx 67M

这包括 WQ,WK,WV,WOW^Q, W^K, W^V, W^O 各一个 dmodel×dmodeld_{model} \times d_{model} 的矩阵。

Causal Masking

在 Decoder-only 模型中(GPT 系列),我们需要确保位置 tt 只能看到位置 1,2,…,t1, 2, \ldots, t 的信息(不能”偷看”未来)。这通过一个下三角掩码(causal mask)实现:

maskij={0if i≥j−∞if i<j\text{mask}_{ij} = \begin{cases} 0 & \text{if } i \geq j \\ -\infty & \text{if } i < j \end{cases}

加在 softmax 之前:

Attention(Q,K,V)=softmax(QKTdk+mask)V\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}} + \text{mask}\right)V

−∞-\infty 经过 softmax 后变为 0,实现了因果遮蔽。

完整的 Transformer Block

一个标准 Transformer Decoder Block 包含以下组件:

输入 x
  ↓
LayerNorm(x)          ← Pre-Norm(现代做法)
  ↓
Multi-Head Attention
  ↓
+ x                   ← 残差连接
  ↓
LayerNorm
  ↓
Feed-Forward Network
  ↓
+ x                   ← 残差连接
  ↓
输出

Pre-Norm vs Post-Norm

原始 Transformer 使用 Post-Norm(先做 Attention/FFN,再 LayerNorm),但现代 LLM 几乎都使用 Pre-Norm(先 LayerNorm,再做 Attention/FFN)。原因是 Pre-Norm 的训练更稳定,梯度更平滑。

数学上的区别:

Post-Norm: xl+1=LN(xl+F(xl))x_{l+1} = \text{LN}(x_l + F(x_l))

Pre-Norm: xl+1=xl+F(LN(xl))x_{l+1} = x_l + F(\text{LN}(x_l))

Pre-Norm 的残差连接形成了一条”梯度高速公路”——无论网络多深,梯度都能直接流回输入。这对训练 100+ 层的 LLM 至关重要。

残差通路本身也可以被学习:Attention Residuals

上面两个公式里,残差项 xlx_l 始终是原样加回的——残差通路是一条固定的、不带参数的加法捷径。这是从 ResNet 继承下来的设计,二十多年来几乎没有被动过。

但”固定”本身就是一个可以被质疑的假设:为什么每一层都只能把自己的输出加进主干,而不能决定如何聚合此前所有层的表示?

Attention Residuals(AttnRes) 正是针对这一点提出的:把固定的加法替换成一次注意力计算,让模型自己学习”主干应该以什么权重吸收各层的输出”。其 Block AttnRes 变体为了减少计算开销,按块(block)而非按层做聚合,已被应用于 Kimi Linear(48B 总参数 / 3B 激活参数),并在 1.4T tokens 规模上完成预训练。

这件事的意义不在于它涨了几个点,而在于它说明:本章讲的这些”基础构件”在 2026 年仍在被重新设计。残差连接通常被当作 Transformer 里最不需要解释的部分——它是背景设施,是默认正确的东西。AttnRes 提醒我们,默认正确的东西里仍然藏着未被榨干的空间,而这类改进一旦成立,收益会作用于所有层、所有任务。

⚠️ 成熟度提示:该工作目前主要来自单一团队的报告,公开发表于 2026-03,第三方独立复现有限。它已经过了 1.4T tokens 规模的训练验证(在架构类创新中属于较强的证据等级),但仍不宜当作可以直接照搬的工程结论。若要在自己的训练中采用,建议先在小规模上做对照实验,重点观察训练稳定性而非只看收敛 loss——改动残差通路会直接影响梯度流,稳定性风险是首要关注点。

RMSNorm

LLaMA 系列引入了 RMSNorm(Zhang & Sennrich, 2019),替代标准的 LayerNorm:

RMSNorm(x)=x1d∑i=1dxi2+ϵ⋅γ\text{RMSNorm}(x) = \frac{x}{\sqrt{\frac{1}{d}\sum_{i=1}^{d} x_i^2 + \epsilon}} \cdot \gamma

与 LayerNorm 的区别:RMSNorm 不做均值减除(re-centering),只做尺度归一化(re-scaling)。实践中效果相当但计算更快(省掉了均值计算)。

Feed-Forward Network

标准 Transformer 的 FFN 是一个两层 MLP:

FFN(x)=W2⋅σ(W1x+b1)+b2\text{FFN}(x) = W_2 \cdot \sigma(W_1 x + b_1) + b_2

现代 LLM 的改进是使用 SwiGLU 激活函数(Shazeer, 2020;被 LLaMA、PaLM 等采用):

FFNSwiGLU(x)=W2⋅(Swish(W1x)⊙(W3x))\text{FFN}_{SwiGLU}(x) = W_2 \cdot (\text{Swish}(W_1 x) \odot (W_3 x))

其中 Swish(x)=x⋅σ(x)\text{Swish}(x) = x \cdot \sigma(x),σ\sigma 是 sigmoid 函数,⊙\odot 是逐元素乘法。

SwiGLU 引入了第三个权重矩阵 W3W_3(gate),但 FFN 的隐藏层通常从 4×dmodel4 \times d_{model} 缩小到 83×dmodel\frac{8}{3} \times d_{model},总参数量大致相同。

一个 FFN 层的参数量(SwiGLU,dmodel=4096,dff=11008d_{model} = 4096, d_{ff} = 11008):

3×dmodel×dff=3×4096×11008≈135M3 \times d_{model} \times d_{ff} = 3 \times 4096 \times 11008 \approx 135M

关键认识:FFN 层的参数量约占整个 Transformer Block 的 2/3。越来越多的研究表明,FFN 实际上充当了”知识存储器”——模型的事实知识主要存储在 FFN 的权重中。

位置编码

Transformer 的 Self-Attention 本身是 位置不变的(permutation-equivariant)——打乱输入顺序,Attention 权重只是做相应的行列置换。因此需要显式注入位置信息。

绝对位置编码

原始 Transformer 使用正弦/余弦绝对位置编码,但这种方法不支持长度外推(训练时 512,推理时无法处理 8192)。

RoPE(Rotary Position Embedding)

RoPE(Su et al., 2021)是目前 LLM 最流行的位置编码方法(LLaMA、Qwen、DeepSeek 等都在用)。核心思想是:将位置信息编码为旋转角度。

对于二维向量 (q0,q1)(q_0, q_1),在位置 mm 处的编码等价于旋转角度 mθm\theta:

(q0′q1′)=(cos⁡mθ−sin⁡mθsin⁡mθcos⁡mθ)(q0q1)\begin{pmatrix} q_0' \\ q_1' \end{pmatrix} = \begin{pmatrix} \cos m\theta & -\sin m\theta \\ \sin m\theta & \cos m\theta \end{pmatrix} \begin{pmatrix} q_0 \\ q_1 \end{pmatrix}

推广到高维,将 dd 维向量分成 d/2d/2 组,每组使用不同的频率 θi\theta_i:

θi=10000−2i/d,i=0,1,…,d/2−1\theta_i = 10000^{-2i/d}, \quad i = 0, 1, \ldots, d/2 - 1

RoPE 的关键性质:位置 mm 和位置 nn 的 query 和 key 的点积 只依赖于相对位置 m−nm - n。这使得 RoPE 天然支持相对位置建模。

RoPE 的长度外推

RoPE 的一个重要优势是可以通过调整基频来支持更长的上下文。比如 YaRN(Yet another RoPE extensioN)通过温度缩放和分段插值,将 RoPE 从 4K 外推到 128K+。

常见的外推策略:

方法思路效果
线性插值将位置 mm 缩放为 m/sm/s简单有效,但需要微调
NTK-Aware调整基频 θ\theta不需要微调,适合短外推
YaRN分频段处理 + 温度缩放效果最好,需要少量微调
Code RoPE高低频分别处理DeepSeek 方案

现代架构变体

GQA(Grouped-Query Attention)

标准 MHA 中每个 head 都有独立的 Q,K,VQ, K, V。GQA(Ainslie et al., 2023)让多个 head 共享同一组 K,VK, V,从而大幅减少 KV Cache 的内存占用。

假设 32 个 query head,8 个 KV head(每 4 个 query head 共享一组 KV):

  • MHA: KV Cache = 2×32×128×L2 \times 32 \times 128 \times L (LL 是序列长度)
  • GQA-8: KV Cache = 2×8×128×L2 \times 8 \times 128 \times L (减少 4 倍!)

GQA 几乎不影响模型质量,但推理时的显存节省非常显著。LLaMA 2 70B 及后续大模型几乎都使用 GQA。

但”等量共享”这个默认假设是有前提的。 上面公式里 KK 和 VV 是等量被砍的(32 → 8,两者一起降到 8)。这个等量其实是稠密注意力的遗产:在稠密注意力里,probability×V\text{probability} \times V 这一步要乘全部上下文,与 QK⊤QK^\top 同量级,所以 K 和 V 一起减半才划算。

一旦注意力变稀疏(每 query 只看一小部分上下文,见后面 SAS / Elastic Threshold 两节),被选中的条目很少,probability×V\text{probability} \times V 这一步的开销就变得可以忽略,瓶颈整个移到 QK⊤QK^\top 那一步。此时正确的做法不是继续等量砍,而是非对称地砍:

  • 多砍 key head → 直接换 QK⊤QK^\top 的速度(现在的瓶颈就在这里);
  • 多留 value head → 保住模型容量,而增加的解码开销很有限。

SAGA(Sparse Asymmetric Group-Query Attention,arXiv:2610.04753,2026-10-03)就是把 K/V 头数解耦来吃这个差价的方案,理论上有形式化论证,并在最长上下文下相对 full-attention GQA 基线取得端到端解码加速超过 2×2\times;从零训练的 SAGA 模型在评测上质量接近同等 GQA 变体。

对工程最要紧的一条是它的可采纳性:作者给出了一个高效的微调方法,可以把已训好的预训练 GQA 模型直接转成 SAGA,不需要重训。这决定了它能不能被现有系统采用——“效果很好但要重训”的方案在生产上基本等于不存在。

⚠️ 限定:以上为 2026-10 预印本、单一团队、论文自报,实证规模到 1.5B 参数,“从预训练转换”亦为作者自报。写入时按”截至 2026-10 的自报结果”读,不要当作已验证的通用结论。

MQA(Multi-Query Attention)

GQA 的极端情况:所有 head 共享同一组 K,VK, V(只有 1 个 KV head)。显存最省,但对模型质量有一定影响。

MLA(Multi-head Latent Attention)

DeepSeek V2 提出的创新。核心思想是用低秩压缩替代直接存储 KV:

ct=WDKV[kt;vt]c_t = W_{DKV} [k_t; v_t]

其中 ct∈Rdcc_t \in \mathbb{R}^{d_c} 是压缩后的表示,dc≪dmodeld_c \ll d_{model}。推理时只需缓存 ctc_t,需要 K,VK, V 时再解压:

kt=WUKct,vt=WUVctk_t = W_{UK} c_t, \quad v_t = W_{UV} c_t

MLA 可以达到比 GQA 更高的压缩率,同时保持接近 MHA 的质量。

SAS(Simple Attention Sparsification)

前面三节(GQA / MQA / MLA)省的是显存:KV Cache 少存一点,注意力仍然对全部上下文做 O(n2)O(n^2) 计算。还有另一条路线:省计算,即每个 query 只看上下文里的一小部分,这就是注意力稀疏化(attention sparsification)。

SAS: Simple Attention Sparsification(2026-09)的贡献不在”又提出一种稀疏 pattern”,而在于指出并修掉了可训练稀疏化里一个普遍存在的方法论漏洞。

问题:排序错配(ranking misalignment)

可训练稀疏化的标准做法是:用一个轻量 selector 给每个上下文单元(token 或 block)打分,然后 hard Top-K 选出要保留的单元。麻烦在于 Top-K 这一步把梯度掐断了——语言建模损失无法从选中的结果反传回 selector。

于是既有方法普遍改用蒸馏:让 selector 去拟合原模型逐层的稠密注意力分布。这看起来合理,实际上引入了一个错配:

selector 学到的排序,是按稠密注意力权重的大小排的;而在固定预算(每个 query 能看的上下文单元数是定值)下,真正该问的是哪些单元对最终预测的边际贡献最大。这两件事并不等价。

一个直觉例子:某个 token 稠密注意力权重很高,但它携带的信息已经被其它保留单元覆盖了,留它等于浪费预算;另一个 token 权重平平,却是唯一记录了关键约束的那一个,丢掉它整题就废了。注意力权重是非次模的——一个单元的价值取决于”还有谁被留下”,而稠密分布的绝对值里没有这个信息。预算越紧,这种错配越致命。

做法:把 gate 塞进 softmax 里面

SAS 的修法极其简单:不再蒸馏,而是把 selector 输出的连续分数以对数形式直接注入 attention logits——

Attn(q)=softmax⁡ ⁣(qK⊤+log⁡g^)V\text{Attn}(q) = \operatorname{softmax}\!\big(\mathbf{q}\mathbf{K}^{\top} + \log \hat{\mathbf{g}}\big)\mathbf{V}

这样整个式子对 selector 参数可导,语言建模损失可以走标准反向传播一路更新 selector,排序目标和最终预测目标就此对齐。

论文强调有三个”看起来是细节、实际决定成败”的选择:

  1. gate 必须放在 softmax 内部、以 log 形式注入。放在 softmax 外面做乘性缩放,梯度行为和校准性质都不对。
  2. 用归一化后的 softmax gate,让历史上下文与”永远保留的当前 block”处在可比的尺度上——否则当前 block 的相对权重会漂。
  3. 保留 selector 的连续分数,而不是只留 hard Top-K 结果。模型要学的是相对优先级,硬选择把这个信息丢掉了。

配套工程上,论文实现了一个 Triton kernel 把 SAS 融进 FlashAttention 式计算,从而支持长序列训练。

收益与限定语

在 1024 token 的紧预算、Qwen3-4B / 8B / 14B 上,SAS 相对可训练稀疏基线 SeerAttention-R 的增益为:MATH500 6.0–7.7 个点、GPQA-Diamond 10.6–15.5 个点。

⚠️ 两组限定,读数字时别跳过去:① 这些增益是相对另一条稀疏基线(SeerAttention-R)而言的,不是相对稠密注意力——稀疏化在紧预算下仍低于 full attention 的上限,SAS 解决的是”同样预算下选得更准”,不是”稀疏能超过稠密”。② 上述全部数字为论文自报结果,截至 2026-09-24 尚无独立复现。

一个反直觉的分析结果

如果只看”每层选中的 block 覆盖了多少注意力质量”这个常用指标,SAS 比蒸馏法覆盖得更少。按这个指标它应该更差,但实际效果更好。原因是论文换了另一个指标,即跨层并集对 full attention oracle 的召回率,在这个指标上 SAS 更高。

结论很有意思:蒸馏法让每一层都去挑”注意力质量最大”的那批块,于是各层挑中的高度重叠;SAS 因为目标是对最终预测有用,各层自动学会了互补分工。“每层覆盖率”这个指标本身隐含了一个假设:各层独立最优。而稀疏化真正要优化的是跨层的联合覆盖。这和本书前面讨论 MoE 时”专家特化”的现象是同构的——约束下的分配问题,局部贪心通常不等于全局最优。

工程可用性

SAS 已开源(GitHub Tencent-Hunyuan/Simple-Attention-Sparsification),推理侧实现为 SGLang 的原生 attention backend,构建在分页 KV Cache 与 FlashInfer kernel 之上,沿用标准的 prefill/decode 分离:prefill 用稠密注意力,decode 用稀疏注意力。论文在单卡、开 CUDA graph、稳态 decode 的设置下报告 Qwen3-4B 的 decode 延迟最高降低 5.6×(batch 1,随上下文长度拉长而增大)。

教学要点:SAS 是”可训练稀疏注意力”这条线的代表,与 GQA / MQA / MLA 属于不同轴:前者省计算(O(n2)→O(n⋅b)O(n^2) \to O(n \cdot b),bb 为预算),后者省显存。生产系统里两者通常叠加使用:KV Cache 用 MLA/GQA 压,注意力计算再用稀疏化砍。SAS 的教训还有普适性:凡是用”拟合原模型中间量”当训练目标的压缩方法,都要追问一句:这个中间量和”压缩后的最终效果”是不是同一个目标。 蒸馏稠密注意力属于典型的代理目标错配。

MoE(Mixture of Experts)

MoE 是当前最重要的架构创新之一。核心思想:不是所有参数都需要在每次前向传播中被激活。

在标准 Transformer 中,每个 token 都经过同一个 FFN。MoE 将 FFN 替换为多个”专家”,每个 token 只激活 top-k 个专家:

MoE(x)=∑i=1Ngi(x)⋅Ei(x)\text{MoE}(x) = \sum_{i=1}^{N} g_i(x) \cdot E_i(x)

其中 gi(x)g_i(x) 是路由函数(router)的输出,Ei(x)E_i(x) 是第 ii 个专家网络,NN 是专家总数。通常只有 top-2 的 gig_i 非零。

DeepSeek V3 的 MoE 配置:

  • 总共 256 个专家 + 1 个共享专家
  • 每个 token 激活 8 个专家
  • 总参数量 671B,激活参数量 37B
  • 效果接近 dense 模型,但推理成本大幅降低

MoE 的关键挑战:

  1. 负载均衡:避免某些专家过载、某些专家闲置
  2. 路由策略:如何高效地选择专家
  3. 通信开销:分布式训练时,不同专家在不同 GPU 上,需要 all-to-all 通信

第三层:同一个权重文件服务多个容量点。 上面讲的是”总参大、激活少”(DeepSeek V3 的 671B/37B),后面 LatentMoE 讲的是”同成本下专家更多”。还有一层本章此前没写:激活规模本身可以在推理时按需切换。

Stepped MoE(arXiv:2610.07348,2026-10-05)把弹性嵌套子网络与稀疏门控 MoE 结合:主干同时以输入上下文和一个目标效率规格为条件,在弹性嵌套子网络内激活任务相关的参数。结果是单个模型即可跨越多个容量点——论文报告可在 1B / 2B / 3B / 4B 激活参数四档之间切换,在知识密集型基准上比同等规模的 dense 模型高 2–5%,延迟与静态版本相当;权重共享还节省端侧磁盘。

工程含义:“训一次、按部署环境切换档位”在 FFN 侧有了答案。这与 GQA / MQA 按显存档位做选择是同一类需求,只是发生在 FFN 而不是 KV——前者按显存选,后者按算力与 DRAM 选。对端侧/DRAM 受限场景尤其直接,因为同一个权重文件可以覆盖从手机到工作站的多档设备。

⚠️ 限定:2026-10 预印本、作者自报;验证规模上限 4B,无前沿规模证据,动机明确是端侧/DRAM 受限场景。不要外推到大模型训练侧。

Efficiency Leverage (EL):ICLR 2026 论文提出 EL 指标量化 MoE 的计算优势:EL=dense 等效计算/MoE 实际计算\text{EL} = \text{dense 等效计算} / \text{MoE 实际计算}。核心发现:EL 主要由专家激活率 α\alpha 和总算力 CC 驱动,遵循幂律 EL∝αa×Cb\text{EL} \propto \alpha^a \times C^b;专家粒度 gg 为非线性调节器,存在最优范围(过大过小都降低 EL)。实测中 MoE-mini(0.85B 激活参数)匹配 6.1B dense 模型,EL≈7.2x。详细讨论见第五章 Scaling Laws。

我们将在第七章深入讨论 MoE 的设计和训练。

混合架构:Mamba + Transformer

纯粹的 Attention 和纯粹的状态空间模型各有局限——能否将二者融合,兼得长序列效率与全局上下文理解?

Mamba SSM 的核心思想

Mamba(Gu & Dao, 2023)提出了一种选择性状态空间模型(Selective State Space Model, S6)。与传统 SSM 的关键区别在于:Mamba 的状态转移参数(B,C,ΔB, C, \Delta)是输入依赖的,而非固定不变。

这意味着模型可以选择性地决定哪些信息写入隐状态、哪些信息被遗忘——类似 LSTM 的门控机制,但计算复杂度从 O(n2)O(n^2) 降到 O(n)O(n)。

核心优势:

  • 线性复杂度:推理时每步只需 O(1)O(1) 的计算和显存(无需 KV Cache)
  • 长序列友好:天然支持超长上下文,不受序列长度限制
  • 选择性信息过滤:输入依赖的参数让模型能”记住重要的事,忘掉无关的”

为什么需要混合?

Mamba 和 Transformer Attention 是互补的:

维度AttentionMamba SSM
复杂度O(n2)O(n^2)O(n)O(n)
全局上下文强——任意位置可直达弱——信息沿状态逐步传递
长序列推理KV Cache 线性增长常数状态,无额外开销
精确检索强——直接关注目标位置弱——依赖状态压缩

简言之:Mamba 擅长长序列处理但缺少全局上下文,Attention 擅长上下文理解但 O(n2)O(n^2) 复杂度限制了长度。混合架构的目标是用最少的 Attention 层获取全局上下文能力,用 Mamba 层处理长序列信息的高效传递。

工业验证:Hunyuan-TurboS

Hunyuan-TurboS(腾讯, 2025)是首个大规模工业部署的 Mamba-Transformer-MoE 混合架构模型:

  • 参数规模:560B 总参数 / 56B 激活参数
  • 性能:在 LMSYS Chatbot Arena 排名前 7,与同级别 dense 模型持平
  • 推理加速:相比同等性能的纯 Transformer 架构,推理速度提升 1.8x
  • 核心设计:采用 AMF/MF 块交替排列模式,在保留全局上下文能力的同时大幅降低推理成本

混合比例设计

Hunyuan-TurboS 的层类型分配:

层类型比例说明
Attention5.5%少量 Attention 层即可提供全局上下文
Mamba244.5%主体序列建模层,线性复杂度
MoE-FFN50%知识存储与稀疏激活

5.5% 的 Attention 看似极少,但实验表明:在混合架构中,少量的 Attention 层足以建立全局信息通道,Mamba 层则负责高效地在序列中传递和整合信息。

AMF 块与 MF 块

Hunyuan-TurboS 的层排列采用两种块模式交替堆叠:

AMF 块(Attention → Mamba2 → MoE-FFN):

输入 x
  ↓
LayerNorm → Multi-Head Attention → 残差
  ↓
LayerNorm → Mamba2 → 残差
  ↓
LayerNorm → MoE-FFN → 残差
  ↓
输出

MF 块(Mamba2 → MoE-FFN):

输入 x
  ↓
LayerNorm → Mamba2 → 残差
  ↓
LayerNorm → MoE-FFN → 残差
  ↓
输出

模型整体由若干 AMF 块和 MF 块交替排列构成。AMF 块中的 Attention 为序列注入全局上下文信息,随后的 Mamba2 在此基础上进行高效的长程信息传递,MoE-FFN 则负责知识存储与条件计算。MF 块省去了 Attention,纯粹依靠 Mamba2 维持信息流,进一步降低计算成本。

三团队架构收敛

一个引人注目的工程现象是:NVIDIA(Nemotron 3 Ultra)、腾讯(Hunyuan-TurboS)和阿里(Qwen 3.5 Small)三个团队独立收敛到了相近的混合架构比例——约 75% SSM + 25% Attention + MoE。Nemotron 3 Ultra(550B/55B,108 层)采用 Mamba-2/MoE 对与 Attention 层交替排列,支持 1M 上下文。这种跨团队收敛说明”少量 Attention 建全局 + 大量 SSM 传长程 + MoE 做条件计算”的混合范式是当前工程最优解,而非单一团队的偏好。

Mamba-3(ICLR 2026) 为这一收敛现象提供了数学基础:它将 Mamba 系列和 DeltaNet 系列统一在同一结构化状态空间对偶(SSD)框架下,证明二者属于同一计算类。“选 Mamba-2 还是 Gated DeltaNet”本质上是工程实现选择而非架构路线分歧。这解释了为何 NVIDIA ��� Mamba-2、Qwen 选 Gated DeltaNet,却能取得可比结果。

RULER 长上下文基准的对比数据量化了混合架构的优势:Nemotron 3 Super(120B/12B)在 RULER@1M 达到 91.75%,而同等参数量的纯 Transformer 模型(GPT-OSS 120B)仅为 22.30%——近 70 个百分点的差距直接证明了混合架构在长上下文场景下的本质优势。在内存效率上,Jamba-1.5-Large 在 256K 上下文下仅需 9GB KV Cache,而同等上下文窗口的 Llama-3.1-70B 需约 80GB(近 9x 差异),这种内存效率差异直接决定了并发用户数和边缘部署可行性。

LatentMoE:低秩压缩让专家更多、推理不更贵

Nemotron 3 Ultra(NVIDIA, 2026)引入了 LatentMoE——一种在压缩隐空间中进行 MoE 路由的机制,突破了”专家数越多推理越慢”的瓶颈。

核心思想:传统 MoE 路由在完整 token 嵌入维度 dd 上执行专家计算,每个激活专家的计算量为 O(d2)O(d^2)。LatentMoE 先将 token 嵌入投射到低秩隐空间 d′≪dd' \ll d,专家在 d′d' 维度上计算,再投射回 dd 维度:

LatentMoE(x)=Wup⋅MoE(Wdown⋅x)\text{LatentMoE}(x) = W_{\text{up}} \cdot \text{MoE}(W_{\text{down}} \cdot x)

其中 Wdown∈Rd′×dW_{\text{down}} \in \mathbb{R}^{d' \times d},Wup∈Rd×d′W_{\text{up}} \in \mathbb{R}^{d \times d'}。

关键优势:同推理成本下激活 4x 专家数。Nemotron 3 Ultra 的配置对比:

维度标准 MoELatentMoE
专家总数64512
激活专家数top-8top-22
路由/计算维度ddd′≪dd' \ll d
同等推理成本—4x 专家数
专业化粒度粗(如”代码”vs”自然语言”)细(如”Python 语法”vs”SQL 逻辑”)

更多专家使路由更精细化——不同子领域激活不同专家组合,而非将宽泛领域交给同一批专家。Nemotron 3 Ultra 的 512 专家/top-22 激活配置,搭配 NVFP4 原生预训练和 1M 上下文窗口,实现了 6x 推理吞吐提升。

架构谱系总览

从原始 Transformer 到现代混合架构,注意力机制的演进可以概括为以下路线:

演进阶段代表模型关键特征复杂度
纯 TransformerGPT-3, LLaMA标准 MHA,每头独立 KVO(n2)O(n^2)
GQA / MQALLaMA 2, Falcon多头共享 KV,减少 KV CacheO(n2)O(n^2)(内存优化)
MLADeepSeek V2/V3低秩压缩 KV,极高压缩率O(n2)O(n^2)(内存大幅优化)
MoEMixtral, DeepSeek V3稀疏激活专家,总参大激活少O(n2)O(n^2)(计算优化)
Mamba+Transformer+MoEHunyuan-TurboS / Nemotron 3 UltraSSM+Attention+MoE 混合,线性+二次复杂度并存O(n)O(n) 主体 + 少量 O(n2)O(n^2)
分数级 SSM-Attention 融合SISA (2026-06)SSM 偏置注入 attention score 矩阵,无需额外层/头O(n2)O(n^2) 主体 + O(n)O(n) 偏置
可训练稀疏注意力SAS (2026-09)selector 分数以 log⁡g^\log \hat{g} 注入 attention logits,端到端优化上下文排序O(n⋅b)O(n \cdot b),bb 为每 query 预算
差分注意力 + 潜在压缩GDLA(Motif 3, 2026-08)Grouped Differential Latent Attention:分组差分注意力叠加 MLA 的压缩 KVO(n2)O(n^2)(内存 + 质量双优化)
可学习 KV 记忆路由ARM (2026-09, ICML 2026)定长记忆槽 + 层级 router,Gumbel-Softmax 选槽、sigmoid 门控软更新替代硬驱逐;推理时动态决定取用多少记忆定长 KV 缓存,与上下文长度解耦
不确定性感知线性注意力Kalman Delta Networks (2026-09)把 delta rule 联想记忆写成 Kalman 滤波形式,显式维护记忆的不确定性O(n)O(n) 循环更新
学习式上下文稀疏解码Elastic Threshold Attention (2026-09)让模型自己学阈值决定长上下文解码时跳过哪些上下文,而非人工设定稀疏 pattern解码期 O(n⋅b)O(n \cdot b),bb 随输入自适应
Mixture-of-Head 原生稀疏注意力NAMOH(arXiv:2609.38832, 2026-09)每 token 激活 HH 个 head 中的 KK 个;每个 head 只保留分配给它的 token,并在该子序列内做因果注意力——head 选择同时决定”激活多少参数”与”能看到多少上下文”均衡分配下固定 KK、增大 HH:每 token 的 KV 访问下降,总 KV 存储不变
非对称稀疏 GQASAGA(arXiv:2610.04753, 2026-10)解耦 K/V 头数:多砍 key head 换速度、多留 value head 换容量;配近似 top-N(Atop-N)研究稀疏度 × 非对称性的交互稀疏注意力下的 O(n⋅b)O(n \cdot b);长上下文端到端解码加速 >2×>2\times(vs full-attention GQA)

混合架构里程碑:Hunyuan-TurboS 首个大规模工业部署 Mamba 架构,Nemotron 3 Ultra 首个开源旗舰级混合架构(550B/55B),三者独立收敛验证了”少量 Attention + 大量 SSM + 稀疏 FFN”设计范式的可行性和优越性。

从融合粒度看,SSM-Attention 混合正经历三级跃迁——块级(交替层,当前主流生产方案)→ 头级(并行头,Falcon-H1/Hymba)→ 分数级(score-level 偏置,SISA, 2026-06)。分数级融合是最新的学术前沿,尚处于 152M 小规模验证阶段(LAMBADA +1.6pp vs 纯 Transformer),但理论优美:它不是”两种机制各做各的”,而是让 SSM 的特性(衰减编码 egi−gje^{g_i-g_j}、数据依赖旋转 R(Φj−Φi)R(\Phi_j-\Phi_i))以偏置形式直接参与 attention score 计算。

上表其实沿着两条不同的轴在演进,读表时别混在一起:GQA / MQA / MLA / GDLA 省的是显存(KV Cache 少存,注意力仍算全部上下文);SAS、Elastic Threshold Attention 以及 SSM 类架构省的是计算(少算一部分上下文,或把二次复杂度换成线性)。两条轴可以叠加——现代推理栈通常是「MLA/GQA 压 KV Cache + 稀疏注意力砍计算 + MoE 砍 FFN」三件套一起上。2026 年的新成员(Kalman Delta Networks 等)还多了第三条轴:不再只问「记多少、算多少」,而是显式建模「记忆本身有多可信」。

还有第四条轴:头数非对称性。 前两条轴都只回答”砍多少”,没回答”砍 K 还是砍 V”。在稠密注意力下这两个问题等价(K、V 一起减半),所以”等量”从来不需要被单独讨论;一旦注意力变稀疏,它们就分开了——SAGA(见 GQA 一节)表明稀疏下应当多砍 key、多留 value。于是谱系表的读法从”两条轴 + 记忆可信度”变成”两条轴 + 记忆可信度 + 一个跨轴的分配问题”。

顺带把本章已经出现过的三处分配问题并列起来看,它们是同构的:

  • MoE 的专家特化:给定激活预算,把 token 分给哪些专家;
  • SAS 的跨层互补分工:给定每层的稀疏预算,各层分别跳过哪些上下文;
  • SAGA 的 K/V 头数比:给定头数预算,砍 K 还是砍 V。

三处的教训也一致:2026 年的注意力优化,越来越不像”选一个稀疏 pattern”,而像”在给定预算下做分配”——而分配问题的局部贪心通常不等于全局最优。(本章 SAS 段已写过这一句,SAGA 是同构的第三个实例。)

参数扩展与上下文扩展也可以合并处理。 NAMOH(arXiv:2609.38832)换了一个问法:通常”增加注意力参数”与”支持更长上下文”是两件分开做、且后者通常更贵的事。NAMOH 让 head 选择同时决定这两件事——每 token 只激活 HH 个 head 中的 KK 个,每个 head 只保留分配给它的 token 并在该子序列内做因果注意力,于是无需扫描完整历史。均衡分配下,固定 KK、增大 HH 会缩短每个 head 的历史、减少每 token 的 KV 访问量,而总 KV 存储不增加。它还支持 head-relative RoPE 以缩短路由子序列内的位置跨度,并声明与 GQA 及现有稀疏注意力机制兼容。这是本章 LatentMoE 段”更多专家使路由更精细”在注意力侧的平行机制:都是靠”更细的分配”而不是”更大的总量”换收益。

⚠️ 限定:NAMOH 为 2026-09 预印本,本轮仅回源至摘要;SAGA 见前节的限定(1.5B、自报)。

完整模型的参数量计算

以一个 7B 参数的 LLaMA-style 模型为例:

组件参数量公式具体值
EmbeddingV×dV \times d32000 × 4096 = 131M
Attention (per layer)4d24 d^2 (GQA 会更少)4 × 4096² = 67M
FFN (per layer)3d×dff3 d \times d_{ff}3 × 4096 × 11008 = 135M
RMSNorm (per layer)2d2d8K
总 (32 layers)32 × (67M + 135M) + 131M ≈ 6.6B
LM Head与 Embedding 共享0 (tied)

思考题:为什么 LM Head 通常与 Embedding 矩阵 tied(共享权重)?这对模型有什么影响?(提示:正则化效果 + 参数效率)

核心组件的 PyTorch 实现

理论需要落地。下面我们用 PyTorch 实现一个现代 LLM 的核心组件——带 RoPE 的 GQA Attention 和 SwiGLU FFN。

RoPE 位置编码实现

import torch
import torch.nn as nn
import torch.nn.functional as F
from typing import Optional, Tuple

def precompute_freqs_cis(dim: int, max_seq_len: int, theta: float = 10000.0):
    """预计算 RoPE 的旋转频率(复数形式)"""
    # θ_i = 10000^{-2i/d}, i = 0, 1, ..., d/2 - 1
    freqs = 1.0 / (theta ** (torch.arange(0, dim, 2).float() / dim))
    # 位置索引 [0, 1, ..., max_seq_len - 1]
    t = torch.arange(max_seq_len, dtype=torch.float32)
    # 外积: [seq_len, dim//2]
    freqs = torch.outer(t, freqs)
    # 转换为复数: e^{i * m * θ} = cos(mθ) + i*sin(mθ)
    freqs_cis = torch.polar(torch.ones_like(freqs), freqs)
    return freqs_cis  # [seq_len, dim//2]

def apply_rotary_emb(xq: torch.Tensor, xk: torch.Tensor,
                     freqs_cis: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]:
    """将 RoPE 应用到 query 和 key"""
    # 将实数张量视为复数: [B, seq, n_heads, dim] → [B, seq, n_heads, dim//2]
    xq_ = torch.view_as_complex(xq.float().reshape(*xq.shape[:-1], -1, 2))
    xk_ = torch.view_as_complex(xk.float().reshape(*xk.shape[:-1], -1, 2))
    # 广播旋转: 复数乘法实现旋转
    freqs_cis = freqs_cis[:, None, :]  # [seq, 1, dim//2] for broadcasting
    xq_out = torch.view_as_real(xq_ * freqs_cis).flatten(-2)
    xk_out = torch.view_as_real(xk_ * freqs_cis).flatten(-2)
    return xq_out.type_as(xq), xk_out.type_as(xk)

GQA Attention 实现

class GroupedQueryAttention(nn.Module):
    """Grouped-Query Attention (GQA) with RoPE
    
    当 n_kv_heads == n_heads 时退化为标准 MHA
    当 n_kv_heads == 1 时退化为 MQA
    """
    def __init__(self, d_model: int, n_heads: int, n_kv_heads: int):
        super().__init__()
        self.n_heads = n_heads
        self.n_kv_heads = n_kv_heads
        self.n_rep = n_heads // n_kv_heads  # 每组 KV 被多少个 Q 头共享
        self.head_dim = d_model // n_heads

        self.wq = nn.Linear(d_model, n_heads * self.head_dim, bias=False)
        self.wk = nn.Linear(d_model, n_kv_heads * self.head_dim, bias=False)
        self.wv = nn.Linear(d_model, n_kv_heads * self.head_dim, bias=False)
        self.wo = nn.Linear(n_heads * self.head_dim, d_model, bias=False)

    def forward(self, x: torch.Tensor, freqs_cis: torch.Tensor,
                mask: Optional[torch.Tensor] = None) -> torch.Tensor:
        B, L, _ = x.shape

        # 投影: [B, L, d] → [B, L, n_heads, head_dim]
        q = self.wq(x).view(B, L, self.n_heads, self.head_dim)
        k = self.wk(x).view(B, L, self.n_kv_heads, self.head_dim)
        v = self.wv(x).view(B, L, self.n_kv_heads, self.head_dim)

        # 应用 RoPE 位置编码
        q, k = apply_rotary_emb(q, k, freqs_cis)

        # GQA: 将 KV 头复制以匹配 Q 头数量
        # [B, L, n_kv, dim] → [B, L, n_heads, dim]
        k = k[:, :, :, None, :].expand(-1, -1, -1, self.n_rep, -1).flatten(2, 3)
        v = v[:, :, :, None, :].expand(-1, -1, -1, self.n_rep, -1).flatten(2, 3)

        # Attention: [B, n_heads, L, L]
        q, k, v = [t.transpose(1, 2) for t in (q, k, v)]
        scores = torch.matmul(q, k.transpose(-2, -1)) / (self.head_dim ** 0.5)
        if mask is not None:
            scores = scores + mask
        attn = F.softmax(scores, dim=-1)
        out = torch.matmul(attn, v)  # [B, n_heads, L, head_dim]

        # 合并多头: [B, L, d_model]
        out = out.transpose(1, 2).contiguous().view(B, L, -1)
        return self.wo(out)

SwiGLU FFN 实现

class SwiGLU_FFN(nn.Module):
    """SwiGLU Feed-Forward Network
    
    FFN_SwiGLU(x) = W2 · (Swish(W1·x) ⊙ W3·x)
    其中 Swish(x) = x · sigmoid(x)
    """
    def __init__(self, d_model: int, d_ff: int):
        super().__init__()
        # 注意: SwiGLU 有 3 个权重矩阵
        self.w1 = nn.Linear(d_model, d_ff, bias=False)   # gate projection
        self.w2 = nn.Linear(d_ff, d_model, bias=False)   # down projection
        self.w3 = nn.Linear(d_model, d_ff, bias=False)   # up projection

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        # Swish 激活 = SiLU in PyTorch
        return self.w2(F.silu(self.w1(x)) * self.w3(x))

# 用法示例: 完整的 Transformer Block
class TransformerBlock(nn.Module):
    def __init__(self, d_model: int, n_heads: int, n_kv_heads: int, d_ff: int):
        super().__init__()
        self.attention = GroupedQueryAttention(d_model, n_heads, n_kv_heads)
        self.feed_forward = SwiGLU_FFN(d_model, d_ff)
        self.norm1 = nn.RMSNorm(d_model)  # PyTorch 2.4+
        self.norm2 = nn.RMSNorm(d_model)

    def forward(self, x: torch.Tensor, freqs_cis: torch.Tensor,
                mask: Optional[torch.Tensor] = None) -> torch.Tensor:
        # Pre-Norm + 残差连接
        x = x + self.attention(self.norm1(x), freqs_cis, mask)
        x = x + self.feed_forward(self.norm2(x))
        return x

动手练习:尝试用上面的代码构建一个完整的 LLM 模型。你需要添加 Embedding 层、因果掩码生成、和 LM Head。提示:LM Head 通常与 Embedding 矩阵共享权重(lm_head.weight = embed.weight)。

从论文到工程

理解架构和实现是前两步,但要训练大规模 LLM,还需要一系列工程优化:

  • FlashAttention(Dao et al., 2022):通过 tiling 和内核融合,将 Attention 的内存复杂度从 O(n2)O(n^2) 降到 O(n)O(n)。在实际使用中,只需将上面的手写 attention 替换为 F.scaled_dot_product_attention()(PyTorch 2.0+),即可自动启用 FlashAttention
  • FlashMLA(DeepSeek, 2025):针对 MLA 的高效 CUDA 内核实现,在 H800 上实现 580 TFLOPS 的 decode 吞吐
  • Native Sparse Attention (NSA)(DeepSeek, 2025):原生可训练的稀疏注意力,将压缩 token、选择性 token 和滑动窗口三个分支并行处理,在保持模型质量的同时大幅降低长序列的计算成本。DeepSeek V3.2 已在生产环境使用
  • Multi-Token Prediction (MTP)(DeepSeek V3):训练时同时预测多个未来 token,每个预测头共享主干但有独立的投影层。MTP 不仅加速训练,还可在推理时用于推测解码
  • Fused Kernels:将多个连续操作(如 LayerNorm + Linear)融合为一个 GPU kernel
  • Tensor Parallelism(Megatron-LM):将模型的权重矩阵沿特定维度分割到多个 GPU
  • Mamba Kernel 优化:Prefill 阶段利用 Mamba2 结构特性增强并行性,Decode 阶段 SelectiveScanUpdate Kernel 减轻显存带宽限制,fp32 Mamba 状态精度保证混合架构长文本质量
  • Mixed Precision:使用 BF16/FP8 混合精度训练,同时保持训练稳定性
  • 按阶段差异化(阶段级优化)(2026-10 补):prefill 与 decode 的瓶颈不同——prefill 并行、算力受限;decode 串行、显存带宽受限——因此可以只对其中一个阶段做变换,另一阶段保持原样。两个已落地的实例:① 稀疏注意力:prefill 用稠密、decode 用稀疏(本章 SAS 段已写);② 只在 decode 阶段剪专家(见下)。

上面前八条都是算子级优化(换一个更快的实现),第九条是阶段级优化(换一个不同的计算图)。这一类是 2026 年 serving 侧的主要增量方向,因为它不需要改算子、只需要在 prefill/decode 的边界上做取舍。

实例:只在 decode 阶段剪专家(SlimWise,arXiv:2609.34117)。MoE 解码的瓶颈不是算力而是加载专家权重——单个 token 只碰几个专家,但一批 decode token 几乎会碰遍整个专家池。常规专家剪枝会把算力受限的 prefill 也一起剪掉,于是质量掉了、吞吐却没涨多少。SlimWise 的做法是分阶段:prefill 仍跑全模型并写出 KV cache,50% 剪枝的 decoder 直接复用这份 cache,无需转换(training-free KV cache handoff),再用一个低成本蒸馏步骤教剪枝后的 decoder 从全模型的 KV cache 继续生成(只更新一小部分参数)。在 vLLM 上跑 Qwen3.6-35B-A3B,50% 专家剪枝下解码吞吐最高 1.81×,精度损失很小。

⚠️ 一条容易被指标漏掉的副作用。 SlimWise 的作者明确指出:基准准确率会掩盖剪枝引起的生成长度变化——分数没掉,不等于行为没变。这是本书反复出现的那个判据(“要问指标看不见什么”)在本章的第一个实例:与第二十九章的 judge 偏差、第三十章的崩溃率测量假象是同一条,可以对照读。

⚠️ 限定:SlimWise 为 2026-09 预印本,1.81× 与长度漂移均为论文自报(长度漂移一条已由摘要原文确认)。

这些将在第八章(分布式训练工程)中详细讨论。


📖 延伸阅读路线