AI Research

07. MoE 混合专家模型:以小博大的架构

07. MoE 混合专家模型:以小博大的架构

Dense 模型的每个 token 都过全部参数。MoE 让每个 token 只过一部分参数——总参数量很大(知识多),但每次计算量很小(速度快)。


一、Dense 模型的瓶颈

上一章我们知道,FFN 占了模型近一半参数,是知识的主要存储地。

要让模型”懂更多”,最直接的方法是加大 FFN。但 FFN 的问题是:每个 token 都要过全部参数

Dense 模型 (GPT-3 175B):
  每个 token 激活全部 175B 参数
  → 计算量巨大
  → 推理慢、成本高

MoE 的思路:把一个大 FFN 拆成多个小的”专家”,每个 token 只选其中几个用


二、MoE 的结构

2.1 专家 (Expert)

把一个 Transformer 层的 FFN 替换为多个独立的 FFN(叫”专家”):

Dense FFN:
  1 个 FFN, 形状 [768, 3072] → [3072, 768]

MoE (8 个专家):
  Expert 0: FFN_0, 形状 [768, 3072] → [3072, 768]
  Expert 1: FFN_1, 形状 [768, 3072] → [3072, 768]
  ...
  Expert 7: FFN_7, 形状 [768, 3072] → [3072, 768]

每个专家的结构完全一样,但参数不同——它们各自”专精”不同的知识。

2.2 Router (路由器)

关键问题:每个 token 该用哪个专家?

Router 是一个小的线性层,根据 token 的隐藏状态决定路由:

router_logits = x @ W_router    (W_router 形状: [768, 8])
router_probs  = softmax(router_logits)

例:
  x = [0.47, 0.50, 0.59, ...]   (某个 token 的隐藏状态)

  router_probs = [0.05, 0.02, 0.35, 0.01, 0.03, 0.04, 0.12, 0.38]
                  E0    E1    E2    E3    E4    E5    E6    E7

  → Expert 7 (38%) 和 Expert 2 (35%) 概率最高

2.3 Top-k 选择

选概率最高的 k 个专家(通常 k=2):

top_k_indices = [7, 2]      (选 Expert 7 和 Expert 2)
top_k_weights = [0.38, 0.35]

重新归一化权重:
  weights = [0.38/(0.38+0.35), 0.35/(0.38+0.35)]
          = [0.521, 0.479]

2.4 最终计算

output = 0.521 × Expert_7(x) + 0.479 × Expert_2(x)

只计算 2 个专家,其余 6 个完全不参与。


三、MoE 的好处

3.1 参数 vs 计算的解耦

Mixtral 8×7B:
  总参数量: 46.7B    (8 个 7B 级别的专家)
  每 token 激活: 12.9B  (只用 2 个专家 + 共享的 Attention)

  → 参数量是 7B Dense 的 6.7 倍
  → 计算量只是 7B Dense 的 1.8 倍
  → 效果接近 70B Dense 模型!
DeepSeek-V3:
  总参数量: 671B
  每 token 激活: 37B   (256 个专家中选 8 个)

  → 参数量 671B → 存储了海量知识
  → 实际计算只用 37B → 推理速度可接受

3.2 天然的”专业分工”

训练后,不同专家会自然”专精”不同类型的知识:

Expert 0: 数学和逻辑推理
Expert 1: 编程和代码
Expert 2: 历史和地理
Expert 3: 日常对话
Expert 4: 科学知识
...

这不是手动分配的——是训练中自然涌现的。Router 学会了把不同类型的输入分配给最合适的专家。


四、训练难题:负载均衡

4.1 问题:专家坍塌

如果 Router 发现 Expert 3 最好用,就会把越来越多的 token 送给 Expert 3。其他专家得不到训练,能力退化。结果 Expert 3 更好用 → 更多 token 送给它 → 正反馈循环。

最终:只有 1-2 个专家在工作,其余闲置。这就叫”专家坍塌”。

4.2 解决方案:辅助损失

在训练损失中加一个负载均衡项

L_total = L_language + α × L_aux

其中:

L_aux = E × Σ(f_i × P_i)   for i = 1..E

f_i = Expert i 被选中的频率 (实际比例)
P_i = Router 给 Expert i 的平均概率 (期望比例)
E = 专家数量
α = 辅助损失系数 (通常 0.01)

当某个专家被选得太多时(f_i 大),L_aux 会增大,惩罚 Router,迫使它分散选择。

理想状态:每个专家被均匀选择,f_i = 1/E。

4.3 容量因子 (Capacity Factor)

另一个技巧:限制每个专家每次能处理的 token 数量。

capacity = (tokens_per_batch / num_experts) × capacity_factor

capacity_factor = 1.25 时:
  batch 有 1024 个 token, 8 个专家
  每个专家最多处理 1024/8 × 1.25 = 160 个 token
  超出的 token → 跳过该专家 → 只用另一个被选中的专家

这强制实现了负载均衡,但代价是部分 token 可能得不到最优的专家处理。


五、实际规模对比

模型总参数每 token 激活参数专家数 E每 token 选 k 个
GPT-3 (Dense)175B175B11
Mixtral 8×7B46.7B12.9B82
DeepSeek-V2236B21B1606
DeepSeek-V3671B37B2568

趋势:专家数量越来越多,每 token 选的比例越来越小。


六、MoE 与 RL 训练的关系

这一点很重要,因为后面学 RL 后训练时会遇到。

在线 RL(如 GRPO)需要在训练中不断更新模型并生成新数据。模型更新会改变 Router 的行为:

训练前: Router 把数学题送给 Expert 0
训练更新后: Router 可能突然把数学题送给 Expert 3
→ Expert 3 没被训练过处理数学 → 输出质量下降
→ RL 奖励信号变差 → 训练不稳定

这就是为什么某些 RL 方法(如 KARL 论文中的 OAPL)在 MoE 上有天然优势——离线训练不会实时扰动 Router。


本章总结

  1. MoE 把 FFN 拆成多个专家,每个 token 只用其中 k 个
  2. Router 是一个小网络,决定每个 token 该走哪些专家
  3. MoE 实现了参数和计算的解耦:参数多(知识丰富),计算少(速度快)
  4. 负载均衡是核心训练难题,用辅助损失和容量限制来解决
  5. 不同专家会自然专精不同领域
  6. MoE 的 Router 在 RL 训练中容易不稳定——这影响后训练方法的选择

下一篇:08. 预训练与 SFT — 模型是怎么从零学到知识的