什么是混合专家(MoE)?它如何做到参数多但计算不变?
简化版
MoE 把 Transformer 的稠密 FFN 换成多个专家,并由路由器为每个 token 选择 top-k 个。总专家参数随 N 增长,而专家计算主要随 k 和单专家尺寸增长,因此可让总参数增长快于每 token FLOPs。这不等于计算严格不变:top-2 会执行两个专家,还包含路由、token 重排和 all-to-all。主要挑战是负载均衡、集群总权重存储、通信和小批次利用率。
详细版
结构:把 FFN 变成”多专家 + 路由”
标准 Transformer 块的 FFN 被替换为:
router 给出每个 token 对 N 个专家的打分 → 选 top-k
输出 = Σ_{i∈topk} g_i · Expert_i(x) # g_i 是路由权重(softmax 归一)
- 专家(Expert):每个就是一个独立的 FFN。
- 路由器(Gating):一个小的线性层,输入 token 表示,输出对各专家的偏好分,选分最高的 k 个。
核心特性:稀疏激活
- 总参数 ∝ N(专家数),但每个 token 只激活 k 个专家。
- 计算量 ∝ k,而非 N。例如 8 专家 top-2:参数约等于 8 个 FFN,计算约等于 2 个 FFN。
- 相比让所有 N 个专家都执行,它把激活 FLOPs 控制在 k 个专家;与某个稠密基线是否“基本不变”,还取决于单专家宽度和共享层。
主要挑战
- 负载不均 / 路由坍缩:若不加约束,路由器倾向于总把 token 发给少数几个「明星专家」,其余专家训不起来。需辅助负载均衡损失、容量上限(capacity)、token 丢弃或 drop-less 策略。
- 权重存储大:所有专家要在服务集群可用,但专家并行可让单卡只放一部分;总显存与通信成本仍高。
- 通信开销:专家常分布在多卡上,token 路由带来 all-to-all 通信。
- 训练稳定性:路由是离散选择,训练更难调。
代表模型
- Mixtral 8×7B:8 专家、top-2。
- DeepSeek-MoE:细粒度专家 + 共享专家(shared expert)。
- Switch Transformer:top-1 路由,极简高效。
完整版教学
一、动机:想要更多参数,又不想付更多算力
增加参数通常提高容量上限,但效果还受数据、训练和架构影响,并非“参数越多必然越好”。稠密 Transformer 中,扩大 FFN 等主体参数通常也会增加每 token 计算,因此容量与 FLOPs 强耦合。
MoE 的思路是打破「参数量」和「单 token 计算量」的绑定:让模型拥有海量参数,但每个 token 只用其中一小部分。就像一家医院有几十个专科医生(专家),但每个病人只看其中最对口的两三个,而不是让所有医生都会诊。这样医院的「总能力」很大,单个病人的「诊疗成本」却很低。
二、稀疏激活如何实现”参数多、算力省”
把一层的 FFN 换成 N 个专家 FFN + 一个路由器:
- token 表示 x 进路由器,得到对 N 个专家的打分;
- 取 top-k(如 k=2)个专家,softmax 得到权重 g;
- 只让这 k 个专家计算,输出按 g 加权求和。
算一笔专家层的账(N=8, k=2, 每个专家与某个单 FFN 同尺寸):
- 参数:约 8 个 FFN 的量(全都要存)。
- 计算:每个 token 只跑 2 个 FFN,FLOPs 约等于 2 个 FFN。
- 相对一个单专家 FFN,总专家参数约 8 倍,激活专家计算约 2 倍;相对“把 8 个专家全执行”的稠密层,激活比例是 1/4。若想与特定稠密基线匹配 FLOPs,需要同步缩小专家中间维或调整其他模块。
这就是“总参数与激活计算不同比例增长”。模型名称中的“8×7B”也不能直接当作八个完整 7B 模型相加:注意力等非专家参数由专家共享。active parameter 数同样不等于与同参数稠密模型有完全相同的延迟,因为通信、内存读取和 kernel 形状不同。
关键区分:总参数(total) 决定容量和显存;激活参数(active) 决定单 token 计算和速度。MoE 的精髓就是「总参数大、激活参数小」。
三、路由器:MoE 的大脑,也是麻烦的源头
路由器决定「每个 token 交给谁」,通常是一个简单的线性层 + softmax + top-k 选择。它很轻,却是训练成败的关键,因为它引入了两个难题:
难题一:稀疏选择的梯度与探索。 top-k 索引是离散的,常用被选门控权重对路由分数传递局部梯度,并以辅助损失或噪声改善探索;未选专家不会从该 token 的专家输出获得主任务梯度。
难题二:负载坍缩(load imbalance)。 训练早期若某几个专家碰巧表现好,路由器就更爱选它们,它们得到更多训练又变更好——正反馈导致少数专家垄断、多数专家饿死。这会浪费容量、损害效果。
四、负载均衡:让专家们”雨露均沾”
解决坍缩是 MoE 工程的核心,常用手段:
- 辅助负载均衡损失(auxiliary loss):额外加一项损失,鼓励「token 在专家间分布均匀」和「路由概率均匀」。它像一个软约束,惩罚「过度集中」。
- 专家容量(capacity factor):给每个专家设一个「本批最多处理多少 token」的上限;超出的 token 被丢弃(drop,直接走残差跳过)或溢出到次优专家。容量太小丢太多、太大浪费,需要调。
- 噪声路由(noisy top-k):给路由打分加噪声,增加探索,避免过早锁死。
- 无丢弃策略(drop-less,如 DeepSeek):通过更精细的路由与分配避免丢 token。
- 共享专家(shared expert,DeepSeek-MoE):设几个「所有 token 都过」的共享专家承载通用知识,其余路由专家学专精知识,缓解冗余与不均。
面试能点出「负载均衡靠辅助损失 + 容量限制」,并说明「为什么会坍缩(正反馈)」,就抓住了要害。
五、代价:省了计算,付出了什么
MoE 不是免费午餐:
- 总权重存储大:服务集群需承载所有专家;专家并行可分摊单卡权重,却增加通信和运维门槛。
- 通信开销:专家常做专家并行分散到多张卡,token 路由需要 all-to-all 通信,网络不好时成为瓶颈。
- 训练更难:离散路由、负载均衡、容量调参都增加了不稳定性。
- 批处理不规整:不同 token 去不同专家,导致计算不规则,需要专门的 kernel/调度优化。
MoE 适合希望在受控激活 FLOPs 下增加总容量、且有专家并行与通信基础设施的场景。它减少的是相对全激活专家的计算,不是消除计算瓶颈,并把一部分压力转移到权重存储、路由和网络。
六、用 Top-2 路由算“总参数大、激活参数小”
假设一层有 8 个同尺寸专家,每个专家含 100M 参数,路由对每个 token 只激活 2 个专家。该层拥有约 800M 专家参数,但单个 token 的专家计算只经过约 200M 参数;这就是 MoE 扩大模型容量而不同比例增加 FLOPs 的来源。
总专家参数 = 8 * 100M = 800M
每 token 激活参数 = top_k(2) * 100M = 200M
理想激活比例 = 2 / 8 = 25%
| 指标 | 理想状态 | 异常信号 |
|---|---|---|
| 专家负载 | 各专家接近平均 | 少数专家长期过载 |
| token 丢弃率 | 接近 0 | 容量不足或路由集中 |
| all-to-all 时间 | 占比可控 | 跨机通信吞没计算收益 |
理想账目没有包含跨卡 all-to-all、容量溢出和负载倾斜。若 1000 个 token 中有 400 个都路由到同一专家,即便平均负载应是 250(Top-2 共 2000 次分配除以 8),该专家也可能成为尾延迟瓶颈,所以路由质量必须和系统吞吐一起看。
七、常见误区与追问
- 误区:MoE 每个 token 都计算所有专家。 稀疏 MoE 的路由器通常只选择 Top-k 专家,因此总参数量大而单 token 激活参数较少。
- 追问:专家负载不均为什么会拖慢整批? 并行步骤要等待最慢设备,热点专家的计算与通信成为 straggler,其他设备空等。
- 误区:辅助负载均衡损失越强越好。 过强会迫使均匀路由,压制专家专门化;需要在均衡、质量和通信之间调权重。
- 追问:容量因子不足会发生什么? 专家接收槽位溢出,token 可能被丢弃、回退或转发,造成质量下降或额外延迟。
- 追问:MoE 为什么常受网络而非 FLOPs 限制? 专家跨设备放置会触发 all-to-all,token 重排和跨机带宽可能吞没稀疏计算节省。
八、加强记忆
MoE 把 FFN 换成多专家与路由器,每 token 只执行 top-k 个,因此总专家参数按 N 增长,专家计算按 k 与专家宽度增长。Top-2 不是“零额外计算”,active parameter 也不直接等于稠密模型延迟。它用稀疏计算换取更大总容量,同时付出集群权重存储、all-to-all、负载倾斜与训练复杂度。验收同时看任务质量、激活 FLOPs、专家负载尾部、溢出率和端到端吞吐。