混合专家(MoE)


文档摘要

混合专家(MoE) 本节摘要:一个稠密 700 亿参数的 Transformer,每个 token 都激活全部参数;一个 6710 亿参数的 MoE,每个 token 只激活 370 亿,却在每个基准上击败前者。稀疏性是这十年最重要的 scale 思想。稠密 Transformer 推理时的 FLOPs 等于参数量(前向乘 2),scale 一上去每个 token 都付全账,2024 年前沿撞上算力墙——想明显更聪明,需要指数级更多的每 token FLOPs。混合专家(Mixture of Experts)打破这道联系:把每个 FFN 换成 个独立专家 + 一个每 token 选 个的路由器。总参数 = ,每 token 激活参数 = 。2026 典型配置 ——存储随 缩放,计算随 缩放。

混合专家(MoE)

本节摘要:一个稠密 700 亿参数的 Transformer,每个 token 都激活全部参数;一个 6710 亿参数的 MoE,每个 token 只激活 370 亿,却在每个基准上击败前者。稀疏性是这十年最重要的 scale 思想。稠密 Transformer 推理时的 FLOPs 等于参数量(前向乘 2),scale 一上去每个 token 都付全账,2024 年前沿撞上算力墙——想明显更聪明,需要指数级更多的每 token FLOPs。混合专家(Mixture of Experts)打破这道联系:把每个 FFN 换成 E 个独立专家 + 一个每 token 选 k 个的路由器。总参数 = E × FFN 大小,每 token 激活参数 = k × FFN 大小。2026 典型配置 E=256, k=8——存储随 E 缩放,计算随 k 缩放。本节带你纯标准库搭一个 MoE 层(路由器 + top-k 门控 + 无辅助损失的负载均衡),讲清三件大事:DeepSeek-V3 的无辅助损失均衡(用每专家偏置只调路由选择、不污染门控权重)、细粒度专家(专家更窄、E 更大,组合数爆炸式增长,质量升而延迟不升)、以及代价:所有专家都得占显存,前沿 MoE 部署必须专家并行,延迟由 all-to-all 通信而非矩阵乘决定。

学习目标

阅读完本节,你应当能够:

  1. 说清 MoE 如何解耦总参数与每 token 激活参数:总参数随专家数 E 缩放,计算随每 token 选中的 k 缩放。
  2. 写出 MoE 块的前向:路由器对每 token 给 E 个专家打分、top-k 选 k 个、softmax 门控加权混合输出。
  3. 解释 DeepSeek-V3 的无辅助损失负载均衡:用每专家偏置只调路由选择、不调门控权重,把路由与表达解耦。
  4. 区分经典粗粒度 MoE(专家同 FFN 宽,Ek 小)与现代细粒度 MoE(专家更窄,E=256+ k=8+,组合数爆炸)。
  5. 说清 MoE 的代价:全部专家都占显存(671B 需约 1.3 TB fp16),前沿部署必须专家并行,延迟由通信而非 matmul 决定。

一、问题与直觉

稠密 Transformer 每 token 付全账,scale 一上去 FLOPs 指数增长。MoE 把每个 FFN 换成 E 个独立专家 + 一个每 token 选 k 个的路由器——存储随 E 缩放,计算随 k 缩放。2026 前沿几乎全是 MoE:DeepSeek-V3(671B 总/37B 激活)、Mixtral 8×22B、Qwen2.5-MoE、Llama 4、Kimi K2、gpt-oss。Artificial Analysis 独立榜单上,开源前十全是 MoE。

FFN 替换

稠密块:

h = x + attn(norm(x)) h = h + FFN(norm(h))

MoE 块:

h = x + attn(norm(x)) scores = router(norm(h)) # (N_tokens, E) top_k = argmax_k(scores) # 每 token 选 E 中的 k 个 h = h + Σ_{e ∈ top_k} gate(scores[e]) · Expert_e(norm(h))

每个专家是一个独立 FFN(通常 SwiGLU),路由器是一个线性层。每个 token 选自己的 k 个专家,得到它们输出的门控混合。

负载均衡问题

如果路由器把 90% 的 token 送进专家 3,其他专家挨饿。试过三种修法:

  1. 辅助负载均衡损失(Switch Transformer、Mixtral)。加一个与专家使用方差成正比的惩罚。有效,但多了一个超参和第二路梯度信号。
  2. 专家容量 + token 丢弃(早期 Switch)。每个专家最多处理 C·N/E 个 token,溢出的 token 跳过本层。伤质量。
  3. 无辅助损失均衡(DeepSeek-V3)。加一个学习的每专家偏置,只移动路由器的 top-k 选择。偏置在训练损失之外更新,不惩罚主目标。2024 年的大解锁。

DeepSeek-V3 的做法:每个训练步后,对每个专家检查其使用率高于还是低于目标,把偏置微调 ±γ选择scores + bias,门控用原始未变的 scores。把路由与表达解耦。

💡 关键洞见:辅助损失会改变主目标的梯度(为了均衡,模型可能牺牲一点质量);DeepSeek-V3 的偏置法完全不动主损失,只在路由选择这一离散决策上施加控制——这是它能在大规模上既均衡又不损质量的原因。

共享专家

DeepSeek-V2/V3 还把专家分成共享路由两类。每个 token 都过所有共享专家,路由专家靠 top-k 选。共享专家捕捉通用知识,路由专家专精。V3 跑 1 个共享专家 + 256 个路由专家中的 top-8。

细粒度专家

  • 经典 MoE(GShard、Switch):每个专家和完整 FFN 一样宽,E 小(864),k 小(12)。
  • 现代细粒度 MoE(DeepSeek-V3、Qwen-MoE):每个专家更窄(1/8 FFN 大小),E 大(256+),k 更大(8+)。总参数相同,但组合数增长快得多——C(256, 8) = 400 万亿种可能的「专家」每 token。质量上升,延迟不变。

成本画像

每 token、每层:

配置 每 token 激活参数 总参数
Mixtral 8×22B 约 39B 141B
Llama 3 70B(稠密) 70B 70B
DeepSeek-V3 37B 671B
Kimi K2(MoE) 约 32B 1T

DeepSeek-V3 几乎在每个基准上击败 Llama 3 70B(稠密),同时每 token 激活 FLOPs 更少。参数越多 = 知识越多;激活 FLOPs 越多 = 每 token 算力越多。MoE 把两者解耦。

代价:显存

不管哪些专家被触发,所有专家都得在 GPU 上。671B 模型 fp16 权重需约 1.3 TB 显存。前沿 MoE 部署必须专家并行——把专家分片到多 GPU,token 跨网络路由。延迟由 all-to-all 通信而非矩阵乘决定。

二、从零实现

完整代码见原课程 phases/07-transformers-deep-dive/11-mixture-of-experts/code/main.py。纯标准库的紧凑 MoE 层:n_experts=8 个 SwiGLU 式专家(为示意各一个线性)、top-k=2 路由、softmax 归一化门控、无辅助损失的每专家偏置均衡。

Step 1:路由器

def route(hidden, W_router, top_k, bias): scores = [sum(h * w for h, w in zip(hidden, W_router[e])) for e in range(len(W_router))] biased = [s + b for s, b in zip(scores, bias)] # 偏置只影响选择 top_idx = sorted(range(len(biased)), key=lambda i: -biased[i])[:top_k] # 门控用「原始」分数的 softmax(只对选中的专家) chosen = [scores[i] for i in top_idx] m = max(chosen) exps = [math.exp(c - m) for c in chosen] s = sum(exps) gates = [e / s for e in exps] return top_idx, gates

偏置影响选择不影响门控权重,这就是 DeepSeek-V3 的技巧——偏置纠正负载失衡,却不操纵模型的预测。

Step 2:跑 100 个 token 过路由器

追踪哪些专家触发多频繁。无偏置时使用倾斜;加上偏置更新循环(过用的 、欠用的 ),几次迭代后使用率收敛到均匀分布。

Step 3:参数量对比

打印一个 MoE 配置的「稠密等价」。DeepSeek-V3 形状:256 路由 + 1 共享、8 激活、d_model=7168。总参数量惊人,激活量却只有稠密 Llama 3 70B 的七分之一。

设计要点:细粒度 MoE 的组合爆炸是质量提升的根源——C(256,8) ≈ 4·10¹⁴,相当于每 token 有 400 万亿种「专家组合」可选,模型的表达能力随 E 组合式增长,而激活算力只随 k 线性增长。

三、框架对比:HuggingFace 与生产推理

from transformers import AutoModelForCausalLM, AutoTokenizer model = AutoModelForCausalLM.from_pretrained("mistralai/Mixtral-8x22B-v0.1")

2026 生产推理:vLLM 原生支持 MoE 路由,SGLang 有最快的专家并行路径,两者都自动处理 top-k 选择和专家并行。

何时选 MoE:

  • 想在更低每 token 推理成本下要前沿质量。
  • 有显存/专家并行基础设施。
  • 工作负载是 token 密集(聊天、代码)而非上下文密集(长文档)。

何时不选 MoE:

  • 边缘部署——任何激活 FLOPs 都要付全部存储代价。
  • 延迟敏感的单用户服务——专家路由增加开销。
  • 小模型(<7B)——MoE 的质量优势只在某个算力门槛(约 6B 激活参数)之上才出现。

四、可复用产物

原课程产出 outputs/skill-moe-configurator.md:一个配置器 Skill,给定参数预算、训练 token 数、部署目标,为新 MoE 选 Ek、共享专家布局。

五、练习

  1. (Easy)code/main.py,看无辅助损失的偏置更新如何在 50 次迭代内抹平专家使用率。
  2. (Medium) 把学习路由器换成哈希路由器(确定性、不学习),对比质量和均衡性。学习路由器为什么更好?
  3. (Hard) 实现 GRPO 式「rollout 匹配路由」(DeepSeek-V3.2 技巧):推理时记录哪些专家触发,梯度计算时强制同样路由。在玩具策略梯度设置上测效果。

本节要点回顾

  1. 稀疏性是 decade 最重要的 scale 思想:671B MoE 每 token 只激活 37B,却击败 70B 稠密——解耦了总参数(知识)与激活 FLOPs(每 token 算力)。
  2. MoE 块 = 路由器 + top-k 门控:路由器一个线性层打分,每 token 选 k 个专家,softmax 门控加权混合。
  3. 负载均衡三法:辅助损失(Switch/Mixtral,加超参和第二路梯度)、容量+丢弃(伤质量)、无辅助损失偏置(DeepSeek-V3,只调选择不调门控,2024 大解锁)。
  4. DeepSeek-V3 的解耦:选择用 scores+bias,门控用原始 scores——均衡不污染主目标。
  5. 共享 + 路由专家:共享专家每 token 都过(通用知识),路由专家 top-k 选(专精);V3 是 1 共享 + 256 选 8。
  6. 细粒度 MoE:专家更窄、E 更大,组合数 C(256,8)≈4·10¹⁴ 爆炸,质量升延迟不变。
  7. 代价是显存:所有专家都占显存(671B 需 ~1.3TB fp16),前沿必须专家并行,延迟由 all-to-all 通信决定。
  8. 门槛约 6B 激活参数:小于此 MoE 优势不显现;边缘部署、延迟敏感单用户、小模型别选 MoE。

下一节,我们解决 MoE 之外的另一道推理墙——KV 缓存与 Flash Attention:如何避免每步重算所有历史 token 的键值,以及如何把注意力的 O(N²) 显存降到 O(N) 而不丢精度。


发布者: 作者: Rohit Gupta 转发
评论区 (0)
U