Skip to content

MoE 混合专家:大模型为什么要学会分工 ​

先看一个小故事 ​

学校里有 8 位老师。有人擅长数字,有人对代码更敏感,也有人更熟悉自然语言。现在来了一摞写着不同内容的小纸条,学校没有让 8 位老师逐张阅读,而是安排了一名分拣员:每拿到一张纸条,他只挑最合适的 2 位老师处理。

老师都在学校里,但一张纸条只会打扰其中两位。

MoE(Mixture of Experts,混合专家)大致就是这个思路:模型里准备多个“专家”,每次只调用少数几个。这样,模型可以拥有很多参数,又不用每生成一个 token 都把所有参数计算一遍。

这个故事里有三种角色:

  • 小纸条对应 token,也就是模型处理文字时的基本单位;
  • 老师对应 Expert(专家);
  • 分拣员对应 Router(路由器),负责选择专家。

这里有个容易误会的地方:模型不是把用户的整句话交给某一位专家。句子会被切成 token,每个 token 都会单独选择专家;到了下一层,同一个 token 还可能换一组专家。

普通模型和 MoE 差在哪 ​

普通的 Dense 模型只有一套固定的前馈网络。无论来了什么 token,都经过同一套参数:

text
token 1 ─┐
token 2 ─┼─> 同一套前馈网络 ─> 下一层
token 3 ─┘

MoE 准备多套前馈网络,再让 Router 挑选其中几个:

text
token 1 ─> Router ─> 专家 2、专家 6 ─┐
token 2 ─> Router ─> 专家 1、专家 6 ─┼─> 合并结果 ─> 下一层
token 3 ─> Router ─> 专家 3、专家 7 ─┘

专家并不是能够独立聊天的小模型。它通常只是 Transformer 层中前馈网络(FFN)的一份独立参数。注意力、词嵌入和输出层等部分仍由大家共用。

Router 怎么选择专家 ​

Router 会看当前 token 的内部表示,给所有专家打分。如果模型规定“每次选两个”,就取分数最高的两个,这叫 Top-2 路由;只选一个就是 Top-1 路由。

例如,Router 给 4 位专家打出下面的分数:

专家分数
专家 10.10
专家 20.55
专家 30.05
专家 40.30

使用 Top-2 时,token 会交给专家 2 和专家 4。两位专家各自处理后,模型再按照分数把结果合并。

这些专家没有人工贴好的“数学专家”“中文专家”标签。它们在训练中慢慢形成不同偏好,而且这种分工未必像课程表一样清楚。某个专家可能经常接到代码 token,也可能只是对某些句式或位置更敏感。

为什么会有两个参数量 ​

看到 MoE 模型介绍时,经常会同时出现“总参数量”和“激活参数量”。可以继续用学校的例子理解:

  • 学校一共有 8 位老师,这是全部资源;
  • 每张纸条只找 2 位老师,这是这次真正参与工作的资源。

假设每个专家都有 1 亿参数,模型共有 8 个专家,每次选择 2 个:

text
专家总参数:8 × 1 亿 = 8 亿
一次激活的专家参数:2 × 1 亿 = 2 亿

真实模型还有注意力、词嵌入等共享参数,因此不能直接用这道乘法算出完整模型大小。不过它足以说明两个数字的区别:总参数量表示模型一共保存了多少参数,激活参数量表示一个 token 实际走过了其中多少参数。

例如,Mixtral 8x7B 有 8 个专家,每个 token 选择 2 个。论文给出的总参数约为 47B,每个 token 激活约 13B。DeepSeek-V3 则有 671B 总参数,每个 token 激活 37B。

这样做有什么好处 ​

最直接的好处,是模型可以继续增加专家、扩大总参数量,而不必让每个 token 都计算所有专家。和“把所有专家全部叫来开会”相比,只叫其中一两位自然会少做很多计算。

不过,激活参数少不等于一定更快。所有专家的权重仍然需要存放在显存或其他存储里;如果专家分布在不同 GPU,token 还要在设备之间传递。搬运数据慢、请求太少,或者大量 token 同时挤向同一位专家时,省下的计算可能又被等待时间吃掉。

所以读到“671B 总参数、37B 激活参数”时,可以理解成“每个 token 只计算模型的一部分”,不能理解成“它只需要 37B 模型的显存,也一定和 37B Dense 模型一样快”。

专家也会遇到排队问题 ​

假设 100 张纸条里有 80 张都被分给同一位老师,这位老师桌上堆满作业,其他老师却没事做。MoE 也会遇到这种情况,通常称为负载不均衡。

训练时,系统会增加一项辅助目标,提醒 Router 不要长期只偏爱少数专家。工程实现还会限制每位专家一次最多接收多少 token。超过上限的 token 怎么办,各个框架做法不同:可能改送其他专家、走原来的残差路径,也可能在特定训练实现中被丢弃。

这也是 MoE 比 Dense 难训练、难部署的主要原因之一。Dense 的路线固定,MoE 的路线会随着 token 改变,系统必须一边选择专家,一边避免有人忙不过来。

几个真实模型怎么做 ​

模型做法记住什么
Switch Transformer每个 token 只选 1 个专家Top-1 路由更简单,但仍要处理负载和训练稳定性
Mixtral 8x7B8 个专家中选择 2 个模型有 47B 总参数,每个 token 约激活 13B
DeepSeekMoE更细地拆分专家,并加入共享专家常用知识交给共享专家,其他专家继续分工
DeepSeek-V3大规模 MoE671B 总参数,每个 token 激活 37B

模型之间不能只比较专家数量。专家大小、每次激活几个、共享参数多少、训练数据和硬件实现都会影响最终效果。

部署时,MoE 和普通模型有什么不同 ​

继续用学校来想:Dense 模型像所有老师都在同一间办公室,每张纸条走固定路线;MoE 像把老师分散到几间教室,分拣员先决定纸条送到哪里,再把处理结果收回来。老师分得越远,送纸条花的时间越值得关注。

部署时要看什么Dense 模型MoE 模型
权重存放所有权重都在固定计算路径上虽然一次只激活少数专家,但所有专家权重仍要存放
多 GPU 切分常按层或矩阵切分除了普通切分,还常把不同专家放到不同 GPU
数据传递token 的计算路线较固定Router 选完专家后,token 可能要跨 GPU 发送再取回
延迟稳定性同类请求的计算量比较接近专家选择不同,某个专家拥挤时会让部分请求等得更久
监控重点显存、GPU 利用率、吞吐和延迟还要看每个专家收到多少 token、是否溢出、跨卡通信花了多久

这会直接影响本地部署。以 Mixtral 8x7B 为例,每个 token 约激活 13B 参数,不代表只需存放 13B 参数;模型约 47B 的总权重仍要装进显存、内存或其他存储。量化和 CPU 卸载可以降低显存压力,但后者可能增加数据搬运和等待时间。

因此,部署 Dense 模型时更常先问“模型能否装下、单次计算要多久”;部署 MoE 时还要多问一句:“专家放在哪些设备上,token 在这些设备之间要跑多远?”

四个常见误会 ​

MoE 是多个模型一起投票吗? ​

不是。专家通常是 Transformer 层里的多份 FFN,不是多个完整聊天模型。它们处理 token 的中间表示,结果在模型内部合并。

每个专家都有明确专业吗? ​

没有预先规定。训练可能让专家形成偏好,也可能出现重复。专家编号不会直接告诉你它负责数学还是代码。

激活参数少,就只需要很少显存吗? ​

不是。没有被当前 token 选中的专家仍要保存。激活参数主要描述这次计算经过了多少参数,不等于完整的存储需求。

MoE 一定比 Dense 快吗? ​

不一定。MoE 少算了一些参数,却多了路由、分组和设备间传输。硬件、请求数量和专家负载都会改变结果。

用一句话说清 MoE ​

MoE 在 Transformer 层中准备多个 FFN 专家,由 Router 为每个 token 选择少数专家参与计算。它用稀疏激活扩大模型容量,但也带来了专家负载和跨设备通信问题。

面试时先说清这句话就够了。对方继续追问,再解释总参数与激活参数、Top-K 路由以及为什么 MoE 不一定更快。

多知道一点:文档里常见的术语 ​

术语简单理解
FFNTransformer 层中的前馈网络,MoE 通常把这一部分复制成多个专家
Top-KRouter 为一个 token 选择分数最高的 K 个专家
Shared Expert所有 token 都会经过的共享专家,用来处理较通用的模式
Load Balancing尽量让专家工作量不要相差太大,避免少数专家排长队
Capacity Factor为每个专家预留多少 token 容量;太小容易溢出,太大容易浪费
Token Dropping专家容量不足时对超额 token 的处理方式,具体行为取决于实现
All-to-All专家分布在多张 GPU 时,把 token 发送到对应专家所用的一类通信操作
Expert Parallel(EP)把不同专家放到不同 GPU;通常还会和数据并行、张量并行一起使用

持续学习,持续实践。