大模型架构 · MoE

什么是 MoE:训练它最难的一步,为什么是路由

参数堆到 6710 亿,每个字却只算 370 亿。这份便宜不是白来的,它把一道选择题塞进了每一次前向传播。

2026-10-01原理拆解 · MoE约 14 分钟

引言:一个 token 的选择题

2024 年 12 月,DeepSeek-V3 的技术报告放出来。里面有个数字被反复引用:总参数 6710 亿,每个 token 只激活 370 亿。比例大约是 5.5%。

这意味着什么?意味着这个模型的权重装满了两个机柜,但处理你打字时输入的每一个字,它只动了其中二十分之一。

这就是混合专家模型(Mixture of Experts,MoE)的全部承诺:把模型的容量和每个 token 的算力拆开。参数可以继续涨,账单不那么涨。

但拆开之后有个问题必须解决。既然只有一部分专家会工作,那是谁来决定哪一部分工作?

答案是个叫"路由"(router,也叫门控 / gating)的小网络。它很轻,通常就是一两层线性变换,参数量在整个模型里几乎可以忽略。但过去八年,从 GShard 到 Switch Transformer,从 Mixtral 到 DeepSeek-V3,几乎所有 MoE 的工程事故都出在它身上。

这篇文章要回答的就是这一件事:为什么这个看起来最简单的部件,是整个 MoE 训练里最难啃的一块。

01什么是 MoE?为什么不干脆把模型做大?

先弄清楚 MoE 换来的到底是什么好处,以及这份好处要拿什么去抵。

稠密模型的逻辑很直白:想更聪明,就堆参数、堆数据、堆算力。问题是这三样是绑在一起的。参数量翻倍,训练和推理的浮点运算量基本也翻倍。到了千亿量级,这条路开始贵得离谱。

MoE 换了个思路。它不把 FFN 层做厚,而是做多。一个 Transformer 层里的前馈网络,原本只有一份;MoE 把它拆成几十上百份,每一份叫一个"专家"(expert)。每个 token 进来,路由只挑其中几个专家来处理它,其余专家的参数这次不参与计算。

于是出现两个不同的参数概念,这两个词必须分清:

两者的比值就是稀疏度。看几个具体模型就明白了。

模型总参数每 token 激活专家配置激活占比
DeepSeek-V3 / R1671B37B1 个共享专家 + 256 个路由专家,激活其中 8 个5.5%
DeepSeek-V2236B21B细粒度专家 + 共享专家8.9%
Mixtral 8x7B46.7B约 12.9B8 个专家,Top-227.6%
Mixtral 8x22B176B约 39B8 个专家,Top-222.2%
Qwen3-Next80B约 3B超稀疏 MoE约 3.7%

稀疏度的高低,一眼能看出来。

Mixtral 8x7B27.6%
DeepSeek-V28.9%
DeepSeek-V35.5%
Qwen3-Next3.7%

横条表示每 token 激活参数占总参数的比例。越短,同样的总参数量下每次计算越省。

但这里有个经常被忽略的坑。MoE 省的是算力,不是显存。所有专家都必须常驻在设备上,才能在需要时被调用。Mixtral 8x7B 每个 token 只用约 12.9B 参数,但 bf16 精度下整套权重仍要占约 90GB 显存,和跑一个 46.7B 的稠密模型没区别,甚至因为调度开销更麻烦。

换句话说,MoE 是拿显存换算力。它解决的问题是"训练和推理太慢、太贵",不是"显存不够"。

那么,省下来的算力是真的吗?取决于两件事:路由挑得准不准,以及被挑中的专家够不够均衡。这就到了最关键的地方。

02一个 token 进门之后,路由到底做了什么?

拆开看,路由只做四件事。但每一件都能出错。

假设一个 token 的隐藏状态是向量 x,进入某一层 MoE。接下来发生的事:

  1. 打分。路由用一个可学习的矩阵 W_g 乘上 x,得到模型对每个专家的"亲和度"分数。router_logits = x · W_g。
  2. 选择。取分数最高的 K 个专家。K=1 是 Switch Transformer 的做法,最省;Mixtral 用 K=2;DeepSeek-V3 用 K=8,另有一个所有 token 都会走的共享专家。
  3. 归一化。把选中专家的分数变成权重,让它们加起来是 1。早期用 softmax,DeepSeek 系改用 sigmoid 算亲和度,再对 Top-K 结果归一化。
  4. 加权求和。output = Σ g_i · Expert_i(x)。每个被选中的专家各算一遍,按权重加起来。

四步里,第二步是分水岭。同样叫路由,实现方式分成两派。

token-choice(token 选专家)是主流,DeepSeek、Qwen、Mixtral 都是这一派。每个 token 主动挑专家,逻辑直白。代价是,热门专家会被挤爆,冷门专家没人光顾。这几乎必然发生。

expert-choice(专家选 token)反过来,让每个专家挑走它最想要的固定数量 token。这样天然均衡。副作用是某些 token 可能一个专家都没挑中,而且推理时每个专家处理的批次大小是变化的,工程上不好写。

还有第三条路:干脆不做离散选择。Soft MoE 用一组权重对所有 token 和所有专家做加权合并,整个过程可微,绕开了"选择"这个动作本身。代价是每个"专家"都要处理所有 token 的一部分,省不下那么多算力。

选完之后还有个物理问题。专家分布在不同 GPU 上。这张卡上的 token,可能被路由判给了另一张卡上的专家。于是前向传播中间必须插一次全对全通信(all-to-all):把 token 发出去,等结果收回来。一次 MoE 层,就多一组这样的往返。

一句话定位:路由不是 MoE 的附属组件,它是调度中枢。它决定了每一层里哪些参数参与计算、多少算力被真正用掉、以及跨卡通信要传多少数据。它的输出只有几行数字,却牵动整张训练图。

03只是挑几个专家,为什么偏偏路由最难?

三个原因叠在一起,每一个都很难单独解决。

原因一:不均衡会自我放大

假设训练刚开始,某个专家的参数因为初始化运气好,比其他专家稍微好一点点。它被选中的概率就高一些。被选中意味着拿到更多 token,拿到更多 token 意味着梯度信号更强,于是它变得更好,然后被选得更多。

这是个正反馈。研究里有个形象的说法叫"富者愈富"。走上几百到几千步,模型就可能只用少数几个专家,剩下几十上百个专家全程没被认真训练过,参数白占了显存,能力一点没贡献。这个现象叫专家坍缩(expert collapse),或者叫路由坍缩。

更麻烦的是它不均匀发生。贫富分化集中在网络的首尾层,中间层反而比较均衡。如果你只抽查中间层,会以为一切正常,问题其实藏在两头。

原因二:离散决策嵌在连续优化里

深度学习的优化器靠梯度。梯度要求函数可微、变化平缓。而 Top-K 选择是个硬切断:分数从第二名掉到第三名,输出会突变。

结果就是,门控权重上一个微小的扰动,可能导致某个 token 的专家分配整个换掉。梯度传不过去,或者传过去的是失真的信号。路由对学习率、批大小、初始化的敏感度,远高于稠密模型。训练过程中的一种典型症状叫"路由器震荡",某个 token 在第 N 步去专家 A,第 N+1 步跳去专家 B,第 N+2 步又跳回来。训练不走直线,在原地打转。

有意思的是,把路由换成确定性的规则(比如用 token 的哈希值固定分配),训练会稳定得多。但实验显示,学习式路由的效果明显更好。稳定和有效,在这里是矛盾的。

原因三:辅助损失和主目标在抢梯度

为了解决不均衡,主流做法是加一个"负载均衡损失"(auxiliary loss / load balancing loss):谁被分配得太多,就罚谁。总损失变成语言建模损失加上这个辅助项,后者前面挂一个系数 α。

α 怎么定?这是个大坑。

Switch Transformer 论文给出的推荐值是 0.01,而搜索范围横跨 10⁻¹ 到 10⁻⁵,中间差了一万倍。这么宽的区间本身就说明了问题:这个系数没有普适解,它随模型规模、专家数量、批大小漂移,换一版配置就得重调一次。

于是这三件事凑成了一个闭环:不均衡逼迫你加辅助损失,辅助损失和主目标抢梯度,路由又因为离散选择而不稳定,不稳定的路由让不均衡更难预测。这也是过去几年 MoE 论文一多半都在处理路由的原因。

04不均衡的代价,究竟有多大?

如果只是"效果好一点差一点",那还只是学术问题。真正的麻烦是它会拖垮整张训练图,甚至让训练直接崩掉。

代价一:被丢掉的 token 白跑了

工程实现里,专家一次能处理的 token 数是有限的,这个上限叫专家容量:

专家容量 = (一个批次里的 token 数 / 专家总数) × capacity_factorcapacity_factor 是超参数,取 1.0 时正好等于平均份额

如果某个专家收到的 token 超过了容量,多出来的 token 会被直接丢弃(token dropping),不经过任何专家,直接靠残差连接穿过这一层。实作中 capacity_factor 取 1.0 到 1.25 效果最好。

丢弃意味着什么?意味着这些 token 在这一层什么都没学到。而且被丢的往往是长尾样本,本来就需要更多算力的那些。训练一乱,它们第一批遭殃。

代价二:通信开销吃掉训练时间

前面提到的 all-to-all,在专家规模做大之后会变成主要瓶颈。在大规模 MoE 训练中,这种通信可以占掉 40% 以上的训练时间;有测试显示,在 DeepSeek-V3 这个量级的集群上,不做优化的话这个比例能过一半。

更糟的是这里的开销和均衡直接挂钩。不均衡时,某些专家收到成倍的 token,对应的通信量也跟着成倍,而其他卡在等,整个集群的速度被最忙的那张卡拉住。

代价三:训练好好的,某一步突然炸掉

这是最难受的一种。MoE 训练里有个经典现象:损失曲线平稳下降几万步,然后某一批数据进来,某个专家被选中得特别多,梯度范数瞬间放大,损失曲线直接拉出一根 spike。轻则反复震荡几天,重则整个训练得回滚到之前的检查点重来。

而回溯去看,触发这一下的往往不是显眼的代码 bug,是路由在这一步做出了一个不太好的分配。整轮训练里最不可控的一环,是这个只有几层的小网络。

代价四:训练时是这样,推理时未必

训练时的批次很大,几千个 token 一起,路由的统计特性比较稳。推理时批次可能只有一两个 token,分布完全不同,模型的专家选择可能偏移。微调、迁移、强化学习阶段也各有各的偏移问题,RL 阶段尤其明显,因为策略在持续变化,路由跟着一起漂。

这就带出下一个问题:既然难点都清楚了,有没有办法绕开辅助损失这套东西?

05DeepSeek 是怎么把这道题解开的?

核心思路一句话:把"均衡"这件事从梯度里拿出来,改成一个不参与求导的调节旋钮。

2024 年底的 DeepSeek-V3 报告里,提出了无辅助损失负载均衡(auxiliary-loss-free load balancing)。做法分三块。

第一块:给每个专家配一个动态偏置

给每个专家 i 加一个偏置项 b_i。关键约束是:这个偏置只参与 Top-K 的排序比较,不进入门控的梯度计算。

更新规则也很简单:

用打比方的方式说:这像给一个超载的电梯调度员加了一摞便签纸。哪个楼层人多,就在那层的便签上划掉一点分数;哪层没人,就补上一点。调度员照着便签排顺序,但他做判断的"业务逻辑"本身没有被改动,梯度不会因为这个偏置而被扭曲。

效果是均衡被拉平了,但语言建模的主目标一点没被干扰。

第二块:留一个极小的序列级保险

纯靠偏置够不够?DeepSeek 还是保留了一点点辅助损失,但换了粒度、也换了权重,序列级的互补均衡损失,系数只有 0.0001。

对比一下:Switch Transformer 的微批次级辅助损失推荐系数是 0.01。这里降了两个数量级,而且只管一件事,防止单条序列内部出现极端不均衡。全局层面交给偏置去调。

第三块:把通信成本框住

光有均衡还不够,通信也得管。V3 采用节点受限路由:每个 token 最多只能被送往 4 个节点(M=4)。这等于给 all-to-all 的规模设了硬上限,再配合 64 路专家并行和计算-通信重叠的流水线设计,把通信开销压到接近可以忽略。

另外补一句架构上的铺垫。更早在 DeepSeekMoE 里提出的两个改动也在起作用:细粒度专家分割(把专家切得更小更专)和共享专家隔离(留一个所有 token 都必经的专家,负责通用知识)。前者的好处是组合空间更大、路由灵活性更高;后者把"通用能力"从路由的赌局里摘出来,减少重复学习。

这三块合起来的结果:据 V3 技术报告,整个训练全程没有出现无法恢复的损失尖峰,也没有因为不稳定而回滚过检查点;同时因为均衡足够好,训练时完全不丢弃 token。报告里的消融实验还显示,这套方案让专家的专业化程度更高,而不是更低。

06这道题解完了吗?

远没有。均衡只是路由问题里最先被工程解决掉的那一层。

先看路线本身还在分化。Qwen3-Next 走到另一个方向:80B 总参数,每 token 只激活约 3B,稀疏度压到 3.7% 左右,配套用全局负载均衡。稀疏度越高,省算力越狠,但路由的容错空间也越小,选错一个专家,代价比在 Mixtral 里大得多。

Soft MoE 那条"取消离散选择"的路依然有人在推。它把路由变成一个可微的加权混合,训练上的麻烦少了一大半。但它放弃了部分稀疏收益,本质上是在用算力换稳定。

然后是 RL 阶段冒出的新问题。2025 年有工作(比如 RSPO)专门处理 MoE 做强化学习时的路由偏移:策略更新会让 token 的分布持续移动,路由跟着漂,原本在预训练阶段调好的均衡会失效。解法之一是监控"router-shift"比率,超过阈值就干预。

还有两个更基础的东西没解决。

一是可解释性。我们知道某个专家被选中了,但很难说清它到底"懂"什么。有研究拆过 MoE 内部的分工,能看到一些模式,但离"这个专家负责数学、那个负责代码"这种干净的结论还很远。路由是黑箱里的黑箱。

二是训练和推理的一致性。预训练时均衡的分配,在推理、微调、蒸馏之后未必还是均衡的。而部署时的批次小、序列长,正好是路由最不擅长的场景。

回过头看,这条路走了八年。GShard 第一次把专家并行和辅助损失凑成可用方案,Switch Transformer 用 K=1 把路由简化到极致,Mixtral 让行业相信 MoE 能打,DeepSeek 把均衡从损失函数里挪出来。每一步都在做同一件事:让那个只有几层的小网络,做出的决定更可靠一点。

下次看到"671B 总参数、37B 激活"这样的宣传数字时,可以多想一层:这个比例能不能兑现,取决于每个 token 进门时,路由有没有替它选对门。选得准,你享受到的是便宜的智能;选不准,你拿到的是一个装满没训练过的专家的大模型。

总结:三句话记住路由

问题答案
MoE 是什么把 FFN 拆成很多专家,每个 token 只激活其中几个,用稀疏激活换取"大容量、小算力"。省算力,不省显存。
路由是什么一个很小的门控网络,负责给每个 token 挑专家。参数量可忽略,但它决定每层哪些参数参与计算、以及跨卡要传多少数据。
为什么路由最难因为它在连续优化里嵌了一个离散的、会自我强化的分配决策:不均衡会自我放大(专家坍缩),离散跳变导致训练震荡,辅助损失又和主目标抢梯度。
目前最好的解法无辅助损失负载均衡:给专家配一个只参与选择、不进梯度的动态偏置;保留 0.0001 系数的序列级损失兜底;用节点受限路由框住通信成本。

如果只记一句:MoE 的收益写在参数比例上,风险写在路由的每一次选择里。

参考资料