C · MoE 混合专家架构
稠密模型的计算瓶颈,如何通过路由机制 (Router) 激活少量专家实现「总参数量大但计算量不变」,以及 DeepSeek 等模型的改进。
C · MoE 混合专家架构
稠密模型(Dense)激活所有参数来处理每个 token。MoE 把 FFN 层替换为若干个「专家」,每个 token 只路由给其中少数几个,实现「参数量大但计算量不变」的效果。
一、动机:扩大模型但不增加计算
Scaling Law 告诉我们更多参数 = 更强能力,但参数量翻倍意味着推理计算量也翻倍。
MoE 的思路:模型有 个专家,但每次前向传播每个 token 只激活其中 个(通常 )。
- 总参数量:,很大
- 激活参数量:,与稠密模型相当
- 推理计算量:基本不变(只多了路由的开销)
典型例子:Mixtral 8×7B 总参数 46.7B,但每个 token 只激活约 13B,推理速度接近 7B 模型,能力接近 70B 模型。
二、架构:把 FFN 换成专家层
标准 Transformer Block:
输入 → Attention → LayerNorm → FFN → 输出
MoE Transformer Block:
输入 → Attention → LayerNorm → Router → [Expert 1, ..., Expert N] → 加权求和 → 输出
其中每个 Expert 就是一个独立的 FFN(两层线性 + 激活),Router 是一个小型线性层,决定每个 token 去哪些专家。
三、路由机制(Router)
3.1 Top-k 路由
对每个 token ,Router 计算对所有 个专家的得分:
其中 是路由权重矩阵, 保留最高的 个分数,其余置为 (softmax 后为 0)。
最终输出是被选中的 个专家输出的加权和:
3.2 负载均衡问题
朴素的 Top-k 路由有严重的折叠问题(Collapse):Router 倾向于总是选择同几个专家,其他专家得不到训练,逐渐退化。
辅助损失(Auxiliary Loss):给训练目标加一个均衡项,惩罚专家负载不均:
其中:
- :在一个 batch 中被路由到专家 的 token 比例(实际分配)
- :所有 token 对专家 的平均路由概率(期望分配)
- :超参数,控制均衡约束的强度
最小化 → 每个专家得到的 token 数量尽可能均等。
3.3 专家容量(Expert Capacity)
为了并行计算,每个专家最多处理固定数量的 token(Expert Capacity):
超出容量的 token 被丢弃(或走残差路径)。Capacity Factor 通常设为 1.0~1.5。
四、DeepSeek MoE 的改进
DeepSeek-V2/V3 对标准 MoE 做了重要改进:
4.1 细粒度专家(Fine-grained Experts)
把每个专家拆成更小的专家(Expert Splitting),同时增大 。
- 标准 MoE:8 个大专家,每次选 2 个
- DeepSeek:64 个小专家,每次选 6 个
优势:更细粒度的组合,每个 token 能激活更多样化的「能力片段」,同时专家的平均负载更均衡。
4.2 共享专家(Shared Experts)
除了若干路由专家(Routed Experts)外,另设若干共享专家,每个 token 必选:
共享专家处理通用能力(语法、基础语义),路由专家处理专业能力(领域知识、推理类型)。减少了路由专家之间的冗余。
五、推理时的工程挑战
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 专家分散在不同 GPU | 大 MoE 模型无法放入单 GPU | 专家并行(Expert Parallelism) |
| All-to-All 通信开销 | 不同 token 要去不同专家 | Token 分组、通信与计算重叠 |
| 负载不均衡 | 某些专家被选中次数更多 | 动态负载均衡、容量限制 |
| 冷启动 | 未被选中的专家参数不更新 | 辅助损失 + 探索机制 |
六、与稠密模型的对比
| 维度 | 稠密模型 | MoE 模型 |
|---|---|---|
| 总参数 | (大得多) | |
| 激活参数 | (相当) | |
| 推理 FLOPs | 高 | 低(约等于激活参数的稠密模型) |
| 训练稳定性 | 好 | 需要辅助损失维持均衡 |
| 部署复杂度 | 低 | 高(需要专家并行) |