无声子夜翩跹指间 谁拾获着散落的碎片 你说忘了吧又回头 不舍得远走 如果你迷失在无明中 我会为你守候 等到春暖花开的时候 都会再度重逢
—— 焚蝶 · 铁痕电台-MSR/Aurora Sky
llama2的架构总算演进到了第三代
题图:《明日方舟:终末地》庄方仪潜能三插图
引子 时值Qwen3.6、DeepSeek-V4相继发布之际,大模型的竞争已从”把参数做大”转向”把结构做巧”——总参数与激活参数解耦,长序列的代价从平方压回线性,推理加速直接做进了权重本身。回望2023年的llama2,它留下的那张图纸依然是今天所有架构的默认值,沿着基线看两代演进,就能看清这三年的路径。看结构是很有必要的。
本文以llama2的结构为基线,逐次展示Qwen3.5-MoE和DeepSeek-V4-Flash相对上一代改了什么、保留了什么。作为读代码比读论文习惯的我,所有维度都直接来自真实的config和权重文件头,不下权重。本文不会介绍训练细节和采样策略,只谈结构。
基线:llama2的结构 以7B为例,我们先看整体——一条直线:
1 2 3 4 5 6 7 input_ids [B,S] ↓ Embedding (32000 → 4096) hidden [B,S,4096] ↓ 32 × TransformerBlock ↓ RMSNorm ↓ lm_head (4096 → 32000) logits [B,S,32000]
每个Block是标准的pre-norm残差结构:
1 2 3 4 5 6 7 8 x ─┬──────────────────┐ ↓ RMSNorm │ 残差 ↓ Attention │ ⊕ ←────────────────┘ ├──────────────────┐ ↓ RMSNorm │ 残差 ↓ SwiGLU FFN │ ⊕ ←────────────────┘
三个组件,逐个看:
注意力 (MHA,70B为GQA):Q/K/V各自线性投影,Q、K做RoPE,因果softmax注意力:
Attention ( Q , K , V ) = softmax ( Q K T d k ) V \text{Attention}(Q,K,V)=\text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V Attention ( Q , K , V ) = softmax ( d k Q K T ) V
其中 Q , K , V ∈ R B × H × S × d h Q,K,V\in\mathbb{R}^{B\times H\times S\times d_h} Q , K , V ∈ R B × H × S × d h 由层输入 x ∈ R B × S × d x\in\mathbb{R}^{B\times S\times d} x ∈ R B × S × d 经 W Q , W K , W V W^Q,W^K,W^V W Q , W K , W V 投影而来(7B:H = 32 H=32 H = 32 、d h = 128 d_h=128 d h = 128 );d k = d h d_k=d_h d k = d h 为缩放维度,S S S 为序列长。
FFN (SwiGLU):
FFN ( x ) = W d o w n ( SiLU ( W g a t e x ) ⊙ W u p x ) \text{FFN}(x) = W_{down}\big(\text{SiLU}(W_{gate}x) \odot W_{up}x\big) FFN ( x ) = W d o w n ( SiLU ( W g a t e x ) ⊙ W u p x )
其中 x ∈ R B × S × d x\in\mathbb{R}^{B\times S\times d} x ∈ R B × S × d 为层输入;W g a t e , W u p ∈ R i n t e r × d W_{gate},W_{up}\in\mathbb{R}^{inter\times d} W g a t e , W u p ∈ R in t er × d 投出门与值,W d o w n ∈ R d × i n t e r W_{down}\in\mathbb{R}^{d\times inter} W d o w n ∈ R d × in t er 降回(7B:d = 4096 d=4096 d = 4096 、i n t e r = 11008 inter=11008 in t er = 11008 )。
中间维11008 ≈ 8 3 × 4096 11008 \approx \frac{8}{3} \times 4096 11008 ≈ 3 8 × 4096 。
归一化 (RMSNorm,子层之前):
RMSNorm ( x ) = x 1 d ∑ i x i 2 + ϵ ⋅ γ \text{RMSNorm}(x) = \frac{x}{\sqrt{\frac{1}{d}\sum_i x_i^2 + \epsilon}} \cdot \gamma RMSNorm ( x ) = d 1 ∑ i x i 2 + ϵ x ⋅ γ
其中 x ∈ R ⋯ × d x\in\mathbb{R}^{\dots\times d} x ∈ R ⋯ × d 为待归一向量,d d d 为 hidden;γ ∈ R d \gamma\in\mathbb{R}^d γ ∈ R d 是可学习缩放,沿最后一维广播;ϵ \epsilon ϵ 防除零。
两个规格:
7B
70B
层数
32
80
hidden
4096
8192
Q头数 / KV头数
32 / 32
64 / 8(GQA)
head_dim
128
128
FFN中间维
11008
28672
上下文
4096
4096
对应总参(逐层累加):
7B:32层 × (注意力 4 × 4096 2 4 \times 4096^2 4 × 409 6 2 + FFN 3 × 4096 × 11008 3 \times 4096 \times 11008 3 × 4096 × 11008 ) + embedding/lm_head 2 × 32000 × 4096 2 \times 32000 \times 4096 2 × 32000 × 4096 ≈ 6.7B
70B:80层 × (注意力 2 × 8192 2 + 2 × 8192 × 1024 2 \times 8192^2 + 2 \times 8192 \times 1024 2 × 819 2 2 + 2 × 8192 × 1024 (GQA) + FFN 3 × 8192 × 28672 3 \times 8192 \times 28672 3 × 8192 × 28672 ) + 2 × 32000 × 8192 2 \times 32000 \times 8192 2 × 32000 × 8192 ≈ 69B
结构上三个特征,后面两代的全部改动都围绕它们:
稠密FFN :每个token激活全部参数
全注意力 :每层都是O ( S 2 ) O(S^2) O ( S 2 ) ,KV cache随序列线性增长
单条残差流 :x ← x + sublayer ( x ) x \leftarrow x + \text{sublayer}(x) x ← x + sublayer ( x )
第一次演进:Qwen3.5-MoE vs llama2 整体形状和llama2一样,还是一条直线——变的只是管子里的维度,外加挂出一个MTP块:
1 2 3 4 5 6 7 8 input_ids [B,S] ↓ Embedding (248320 → 2048) ← 词表32000→248320;视觉特征替换image/video占位 hidden [B,S,2048] ← hidden 4096→2048 ↓ 40 × Block ← 32→40层 ↓ RMSNorm ↓ lm_head (2048 → 248320) logits [B,S,248320] └→ MTP块 (0.84B) ← 新增,投机解码用
Block内部,pre-norm残差的骨架原封不动,两个子层的算子都被换了 :
1 2 3 4 5 6 7 8 x ─┬────────────────────────┐ ↓ RMSNorm │ 残差 ↓ GDN / Full Attention │ ← 换:全注意力 → 混合注意力,3:1交替 ⊕ ←──────────────────────┘ ├────────────────────────┐ ↓ RMSNorm │ 残差 ↓ MoE (256选8 + 1共享) │ ← 换:稠密SwiGLU → MoE ⊕ ←──────────────────────┘
规格:40层,hidden 2048,上下文256K。总参数36B,其中专家权重 40层×256×3×2048×512 ≈ 32.2B,占90%;每token激活约3B ≈ 40层×9个专家×3.15M的FFN(≈1.1B) + 注意力投影(≈1.2B) + embedding/lm_head(2 × 248320 × 2048 2 \times 248320 \times 2048 2 × 248320 × 2048 ≈ 1.0B)。
变化一:稠密FFN → 256选8的MoE llama2每层一个大FFN(4096→11008→4096,3 × 4096 × 11008 ≈ 136 M 3 \times 4096 \times 11008 \approx 136M 3 × 4096 × 11008 ≈ 136 M 参数);Qwen把它拆成256个小专家加1个共享专家,每token只过其中9个。我们看看MoE层内部:
1 2 3 x → router: softmax(W_r x) → top-8 专家编号+权重 ├→ 8个routed专家: SwiGLU(中间维仅512),加权求和 └→ 共享专家: SwiGLU,必过,输出再乘sigmoid门
p = softmax ( W r x ) , I = topk 8 ( p ) , w i = p i ∑ j ∈ I p j p = \text{softmax}(W_r x), \quad I = \text{topk}_8(p), \quad w_i = \frac{p_i}{\sum_{j \in I} p_j} p = softmax ( W r x ) , I = topk 8 ( p ) , w i = ∑ j ∈ I p j p i
其中 x ∈ R T × 2048 x\in\mathbb{R}^{T\times 2048} x ∈ R T × 2048 为展平后的 token(T = B × S T=B\times S T = B × S );W r ∈ R 256 × 2048 W_r\in\mathbb{R}^{256\times 2048} W r ∈ R 256 × 2048 为路由矩阵;p ∈ R T × 256 p\in\mathbb{R}^{T\times 256} p ∈ R T × 256 是逐专家概率;I I I 为选中的 8 个专家号;w i w_i w i 为组内归一化权重。
完整前向——8个routed专家加权求和,再加sigmoid门控的共享专家:
y = ∑ i ∈ I w i ⋅ W d o w n ( i ) ( SiLU ( W g a t e ( i ) x ) ⊙ W u p ( i ) x ) + σ ( g s ( x ) ) ⋅ shared ( x ) y = \sum_{i \in I} w_i \cdot W_{down}^{(i)}\Big(\text{SiLU}\big(W_{gate}^{(i)}x\big) \odot W_{up}^{(i)}x\Big) + \sigma(g_s(x)) \cdot \text{shared}(x) y = i ∈ I ∑ w i ⋅ W d o w n ( i ) ( SiLU ( W g a t e ( i ) x ) ⊙ W u p ( i ) x ) + σ ( g s ( x )) ⋅ shared ( x )
其中 W g a t e ( i ) , W u p ( i ) ∈ R 512 × 2048 W_{gate}^{(i)},W_{up}^{(i)}\in\mathbb{R}^{512\times 2048} W g a t e ( i ) , W u p ( i ) ∈ R 512 × 2048 、W d o w n ( i ) ∈ R 2048 × 512 W_{down}^{(i)}\in\mathbb{R}^{2048\times 512} W d o w n ( i ) ∈ R 2048 × 512 为第 i i i 个专家的 SwiGLU 权重;g s ( x ) ∈ R T × 1 g_s(x)\in\mathbb{R}^{T\times 1} g s ( x ) ∈ R T × 1 为共享专家 sigmoid 门;shared ( x ) ∈ R T × 2048 \text{shared}(x)\in\mathbb{R}^{T\times 2048} shared ( x ) ∈ R T × 2048 为共享专家输出。
权重布局上,256个专家融合成两个大张量,按专家号索引:
W g u ∈ R 256 × 1024 × 2048 , W d o w n ∈ R 256 × 2048 × 512 W_{gu} \in \mathbb{R}^{256 \times 1024 \times 2048}, \quad W_{down} \in \mathbb{R}^{256 \times 2048 \times 512} W g u ∈ R 256 × 1024 × 2048 , W d o w n ∈ R 256 × 2048 × 512
其中第一维 256 为专家号,按号索引;1024 = 2 × 512 1024=2\times 512 1024 = 2 × 512 是 gate|up 拼接;2048 为 hidden;512 为专家中间维。
一层约840M参数里专家占 256 × 3 × 2048 × 512 = 805 M 256 \times 3 \times 2048 \times 512 = 805M 256 × 3 × 2048 × 512 = 805 M (96%),但每token只算约28M = ( 8 + 1 ) × 3 × 2048 × 512 (8+1) \times 3 \times 2048 \times 512 ( 8 + 1 ) × 3 × 2048 × 512 。防坍缩靠辅助损失:f i f_i f i 是专家实际分到的token比例,P i P_i P i 是路由器给它的平均概率:
L a u x = α ⋅ N ⋅ ∑ i f i ⋅ P i L_{aux} = \alpha \cdot N \cdot \sum_i f_i \cdot P_i L a ux = α ⋅ N ⋅ i ∑ f i ⋅ P i
其中 α = 0.001 \alpha=0.001 α = 0.001 为损失系数;N = 256 N=256 N = 256 为专家数;f i f_i f i 为专家 i i i 实际分到的 token 比例(top-k 选出,不可导);P i P_i P i 为路由器给 i i i 的平均 softmax 概率(可导,梯度由此进入)。
变化二:全注意力 → 混合注意力(3线性+1全) llama2每层都是全注意力;Qwen把40层排成”3层线性注意力+1层全注意力”的循环,全注意力只在层3, 7, …, 39:
1 2 层0 层1 层2 层3 层4 层5 层6 层7 GDN GDN GDN Full GDN GDN GDN Full ...
线性注意力层是Gated DeltaNet:没有注意力矩阵,维护固定大小的记忆矩阵S ∈ R 32 × 128 × 128 S \in \mathbb{R}^{32 \times 128 \times 128} S ∈ R 32 × 128 × 128 (约0.5M个状态单元,是状态不是权重),逐token递推:
S t = e g t ⋅ S t − 1 + β t k t ( v t − S t − 1 ⊤ k t ) ⊤ S_t = e^{g_t} \cdot S_{t-1} + \beta_t k_t (v_t - S_{t-1}^\top k_t)^\top S t = e g t ⋅ S t − 1 + β t k t ( v t − S t − 1 ⊤ k t ) ⊤
其中 S t ∈ R 32 × 128 × 128 S_t\in\mathbb{R}^{32\times 128\times 128} S t ∈ R 32 × 128 × 128 为记忆矩阵(32 个 V 头,各 128 × 128 128\times 128 128 × 128 );k t , v t ∈ R 32 × 128 k_t,v_t\in\mathbb{R}^{32\times 128} k t , v t ∈ R 32 × 128 (16 个 K 头复制一倍对齐 V 头);g t , β t ∈ R 32 g_t,\beta_t\in\mathbb{R}^{32} g t , β t ∈ R 32 为逐头衰减与写入强度标量。
o t = S t ⊤ q t o_t = S_t^\top q_t o t = S t ⊤ q t
其中 q t ∈ R 32 × 128 q_t\in\mathbb{R}^{32\times 128} q t ∈ R 32 × 128 为 query 头;o t ∈ R 32 × 128 o_t\in\mathbb{R}^{32\times 128} o t ∈ R 32 × 128 为逐 token 读出的注意力输出。
完整实现——QKV一次投出过kernel=4的因果卷积,衰减与写入强度来自标量投影,输出再过门:
[ q t , k t , v t ] = SiLU ( Conv1d 4 ( W q k v x t ) ) , z t = W z x t [q_t, k_t, v_t] = \text{SiLU}\big(\text{Conv1d}_4(W_{qkv}x_t)\big), \quad z_t = W_z x_t [ q t , k t , v t ] = SiLU ( Conv1d 4 ( W q k v x t ) ) , z t = W z x t
其中 W q k v ∈ R 8192 × 2048 W_{qkv}\in\mathbb{R}^{8192\times 2048} W q k v ∈ R 8192 × 2048 一次投出 Q|K|V(2048|2048|4096),过 kernel=4 因果卷积;W z ∈ R 4096 × 2048 W_z\in\mathbb{R}^{4096\times 2048} W z ∈ R 4096 × 2048 投出输出门 z t z_t z t 。
g t = − exp ( A ) ⋅ softplus ( W a x t + Δ ) , β t = σ ( W b x t ) g_t = -\exp(A) \cdot \text{softplus}(W_a x_t + \Delta), \quad \beta_t = \sigma(W_b x_t) g t = − exp ( A ) ⋅ softplus ( W a x t + Δ ) , β t = σ ( W b x t )
其中 A , Δ ∈ R 32 A,\Delta\in\mathbb{R}^{32} A , Δ ∈ R 32 为逐头可学习衰减参数;W a , W b ∈ R 32 × 2048 W_a,W_b\in\mathbb{R}^{32\times 2048} W a , W b ∈ R 32 × 2048 为标量投影。
out t = W o u t ( RMSNorm ( o t ) ⊙ SiLU ( z t ) ) \text{out}_t = W_{out}\big(\text{RMSNorm}(o_t) \odot \text{SiLU}(z_t)\big) out t = W o u t ( RMSNorm ( o t ) ⊙ SiLU ( z t ) )
其中 W o u t ∈ R 2048 × 4096 W_{out}\in\mathbb{R}^{2048\times 4096} W o u t ∈ R 2048 × 4096 把逐头输出拼回 hidden;门控 SiLU ( z t ) \text{SiLU}(z_t) SiLU ( z t ) 逐头相乘。
g t g_t g t 是每头衰减系数,
β t \beta_t β t 是写入强度——带遗忘的纠错式记忆。序列多长状态都不变,decode成本恒定。这就是对llama2"KV cache线性增长"的回应:30层不再产生KV cache。
变化三:保留的10层全注意力也加强了 相对llama2的MHA/GQA:
输出门控 :q_proj输出双倍,一半是Q、一半是gate,注意力输出先乘sigmoid ( g a t e ) \text{sigmoid}(gate) sigmoid ( g a t e ) 再进o_proj
部分RoPE :head_dim=256只旋转前64维,其余192维位置无关(llama2是全维旋转)
强GQA :16个Q头共享2个KV头(8:1),比llama2-70B的64/8更激进
完整实现——q_proj投出双倍维度拆成Q和gate,RoPE只旋转前64维(RoPE 64 \text{RoPE}_{64} RoPE 64 ),KV的2个头复制8份对齐Q头:
Q , g = split ( W q x ) , Q ~ = RoPE 64 ( Q ) , K ~ = RoPE 64 ( W k x ) Q, g = \text{split}(W_q x), \quad \tilde Q = \text{RoPE}_{64}(Q), \quad \tilde K = \text{RoPE}_{64}(W_k x) Q , g = split ( W q x ) , Q ~ = RoPE 64 ( Q ) , K ~ = RoPE 64 ( W k x )
其中 W q ∈ R 8192 × 2048 W_q\in\mathbb{R}^{8192\times 2048} W q ∈ R 8192 × 2048 输出双倍,拆成 Q ∈ R 16 × 256 Q\in\mathbb{R}^{16\times 256} Q ∈ R 16 × 256 (每 token)与门 g g g ;W k ∈ R 512 × 2048 W_k\in\mathbb{R}^{512\times 2048} W k ∈ R 512 × 2048 (2 KV 头×256);RoPE 64 \text{RoPE}_{64} RoPE 64 只旋转前 64 维。
Attn ( x ) = W o ( softmax ( Q ~ K ~ ⊤ 256 ) V ~ ⊙ σ ( g ) ) \text{Attn}(x) = W_o\Big( \text{softmax}\big(\tfrac{\tilde Q \tilde K^\top}{\sqrt{256}}\big)\tilde V \odot \sigma(g) \Big) Attn ( x ) = W o ( softmax ( 256 Q ~ K ~ ⊤ ) V ~ ⊙ σ ( g ) )
其中 V ~ \tilde V V ~ 由 2 个 KV 头复制 8 份对齐 16 个 Q 头;σ ( g ) ∈ R B × S × 4096 \sigma(g)\in\mathbb{R}^{B\times S\times 4096} σ ( g ) ∈ R B × S × 4096 为输出门;W o ∈ R 2048 × 4096 W_o\in\mathbb{R}^{2048\times 4096} W o ∈ R 2048 × 4096 。
这10层每层的投影参数约27M:q_proj 2048 × 8192 2048 \times 8192 2048 × 8192 (含输出门) + k/v_proj 2 × 2048 × 512 2 \times 2048 \times 512 2 × 2048 × 512 + o_proj 4096 × 2048 4096 \times 2048 4096 × 2048 。
变化四:新增MTP与多模态 checkpoint里多了一个MTP块(0.84B ≈ 一层全注意力约27M + 一层MoE约809M):主干最终hidden与下一token的embedding拼接后,再过一层注意力+MoE,预测更后面的token,用于投机解码。另外加了ViT视觉编码器(约0.45B:27层×(4 × 1152 2 + 2 × 1152 × 4608 4 \times 1152^2 + 2 \times 1152 \times 4608 4 × 115 2 2 + 2 × 1152 × 4608 ) ≈ 0.43B,加patch嵌入与merger),embedding层的image/video占位位置由视觉特征替换。
MTP前向——h t h_t h t 是主干最后一层输出,e t + 1 e_{t+1} e t + 1 是下一token的embedding(与主干共享):
h t m t p = Block ( W f c [ h t ; e t + 1 ] ) , x ^ t + 2 = W l m h t m t p h^{mtp}_t = \text{Block}\big( W_{fc}[\,h_t \,;\, e_{t+1}\,] \big), \quad \hat x_{t+2} = W_{lm}\, h^{mtp}_t h t m tp = Block ( W f c [ h t ; e t + 1 ] ) , x ^ t + 2 = W l m h t m tp
其中 h t ∈ R B × S × 2048 h_t\in\mathbb{R}^{B\times S\times 2048} h t ∈ R B × S × 2048 为主干末层输出;e t + 1 ∈ R B × S × 2048 e_{t+1}\in\mathbb{R}^{B\times S\times 2048} e t + 1 ∈ R B × S × 2048 为下一 token 的 embedding(与主干共享);W f c ∈ R 2048 × 4096 W_{fc}\in\mathbb{R}^{2048\times 4096} W f c ∈ R 2048 × 4096 把拼接 [ ; ] [\,;\,] [ ; ] 降回 hidden;W l m ∈ R 248320 × 2048 W_{lm}\in\mathbb{R}^{248320\times 2048} W l m ∈ R 248320 × 2048 出 logits。
第二次演进:DeepSeek-V4-Flash vs Qwen3.5-MoE 这次连”一条直线”的形状都变了——单条残差流被拆成4条并行流(mHC) ,首尾各多一个折叠/展开算子:
1 2 3 4 5 6 7 8 9 input_ids [B,S] ↓ Embedding (129280 → 4096) ← 词表248320→129280;hidden 2048→4096 streams [B,S,4,4096] ← 新增:单流 → 4流mHC ↓ 43 × Block ↓ HyperHead (4流 → 1流) ← 新增 ↓ RMSNorm ↓ lm_head (4096 → 129280) logits [B,S,129280] └→ MTP + DSpark ← 新增
Block内部,pre-norm残差还在,但每个子层被mHC包了一层”4流折叠→计算→写回”:
1 2 3 4 5 6 7 8 9 10 streams[4流] ─┬──────────────────────────┐ ↓ attn_hc 折叠 (4流→1流) │ mHC写回 ↓ RMSNorm │ ↓ 滑窗 / CSA / HCA 压缩注意力 │ ← 换:递归GDN → 压缩+检索 ⊕ ←──────────────────────────────────┘ ├──────────────────────────┐ ↓ ffn_hc 折叠 (4流→1流) │ mHC写回 ↓ RMSNorm │ ↓ MoE (256选6 + 1共享) │ ← 换:选8→选6,辅助损失→无损失,前3层hash ⊕ ←──────────────────────────────────┘
规格:43层,hidden 4096,上下文1M,以FP8+专家FP4发布。总参数304B,其中专家权重 43层×256×3×4096×2048 ≈ 277B,占91%。
变化一:token mixer从递推换成压缩+检索 Qwen的30层递归状态在DeepSeek这里完全消失,43层全是”滑动窗口+压缩KV”的注意力:
1 2 层0 层1 层2 层3 层4 层5 ... 层42 滑窗 滑窗 CSA HCA CSA HCA ... CSA
滑窗层 (2层):只看局部128个token
CSA层 (21层):每4个token门控加权压成1条KV——1M上下文会产生26万条,所以配一个Lightning Indexer 支路(每层约11M参数:2 × 4096 × 256 2 \times 4096 \times 256 2 × 4096 × 256 压缩投影 + 1024 × 8192 1024 \times 8192 1024 × 8192 query投影 + 4096 × 64 4096 \times 64 4096 × 64 头权重),给每个query打分挑top-512:
s w = ∑ h w h ⋅ ReLU ( q h ⊤ K w ) s_w = \sum_h w_h \cdot \text{ReLU}(q_h^\top K_w) s w = h ∑ w h ⋅ ReLU ( q h ⊤ K w )
其中 q h ∈ R 128 q_h\in\mathbb{R}^{128} q h ∈ R 128 为第 h h h 个 index 头的 query(共 64 头,由 Q 低秩中间量 u u u 投出);K w ∈ R 128 K_w\in\mathbb{R}^{128} K w ∈ R 128 为第 w w w 条压缩 key;w h w_h w h 为头重要性(由 x x x 投出,∈ R 64 \in\mathbb{R}^{64} ∈ R 64 )。
HCA层 (20层):每128个token压成1条,1M上下文只有约8192条,全量可见
压缩本身是窗内softmax门控凸组合,CSA用交叠窗(上一窗C a C_a C a ⊕ 本窗C b C_b C b 共8槽)避免硬切边界。对比Qwen的路线:一个把历史递推成固定状态,一个把历史压成可检索的条目。
压缩的完整实现——窗内成员按门控权重做凸组合,p t m o d R p_{t \bmod R} p t mod R 是窗内位置偏置:
c w = RMSNorm ( ∑ t ∈ w i n w α t ⊙ k v t ) , α t = softmax t ( g a t e t + p t m o d R ) c_w = \text{RMSNorm}\Big(\sum_{t \in win_w} \alpha_t \odot kv_t\Big), \quad \alpha_t = \text{softmax}_t\big(gate_t + p_{t \bmod R}\big) c w = RMSNorm ( t ∈ w i n w ∑ α t ⊙ k v t ) , α t = softmax t ( g a t e t + p t mod R )
其中 k v t , g a t e t ∈ R 512 kv_t,gate_t\in\mathbb{R}^{512} k v t , g a t e t ∈ R 512 为窗内每 token 的内容与门(各由一个 512 × 4096 512\times 4096 512 × 4096 投影投出);p t m o d R ∈ R 512 p_{t\bmod R}\in\mathbb{R}^{512} p t mod R ∈ R 512 为窗内位置偏置;α t \alpha_t α t 为窗内 softmax 权重(和为 1);c w ∈ R 512 c_w\in\mathbb{R}^{512} c w ∈ R 512 为压缩条目;R = 4 R=4 R = 4 (CSA)或 128 128 128 (HCA)。
压缩条目在窗位置w R wR w R 上做RoPE后,与滑窗KV拼接参与注意力;CSA层再把可见集限制到indexer选出的top-512:I ( q ) = topk 512 ( s ( q ) ) \mathcal{I}^{(q)} = \text{topk}_{512}(s^{(q)}) I ( q ) = topk 512 ( s ( q ) ) 。
变化二:注意力本体——K==V、低秩、门控sink Qwen的全注意力层还是经典形状(Q/K/V分开,16头),DeepSeek的注意力本体激进得多:
K==V :只有1个KV头,同一张量既当K又当V,KV cache压到极致;代价是输出要做一次共轭旋转抵消V上的RoPE
Q两段低秩 :4096 → 1024 → 64 × 512 4096 \to 1024 \to 64 \times 512 4096 → 1024 → 64 × 512 ;输出分组低秩投回:64头拆8组各4096 → 1024 4096 \to 1024 4096 → 1024 ,拼成8192再混合回4096
可学习sink :softmax里每头加一列”垃圾桶”logit,概率算完即丢,稳定长上下文注意力
完整实现——Q两段低秩,K/V共享一个投影,sink列s s s 进softmax分母后丢弃,RoPE − \text{RoPE}_{-} RoPE − 表示在query位置用− sin -\sin − sin 的共轭旋转:
u = RMSNorm ( W q a x ) , Q = W q b u ∈ R 64 × 512 , K = V = RMSNorm ( W k v x ) ∈ R 512 u = \text{RMSNorm}(W_{qa}x), \quad Q = W_{qb}u \in \mathbb{R}^{64 \times 512}, \quad K = V = \text{RMSNorm}(W_{kv}x) \in \mathbb{R}^{512} u = RMSNorm ( W q a x ) , Q = W q b u ∈ R 64 × 512 , K = V = RMSNorm ( W k v x ) ∈ R 512
其中 x ∈ R B × S × 4096 x\in\mathbb{R}^{B\times S\times 4096} x ∈ R B × S × 4096 为层输入;W q a ∈ R 1024 × 4096 W_{qa}\in\mathbb{R}^{1024\times 4096} W q a ∈ R 1024 × 4096 、W q b ∈ R 32768 × 1024 W_{qb}\in\mathbb{R}^{32768\times 1024} W q b ∈ R 32768 × 1024 为 Q 的两段低秩(32768 = 64 × 512 32768=64\times 512 32768 = 64 × 512 );W k v ∈ R 512 × 4096 W_{kv}\in\mathbb{R}^{512\times 4096} W k v ∈ R 512 × 4096 为单 KV 头投影,K 与 V 共用。
p j = exp ( z j ) ∑ j ′ exp ( z j ′ ) + exp ( s ) , o = RoPE − ( ∑ j p j v j ) p_j = \frac{\exp(z_j)}{\sum_{j'} \exp(z_{j'}) + \exp(s)}, \quad o = \text{RoPE}_{-}\Big(\sum_j p_j v_j\Big) p j = ∑ j ′ exp ( z j ′ ) + exp ( s ) exp ( z j ) , o = RoPE − ( j ∑ p j v j )
其中 z j z_j z j 为第 j j j 个 key 的注意力 logit;s s s 为可学习 sink 标量(每头一个),进分母后该列被丢弃;v j v_j v j 即 K j K_j K j (K==V);RoPE − \text{RoPE}_{-} RoPE − 为共轭旋转。
分组低秩输出投影(8组各4096 → 1024 4096 \to 1024 4096 → 1024 ,拼接后混合):
out = W o b [ G 1 o 1 ; G 2 o 2 ; … ; G 8 o 8 ] \text{out} = W_{ob}\big[\,G_1 o_1 \,;\, G_2 o_2 \,;\, \dots \,;\, G_8 o_8\,\big] out = W o b [ G 1 o 1 ; G 2 o 2 ; … ; G 8 o 8 ]
其中 o i ∈ R 4096 o_i\in\mathbb{R}^{4096} o i ∈ R 4096 为第 i i i 组(64 头拆 8 组,每组 8 头×512)的注意力输出;G i ∈ R 1024 × 4096 G_i\in\mathbb{R}^{1024\times 4096} G i ∈ R 1024 × 4096 为组内降秩;W o b ∈ R 4096 × 8192 W_{ob}\in\mathbb{R}^{4096\times 8192} W o b ∈ R 4096 × 8192 把拼接结果混合回 hidden。
输出投影的参数量对比:直接投 32768 × 4096 ≈ 134 M 32768 \times 4096 \approx 134M 32768 × 4096 ≈ 134 M ;分组低秩 8 × 4096 × 1024 + 8192 × 4096 ≈ 67 M 8 \times 4096 \times 1024 + 8192 \times 4096 \approx 67M 8 × 4096 × 1024 + 8192 × 4096 ≈ 67 M ,省一半。
变化三:残差从单流变4流(mHC) llama2和Qwen都是单条残差x ← x + sublayer ( x ) x \leftarrow x + \text{sublayer}(x) x ← x + sublayer ( x ) ;DeepSeek把它扩成4条并行流,每个子层动态决定读哪些流、输出写回哪些流。折叠与三组系数都由当前流内容经一个线性层动态算出:
x = ∑ i p r e i S i , p r e i = σ ( ⋅ ) + ϵ , p o s t i = 2 σ ( ⋅ ) ∈ [ 0 , 2 ] x = \sum_i pre_i S_i, \quad pre_i = \sigma(\cdot) + \epsilon, \quad post_i = 2\sigma(\cdot) \in [0,2] x = i ∑ p r e i S i , p r e i = σ ( ⋅ ) + ϵ , p os t i = 2 σ ( ⋅ ) ∈ [ 0 , 2 ]
其中 S i ∈ R B × S × 4096 S_i\in\mathbb{R}^{B\times S\times 4096} S i ∈ R B × S × 4096 为第 i i i 条残差流(共 4 条);p r e i , p o s t i pre_i,post_i p r e i , p os t i 为逐 token 标量系数,由 4 流拼平(16384 16384 16384 维)经一个 24 × 16384 24\times 16384 24 × 16384 线性层动态算出。
C = Sinkhorn ( softmax ( ⋅ ) ) , o = Sublayer ( RMSNorm ( x ) ) C = \text{Sinkhorn}\big(\text{softmax}(\cdot)\big), \quad o = \text{Sublayer}\big(\text{RMSNorm}(x)\big) C = Sinkhorn ( softmax ( ⋅ ) ) , o = Sublayer ( RMSNorm ( x ) )
其中 C ∈ R 4 × 4 C\in\mathbb{R}^{4\times 4} C ∈ R 4 × 4 为流间混合矩阵(同一线性层的 16 个输出经 softmax+Sinkhorn);o o o 为折叠单流 x x x 过子层(注意力或 MoE)的输出。
回写规则:
S k n e w = p o s t k ⋅ o + ∑ j C j , k S j S^{new}_k = post_k \cdot o + \sum_j C_{j,k} S_j S k n e w = p os t k ⋅ o + j ∑ C j , k S j
其中 p o s t k ⋅ o post_k\cdot o p os t k ⋅ o 把子层输出按强度写回第 k k k 条流;∑ j C j , k S j \sum_j C_{j,k} S_j ∑ j C j , k S j 为旧流的双随机混合。
混合矩阵C C C 经20次Sinkhorn迭代投影成双随机矩阵,于是∣ C ∣ 2 ≤ ∣ C ∣ 1 ∣ C ∣ ∞ = 1 |C|_2 \le \sqrt{|C|_1 |C|_\infty} = 1 ∣ C ∣ 2 ≤ ∣ C ∣ 1 ∣ C ∣ ∞ = 1 ——86个子层复合下来残差路径非膨胀,这是深堆叠训练的骨架级保险。代价很小:每个HC位 24 × 16384 ≈ 0.4 M 24 \times 16384 \approx 0.4M 24 × 16384 ≈ 0.4 M 参数,全模型2位×43层 ≈ 34M;换来的是残差激活内存×4。
变化四:路由从辅助损失换成无损失纠偏 Qwen靠L a u x L_{aux} L a ux 均衡专家;DeepSeek的noaux_tc不用辅助损失:打分用softplus \sqrt{\text{softplus}} softplus ,选择时加专家纠偏偏置b b b ,加权时用原始分:
σ = softplus ( W r x ) , I = topk 6 ( σ + b ) , w ∝ σ I \sigma = \sqrt{\text{softplus}(W_r x)}, \quad I = \text{topk}_6(\sigma + b), \quad w \propto \sigma_I σ = softplus ( W r x ) , I = topk 6 ( σ + b ) , w ∝ σ I
其中 W r ∈ R 256 × 4096 W_r\in\mathbb{R}^{256\times 4096} W r ∈ R 256 × 4096 为路由矩阵;σ ∈ R T × 256 \sigma\in\mathbb{R}^{T\times 256} σ ∈ R T × 256 为 sqrtsoftplus 打分;b ∈ R 256 b\in\mathbb{R}^{256} b ∈ R 256 为专家纠偏偏置(只影响选择);I I I 为 top-6 专家号;加权 w w w 用不含 b b b 的原始分 σ I \sigma_I σ I 。
另外前3层用hash路由 :选哪些专家由冻结表tid2eid [ input_id ] \text{tid2eid}[\text{input\_id}] tid2eid [ input_id ] 直接查,权重仍是学习的——浅层词面特征按token静态分工,换可预测的访存和天然负载均衡:
I = tid2eid [ input_id ] , w j ∝ σ I j I = \text{tid2eid}[\text{input\_id}], \quad w_j \propto \sigma_{I_j} I = tid2eid [ input_id ] , w j ∝ σ I j
其中 tid2eid ∈ Z 129280 × 6 \text{tid2eid}\in\mathbb{Z}^{129280\times 6} tid2eid ∈ Z 129280 × 6 为冻结查找表,由 token id 直接查出 6 个专家号(不依赖 x x x );σ I j \sigma_{I_j} σ I j 为路由在这些专家上的原始分,仍由 W r x W_r x W r x 学习。
两种路由的矩阵都只有 256 × 4096 ≈ 1 M 256 \times 4096 \approx 1M 256 × 4096 ≈ 1 M /层;tid2eid \text{tid2eid} tid2eid 是 129280 × 6 129280 \times 6 129280 × 6 的冻结查找表,不计入可学习参数。
变化五:推理与精度做进权重 Qwen的MTP之外,DeepSeek加了DSpark:用主干最后3层特征+低秩Markov结构按块草拟,草稿与目标同checkpoint。目标模型验证草稿token按拒绝采样接受——生成必须串行,但验证可以并行,一次forward给全部候选打分:
以概率 min ( 1 , p t a r g e t ( d i ) p d r a f t ( d i ) ) 接受草稿 d i \text{以概率} \min\Big(1, \frac{p_{target}(d_i)}{p_{draft}(d_i)}\Big) \text{接受草稿} d_i 以概率 min ( 1 , p d r a f t ( d i ) p t a r g e t ( d i ) ) 接受草稿 d i
其中 d i d_i d i 为草稿模型第 i i i 个候选 token;p d r a f t ( d i ) p_{draft}(d_i) p d r a f t ( d i ) 为草稿给它的概率;p t a r g e t ( d i ) p_{target}(d_i) p t a r g e t ( d i ) 为目标模型一次 forward 在对应位置并行算出的概率;第一个被拒位置之后的草稿全部丢弃。
发布精度也从bf16变成FP8(e4m3,128×128块)+专家FP4,SwiGLU里的± 10 \pm 10 ± 10 clamp就是低精度的数值护栏。
总结 三代结构摆在一起:
llama2-70B
Qwen3.5-MoE
DeepSeek-V4-Flash
总参数 / 激活
70B稠密
36B / 约3B
304B / 远小于总参
上下文
4096
256K
1M
token mixer
全注意力×全部层
30层GDN递归+10层门控全注意力
滑窗+CSA/HCA压缩+indexer
KV cache
全层线性增长
仅10层有
低秩+逐层压缩
FFN
稠密SwiGLU
256选8,辅助损失
256选6,noaux_tc,前3层hash
残差
单流
单流
4流mHC
投机解码
无
MTP
MTP+DSpark
发布精度
bf16
bf16
FP8+FP4
三条趋势:
从全激活到按需激活 :MoE把容量和成本拆开
从全注意力到两条稀疏路线 :递推压缩(Qwen)或条目检索(DeepSeek),都在回答”长序列里大部分token不值得O ( S 2 ) O(S^2) O ( S 2 ) 的注视”
推理优化架构化 :MTP、DSpark、量化从部署技巧变成训练时的一等公民
Don’t you get there? It calls, it calls, 我盼你凯旋 念念不忘, 仰いだ空が色を変えるから, 曾日复仰望的天空新彩焕然, My naked heart can hear echoes, echoes, 这露骨心声 终闻回响, 識らず求めた Avidity, 却仍不知不觉地切盼, Whisper your name again, 不甘低喃你名字, Then restart it right away, 念完一次又一次, Oh my bitter color ardor wander, 我的痛苦 欢愉 热情 犹疑, Gotta feel it undercover, 只有暗暗藏于心底, 行方も知らない あの日の群青, 那天奔赴战场的你 至今下落仍是不明。
—— SawanoHiroyuki[nZk] / 瑞葵(mizuki)《Avid》
Reference