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) | 175B | 175B | 1 | 1 |
| Mixtral 8×7B | 46.7B | 12.9B | 8 | 2 |
| DeepSeek-V2 | 236B | 21B | 160 | 6 |
| DeepSeek-V3 | 671B | 37B | 256 | 8 |
趋势:专家数量越来越多,每 token 选的比例越来越小。
六、MoE 与 RL 训练的关系
这一点很重要,因为后面学 RL 后训练时会遇到。
在线 RL(如 GRPO)需要在训练中不断更新模型并生成新数据。模型更新会改变 Router 的行为:
训练前: Router 把数学题送给 Expert 0
训练更新后: Router 可能突然把数学题送给 Expert 3
→ Expert 3 没被训练过处理数学 → 输出质量下降
→ RL 奖励信号变差 → 训练不稳定
这就是为什么某些 RL 方法(如 KARL 论文中的 OAPL)在 MoE 上有天然优势——离线训练不会实时扰动 Router。
本章总结
- MoE 把 FFN 拆成多个专家,每个 token 只用其中 k 个
- Router 是一个小网络,决定每个 token 该走哪些专家
- MoE 实现了参数和计算的解耦:参数多(知识丰富),计算少(速度快)
- 负载均衡是核心训练难题,用辅助损失和容量限制来解决
- 不同专家会自然专精不同领域
- MoE 的 Router 在 RL 训练中容易不稳定——这影响后训练方法的选择
下一篇:08. 预训练与 SFT — 模型是怎么从零学到知识的