更大更省:MoE、线性/稀疏注意力与长上下文
主线定位
点任一已学环节,看这一步的输入 → 输出形状、参数量,以及它解决了什么问题(数字取自 Qwen/Qwen3.8-27B 真实 config)。
- 上游 · C10 并行:一张卡放不下、算不完的模型,切到很多张卡上跑起来了。C10 的岔路 2 已经讲了 MoE 的专家怎么跨卡放、token 怎么用 all-to-all 送过去。
- 本章:想要更多参数、更长上下文,但每个 token 的计算和显存不能跟着等比例涨。三条线:FFN 拆成专家、每个 token 只算其中几个(MoE,第 1–3 课);注意力改成固定大小的状态或只读一部分(线性 / 稀疏注意力,第 4–5 课,锚点 Qwen3.8 的另外 48 层在这里揭晓);训练时先短后长(第 6 课)。
- 下游 · C12 后训练:模型会续写、能读长文,可它只会续写。怎么让它听话、推理、做事,是下一章的事。
贯穿例句仍是「小明把苹果给了小王」,Qwen3.8 真 tokenizer 切成 5 个 token:小明 · 把 · 苹果 · 给了 · 小王。它在第 1、3、4 课和岔路课里被继续加工;负载均衡、稀疏注意力和长度课程这三件事要么是整批统计量、要么只在长序列上才有意义,那几课会写明为什么换例子。
本章问题链
每一课只回答一个问题;上一课的失败,逼出下一课的问题。
| 课 | 这一课的问题 | 朴素方案在哪个真数字上失败 | 一句话 |
|---|---|---|---|
| 第 1 课 | 更多参数,但不要更多算力? | dense 放大到 2.4T:每 token 前向约 4.84 TFLOPs,是锚点 27B 的 94 倍 | MoE 让容量跟着专家总数涨、每 token 的计算只跟着 k 涨;但所有专家的权重都得常驻显存 |
| 第 2 课 | 专家为什么抢活、闲置? | 不做均衡的微训练:一个专家拿走 74.4% 的 token,两个几乎为 0 | 路由会自我强化地偏心;偏置只改「选谁」、不碰梯度;统计范围比「用不用 loss」更要紧 |
| 第 3 课 | 专家该大还是小? | 16 选 2 只有 120 种组合 | 专家切细,同样的参数和计算拼出多得多的组合;共享专家不是共识 |
| 第 4 课 | 长文本的 KV 还能再压吗?(揭晓另外 48 层) | 只加不减的线性注意力:同一个键写两次,读回两个值之和 | 先擦后写、每步衰减的固定状态;锚点 3:1 把 KV 降到 1/4,代价是容量有限 |
| 第 5 课 | 稀疏注意力省了什么,没省什么? | DSA 只读 2,048 条,KV 一条不少:每 token 48,068 字节 | 按内容挑 top-k 省计算不省 KV;要省内存得压序列、压层、压精度 |
| 第 6 课 | 训练 4K,使用 128K? | 从头长训:64 层全注意力在 128K 时每 token 训练成本是 4K 时的 2.95 倍 | 先在短序列上学语言,最后用很少的 token 把长度拉上去;注意力变便宜后,课程也在缩短 |
| 岔路 | 只预测下一个 token,是不是太短视? | — | MTP 让每个位置多学一个更远的目标,推理时还能当草稿;它是可以拆掉的辅助项 |
| 实验课 | 4 个专家在我们自己的模型上抢活吗? | — | 同一模型只改均衡方式:先预测,再看负载与 loss,连同比较口径一起报告 |
演进地图
① 更多参数,不要更多算力(MoE)
- 解决了结构最简单:所有参数对每个 token 都生效。卡在锚点 Qwen3.8-27B 每 token 前向约 51.2 GFLOPs;同家族 2.4T 规模若是 dense,约 4.84 TFLOPs(94 倍)。
- 解决了每个 token 只算 top-k 个专家:Qwen3.8-2.4T-A95B 每 token 约 186.5 GFLOPs,是同参数 dense 的 26 分之一。卡在路由会自我强化地偏心:8 个专家全挤到 1 个时,Switch 负载损失从 0.01 升到 0.08;所有专家的权重仍要常驻显存。
- 解决了把「均衡」写进 loss,路由器被梯度推向均匀。卡在α 难调:太小拉不平,太大干扰主 loss(Switch 在 10⁻¹ 到 10⁻⁵ 之间扫;Wang 2024 的出发点)。
- 解决了偏置只改「选谁」,不进门控、不产生干扰梯度;DeepSeek-V3 前 14.3T token 用 γ = 0.001,最后 500B 设为 0。卡在固定步长在近千个专家时太慢或来回震荡(Kimi K3 报告)→ Quantile Balancing;而且统计范围(整批 vs 单条序列)比「有没有 loss」更要紧。
- 解决了同参数同计算,16 选 2 的 120 种组合变成 64 选 8 的 4,426,165,368 种;共享专家装公共知识。卡在显存账不减:Qwen3.8-2.4T 路由专家占主干参数 97.98%,BF16 权重 4.89 TB。
- 解决了Qwen3.8-2.4T 512 选 10 + 1 共享;K3 896 选 16 + LatentMoE + Quantile Balancing;V4.1 图文两套偏置。卡在共享专家 0、1、2 个都有人用(Qwen3 一个不设),稀疏度从 32 到 64 都有(GLM-5.3 与 V3 为 32、GLM-5.3-Flash 36、K2 48、Qwen3.8 51、K3 56、V4.1-Flash 64)——都是实验选择。
② 长文本:KV 与计算不再随长度等比例涨
- 解决了每个 token 都能精确回看任意一个前文 token。卡在KV ∝ 长度:锚点若 64 层全是全注意力,262,144 token 时 64 GiB。
- 解决了去掉 softmax,求和提前累加成一个固定大小的状态,与长度无关。卡在只加不减:同一个键写两次,读回的是两个值之和;状态最多装 d 对互不干扰的键值(C0 岔路)。
- 解决了写前先擦(delta)、每步衰减(门):锚点 48 层状态共 144 MiB(FP32)、与长度无关;KV 降到四分之一(262,144 时 16 GiB 对 64 GiB)。卡在剩下四分之一的全注意力层仍按长度涨;容量有限,3:1 是实验选出来的。
- 解决了每通道一个衰减;g_min = −5 让 16 token 块内累积不低于 −80,e⁸⁰ ≈ 5.5 × 10³⁴ 在 BF16 范围内(上限约 3.4 × 10³⁸),慢路径删除。卡在MiniMax M1 用线性混合、M2 又退回全注意力:大规模下多跳推理缺陷、训练受访存限制、低精度与缓存难题(官方博客)。
- 解决了lightning indexer 每个 query 只挑 top-2048 条做核心注意力。卡在省计算不省内存:KV 一条不少,每 token 48,068 B;indexer 本身仍要扫全部前文。
- 解决了V3.2 每 token 48,068 B → V4-Flash 3,514 B → V4.1-Flash 890 B(1M 时 0.87 GiB)。卡在是近似:V4.1 自陈 Bounded Replay「数学上不等价」、选择误差可能在未测过的边界情况退化。
③ 训练 4K,使用 128K
- 解决了训练与使用同一个长度,不需要任何折算。卡在注意力项随长度涨:Qwen3-32B(64 层全注意力)在 131,072 时注意力项是 6N 的 215%;早期长序列还带来梯度方差极端值(Li 2021)。
- 解决了DeepSeek-V3 的 14.8T token 全在 4K,之后两段各 1,000 步扩到 32K、128K,只占全部训练 token 的 0.84%;Llama 3 405B 六段、约 800B token。卡在长序列阶段的数据要专门配(长度上采样、领域均衡、合成跨全文任务)。
- 解决了K3:8K → 64K → 256K → 1M(NoPE 也照走课程);V4.1 注意力从头就是压缩稀疏的,直接从 64K 起训。卡在各家配方大多只公开阶段、不公开每段 token 数,无法横向比较成本。
- 解决了每个位置多学一个更远的目标;推理时当草稿,接受率 α 时每步期望产出 1 + α 个 token。卡在DeepSeek-V3 第 2 个 token 接受率 85%–90%,实测 1.8 倍 TPS;V4.1 预训练干脆去掉 MTP,没有公开消融。
三层交互
| 层 | 本章里的组件 | 在哪一课 |
|---|---|---|
| 概念动画 | 路由选择链逐步展开(分数 → 索引 → 掩码 → 门控);4 × 4 状态逐步写入;稀疏选择链;层排布条 | 第 1、4、5 课 |
| 算法模拟器(真算法、小数据) | 4 个专家的浏览器内微训练(不均衡 / 辅助损失 / 偏置 / Quantile Balancing,真梯度下降);QB 逐步求解;专家切细的组合数;加法 / delta / 门控 delta 三种写法;DSA 式 top-k 召回;两本账、混合栈账本、KV 阶梯、长度成本,全部由官方 config 现算 | 第 1–6 课、岔路 |
| 真模型 / 真数据 | 我们自己从 0 训练的 4 专家 MoE:三种均衡方式的逐层负载与 val loss(真实日志回放);Qwen3.8-27B / 2.4T、DeepSeek V3 / V3.2 / V4 / V4.1、Kimi K3、GLM-5.3 的官方 config;HF transformers 的 Qwen3.5 源码;贯穿例句的真 token | 第 1–5 课与实验课 |
项目推进:给我们的模型换上 MoE
对应 04-实践项目/MILESTONES.md 的「C11 MoE 与长上下文」。代码 AI 来写,决策你来做。MoE 模块(n_experts、moe_top_k、moe_aux_loss_coef、moe_bias_update_rate)、逐层负载日志与对照脚本 experiments/exp_c11_moe.py 已经写好,实验导出本章组件读取的 c11-moe.json。
你要拍板的三件事
- 和稠密模型比,用什么口径?项目里每个专家和稠密 FFN 一样宽,于是 MoE 的总参数和激活参数都比稠密大。「总参数相同」「激活参数相同」「训练 FLOPs 相同」三种口径,结论可能完全不同(第 1 课、实验课)。
- 负载均衡用辅助损失还是偏置更新?理由要同时引用负载曲线与 val loss,并说明差距是否超出重跑噪声(第 2 课、实验课)。
- 长上下文怎么训?C2 给出了训练 128、读 512 的零样本缩放结果;续训(
init_from)还没排期。写下你会怎么排长度课程、每段用多少 token(第 6 课)。
验收标准(全部可测):
- 报告四组的总参数、激活参数、val loss、每层最忙专家的占比(完全均衡 = 1/E = 0.25)。
- 判据修订:MILESTONES 原写「是否出现某专家负载 > 0.5」。项目按 top-2 计数、每层和为 1,单个专家的上限就是 1/k = 0.5(每个 token 都把一个名额给了它),这个判据永远不会成立。改为:最忙专家是否触顶(≥ 0.49)、最闲专家是否长期低于 0.05,以及最后 100 步平均偏离 0.25 多少。
- val loss 的差距要和同配置重跑的噪声比(C14 实测 5 次重跑)。
坑与带走
| 坑 | 症状 | 后果 | 怎么办 |
|---|---|---|---|
| 以为 MoE 省显存 | 按激活参数估显存,上机就爆 | 2.4T 的权重 BF16 要 4.89 TB | 显存按总参数算;MoE 省的是每 token 的计算(第 1 课、C9、C10) |
| MoE 与稠密比较不写口径 | 「MoE 更好」的结论换个口径就反过来 | 决策失误 | 写明总参数、激活参数、训练 FLOPs 三个数(第 1 课、实验课) |
| 不做负载均衡 | 某几个专家长期触顶、另几个接近 0 | 死专家 = 白花了参数;专家并行时所有卡等最忙的那张 | 辅助损失或偏置;看负载曲线,不只看 loss(第 2 课) |
| 把偏置乘进门控 | 输出随偏置变化 | 偏置变成了会干扰学习的参数 | 偏置只进「选谁」,门控仍用原分数(第 2 课) |
| 均衡范围太细(按单条序列) | 专家学不出领域分工 | 效果变差 | 按整批 / 全局批统计(DeepSeek-V3 §4.5.3、Qwen3)(第 2 课) |
| 按 MPS 的动态形状分发 token | 每步重编译,60 步用了 107 秒 | 训练慢到不可用 | 小实验用「每个专家都算、乘掩码」的固定形状实现(项目实测 6.6 秒)(实验课) |
| 以为线性注意力在任何长度都更省 | 短请求显存反而更大 | 部署估算失误 | 锚点交叉点 768 token;短于它,固定状态比 KV 还大(第 4 课) |
| 以为 GDN 层也做 RoPE | 读不懂源码、改位置编码改错层 | 长上下文扩展失败 | 只有全注意力层旋转 Q、K;GDN 不接收位置编码(第 4 课) |
| 以为稀疏注意力省显存 | 1M 上下文照样爆 | 选型失误 | DSA 省计算不省 KV;要省存储得压序列 / 层 / 精度(第 5 课) |
| 直接横比「每 token KV 字节」 | 不同精度、不同层数混在一起比 | 结论失真 | 对齐精度、是否含索引器、滑窗与固定状态是否另计(第 5 课) |
| 从头就用长序列训 | 每步成本翻倍,早期还不稳 | 预算浪费 | 先短后长;长序列阶段只占预算的一小角(第 6 课) |
| 以为 NoPE 模型不需要长上下文训练 | 长度外推「能跑」但用不好 | 长文能力缺失 | K3 用 NoPE 照样走四段课程(第 6 课) |
这一章你应该带走的(各课「一句话」):
- MoE 把 FFN 拆成很多专家、每个 token 只算其中 k 个:容量跟着专家总数涨,每 token 的计算只跟着 k 涨;但所有专家的权重都得常驻显存。
- 路由会自我强化地偏心;辅助损失能拉平却难调,偏置只改「选谁」、不碰梯度——而统计范围(整批还是单条序列)比「用不用 loss」更要紧。
- 专家切细,同样的参数和计算能拼出多得多的组合,共享专家兜住公共部分——但这是实验选择,Qwen3 一个共享专家都不设。
- Gated DeltaNet 用固定大小的状态记前文:写之前先擦掉同一个键的旧值,每步整体衰减一点;锚点每 4 层留 1 层全注意力,KV 降到 1/4,代价是容量有限、精确回看靠那 1/4。
- 按内容挑 top-k 省的是计算,不是 KV;要省内存得压序列、压层、压精度——DeepSeek 三刀一起砍到 890 字节。
- 注意力的计算随长度涨,所以先在短序列上把语言学会,最后用很少的 token 把长度一段段拉上去;注意力本身变便宜之后,这条课程也在缩短。
- MTP 让每个位置多学一个更远的目标,训练信号更密,推理时还能当草稿;它是可以拆掉的辅助项,2026 年有人把它挪到了预训练之后。
深入这一章
每条都在 2026-09-26 实际打开核对过:写清它讲清了什么、对应哪一课、为什么推荐。站外资料标「需联网」;本地 PDF 断网可读。spaces.ac.cn 对脚本访问有防护,浏览器里打开正常。
🎮 想更直观 10–30 分钟
🔬 想吃透原理 1–3 小时
📄 想读原文 按需
排除了什么(也是筛选标准):① CSDN《DeepSeek 核心策略解析:为何 MoE 负载均衡是关键选择?》(2025,面试题体)——例题把加了偏置之后的分数 0.39 直接乘进专家输出算出 124.5,正好和 DeepSeek-V3 式 (16)「门控值仍由原始分数得出」相反,文末是课程广告;② CSDN《【深度拆解 Qwen3-Next】Gated DeltaNet 线性注意力的实现与优化》(2026-01)——源码逐行注释有参考价值,但开篇把固定状态说成「内存占用仅呈线性增长」「彻底解决长文本卡顿」,且讲的是 Qwen3-Next 旧版的合并投影(in_proj_qkvz),与 Qwen3.5 / 3.8 的写法不同;③ 旧版课程的 RouteCompareDemo 里「1M 时 GLM 56% / K3 26% / V4 3%」——常数是示意值、K3 一列还漏乘了潜向量折扣,本章改由官方 config 现算;④ 旧版课程里 IndexShare 的「1.82× / 1.48×」——2026-09-26 已在 IndexCache 原文核到(arXiv 2603.12201 摘要与表 1,需联网):那是 30B 的 DSA 模型、200K 上下文、只保留 1/4 索引器时的 prefill 与单请求 decode 加速,不能拿来给 GLM-5.2 的 1M 背书,所以本章不当作 IndexShare 的收益引用(口径见 C14 岔路)。