混合专家模型 (MoE) 深度剖析:从稀疏架构到负载均衡¶
在大模型卷参数量的时代,如何用可控的计算成本撬动更大的模型容量?混合专家模型 (Mixture of Experts, MoE) 几乎成了标准答案。它不是简单地堆叠层数,而是通过“稀疏激活”让模型学会“按需调用”参数,让一部分参数专门处理动词、一部分专门处理名词,形成自然的分工。下面我把MoE的每个核心组件拆开揉碎,结合实践中踩过的坑,把设计动机和实现细节彻底聊清楚。
MoE 模型的基本结构:把 FFN 变成一个“专家团队”¶
在标准 Transformer 中,每个 token 经过自注意力后会进入一个共享的前馈网络 (FFN)。这个 FFN 虽然宽(通常是隐藏维度的 4 倍),但所有 token 共享同一组权重。这就好比一个公司里所有员工都只会做同一件事,无论来什么活都是那一套流程。MoE 的灵魂改造就是把这一层 FFN 替换为一组并行的、独立的 FFN,称为“专家”(Experts),并引入一个门控网络 (Router/Gate) 来决定每个 token 应该分发给哪些专家,相当于给公司配了多个不同技能的团队,每件事只交给最擅长的人去处理。
直观的结构是:
-
输入序列经过自注意力层,得到每个 token 的表示。自注意力负责 token 间通信,MoE 只替换 FFN,两者分工明确。
-
这个表示进入门控网络,计算出每个 token 对各个专家的“偏好分数”。门控网络本身通常就是一层线性变换:
logits = x @ W_gate,其中 W_gate 的形状是 [d_model, num_experts],参数量很小(通常不到模型总参数的 1%)。 -
根据偏好分数,通过 Top-k 策略选出最合适的 1 个或 2 个专家。具体怎么做:对 logits 取 softmax 得到概率分布,然后选概率最高的 k 个索引。被选中的专家对应的 softmax 概率值作为后续加权合并的权重。
-
Token 被送往选中的专家进行计算,得到各自输出。每个专家内部就是标准的 FFN,通常是 SwiGLU 结构(两个线性层加门控激活),从隐藏维 d_model 升到中间维 d_ff(通常 4 倍或 8/3 倍),再降回 d_model。
-
最后,门控的权重对多个专家输出进行加权合并。如果 k=1,就直接用那个专家的输出乘以它的路由权重;如果 k>1,就把多个专家的输出按各自的路由概率加权求和。合并后的结果就是这个 token 最终的 FFN 输出,送入下一层或残差相加。
整个 MoE 层因此由三部分构成:一个门控路由器、多个专家 FFN,以及一个稀疏计算调度器——在分布式环境下,专家分布在不同 GPU 上,这个调度器负责通过 all-to-all 通信高效分发和收集 token。调度器的实现非常关键,做不好会成为性能瓶颈。
为什么 MoE 能增加参数却不显著增加计算量?¶
核心就在于“稀疏激活”。标准稠密模型中,无论输入是什么,FFN 的所有参数都要参与计算,每个 token 都要走过完整的矩阵乘法。而在 MoE 中,假设总共有 N 个专家,每个 token 只激活其中 k 个(通常 k=1 或 2)。那么该 token 实际经历的计算量只是 k 个专家 FFN 的计算量,与稠密模型中一个较大的 FFN 的计算量在同一量级(甚至更小,因为专家 FFN 的隐藏维度可以设计得较窄)。模型总参数量却因为拥有 N 个专家而膨胀了约 N/k 倍。
用一个具体数字举例:一个标准 Transformer 的 FFN 有 1 亿参数。如果我们用 MoE 替换,设置 8 个专家,每个专家设计为同样规模,总参数就是 8 亿。但每个 token 只激活 1 个专家,计算量仍然是 1 亿参数的计算量。这就好像你有一个八人团队,但每次干活只有一个人在忙,其他人休息——团队规模(参数)大了,但单次人力消耗(计算)没变。这种“参数膨胀而计算不膨胀”的特性,让 MoE 在扩大模型容量时,推理和训练的计算成本呈亚线性增长,成为大模型时代的“免费午餐”。
当然,实际中并非完全没有额外开销。门控网络计算本身计算量很小可以忽略,但 token 的分发和收集会产生通信和调度成本,尤其在分布式环境下。如果专家分布在不同的 GPU 上,需要通过网络把 token 从路由所在的 GPU 发送到专家所在的 GPU,计算完再发回来,这两次 all-to-all 通信是 MoE 训练的主要额外开销。此外,动态路由使得每次迭代的计算负载不固定,对集群的负载均衡提出挑战。
什么是“稀疏激活”?在 MoE 中如何体现?¶
稀疏激活指的是:对于每个输入 token,只有整个网络参数的一小部分被“唤醒”参与计算,其余参数处于休眠状态,不参与前向和反向传播。这与人脑的工作方式相似——面对不同刺激,不同的神经元集群被激活。
在 MoE 中,稀疏激活体现在门控路由的选择上。当 token 通过路由网络计算出对各专家的偏好后,只有得分最高的 Top-k 专家被激活,token 被送到这些专家中进行 FFN 计算,其余专家的输出对该 token 为零。反向传播时,也只有被激活的专家参数被更新,未被激活的专家对当前 token 没有梯度。这带来两个重要特性:一是计算负载的动态性,不同 token 可能激活不同的专家组合,整个 batch 的计算模式不是固定的;二是专家的特化,如果训练得当,不同专家会逐渐专注于处理不同类型的数据,形成“术业有专攻”的分工。
举个例子:训练一个多语言模型,MoE 层可能会自发地让专家 0 擅长英语语法、专家 1 擅长中文语法、专家 2 擅长代码等等。这种分工不是人为设定的,而是路由网络在训练中自动学出来的。当输入是英文句子时,大部分 token 被路由到专家 0;输入是中文时,切换到专家 1。这种动态激活让模型用更少的总计算量处理了更多样的任务。
MoE 中的“专家”通常是什么?一个 FFN 层。¶
在当今的 Transformer MoE 中,专家几乎无一例外是标准的前馈网络 (FFN) 层。具体来说,就是传统 Transformer 里 Attn 之后的两层全连接(升维+非线性+降维)。现代 MoE 中,专家通常采用 SwiGLU 等门控激活变体,因为这类激活在同等参数下表现更好。SwiGLU 的 FFN 有三个权重矩阵:W_gate、W_value 和 W_out,比传统 ReLU-FFN(只有两个权重矩阵)多一个,但通过把中间维度设为原来的 2/3,总参数量可以保持不变。
为什么专家是 FFN 而不是注意力头?因为自注意力本身已经负责了 token 间的信息聚合,而 FFN 承担的是对每个 token 内部表示的独立非线性变换,即“知识存储和特征处理”。这部分参数量巨大且相对独立,非常适合用 MoE 来横向扩展。此外,FFN 的计算是 token 级别独立的,不需要跨 token 交互,路由分发相对简单——每个 token 可以独立决定自己去哪个专家。
如果把注意力也设计成专家,会增加系统复杂性。注意力计算需要不同 token 的 QKV 交互,如果不同 token 被路由到不同的注意力专家,它们之间怎么交互?这需要更复杂的跨专家通信机制,工程实现难度大且通信代价高。因此,目前主流 MoE 都只在 FFN 层引入专家。
描述 Top-k 路由 (Routing) 机制:如何选择专家。¶
Top-k 路由机制的目标是:为每个 token 从 N 个专家中选出最合适的 k 个(k 通常为 1 或 2),并将 token 送往这些专家。流程如下:
-
门控网络接收 token 表示 h (shape: [batchseq, d_model]),输出 logits z = h @ W_gate (shape: [batchseq, N])。W_gate 是可学习的线性投影矩阵,形状 [d_model, N],N 是专家数量。
-
对 logits 取 softmax,得到概率分布 p = softmax(z)。p_i 表示这个 token 选择第 i 个专家的概率。
-
选择 p 中最大的 k 个值对应的专家索引。例如 k=2 时,取 top-2 概率对应的专家。
-
将 token 分发到对应专家。如果 k>1,token 会被复制多份分别发送到不同的专家。在分布式环境下,这一步通过 all-to-all 通信实现:每个 GPU 上的 token 按目标专家分组,发送到对应 GPU。
-
每个专家独立处理收到的 token 子集(做 FFN 前向),输出处理后的结果。
-
最终输出根据路由权重进行合并。对于 k=1,直接取该专家输出乘以路由权重(或不乘,实验表明不乘权重有时效果更好)。对于 k>1,按各专家的路由概率加权求和。
在实际训练中,还有一些技巧。比如在 Top-k 选择前加入噪声(如 Gumbel softmax),让模型有一定的随机探索能力,避免初期路由塌缩——即门控很快就只选一个专家,其他专家完全收不到 token 训练。噪声可以在训练初期较大,逐渐减小。另外,还可以设置容量因子(capacity factor),限制每个专家最多处理多少 token,超出的 token 被丢弃或路由到备用专家,防止某个专家过载而拖慢整个 batch。
路由网络 (Gate/Router) 的输出是什么?概率分布还是分数?¶
路由网络的原始输出是 logits 分数,形状为 [num_tokens, num_experts]。经过 softmax 后转化为概率分布。这个概率分布有两个用途:一是用于 Top-k 选择(选概率最高的 k 个索引),二是作为专家输出的加权系数(概率值乘以专家输出,然后求和)。
需要注意:最终送往专家的“权重”通常就是这 k 个专家对应的 softmax 概率值。但实践中也有变体——比如只选专家不乘权重(所有选中专家输出直接等权求和),或者用 logits 本身的值(而不是 softmax 后的概率)作为权重。这些变体各有优劣:乘概率可以让模型更精细地控制信息流,但也增加了计算和通信;不乘权重则更简单,有时反而更稳定。目前主流做法是保留概率加权。
为什么需要负载均衡损失?写出其公式。¶
MoE 训练中一个非常头疼的问题是“专家坍塌”:路由网络在训练初期可能迅速收敛到只激活极少数几个专家(甚至仅 1 个),其他专家收不到 token,得不到训练,形同虚设。这完全浪费了 MoE 的容量优势。坍塌的原因是门控网络存在正反馈循环——某个专家碰巧在初期被多选了几次,它学得稍微好一点,下一轮就更可能被选中,形成富者愈富的马太效应。
负载均衡损失就是为了打破这个正反馈而设计的。它鼓励所有专家被均匀使用,具体做法是在训练损失中加一个辅助项,惩罚专家间的 token 分配不均。
公式:
其中:
-
N 是专家数量。
-
f_i 是第 i 个专家实际处理到的 token 比例(在整个 batch 中,有多少比例的 token 被路由到了专家 i)。计算方式是对该专家的路由概率求和后归一化。
-
P_i 是第 i 个专家的平均路由概率(所有 token 对专家 i 的 softmax 概率的均值)。
-
α 是负载均衡损失的权重,通常设为一个较小的值,如 0.01。太大了会强制所有专家完全均分 token,破坏专家的特化能力;太小了又起不到均衡作用。
这一项的直观含义是:如果 token 集中在少数专家上,f_i 和 P_i 会同时偏大,乘积增大,损失增加,迫使门控把 token 分配给更多专家。训练初期通常需要设置较大的 α 来建立均衡,随着训练进行可以逐渐减小 α 让专家更自由地分化。监控指标是每个专家的 token 接收量,理想情况是各专家负载大致均衡,但允许有一定差异。
为什么推荐选择 Top-2 路由,而不是 Top-1 或 Top-3?¶
实践中,Top-2 通常是效果和开销的最佳平衡点。
-
Top-1 (Switch Transformer):计算开销最小,每个 token 只激活一个专家。但缺点是对路由决策的准确性要求极高,一旦路由选错专家,该 token 信息处理完全依赖一个可能不合适的专家,表达能力受损。同时训练稳定性较差,容易坍塌到少数专家。
-
Top-2 (大多数 MoE 模型,如 GShard, GLaM, Mixtral):计算量是 Top-1 的两倍,但仍远小于稠密模型。两个专家可以互补,即使一个选得不太准,另一个也能兜底。两个专家的输出加权组合也增加了模型的表达能力。训练时更稳定,专家更容易分化。
-
Top-3 或更高:计算量继续增大,但边际收益递减。更多的专家意味着每个 token 的计算更接近稠密模型,丧失了稀疏激活的省计算优势。而且不同专家的输出容易趋同,专家特化能力减弱。此外通信开销也线性增加。
因此,Top-2 是目前最主流的选择。以 Mixtral 8x7B 为例,它就是每个 token 选 Top-2 专家。
专家容量 (Capacity) 是什么?如何限制专家负载?¶
专家容量是对每个专家能处理的 token 数量的硬性上限。设置容量的目的是防止某个专家负载过重,拖慢整个 batch 的训练速度,同时在分布式环境下避免某些 GPU 因接收过多 token 而显存爆炸。
容量公式:
其中 total_tokens 是整个 batch 的 token 总数,num_experts 是专家数,capacity_factor 是容量因子(通常设为 1.0~1.5)。容量因子 1.0 意味着每个专家只能处理平均分配量的 token。容量因子 1.5 允许单个专家处理 1.5 倍的均量,提供一定弹性。
如何限制负载:当某个专家收到的 token 数超过容量时,多余的 token 会被“溢出”。溢出的处理方式有几种:
-
直接丢弃:这些 token 不经过任何专家处理,直接跳过 MoE 层(残差连接会保留原始信息)。实现简单,但可能丢失重要信息。
-
路由到下一个专家:将溢出 token 重新分配给仍有容量的专家,但可能打乱原来的路由意图。
-
使用共享专家:额外设置一个不参与路由的“共享专家”,所有溢出 token 统一送到这里处理。
在实践中,容量因子通常设为 1.25~1.5,既能保证大部分 token 不被丢弃,又不让任何专家过载。监控指标是每个专家的实际 token 处理量,理想情况下应接近容量但不超过它。
负载均衡损失的权重如何设置?对训练的影响¶
负载均衡损失权重 α 是 MoE 训练中最敏感的超参数之一。它控制着专家间 token 分配的均匀程度:过大导致专家丧失特化能力,过小则无法阻止路由坍塌。
权重设置经验:
-
α通常取值在 0.01 ~ 0.1 之间,最常见的是 0.01。Switch Transformer 使用0.01,GShard 使用0.001~0.01。 -
专家数量越多,token 分配越容易不均衡,可适当增大
α(如 0.05)。 -
全局批次越大,统计上越均匀,
α可适当减小。 -
容量因子越小(溢出风险高),需要更强的负载均衡来防止溢出,可增大
α。
辅助损失的计算:该损失仅作用于门控网络参数,不影响主任务损失的梯度流向。公式为:

对训练的影响:
-
α过大:路由权重趋于均匀分布,所有专家处理相近数量的 token,专家特化能力被抑制,模型最终效果下降。此时每个专家都变成“通才”,失去了 MoE 结构带来的容量提升。 -
α过小:门控网络缺乏约束,正反馈导致 token 迅速集中到少数专家,其他专家“饿死”。模型有效参数量骤减,退化回稠密模型,且由于溢出丢弃大量 token,训练损失震荡甚至发散。 -
调试时可监控专家接收 token 数量的直方图。若某专家长期无 token,需增大
α;若所有专家负载完全均匀但下游指标不佳,可减小α给特化留出空间。理想状态是大部分专家负载大致均衡,但允许最忙专家接收量是最闲专家的 2~3 倍。
什么是“专家容量” (Expert Capacity)?为什么需要?¶
专家容量是每个专家在一个批次中能处理的 token 数量上限。它像餐厅的座位数——超出座位数的客人必须离开(溢出)。
为什么需要专家容量?
-
计算效率:在分布式训练中,专家分布在不同 GPU 上。若无容量限制,门控可能将大量 token 路由到同一 GPU,导致该 GPU 计算和显存骤增,其他 GPU 闲置,整个 batch 等待最慢的 GPU,严重拖慢训练。
-
显存约束:每个专家需要为接收的 token 分配中间激活缓冲区。大量 token 涌入同一专家会导致显存峰值不可控,可能触发 OOM。
-
可预测性:容量限制使每步计算和显存占用可预测,利于资源调度和稳定性。
容量公式:

专家容量如何计算?公式:capacity = (tokens_per_batch / num_experts) * capacity_factor。¶
具体推导:

当 token 超过专家容量时,发生“溢出” (overflow),如何处理?丢弃或绕路。¶
当路由到某个专家的 token 数超过其容量时,多出的 token 称为“溢出 token”,必须处理。
处理方法:
-
丢弃:将溢出 token 的专家输出置为 0,相当于只依赖残差连接跳过该 MoE 层。实现简单,但信息丢失。少量随机溢出(<5%)影响不大,大量溢出则损害模型。
-
绕路(残差路径):基本等同于丢弃,因为 MoE 层输出为残差加法,溢出 token 直接使用输入作为输出。
-
共享专家兜底:为所有溢出 token 设置一个不参与路由的独立 FFN(共享专家),统一处理溢出,保证每个 token 都得到专家处理。此方法更精细,但额外增加参数。
在 Switch Transformer 和 GShard 中,直接采用丢弃策略,配合足够大的容量因子(≥1.25)将溢出率控制在 1% 以下。
什么是“容量因子” (Capacity Factor)?常用值是多少?¶
容量因子是控制专家容量弹性的乘数,表示专家可处理 token 数相对于平均分配量的倍数。
常用值:1.0 ~ 1.5。
-
1.0:刚好平均,没有余量,一旦不均立即溢出。
-
1.25:留有 25% 余量,常见折中值。
-
1.5:更宽裕,溢出率更低,但资源浪费略多。
分析容量因子过小或过大的后果。¶
容量因子过小(如 ≤1.0)¶
-
大量 token 溢出丢弃,模型有效信息损失。
-
训练损失震荡,收敛困难。
-
门控网络可能学习“捷径”:将 token 发送到不易溢出的专家,破坏负载均衡。
-
极端情况(0.5)导致 MoE 层几乎退化,模型性能大幅下降。
容量因子过大(如 ≥2.0)¶
-
每个专家预留大量显存和计算资源,实际使用率低,资源浪费。
-
训练吞吐下降,GPU 利用率降低。
-
门控缺乏压力,可能加剧不均衡——既然随便怎么分都不溢出,负载均衡损失更难生效。
-
显存峰值过高,可能导致 OOM。
MoE 训练中,如何保证各专家接收的 token 数均衡?¶
-
负载均衡损失:核心手段,惩罚分配不均。
-
容量与溢出机制:间接约束门控避免热门专家溢出。
-
路由随机性:Top-k 选择前加入 Gumbel 噪声或随机采样,鼓励探索,训练初期常用。
-
调度器智能分发:部分框架(DeepSpeed-MoE)支持对溢出 token 二次分配。
-
监控与动态调参:实时观察专家负载直方图,动态调整
α或容量因子。
为什么 MoE 容易发生“专家坍塌” (Expert Collapse)?部分专家不被使用。¶
专家坍塌是指门控迅速将几乎所有 token 路由到极少数专家,其余专家闲置,模型退化为稠密模型。
坍塌原因:
-
门控正反馈:初期某专家稍占优势,学到更多,得分更高,吸引更多 token,形成富者愈富循环。
-
确定性 Top-k 选择:缺乏随机性,门控快速收敛到局部最优。
-
batch size 过小:统计波动大,门控容易固化。
-
负载均衡损失不足:权重过小无法抵抗正反馈。
缓解措施:
-
增大负载均衡损失权重。
-
加入路由噪声(Gumbel softmax)。
-
使用足够大的 batch size 和容量因子。
-
训练初期监控,必要时重置门控权重或调低热门专家学习率。
以上是 MoE 负载均衡与专家容量的系统解析。实际训练中,这些策略通常组合使用,并根据实时监控指标动态调整,才能让 MoE 模型稳定发挥其稀疏激活的优势。
怎样检测专家坍塌?通过监控各专家处理的 token 数。¶
专家坍塌是 MoE 训练中最隐蔽也最致命的故障模式。它的本质是门控网络的正反馈循环——某个专家初期碰巧被多选了几次,学得稍好,下一轮得分更高,吸引更多 token,最终垄断所有输入;其他专家收不到 token,梯度为零,参数永久停滞。检测坍塌的关键在于建立一套全面的专家负载监控体系,而不是等到 loss 异常才去排查。
最直接的指标:每个专家每步接收的 token 数量。在训练循环中,每完成一次路由,统计各专家实际处理的 token 数。可以记录以下几个维度:
-
实时分布:每一步各专家的 token 数直方图。如果直方图高度集中在少数几个专家上(比如只有 2 个专家有数据,其余 6 个为 0),说明已经严重坍塌。正常情况应该是所有专家都有一定数量的 token,呈相对均匀分布。
-
移动平均:单步统计可能因 batch 差异有波动,因此需要维护一个滑动窗口(比如最近 100 步)的移动平均值。如果某个专家的移动平均 token 数长期为零或极低(比如不到平均值的 5%),那么该专家已经“死亡”。
-
使用率百分比:每个专家处理的 token 数占总 token 数的比例。用 TensorBoard 或 wandb 绘制饼图或堆叠柱状图,直观展示负载分布。一旦某个专家的使用率持续低于
1/(N*2)(即不到均匀分配的一半),应发出告警。 -
路由熵:计算每个 token 对各专家路由概率的熵。健康状态下,门控 softmax 输出应有一定不确定性(熵较高,说明模型在多个专家间权衡)。坍塌时,大部分 token 的 softmax 输出极度尖锐(熵极低,几乎只选一个专家)。
辅助监控指标:
-
各专家参数的梯度范数:若某专家的梯度范数持续为零或极低,该专家已停止学习。
-
专家权重更新量:类似地,检查
optimizer.step()前后专家权重的变化量。坍塌的专家更新量为零。
检测到坍塌后的处置:立即暂停训练,分析原因。可以先增大负载均衡损失权重或容量因子,从最近的健康 checkpoint 恢复训练。若问题持续,可能需要重新初始化门控权重,或暂时降低热门专家的学习率给冷门专家追赶的机会。
如何缓解专家坍塌?调整负载均衡损失权重、添加噪音等。¶
缓解专家坍塌需要多管齐下,形成“约束+探索+兜底”的组合防线。单一手段往往效果有限,实际中通常同时启用以下策略。
硬约束:负载均衡损失 (Load Balance Loss)
这是最基础的防线,直接惩罚路由分配不均。公式为 L_aux = α * N * Σ(f_i * P_i),其中 f_i 是实际分到专家 i 的 token 比例,P_i 是平均路由概率。权重的选择直接影响效果:在训练初期,门控不稳定,通常将 α 设得较大(如 0.1),强制所有专家获得相近的训练机会;待各专家初步建立能力后,可以逐步减小 α(如 0.01),给专家特化留出空间。如果监控发现某些专家仍然收不到 token,可以直接临时增大 α。
探索机制:路由噪声 (Gumbel Softmax / Noisy Top-k)
标准 Top-k 路由是确定性的——永远选分数最高的专家。这容易导致初期固化。通过在 softmax 前加入 Gumbel 噪声,路由变为随机采样:专家 i 被选中的概率正比于其分数,但有一定随机性。即使某专家当前分数略低,仍有机会被“探索”。噪声强度在训练初期较大,随着训练推进逐步衰减,让模型从探索过渡到利用。Switch Transformer 中使用了这种随机路由策略,有效防止了早期坍塌。
容量限制:防止热门专家过载
设置专家容量(capacity = avg_tokens * capacity_factor),当热门专家接收 token 超过容量时,多余的 token 被丢弃(或路由到其他专家)。这从物理上限制了单个专家的负载上限,避免形成绝对垄断。即使门控想给某个专家更多 token,容量限制也会强制部分 token 流向他处。
学习率隔离与重置
如果发现热门专家与冷门专家差距过大,可以对热门专家使用较小的学习率(减缓其更新),冷门专家使用较大的学习率(加速追赶)。在极端情况下,直接重新初始化冷门专家的权重或整个门控网络,让训练重新开始。
监控与自动化
建立自动化告警系统:当某个专家的移动平均 token 数连续 N 步低于阈值时,自动触发 α 增大、容量因子提升或门控噪声增强,实现“自动驾驶”式的训练调整。
解释“Switch Transformer” 的简化路由:top-1 路由。¶
Switch Transformer 是 Google 在 2020 年提出的 MoE 架构,它采用了一种极致的简化——Top-1 路由。顾名思义,每个 token 不再像传统 MoE 那样选择 Top-2 或多个专家,而是只被路由到唯一一个专家。这是对“稀疏激活”理念的最彻底实践。
具体流程:
-
门控网络接收 token 表示,输出对各专家的 logits。
-
对 logits 取 softmax,得到概率分布 p。
-
选择 p 中最大的那个专家索引,将 token 发送给该专家。
-
专家处理 token,输出结果。由于只有一个专家,不存在加权合并,直接将该专家的输出作为 FFN 层输出。
为什么用 Top-1?
-
最小化计算量:每个 token 只激活一个专家,计算量最低,稀疏激活的优势最大化。
-
结构简单:省去了多专家输出加权合并的步骤,实现更直接。
-
效果不差:实验表明,在合适的容量和负载均衡下,Top-1 路由的效果可以与 Top-2 媲美,而计算成本更低。
挑战:Top-1 路由对门控的准确性要求极高。一旦路由决策失误,token 被送到不擅长的专家,输出质量就会下降。此外,Top-1 更容易发生专家坍塌,因为缺乏多专家之间的互补和缓冲。因此 Switch Transformer 需要配合更强的负载均衡策略、更大的容量因子以及训练中的随机路由来确保稳定。
Switch Transformer 如何实现稳定训练?(选择性精度、容量因子等)¶
Switch Transformer 采用了一系列工程技巧来克服 Top-1 路由带来的训练不稳定性,这些技巧后来也成为 MoE 训练的通用最佳实践。
选择性精度 (Selective Precision)
并非所有操作都需要 FP32 或 FP16。Switch Transformer 采用了一种“混合精度+选择性 FP32”策略:
-
大型矩阵乘法(专家 FFN 内部的计算)使用 FP16/BF16,利用 Tensor Core 加速。
-
路由网络的计算使用 FP32,因为门控输出直接影响 token 分发,对精度敏感。FP32 的精度能确保 softmax 概率估计更准确,避免因精度问题导致路由偏差。
-
梯度同步和优化器状态也使用 FP32,保证更新稳定。
容量因子 (Capacity Factor)
Switch Transformer 大量依赖容量因子来控制专家负载。通常设置 capacity_factor = 1.25,意味着每个专家能处理平均分配量 1.25 倍的 token。如果某个专家收到的 token 超过这个上限,多余的 token 直接被丢弃(残差连接兜底)。这个机制从物理上防止了任何专家过载,即便门控网络试图把所有 token 发给同一个专家,容量限制也会强制溢出部分 token 到其他专家或丢弃,保护训练稳定性。
负载均衡损失
Switch Transformer 使用了一个简化的负载均衡损失公式:L_aux = α * N * Σ(f_i * P_i),其中 α=0.01。这个损失鼓励均匀分配。与容量因子配合,两者形成了“软约束+硬限制”的双重保障。
随机路由 (Stochastic Routing)
训练初期,Switch Transformer 在 Top-1 选择时加入 Gumbel 噪声,使路由随机化,鼓励探索。随着训练进行,噪声逐步衰减,模型逐渐过渡到确定性 Top-1 路由。
初始化技巧
门控网络的权重初始化为均值为 0、方差较小的正态分布,使得初始时各专家被选中的概率接近,避免一开局就坍塌。
大批量训练
Switch Transformer 使用极大的 batch size,使专家负载统计更稳定,减少单步波动。
MoE 模型在分布式训练中如何做“专家并行” (Expert Parallelism)?¶
专家并行是一种专门为 MoE 设计的分布式策略,将不同的专家放置在不同的 GPU 上,每个 GPU 只负责计算自己持有的专家。
工作流程:
-
每个 GPU 上运行完整的自注意力层(这部分可以是数据并行),产出 token 表示。
-
进入 MoE 层后,每个 GPU 独立运行门控网络,计算本地 token 对各专家的路由分数。
-
根据路由决策,每个 GPU 知道自己的 token 需要被送往哪些专家(可能在本卡也可能在其他卡)。
-
执行 All-to-All 通信:各 GPU 将 token 重新分发,属于专家 0 的 token 全部汇集到持有专家 0 的 GPU,属于专家 1 的 token 汇集到持有专家 1 的 GPU,以此类推。
-
每个 GPU 在自己持有的专家上对收集到的 token 执行 FFN 计算。
-
再次执行 All-to-All 通信:将处理完的 token 送回其原始 GPU,恢复原始顺序。
-
继续后续层的计算。
专家并行的优势在于:模型参数(专家 FFN)被分布到多卡,每张卡只存储一部分专家,显存压力减轻;同时每个 token 只激活 1~2 个专家,计算负载也被分散。这天然适合大规模 MoE 训练。
专家并行的通信核心是什么?All-to-All。¶
专家并行的通信核心是 All-to-All 集合通信操作。它不同于 AllReduce(所有卡求和后广播)或 AllGather(各卡贡献一部分拼接后广播),All-to-All 的特点是:每张卡向其他所有卡发送不同的数据块,同时从其他所有卡接收不同的数据块。操作完成后,各卡持有的数据被完全重新分布。
在 MoE 场景中:
-
第一次 All-to-All:将 token 从“当前 GPU”分布到“专家所在 GPU”。每张卡根据路由决策,把属于不同专家的 token 打包发送给对应卡,同时接收其他卡发来的、应由本卡专家处理的 token。
-
第二次 All-to-All:将处理完的 token 从“专家所在 GPU”送回“原始 GPU”。每张卡把处理完的 token 按原始卡编号打包发回,恢复数据的原始分布。
All-to-All 的通信量正比于 num_tokens * hidden_dim(每个 token 的表示向量)。当序列很长或 batch size 很大时,通信量可能成为瓶颈。因此,优化 All-to-All 是实现高效 MoE 训练的关键。
分析 All-to-All 在 MoE 训练中的通信量:每个 token 需要传输到对应专家。¶
设每个 token 的隐藏维度为 H(FP16 下 2 字节),批次中共有 T 个有效 token。每个 token 需要经历两次 All-to-All(前向分发、前向收集,反向同理)。
-
前向分发:每个 token 的表示向量(H 维)从原 GPU 发送到目标专家 GPU。总通信量为
T * H * 2 bytes。 -
前向收集:专家处理后的 token 表示(同样 H 维)从专家 GPU 发送回原 GPU。总通信量同为
T * H * 2 bytes。 -
反向传播:梯度的传输与前向激活类似,同样两次 All-to-All,通信量基本等同。
因此,单步训练中,All-to-All 总通信量约为 4 * T * H * 2 bytes(前向+反向各两次)。对于大模型,这可能是非常大的数据量,需要高效的网络硬件(如 InfiniBand)和通信优化来支撑。
如何优化 MoE 的 All-to-All 通信?通过混合精度、通信融合。¶
通信量化:将待传输的 token 数据量化为 INT8 甚至 INT4,反量化后再计算。ZeRO++ 和 DeepSpeed-MoE 中使用了类似技术,将 All-to-All 通信量压缩到 1/2 或 1/4。
分层 All-to-All:利用节点内 NVLink 高带宽和节点间 IB 低带宽的层级结构。先在节点内各 GPU 间做一次 All-to-All 聚合,减少节点间通信的数据量,再由代表 GPU 跨节点通信。
融合通信与计算:将 All-to-All 通信与专家计算流水线化。在等待 token 到达时,先处理已到达的 token;在发送结果时,继续处理剩余 token。通过 CUDA Stream 异步执行,隐藏通信延迟。
增大容量因子:可以减少溢出丢弃的 token 数,从而降低无效通信(被丢弃的 token 仍会经历通信但无计算产出)。
拓扑感知的专家放置:将经常被共同激活的专家放在同一节点内,减少跨节点 All-to-All 的通信量。
使用高速网络:InfiniBand NDR/HDR 配合 GPUDirect RDMA,最大化 All-to-All 的带宽利用率。
专家并行可以和 DP、TP 组合吗?常见的组合方式。¶
专家并行 (EP) 可以与数据并行 (DP) 和张量并行 (TP) 灵活组合,形成多维度并行策略,以训练更大的 MoE 模型。
EP + DP:这是最基础的组合。专家被分布到 EP 组内各 GPU 上,而不同 EP 组之间构成数据并行。即:多个模型副本,每个副本内部使用 EP 放置专家,副本间通过 DP 同步非专家参数(如注意力权重)。DeepSpeed-MoE 默认采用此方案。
EP + TP:将单层专家内部的权重矩阵沿隐藏维度切分到多卡(TP),同时专家被分布到不同卡(EP)。TP 切分专家计算,EP 分布专家存储。Megatron-LM 的 MoE 实现支持在 EP 基础上叠加 TP,通常 TP 组限制在节点内(利用 NVLink),EP 可跨节点。
EP + TP + DP:三维并行。例如:TP=2(单节点内切分专家内部),EP=8(专家分布在 8 个节点),DP=16(16 个模型副本)。这是训练超大规模 MoE(如千亿参数)的标准配置。
通信考量:EP 依赖 All-to-All 通信,TP 依赖 AllReduce。组合时需要避免两种通信相互阻塞,通常将 EP 和 TP 组解耦,或者利用 NCCL 的并发通信能力自动调度。
在 Megatron-LM 中如何配置 MoE 的 TP 和 EP?(Expert Parallel + Tensor Parallel)¶
Megatron-LM 通过层次化进程组来管理 TP 和 EP。假设总 GPU 数为 G,TP 并行度为 T,EP 并行度为 E。
-
TP 组:包含 T 张卡,通常在节点内。在 TP 组内,专家内部的线性层(如 FFN 的 W1, W2)被切分。
-
EP 组:包含 E 张卡,通常跨节点。专家被分布到 EP 组内各卡上。每个 EP 组内的专家数量为
num_experts / E。 -
DP 组:剩余维度,
DP = G / (T * E)。
配置时,Megatron 允许指定 --expert-model-parallel-size(EP 并行度)和 --tensor-model-parallel-size(TP 并行度)。TP 切分专家内部矩阵(类似稠密模型的 TP),EP 负责将不同专家放置在不同 GPU 上。两者协同,使得每个 GPU 只存储部分专家的部分权重,显存得到极大压缩。
为什么 MoE 的 TP 通常只切分专家的内部矩阵,而不跨专家?¶
TP 的设计哲学是切分单个操作内部的张量,使得计算可以在多卡上并行,然后通过集合通信合并结果。专家的内部矩阵(如 FFN 的升维和降维矩阵)天然适合 TP 切分——按列切分 W1,按行切分 W2,中间通过 AllReduce 合并。
如果试图“跨专家”做 TP,即把不同专家的权重矩阵也切分,会破坏专家之间的独立性。每个专家的参数是独立的逻辑单元,不同专家处理的 token 不同,它们的输出不是简单的求和关系,而是由路由权重决定的选择性合并。跨专家切分会导致:
-
通信模式混乱:不同专家的 token 混在一起,无法有效利用 All-to-All 的分发。
-
计算依赖复杂:TP 要求所有卡上的输入相同,而 EP 中不同卡接收的 token 不同。
因此,TP 只切分专家内部的矩阵乘法,而专家的分布则由 EP 负责。两者分工明确,互不干扰。
解释 DeepSpeed-MoE 的设计思想:将 ZeRO 和专家并行结合。¶
DeepSpeed-MoE 的设计核心是将 ZeRO 的显存优化思想与 MoE 的稀疏结构深度融合,实现超大 MoE 模型的高效训练。
层次化 ZeRO:
-
非专家参数(注意力层、门控网络):使用标准 ZeRO-1/2/3 进行分片,消除数据并行中的冗余存储。
-
专家参数:采用专家并行(EP)分布到不同 GPU 上,每个专家只驻留在少数 GPU 上,天然避免了全量存储。同时,ZeRO-3 的参数分片也可应用到专家参数上,进一步降低单卡显存。
通信优化:
-
DeepSpeed-MoE 对 All-to-All 通信进行了极致优化,包括量化通信、分层通信、与计算的流水线重叠。
-
支持灵活组合 EP、TP、DP,让用户根据集群拓扑选择最优策略。
负载均衡与容量:
-
内置了负载均衡损失和专家容量限制,训练时自动平衡专家负载。
-
提供了 dropout-based 的溢出处理:溢出的 token 被随机丢弃,依赖残差连接保证信息不完全丢失。
易用性:
-
通过配置文件的简单参数即可启用 MoE 和设置并行度,无需修改模型代码。
-
支持从 HuggingFace 等主流模型库加载预训练权重并扩展为 MoE 结构。
MoE 的训练显存分析:所有专家的参数都必须常驻显存吗?¶
不是。 在标准的 MoE 训练中,是否需要所有专家常驻显存完全取决于你采用的分布式并行策略。
-
无专家并行(纯数据并行):如果只是简单地将 MoE 放在单卡或多卡数据并行但每张卡都拥有全部专家,那么所有专家的参数确实必须常驻在该 GPU 的显存中。因为路由网络可能将任意 token 分配给任意专家,GPU 必须随时准备好计算任何专家。这种模式下,MoE 的显存开销巨大,专家数量一多就无法承受。
-
专家并行 (Expert Parallelism, EP):这是专门为 MoE 设计的分布式策略。将不同的专家放置在不同的 GPU 上,每张 GPU 只持有一部分专家的参数。当 token 需要被路由到专家时,通过 All-to-All 通信将 token 发送到对应的 GPU 上完成计算,再传回来。这样,单卡显存只需存储它负责的那部分专家,而不是全部专家。专家并行使得参数量可线性扩展,是训练超大 MoE 的基础。
-
ZeRO-3 参数分片:更进一步,即使在同一张 GPU 上,也可以利用 ZeRO-3 的思想,将专家参数分片存储,前向时按需 AllGather。但通常 EP 已经极大降低了每卡参数,ZeRO-3 主要用来分片那些非专家参数(注意力层、嵌入层等)。
-
激活值显存:每个 token 只会激活少数专家,所以中间激活只需要为被选中的专家分配空间,而不是全部专家。因此激活显存并不会随专家数爆炸,主要取决于一个 batch 中的 token 总数和容量限制。
因此,通过 EP 和 ZeRO 的组合,只有每个 GPU 负责的那部分专家参数才需要常驻该卡显存,其余专家参数分布在其他 GPU 上,按需通信获取。这是 MoE 能扩展到数百个专家的关键。
如何估算 MoE 模型的总参数量和激活参数量。¶
总参数量 = 非专家参数 + 专家数 × 每个专家的参数量
-
非专家参数:包括嵌入层、所有 Transformer 层中的自注意力模块(QKV 投影、输出投影)、LayerNorm/RMSNorm、以及门控网络本身。这些参数数量与一个同配置的稠密模型完全一致,与专家数无关。
-
专家参数:每个专家本质上就是一个完整的 FFN 层。在现代 MoE 中,专家通常采用 SwiGLU 结构,包含三个权重矩阵:
W_gate(d_model -> d_ff)、W_value(d_model -> d_ff)和W_out(d_ff -> d_model)。所以每个专家的参数量 = 3 × d_model × d_ff(忽略偏置)。如果 FFN 中间维度是标准 4 倍,则每个专家参数约为12 * d_model^2;若使用 8/3 倍以对齐总参数量,参数量会相应调整。
激活参数量(又称动态参数量、每 token 实际计算量) = 非专家参数 + (每个 token 激活的专家数 k) × 每个专家的参数量
-
由于每个 token 通常只激活 Top-1 或 Top-2 个专家,所以激活参数量远小于总参数量。这是 MoE 的核心魅力:用大量总参数获得容量,用少量激活参数控制计算成本。
-
注意:激活参数量不是简单的参数个数,而是前向传播中实际参与运算的矩阵乘法规模。因此,推理时计算量是稠密模型的
1/N * k倍(N 为专家数,假设专家容量与稠密 FFN 相同),但总参数量是稠密模型的N * k倍。例如 Mixtral 8x7B,总参数 47B,但每个 token 只激活 Top-2 专家,激活参数约 13B,推理计算量约等于一个 13B 的稠密模型,却拥有接近 7B×8 的知识容量。
推理时 MoE 的优势:只激活部分专家,推理计算量小。¶
在推理阶段,MoE 的优势尤为突出,因为它完美诠释了“大容量、低成本”。
-
计算量可控:对于每个 token,模型仍然通过门控选出 Top-k 个专家(通常 k=1 或 2),然后只在这些专家上进行 FFN 计算,其余专家完全闲置。因此,单 token 的计算量仅相当于一个具有相同隐藏维度的稠密模型 FFN 的 k 倍(若专家维度与稠密 FFN 相同)。如果专家维度被等比缩小(如 Mixtral 的专家维度只是稠密模型的一半),总计算量甚至可以更低。
-
显存占用:虽然所有专家的权重都需要存放在显存中(或通过 EP 分布存储),但在生成时,KV Cache 才是显存的主要消耗者,而 MoE 的注意力部分与稠密模型完全相同,KV Cache 大小也相同。只是模型权重多了一些,但可以通过多 GPU 分担。对于长序列生成,KV Cache 往往比权重更占显存,所以 MoE 的显存劣势并不明显。
-
速度与质量的权衡:MoE 可以用比同参数稠密模型快得多的速度完成推理,同时因为总参数大而保持更好的性能。例如,Mixtral 8x7B 的推理速度约等于一个 13B 的稠密模型,但性能却接近 30B 的稠密模型。这就是 MoE 在推理上的巨大优势。
-
工程优化:在部署时,可以将热门专家缓存,冷门专家卸载到 CPU 内存,动态调度。vLLM 等框架已经支持 MoE 模型的专家并行和动态加载,进一步降低了单卡门槛。
MoE 模型训练的前向传播过程:路由→分发→专家计算→收集。¶
每一步都包含精密的计算与通信,以下以分布式专家并行为例,描述一个标准 MoE 层的前向传播流程:
- 路由 (Routing/Gating):
- 输入 token 表示
x(形状[batch_size, seq_len, d_model])经过门控网络(一个线性层W_gate)得到 logits。 - logits 通过 softmax 转换为概率分布
p。 - 根据
p,进行 Top-k 选择:对每个 token,选取概率最高的 k 个专家索引,以及对应的概率值g。 -
注意:在前向传播时,有时为了训练稳定性,会加入噪声(如 Gumbel 噪声)来实现随机路由,但在标准的评估/推理阶段,通常直接使用确定性 Top-k。
-
分发 (Dispatch/All-to-All):
- 根据路由决策,每个 GPU 上的 token 需要被送到它们各自对应的专家所在的 GPU。这一步通过第一轮 All-to-All 通信完成。
- 各个 GPU 将本地的 token 按照目标专家分组,打包,发送给对应的 GPU,同时接收其他 GPU 发来的、应由本卡专家处理的 token。
-
通信的数据量 =
num_tokens * d_model。为了优化,可以将 token 和其路由权重一起打包。 -
专家计算 (Expert Computation):
- 每个 GPU 在自己持有的专家上独立计算。对于每个接收到的 token,调用对应的专家 FFN,使用该 token 的表示作为输入,得到输出
y_i。 -
如果容量限制导致溢出,超出的 token 将被丢弃(输出为 0,实际走残差连接)。
-
收集 (Combine/All-to-All):
- 专家计算完成后,需要将 token 结果送回其原始 GPU。这是第二轮 All-to-All,方向与分发相反。
- 各 GPU 将处理后的 token 按原始 rank 打包发回。
- 回到原始 GPU 后,每个 token 可能会收到多个专家的输出(如果 k>1),按照路由权重
g进行加权求和,得到最终的 FFN 层输出。 - 最后将输出加到残差连接上,完成本层的前向传播。
在反向传播中,MoE 的梯度如何流经 All-to-All?¶
All-to-All 通信在反向传播中完美对称,梯度的流动与数据的前向流动方向相反,不需要显式地设计新的通信模式。
-
前向分发 (Token -> Expert GPU):对应于反向的梯度收集。专家计算产生的梯度需要传回给产生该 token 的原始 GPU。因此,反向阶段同样会执行一次 All-to-All,其通信模式与前向的“收集”类似:专家 GPU 将梯度发回 token 原 GPU。
-
前向收集 (Expert GPU -> Token GPU):对应于反向的梯度分发。原始 GPU 需要将输出的梯度传给各个专家 GPU,以便计算专家权重的梯度。所以,反向阶段还会执行另一次 All-to-All,类似于前向的“分发”。
简而言之,前向传播的两次 All-to-All,在反向传播时正好对调角色,同样是两次 All-to-All,总通信量不变。这种对称性使得框架可以自动求导,无需手动编写反向通信逻辑。
对于专家参数的梯度,它只来自于该专家实际处理的那部分 token。这部分梯度在专家所在的 GPU 上直接计算,不参与跨设备的 All-to-All。而门控网络的梯度则来自最终输出对路由权重的偏导,由于 Top-k 的离散性,通常使用直通估计器 (Straight-Through Estimator, STE) 或 Gumbel Softmax 等技巧将梯度传回。
为什么 MoE 的训练稳定性比密集模型更差?¶
MoE 的不稳定性根源于离散路由决策、负载动态变化以及多专家协同训练的竞争关系:
-
离散性带来的梯度偏差:Top-k 操作是离散的,argmax 不可导。我们只能用近似梯度(如 STE)传回,这导致门控网络的梯度估计有偏且方差大。这种有噪梯度容易让路由震荡,甚至陷入坍塌。
-
正反馈循环:训练初期,某个专家若被偶然多选几次,其参数更新更快,下一轮得分更高,吸引更多 token,形成“富者愈富”的循环,导致其他专家“饿死”。这就是典型的专家坍塌。
-
负载不平衡的连锁反应:即使有负载均衡损失,实际训练中负载波动不可避免。当某个专家瞬时负载过高,超出容量限制时,部分 token 被丢弃(输出为零),损失函数中这些 token 的贡献异常,引起 loss 尖峰。
-
通信与计算的耦合:分布式 MoE 中,All-to-All 通信性能高度依赖于负载均衡。一旦某 GPU 上专家过载,该 GPU 计算变慢,导致通信步调不一致,产生额外等待,放大了训练的不稳定性。
-
超参数敏感性:专家数量、容量因子、负载均衡损失权重、学习率等强耦合,调整一个可能导致其他指标失控。
如何针对 MoE 设计专门的初始化方法?¶
MoE 的初始化需要特殊照顾,核心目标是让所有专家在训练初期获得均等的训练机会,避免一开局就坍塌。
-
门控网络初始化:通常采用均值为 0、标准差较小的正态分布(如
N(0, 1/d_model))。这样可以确保初始 logits 值很小,经过 softmax 后接近于均匀分布,每个专家被选中的概率大致相等。例如,Megatron-LM 中会使用--init-method-std 0.02之类的参数来控制。 -
专家 FFN 初始化:与稠密 Transformer 中 FFN 的初始化保持一致(如 Xavier、He 初始化)。通常不需要特殊处理,但有些工作会略微缩小专家权重的初始方差,以减小专家间的初始差异。
-
路由权重零初始化:有时会将门控网络的输出权重(W_gate)初始化为 0,确保初始概率完全均等。不过随着训练进行,模型会迅速打破对称性。
-
Switch Transformer 的技巧:使用均值为 0、标准差为
1/num_experts的高斯分布初始化门控,辅助以 Gumbel noise 和较高的 dropout 率,增强早期探索。 -
学习率缩放:由于门控网络更新的有效样本数远小于专家(每个 token 只更新被激活的专家路径),门控参数的学习率可以适当降低,避免剧烈波动。
MoE 模型中,除了 FFN 作为专家,其他层可以吗?(如 Attention MoE)¶
可以,但实践中绝大多数 MoE 都只把 FFN 层替换为专家,极少数工作会尝试 Attention MoE。
- 为什么 FFN 首选?
- FFN 是token-wise 独立的操作(每个 token 自己升维+非线性+降维),不涉及 token 间的交互。路由决策可以在每个 token 上独立进行,不会破坏序列结构。
- FFN 参数量巨大(通常占总参数的 2/3),用 MoE 扩充容量性价比最高。
-
分布式实现简单:token 分发和收集只需 All-to-All 搬运 token 表示,不涉及复杂的依赖。
-
Attention MoE 的挑战:
- 自注意力需要计算
Q K^T,这依赖于所有 token 的 Q 和 K。如果不同 token 被路由到不同的注意力专家,它们之间的交互如何设计?一种方案是:所有 token 共享 Q 和 K 的投影,然后由不同专家计算不同的注意力模式,但这样会增加大量通信和计算复杂度。 - 有些工作(如 Switch Transformer 的实验)尝试过将 MoE 应用于注意力,但发现增益远不如 FFN-MoE,且训练困难。
- 因此,目前主流的 MoE 仅作用于 FFN,Attention 保持稠密。
什么是“Hash 路由”?与学习式路由的对比。¶
Hash 路由是一种非学习的路由策略,完全根据 token 的某种哈希值来决定送往哪个专家。
-
实现:对每个 token 计算一个哈希函数(如取 token ID 的 hash,或者 token 嵌入的随机投影),然后对专家数取模,得到专家索引。哈希函数是固定的,不参与训练。
-
优点:
- 天然负载均衡:如果哈希函数均匀,专家负载自然均衡,无需额外的辅助损失或容量限制。
- 训练稳定:没有门控网络的正反馈问题,不会坍塌。
-
计算开销极低:不需要计算 softmax 和 top-k,路由几乎是零成本。
-
缺点:
- 缺乏适应性:哈希路由无法根据 token 的语义内容动态分配专家,专家的特化能力较弱。
- 可能将语义相近的 token 分散到不同专家,不利于专家形成专门知识。
学习式路由(基于门控网络)则相反,它通过学习来决定分配,可以按语义聚合,但存在坍塌风险。目前主流仍以学习式路由为主,因为它能带来更好的模型效果。Hash 路由通常作为一种正则化策略或初始化阶段的辅助手段。
随机路由在 MoE 中有什么作用?¶
随机路由(Stochastic Routing)指在训练时,不是确定性地选择 Top-k 专家,而是以一定的概率根据门控输出的分布进行采样,使得每个专家都有被选中的机会。
- 作用:
- 鼓励探索:在训练初期,模型还没有形成稳定的路由偏好,随机路由可以强制 token 探索不同的专家,避免过早集中到少数专家。
- 防止坍塌:它为冷门专家提供了“被看见”的机会,让它们也能获得训练数据,从而维持专家的多样性。
-
平滑梯度:采样过程虽然离散,但配合 Gumbel Softmax 等重参数化技巧,可以使梯度更平滑地流回门控网络,改善训练稳定性。
-
实现:通常在 softmax 之前加入 Gumbel 噪声,然后进行采样。或者使用Top-k 加噪声:先给 logits 加上高斯噪声,再取 Top-k。噪声的幅度可以随着训练逐步减小(退火),让模型从探索过渡到利用。
-
效果:实验表明,使用随机路由训练的 MoE 模型,专家负载更加均衡,最终泛化性能更好,且对超参数不那么敏感。
如何通过“抖动” (Jitter) 噪声改善路由探索?¶
抖动噪声是一种简单有效的随机化手段,其思想是在门控网络的输入或 logits 上添加可控的随机扰动,迫使路由决策具有不确定性,从而促进探索。
- 具体做法:
- 在计算门控 logits 之前,给输入 token 表示
x添加一个小的随机高斯噪声:x_noisy = x + ε * N(0, 1),其中 ε 是噪声系数,通常从较大值(如 0.1)开始,在训练过程中逐渐衰减。 - 或者,直接在 logits 上添加噪声:
z_noisy = z + ε * N(0, 1),然后再 softmax 和 Top-k。 -
这种随机扰动使得每次前向传播时,token 的路由可能略有不同,给予模型尝试不同专家组合的机会。
-
作用原理:
- 初期较大的噪声可以让 token 在各个专家之间“跳来跳去”,帮助模型收集多样化的梯度信号,避免路由陷入局部最优。
- 随着训练推进,噪声逐渐减小,路由趋于稳定和确定,模型可以精细优化专家分工。
-
相比负载均衡损失的软约束,抖动噪声是一种前向过程中的硬探索,能更直接地打破固化。
-
与其他技术的配合:抖动噪声通常与负载均衡损失、Gumbel Softmax 等联合使用,形成多层次的探索-利用调度。例如,在训练的前 10% 步使用较大噪声和 Gumbel,中间逐步衰减,后 50% 步完全采用确定性 Top-k,同时保持负载均衡损失。这种策略在实践中被证明能有效提升 MoE 的最终性能。
DeepSpeed-MoE 让 MoE 训练从“研究阶段”走向“生产可用”,是当前最成熟的 MoE 训练框架之一。