混合专家 MoE:让每个 token 只激活少数前馈网络
从 top-k 路由与加权输出,到负载均衡、容量溢出、all-to-all、专家专化和推理批处理。
- token 表示进入路由器
- 选择 top-k 并分配容量
- all-to-all 发送至专家
- 专家并行计算并加权返回
- 均衡/溢出控制热点
- 质量、通信、容量和切片联合验收
1总参数大,不等于每个 token 全部计算直觉
混合专家(Mixture of Experts, MoE)要解决的直接问题,是 Transformer 中前馈网络(FFN)的计算成本与模型容量之间的矛盾。在稠密 Transformer 里,每个 token 都会完整经过同一个 FFN:token 数量乘以 FFN 参数量,就是每次前向必须执行的计算量。想让模型更有能力,通常就要加宽 FFN,而加宽 FFN 会让每一个 token 的每一层都变慢。MoE 的切入点正是打破“每个 token 都调用全部 FFN 能力”这一默认假设。
MoE 的结构替换:把那个每个 token 必经过的单一 FFN,替换成多个并列、可选的 FFN,每一个被称为一个“专家”(expert)。在每一层,一个路由器(router)读取当前 token 的上下文表示(即该 token 到达本层时的隐藏向量),为各专家打分,只选出分数最高的一个或两个专家真正执行计算,这就是 top-1 或 top-2 选择。一个拥有 8 个专家的模型里,token “退款”可能只经过其中 2 个专家;其余 6 个专家这一次完全不被计算。未选中的专家本次不参与,但注意力、词嵌入、层归一化以及其他所有共享层仍然对每个 token 稠密执行——节省只发生在前馈专家部分。
从输入输出的角度看,接口没有变化。输入仍是每个 token 的上下文表示;输出仍是与原 FFN 相同维度的更新表示。也就是说,MoE 是 FFN 内部的实现替换,层与层之间传递的张量形状、残差连接、归一化位置都不必因此改变,这正是它可以被当作“直接换掉 FFN”的原因。
理解 MoE 的代价与收益,关键在于区分三个经常被混为一谈的数字。总参数量(total parameters)是模型存储下来的全部参数之和,它决定的是存储、加载和训练状态的开销,也决定可供条件选择的容量上限。每个 token 的激活参数量(active parameters per token)是该 token 实际经过的共享层参数与专家参数之和,它更接近单 token 的真实计算量,但它仍然不包含路由打分与通信开销。FLOPs 是实际执行的浮点运算次数,最能反映真实的算术工作量。一个模型可以拥有极大的总参数量,同时每个 token 只激活其中很小的一部分。
由此得到三条因果判断。第一,总参数大只说明可供条件选择的容量多,不代表每个 token 调用了全部能力:8 个专家并存与“每个 token 都算 8 个专家”是完全不同的两件事。第二,总参数大也不保证墙钟时间更快:参数更多意味着存储、加载、训练状态的负担更大,激活参数之外还有路由和通信的开销,真正的速度要由 FLOPs 和系统实现共同决定。第三,MoE 的本质是一种交换——用更大的参数容量和更高的通信复杂度,换取条件计算(conditional computation):只有部分专家为一个 token 干活。它不是把一万亿参数“免费”变成稠密的一万亿能力;稠密模型每 token 调用的能力比例是 100%,MoE 每 token 只调用其中一小部分,两者在单 token 能力与总容量之间的取舍完全不同。评价一个 MoE 模型,必须同时看总参数、激活参数和 FLOPs 三个口径,任何单独一项都会产生误导。
2路由器如何选择并组合专家机制
路由器的工作可以拆成打分、选择、重新归一化、加权合成四步,每一步都有明确的输入输出。
第一步,打分。设 x 是当前 token 到达本层的上下文向量,Wᵣ 是路由器的权重矩阵。路由器先做一次线性变换 Wᵣ·x,为每个专家得到一个分数,分数越高表示路由器认为该专家越适合处理这个 token。第二步,softmax。把这些分数经过 softmax 得到每个专家的概率向量 g:
g = softmax(Wᵣ·x)
其中第 e 个分量 gₑ 满足 gₑ = exp((Wᵣ·x)ₑ) / Σⱼ exp((Wᵣ·x)ⱼ)。softmax 把任意实数的分数压成一个和为 1 的概率分布:每个专家得到 0 到 1 之间的概率,所有专家的概率加起来正好是 1。gₑ 就是路由器认为“该 token 应该由专家 e 处理”的相对置信度。第三步,top-k 硬选择。k 是每个 token 激活的专家个数,S 是概率最高的 k 个专家的编号集合;集合之外的专家本次不参与计算。第四步,重新归一化并合成。被选中的 k 个专家的原始概率之和通常小于 1,所以要在集合 S 内部重新归一化:ĝₑ = gₑ / Σ_{e'∈S} g_{e'},使得选中专家的权重之和重新变成 1。最终输出 y 是选中专家各自 FFN 输出的加权和:
y = Σ_{e∈S} ĝₑ · Eₑ(x)
其中 Eₑ(x) 是专家 e 的前馈网络对该 token 的输出,ĝₑ 是重新归一化后的权重。这样一个 token 的更新表示就是两个(或一个)专家输出的凸组合,而不是简单拼接或平均。
top-1 与 top-2 的选择是一场容错与成本的权衡。top-1 每个 token 只激活一个专家,计算量和通信量最小;但整条路径完全押注在单个专家上,一旦该专家对当前输入表现不佳,没有第二条路径可以弥补,单一路径更脆弱。top-2 同时激活两个专家,引入了冗余和更强的表达组合能力,一个专家失误时另一个仍能贡献输出;代价是专家分支的计算成本近似翻倍,通信量也相应上升。这里的“近似翻倍”来自硬选择本身:选中的每个专家都要完整执行一次 FFN。
硬 top-k 还带来一个训练上的关键后果。选择是离散的:一个专家要么被选中、要么不被选中,未选中的专家这一次完全收不到当前 token 的任务梯度。如果只靠这种硬选择,路由器很难被有效训练——因为选择动作本身不可微,且大量专家可能长期得不到梯度。因此训练中还需要两样东西:可微的路由分数(softmax 概率本身处处可微,可以让梯度经由权重 g 传回路由器),以及均衡目标(促使各专家被选中的频率大致均衡,避免少数专家垄断)。前者解决“怎么学”,后者解决“学得均匀”。
不同实现还会在结构上做加法。有的架构除了路由专家(routed experts)之外,还设一个共享专家(shared expert):每个 token 无条件经过它,路由专家只在其上叠加。这样通用模式总是有一条共享路径兜底,路由只负责挑选增量能力。这些细节因实现而异,共享专家是否存在、k 取几、重新归一化的具体方式都可能不同,不能只凭“MoE”这个标签就假定其内部结构。
3运行示例:6 个 token 的 top-2 分发逐步演算
用一个具体的小批量把路由负载算清楚:4 个专家 E1 到 E4,一批 6 个 token,每个 token 走 top-2 路由,即每个 token 同时向两个专家发出计算请求。
先把总量算出来。6 个 token 每个产生 2 个专家请求,本批总共 6×2 = 12 条路由请求。平均到 4 个专家,每个专家应接 12/4 = 3 条。这就是容量因子 c = 1.0 的含义:不给任何安全余量,每个专家的容量恰好等于平均负载。容量公式把这个过程一般化:
C = ceil(c × N × k / E)
其中 C 是单个专家在这一批最多接收的路由数,ceil 是向上取整,c 是容量因子,N 是 token 数,k 是每个 token 选择的专家数,E 是专家总数。代入本例:ceil(1.0 × 6 × 2 / 4) = ceil(3) = 3。向上取整保证容量至少不小于平均负载,不会因为除不尽而把容量压到平均值以下。
但平均值不是每个专家的实际值。路由器按 token 内容自由选择,分布不会均匀。图示中 E1 收到了 5 条路由请求,而容量只有 3:5 路中有 2 路必须按溢出处理。这暴露了容量机制的本质——容量按平均路由数乘安全系数分配,热点专家仍然可能溢出;容量只限制“单个专家最多接多少”,不负责把负载抹平。
面对 E1 的 2 路溢出,常见有三种应对,各自在质量与资源之间取舍。第一种是 drop:直接丢弃这 2 条请求,对应 token 的专家输出里少了这一路。损失是可能伤到该 token 的表示——被丢弃的正是路由器打分最高的专家之一;好处是资源固定,本批的计算和通信总量不会膨胀。第二种是 second/backup 转投:把溢出的请求转给其他还有余量的专家。token 的表示可以恢复完整,但承接的是路由器本来没选的专家,语义会变——被转投的专家未必适合这个 token;同时多了调度环节,通信量增加。第三种是提高容量因子,例如 CF=2:容量变成 ceil(2 × 6 × 2 / 4) = 6,每个专家最多接 6 路,本例中 E1 的 5 路全部放得下,丢弃几乎不发生。代价同样明确:缓冲按容量预留,最坏情况下的计算和通信预算都跟着容量上限上升,即使实际平均负载还是 3。
所以容量因子是一个显式的工程旋钮:调大它,溢出和丢弃减少、质量更稳,但预留的缓冲与最坏情况成本上升;调小它,资源更省,但热点专家的溢出会更多,代价转嫁到 token 表示的完整性或转投带来的语义偏移上。这个权衡在训练与推理中都会出现,只是两边的约束不同。
| 策略 | E1 溢出处理 | 质量 | 资源 |
|---|---|---|---|
| drop | 丢 2 路 | 可能伤 token 表示 | 固定 |
| second/backup | 转其他专家 | 可恢复但语义变 | 通信增加 |
| CF=2 | 容量 6 | 少丢弃 | 缓冲与最坏计算增 |
4为什么路由会坍缩到少数专家均衡
路由坍缩是一个自我强化的正反馈过程。假设训练初期专家 E1 因为随机初始化或数据顺序的原因,比其他专家略微强一点。路由器会更多地把 token 分给 E1;E1 因此获得更多的任务梯度,训练信号更足,变得更强;更强的 E1 又让路由器更加偏爱它。这个循环一旦启动,其他专家几乎收不到样本和梯度,训练机会趋近于零,变得越来越“饿”,这就是专家饥饿(expert starvation)。模型名义上有 E 个专家,实际承担计算的只剩少数几个,其余参数白占了存储和加载成本。
要理解这个循环为什么会自然发生,需要看清它的输入与输出。路由器的输入是它对每个专家给出的概率,输出是实际分配;而优化的目标有两个、且相互拉扯:既要任务质量高(把 token 交给最合适的专家),又要专家负载均衡(每个专家都有机会学习)。只用任务损失训练时,第二个目标没有任何力量约束,正反馈就能畅通无阻。
对抗坍缩的手段各有针对的环节。辅助损失(auxiliary loss)直接惩罚“少数专家概率过高或实际 token 占比过高”的情形,把均衡目标变成梯度的一部分,作用在路由器和专家的学习过程上。路由噪声在训练时给路由分数加随机扰动,迫使路由器偶尔探索本不会选择的专家,为饥饿专家创造被尝试的机会。z-loss 约束路由 logits 不要无限变大:logits 变大意味着 softmax 更尖锐,路由器越来越自信于少数专家,同时大 logits 还会带来数值不稳定,z-loss 相当于给这种发散踩刹车。专家容量限制单个专家最多接收多少路由,从分配层面兜底,即使路由器想一股脑把 token 塞给 E1,容量也会把溢出部分挡出去或转投其他专家。
但这些手段都不能无限加强。均衡过强时,本应进入专业专家的 token 被硬摊开到无关专家上,语义路由被破坏,任务质量受损。正确的位置不是追求绝对均匀,而是同时观察多个信号:任务 loss、专家熵(分配概率分布的分散程度)、每专家 token 数、溢出率和整体质量。负载均匀本身只是计算分配的效率信号,说明算力没有被浪费;它不能证明不同语言或不同群体的 token 获得了同等的表示质量——一个专家负载均衡的模型,完全可能在质量上厚此薄彼。把“分配均匀”当成“质量公平”是对 MoE 最常见的误读之一。
5all-to-all 让通信成为第一等成本系统
当专家分散在多张 GPU 上时,一个 token 的行程里多出两段通信。输入 token 先在本地设备完成注意力和路由打分,然后按目的地专家打包:所有要去 E1 的 token 归为一组,去 E2 的归为另一组,依此类推。接着做一次 all-to-all 交换——每张 GPU 把打包好的 token 发往持有相应专家的设备,同时接收其他 GPU 发来、要由本地专家处理的 token。持有专家的设备完成 FFN 计算后,再反向做一次 all-to-all,把每个 token 的结果按原顺序送回它出发的 GPU。于是每一层 MoE 都包含两段全交换通信,通信不再是隐藏细节,而是和专家计算并列的第一等成本。
这个模式在理想条件下很快,在现实条件下却容易让网络闲不下来、也满不起来,形成多种瓶颈。
专家热点是第一种。某几个专家被大量 token 选中,持有它们的 GPU 积压大量请求,而其他 GPU 早早算完只能等待,或触发容量溢出。缓解手段是均衡负载,以及对特别热门的专家做复制,让同一专家的副本分散到多台设备上分担流量。
跨节点带宽是第二种。all-to-all 的数据总量与批次和专家分布成正比,当专家跨机器分布时,网络交换在单步耗时中的占比急剧上升,GPU 算力反而在等数据。拓扑感知放置与分组路由可以减少跨节点的通信量:把经常互发消息的设备放在同一节点内,或把路由范围限制在组内。
小消息是第三种。通信延迟由等待时间和传输时间共同构成,消息越小、传输时间越短,等待时间的占比就越高,延迟主导了整个通信。增大 token 批次、把多个小消息融合成更大的传输单元,可以让网络真正忙起来。
长尾序列是第四种。动态批处理里序列长度参差不齐,短序列早早结束、长序列拖着尾巴,各设备的工作量此起彼伏,批与批之间负载不均。这需要容量策略与调度策略配合,而不是只调均衡损失。
这些瓶颈共同指向一个结论:每 token FLOPs 的下降不保证墙钟延迟下降。MoE 在算术上省下的计算,可能被通信延迟和等待吃掉;它比稠密模型更依赖高速互连与足够的批量规模。用 FLOPs 判断 MoE 的“快”,忽略了通信这个第一等成本。
| 瓶颈 | 表象 | 缓解 |
|---|---|---|
| 专家热点 | 部分 GPU 等待/溢出 | 均衡、复制热门专家 |
| 跨节点带宽 | all-to-all 占比高 | 拓扑感知放置/分组路由 |
| 小消息 | 延迟主导 | 增大 token batch/融合 |
| 长尾序列 | 动态批不均 | 容量和调度策略 |
6训练与推理的热点分布可能不同部署
训练时负载均衡做得很好,推理时某个专家仍可能被瞬间打满,原因是两边的流量结构根本不同。训练语料是混合语言、混合领域的大批量数据,路由看到的是一锅搅匀的输入,热点天然被摊薄;均衡目标也在这个分布上生效。生产流量却不是这样:某个时段用户突然集中询问同一主题(比如一次热点新闻事件),大批语义相近的请求涌向同一个专家,批次又小、逐 token 生成,路由分布比训练时尖锐得多。训练时测出来的“均匀”,是在训练分布上的均匀,不能自动迁移到推理分布上。
因此推理需要自己的监控维度,而不是信任训练指标:每层、每个专家的实际负载,路由熵(分配是否过于集中),溢出率,all-to-all 耗时,以及批量和切片质量。针对可能出现的峰值主题做压测,比事后发现某个 GPU 排队更有价值。这些监控的对象是系统行为,不是模型质量本身。
并行策略也要为推理的尖峰留出组合空间。专家并行(expert parallel)把不同专家放到不同设备,配合张量并行或数据并行可以同时利用设备内与设备间的算力;但组合越复杂,网络拓扑设计和故障恢复就越复杂——一个节点故障时,它的专家副本或重算路径必须能顶上。
最后一条边界容易被忽视:稀疏计算不等于稀疏存储。未激活的专家当次不算,但权重通常仍需驻留在显存,或处于能快速访问的分层存储中。总参数量因此直接影响显存占用和启动时间:一个总参数万亿的 MoE 模型,即便每个 token 只激活百亿参数,启动时仍然要为全部权重找好落脚的地方。稀疏性省下的是每个 token 的算术,不是存储。
7专家“专业名称”需要因果证据解释
某个专家经常处理代码相关 token,是否就能称它为“代码专家”?统计上的频繁出现远不足以支撑这个标签。
首先,路由的分工依据未必是语义。专家可能按词频、位置、标点、语言等表面特征分工,也可能只是计算均衡目标的产物——辅助损失把 token 摊开到各专家,某些专家只是“被分配”了代码样本而已。拿少数高频 token 的例子讲故事,特别容易把随机分工拟人化。
互信息(mutual information)在这里衡量的是:已知一个 token 属于某个切片(比如某种语言或主题)之后,能在多大程度上预测它会被路由到哪个专家。它能发现稳定的统计关联,比如“德语 token 更常去 E3”,但关联不等于因果。路由可能是顺着某个与德语共现的特征走的,而不是因为专家“懂德语”。
要检验“专家承担了某种功能”,需要因果干预而不是观察统计。验证的输入是路由日志与能力切片,输出不只是关联统计,还包括交换、屏蔽专家之后的能力变化。如果移除或交换某个专家后,代码相关能力出现选择性下降,同时其他混杂因素(如总体参数减少、其他能力同步受损)被控制,才有较强的证据说该专家与代码功能相关。而且同一编号的专家在不同层的含义可能不同:第 3 层的 E2 和第 21 层的 E2 是两个不同的参数块,分工可以毫无关系。
更深一层的限制来自 MoE 的架构本身。专家不是独立模块:共享的注意力层先把上下文混合起来,token 到达专家时已经带着整句甚至整段的信息;一个行为的产生是多个层的路由与共享层共同作用的结果。因此不能根据某一层某个专家的标签,反推整条回答为什么这样生成,更不能把专家边界当作权限边界——例如“内容专家没被激活,所以模型不可能输出错误事实”这类说法不成立。路由日志记录的是“谁被用了”,它证明不了“因为某个语义理由才被用”。
8MoE 与应用模型路由和多智能体不同消歧
“路由”这个词在 MoE、应用模型路由和多智能体系统中都被使用,但三者的决策粒度与目标完全不同,把它们混为一谈会让定位问题变得困难。
MoE 的选择单位是每层、每个 token。每一层里,路由器为当前 token 在模型内部的多个 FFN 专家之间做选择,候选是同一模型里的参数块。主要目标是参数容量与稀疏计算:用更大的总容量承载更多能力,同时让单个 token 只激活一部分参数。这个路由是模型参数的一部分,随训练学习而来,对使用者不透明。
应用模型路由的选择单位是每个请求或请求中的某个阶段。候选是完整的大模型或不同服务,比如简单请求走小模型、复杂请求升级到大模型,或按模态、按功能把请求发往不同的模型端点。主要目标是质量约束下控制成本:同样的请求量,用小模型处理大部分流量,省下调用开销。这种路由由产品规则显式控制,日志可观测、规则可修改,与 MoE 内部学得的参数路由有本质区别。
多智能体系统的选择单位是子任务。一个任务被拆解后,调度者把子任务分配给不同的角色、工具或上下文环境里的智能体。主要目标是分工、并行与隔离:不同智能体各司其职,任务可以并发推进,错误和权限也被隔离在各自的上下文里。
三者可以叠加使用:一个应用可以在外层做模型路由选择服务,被选中的模型内部再用 MoE 路由做稀疏计算,请求进入模型后还可以由多智能体编排。因此评测时必须分清错误或延迟发生在哪一层:是产品规则选错了模型,是 MoE 的某个专家分配不佳,还是智能体之间的分工出了问题。归错层,修复措施就会打在错误的地方。
| 机制 | 选择单位 | 候选 | 主要目标 |
|---|---|---|---|
| MoE | 每层每 token | 模型内部 FFN 专家 | 参数容量/稀疏计算 |
| 模型路由 | 每请求/阶段 | 完整模型或服务 | 质量约束下成本 |
| 多智能体 | 子任务 | 角色/工具/上下文 | 分工、并行、隔离 |
9评测要同时看容量、质量与系统效率评测
总参数翻 8 倍、激活 FLOPs 近似不变,这样的扩展是否值得,不能靠参数数字回答,而要做一个受控对比。评测的输入是一对模型:MoE 模型与激活 FLOPs 相同的稠密基线,两者在同一任务、同一硬件、同一网络和同一批量下运行。只有把激活计算量对齐,比较才公平——否则分不清优势来自稀疏机制,还是只是多算了。
质量侧与系统侧各有一组指标。质量侧看验证损失、具体任务表现、各语言切片、安全行为、校准度与稳定性。系统侧看 tokens/s 吞吐、TTFT(首 token 延迟)、TPOT(每输出 token 延迟)、显存占用、all-to-all 通信占比、溢出率、功耗与故障恢复时间。MoE 的收益常常在系统侧被通信吃掉,只在质量侧打分会把一个“算得快但墙钟慢”的模型误判为成功。
负载均衡需要一个明确的口径。专家负载 CV 是各专家负载的标准差除以平均值:CV = 0 表示完全均匀,数值越大表示相对偏斜越严重。它是衡量算力分配均匀性的工具,但低 CV 不等于语义路由合理,也不等于各语言或各群体的质量更好——负载均匀只是分配均匀。检验功能是否稳健需要更硬的干预:做专家消融(逐一或成组移除专家)与路由扰动,观察少数专家故障时能力是否整体崩溃,而不是被冗余平滑吸收;同时把训练分布与生产分布下的热点分别拿出来比较,看推理时的偏斜是否在预期范围内。
最终的报告必须列出总参数量与激活参数量、top-k、容量因子和并行拓扑,这几项缺一,参数数字就可能误导读者。判断“值得”的标准是:在目标网络与批量条件下,质量—成本前沿可复现地改善,并且这种吞吐提升不是靠丢 token、靠个别切片退化换来的。任何一项成立,都说明扩展的收益被低估或伪造了。
10把因果链连起来综合
把前面各环节连成一条完整的因果链,MoE 从“一个 token 进来”到“一次扩展被验收”之间的每一步因果都是清晰的。
起点是 token 的上下文表示进入路由器。经过注意力层混合上下文之后,这个向量带着该 token 在当前语境下的全部信息,路由器用它为每个专家打出一个分数,再经 softmax 变成概率分布。路由器的输出不是一个标签,而是一组可微的权重——这一设计同时决定了选择(谁被选中)与可训练性(梯度能经由这些权重传回路由器)。
第二步是 top-k 选择与容量分配。路由器选出概率最高的 k 个专家,选中的专家按集合内重新归一化后的权重参与合成;同时,每个专家的容量上限按容量因子 × 平均负载预先划定,热点专家超出容量的请求进入溢出处理。这一步把“模型想算谁”和“系统允许算多少”两股力量合到了一起:前者追求语义匹配,后者限制单点过载。
第三步是 all-to-all 发送。token 按目的地专家打包,跨越设备边界被送到持有专家的 GPU。通信在这里第一次成为显性成本:路由偏斜、跨节点链路、小消息和长尾序列都会让这步变得昂贵。第四步,专家并行计算并加权返回。持有专家的设备执行 FFN,把各专家的输出按重新归一化权重合成为最终的更新表示,再反向 all-to-all 送回原 token 出发的位置,恢复原有顺序进入下一层。
第五步,均衡与溢出控制作用于全程。辅助损失和 z-loss 在训练时防止路由坍缩、抑制 logits 发散;容量与转投策略在运行时兜住热点;推理侧还需按生产分布监控各层专家负载、路由熵与溢出率——因为推理流量的热点分布可能与训练完全不同。第六步,联合验收。判断一次 MoE 扩展是否值得,要看质量、通信、容量和切片四个维度在同一组受控条件下的共同表现:质量侧对齐激活 FLOPs 的稠密基线,系统侧测量吞吐、TTFT、TPOT 与 all-to-all 占比,容量侧核对总参数、激活参数与专家负载 CV,切片侧确认没有哪个语言或群体以退化换取整体数字。任何一环失衡,都会在链上留下具体的位置:路由坍缩看第四步前的梯度与均衡,通信瓶颈看第三步,溢出看第二步的容量设定,质量滑坡看第一步的路由语义。链是闭环的——验收暴露的问题,正是指向链条上对应环节的因果证据。
- Outrageously Large Neural Networks:稀疏门控 MoE
- GShard:大规模专家并行与容量
- Switch Transformers:top-1 路由与均衡
- ST-MoE:稳定训练与迁移