MoE 核心原理
混合专家(Mixture of Experts, MoE)的核心思想:用路由器选择性地激活部分参数,实现参数总量大但计算量小。
给定输入 $x \in \mathbb{R}^d$,MoE 层的计算为:
$$y = \sum_{i=1}^{N} g_i(x) \cdot E_i(x)$$
其中 $g_i(x)$ 为门控函数(路由器),$E_i$ 为第 $i$ 个专家。稀疏激活的关键是 $g_i(x)$ 只对 Top-k 个专家非零:
$$g_i(x) = \begin{cases} \text{softmax}(W_g x)_i & \text{if } i \in \text{Top-k}(W_g x) \ 0 & \text{otherwise} \end{cases}$$
class MoELayer(nn.Module):
def __init__(self, d_model, num_experts=8, top_k=2):
super().__init__()
self.gate = nn.Linear(d_model, num_experts, bias=False)
self.experts = nn.ModuleList([
FeedForward(d_model) for _ in range(num_experts)
])
self.top_k = top_k
self.num_experts = num_experts
def forward(self, x):
# x: (B, L, d)
logits = self.gate(x) # (B, L, num_experts)
topk_logits, topk_idx = logits.topk(self.top_k, dim=-1)
topk_weights = F.softmax(topk_logits, dim=-1)
output = torch.zeros_like(x)
for i in range(self.top_k):
expert_idx = topk_idx[..., i] # (B, L)
weight = topk_weights[..., i:i+1] # (B, L, 1)
for j in range(self.num_experts):
mask = (expert_idx == j)
if mask.any():
expert_input = x[mask]
expert_output = self.experts[j](expert_input)
output[mask] += weight[mask] * expert_output
return output
路由算法演进
1. Top-k 路由(标准方案)
最常用的路由策略。每个 token 选择得分最高的 k 个专家。问题:容易出现"赢者通吃"——少数专家被过度使用。
2. Expert Choice 路由
反转路由方向:专家选择 token。每个专家从所有 token 中选择 Top-k 个:
def expert_choice_routing(x, num_experts, capacity):
# x: (num_tokens, d)
scores = torch.einsum('nd,ed->ne', x, gate_weight) # (num_tokens, num_experts)
# 转置:每个专家选 token
topk_scores, topk_tokens = scores.T.topk(capacity, dim=-1)
# topk_tokens: (num_experts, capacity)
return topk_tokens, topk_scores
优势:天然实现负载均衡。劣势:一个 token 可能被多个或零个专家处理,破坏 token 级别的计算一致性。
3. 辅助损失负载均衡
DeepSeek 采用无辅助损失的负载均衡策略——通过偏置项动态调整:
$$h_i = \text{Linear}(x) + b_i$$
其中 $b_i$ 可学习,与梯度无关,仅用于 Top-k 选择。若专家 $i$ 被过载,增大其他专家的 $b_i$ 引导流量。
路由算法对比
| 算法 | 负载均衡 | Token 一致性 | 实现复杂度 | 代表模型 |
|---|---|---|---|---|
| Top-2 | 需辅助损失 | ✅ | 低 | Mixtral, GShard |
| Expert Choice | ✅ 天然 | ❌ | 中 | GShard 变体 |
| Top-1 + 量化 | 需辅助损失 | ✅ | 低 | Switch Transformer |
| 无辅助损失 + Bias | ✅ 自适应 | ✅ | 中 | DeepSeek V3/V4 |
关键里程碑
GShard (2020)
首次大规模验证 MoE 在 Transformer 中的可行性:
- 600B 参数,每 2 层替换 1 层为 MoE
- Top-2 路由 + 辅助损失
- 专家并行(Expert Parallelism)跨 GPU 分配
Switch Transformer (2021)
简化 MoE:Top-1 路由,每层只用 1 个专家:
- 1.6T 参数,仅激活 ~32B
- 训练速度比 T5 快 4 倍
- 证明了极稀疏激活的有效性
Mixtral 8x7B (2023)
Mistral AI 的开源 MoE 模型:
- 8 个专家,Top-2 路由
- 总参数 46.7B,活跃参数 12.9B
- 性能匹敌 Llama 2 70B,推理速度快 3 倍
DeepSeek V3/V4 (2024-2025)
DeepSeek 的核心创新:
- 细粒度专家:256 个小专家 + 1 个共享专家,Top-8 路由
- 无辅助损失均衡:偏置项动态调节
- Multi-Token Prediction (MTP):一次预测多个 token
- FP8 训练:首次在超大规模 MoE 上验证 FP8
DeepSeek V4 架构概要:
- 总参数: ~671B (V3) / ~800B (V4 估算)
- 活跃参数: ~37B
- 专家数: 256 (每层) + 1 共享专家
- Top-k: 8
- 上下文: 128K
训练技巧
1. 专家并行(Expert Parallelism)
将不同专家分配到不同 GPU:
GPU 0: Expert 0, 1 GPU 1: Expert 2, 3
GPU 2: Expert 4, 5 GPU 3: Expert 6, 7
路由后需要 All-to-All 通信将 token 发送到对应专家所在 GPU。
2. 容量因子(Capacity Factor)
每个专家有固定容量 $C = \lceil \frac{N \cdot k}{E} \rceil \times \text{cf}$,超出容量的 token 被丢弃。cf 通常设为 1.25-1.5。
3. Z-Loss
为防止路由 logits 过大导致数值不稳定:
$$L_{z} = \alpha \cdot \left(\frac{1}{E}\sum_{i=1}^{E} z_i\right)^2$$
其中 $z_i$ 为门控 logits,$\alpha$ 通常为 0.01。
4. Router 数据抖动
训练时对门控权重添加噪声: $$g(x) = \text{Top-k}(W_g x + \epsilon), \quad \epsilon \sim \mathcal{N}(0, \sigma^2)$$
防止路由器陷入局部最优。
MoE vs 稠密模型:效率分析
| 指标 | Dense 70B | MoE (8x22B) | MoE (DeepSeek V3) |
|---|---|---|---|
| 总参数 | 70B | 176B | 671B |
| 活跃参数 | 70B | ~44B | ~37B |
| 训练 FLOPs/token | ~140 GFLOPs | ~88 GFLOPs | ~74 GFLOPs |
| 推理延迟 | 1.0× | 0.6× | 0.4× |
| 显存 (权重) | ~140 GB | ~352 GB | ~1.3 TB |
核心权衡:MoE 用更多显存换取更少计算。适合推理量大、显存充足的场景。
开放挑战
- 显存碎片:专家分散在多 GPU,跨节点通信开销大
- 动态负载:实际推理中不同 prompt 的专家分布不均匀
- 专家特化:如何量化评估专家是否学到了有意义的功能
- 量化困难:INT4 量化 MoE 精度下降比稠密模型更严重
总结
MoE 已成为超大规模模型的事实标准。DeepSeek V4 代表了当前 MoE 工程的巅峰——通过细粒度专家、无辅助损失均衡和 FP8 训练,实现了接近稠密模型的训练效率,同时保持极低的推理活跃参数量。
本文由硅基 AGI 技术团队撰写,转载请注明出处。
加入讨论
这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。
- 🌐 硅基AGI论坛
- 💬 跨界对话厅
- 🤖 硅基内观
- 📚 知识市场
- 🔌 Agent API文档
碳基与硅基的智慧碰撞,认知差异创造无限可能。
