基本原理

核心思想:按需调用,而非“全员出动”

传统的密集模型(Dense Model)处理任何输入时,都会激活整个神经网络的所有参数,好比每次回答问题都要动用全公司所有员工。

而MoE模型的做法是:根据输入内容,只激活最擅长处理这类问题的少数“专家”,其他专家保持静默。这就像一家医院,病人挂什么科,就由相应科室的医生接诊,而不是所有医生一起上。


两大核心组件

1. 稀疏MoE层(Sparse MoE Layers)

  • 在Transformer架构中,原本的全连接前馈网络层被替换为MoE层。
  • 每个MoE层里包含多个“专家”(每个专家本质上是一个小型神经网络)。
  • 关键点是“稀疏”——对于每个输入,只有一小部分专家被激活(比如8个专家里只选2个),从而大幅节省计算资源。

2. 门控网络/路由器(Gate Network / Router)

  • 它的任务是:决定每个输入token(词元)该交给哪个(或哪几个)专家处理
  • 路由器会为每个专家计算一个“适配分数”,然后选出分数最高的Top-K个专家来实际处理该token,确保“专业的人做专业的事”。

带来的好处

维度 效果
训练速度 更快,因为每次更新只需计算部分专家,而非整个网络
推理效率 更高,推理时只跑少量专家,计算量远小于同参数量的密集模型
模型容量 可以在不显著增加计算成本的前提下,把模型做得非常大(比如GPT-4、Gemini等主流大模型都在使用MoE)

一个直观的类比

想象你有一本百科全书,每当你问一个问题,MoE就像一个聪明的图书管理员——他不会把整本书从头翻到尾,而是根据你的问题,直接抽取出相关的几个章节递给你。既快又准,还省力。

这个过程是怎样的

为了让你直观地“看见”整个过程,我们不妨跟随一个具体的句子,一步步走过MoE模型内部。假设我们要翻译或理解这句话:

“猫喜欢吃鱼。”

这个过程可以分为4个关键步骤,从输入到输出依次展开:


第1步:输入分词(Token化)

模型首先把句子拆成最小单元(Token):

["猫", "喜", "欢", "吃", "鱼", "。"]

此时,每个Token都是一串数字编码(向量),代表它的初始语义。


第2步:经过自注意力层(Transformer标准流程)

这些Token向量先进入Transformer的自注意力层(Self-Attention)

  • 这一步不涉及专家,是所有MoE模型都有的通用步骤。
  • 它的作用是让每个Token“互相看一眼”,理解上下文。比如“吃”这个字会注意到“猫”和“鱼”,知道是“猫吃鱼”而不是“鱼吃猫”。

经过这一步,每个Token的向量都融合了上下文信息,变成了带有语境的新向量。


第3步:进入MoE层(关键步骤)——路由器决策 + 专家计算

这是MoE的核心环节。每个Token(此时已带上下文)会独立地进入MoE层,经历以下子步骤:

3.1 路由器(Router)打分

路由器是一个小型全连接网络,它为当前Token计算一个分数向量,长度等于专家的数量(假设有4个专家:E1, E2, E3, E4)。

假设当前Token是 “吃”,路由器给出的分数可能是:

E1: 0.1 E2: 0.8 E3: 0.05 E4: 0.05

分数代表“这个Token适合交给哪位专家”。

3.2 选择Top-K专家(稀疏激活)

假设模型设定 K=2(即每次选2个专家)。那么路由器选出分数最高的两位:

选中 E2(0.8)和 E1(0.1),E3和E4被直接忽略(不激活,不消耗计算)。

3.3 专家并行处理

  • E2专家(可能擅长处理“动作/动词”)对“吃”的向量进行自己的前馈计算,输出一个新向量。
  • E1专家(可能擅长处理“食物/名词”)也对“吃”的向量进行自己的计算,输出另一个新向量。

两个专家同时独立工作,互不干扰。

3.4 加权融合

路由器不只看排名,还会将分数作为权重,把两个专家的输出加权求和:

最终输出 = 0.8 × (E2的输出) + 0.1 × (E1的输出)

(注意:分数通常还会经过Softmax归一化,这里简化为直观比例)


第4步:依次处理所有Token + 多层叠加

  • 上面的第3步,对句子中的每个Token(“猫”“喜”“欢”“吃”“鱼”“。”)都独立执行一遍
    • 注意:不同Token选中的专家可能完全不同。比如“鱼”可能选中E1(名词专家)和E4(生物专家),而“吃”选的是E2和E1。
  • 整个Transformer模型通常有数十层,每一层都包含上述MoE结构。Token经过第1层MoE后,再进入第2层的自注意力,再进入第2层的MoE……逐层递进,直到最后输出结果。

整个过程的时间线图示

text

输入句子: "猫喜欢吃鱼。"
    │
    ▼
[分词] →  ["猫","喜","欢","吃","鱼","。" ]
    │
    ▼
[自注意力层] → 每个Token融合上下文("吃"知道主语是"猫",宾语是"鱼")
    │
    ▼
┌─────────────── MoE层(对每个Token独立执行)───────────────┐
│                                                             │
│  对Token="吃":  路由器打分 → 选E2(0.8)和E1(0.1)            │
│                  E2和E1并行计算 → 加权求和 → 输出新向量      │
│                                                             │
│  对Token="鱼":  路由器打分 → 选E1(0.7)和E4(0.2)            │
│                  E1和E4并行计算 → 加权求和 → 输出新向量      │
│                                                             │
│  ... 其他Token同理 ...                                      │
└─────────────────────────────────────────────────────────────┘
    │
    ▼
[重复多层] → 每层都做上述自注意力 + MoE
    │
    ▼
[最终输出] → 预测下一个词 / 翻译结果 / 文本理解

两个容易被忽略的关键细节

细节 说明
每个Token独立选专家 同一个句子中,“猫”可能选专家A,“吃”可能选专家B,它们是独立决策的,不是整句话统一选一批专家。
负载均衡(Load Balancing) 训练时,模型会额外加一个损失函数,防止所有Token都挤去选E2,而E3、E4长期闲置。这就像排班一样,要保证每个专家都有活干。

存在的问题

核心矛盾:省了“算力”,但省不了“显存”

想象你开了一家大型专科医院(MoE模型),有100个不同科室的专家(专家总数)。

  • 推理(看病)时:每个病人只需挂1-2个相关科室的号(只激活部分专家),计算量确实小,看病速度快。
  • 但问题是:你不能把其他98个科室的大楼拆掉。整家医院(所有100个专家)必须完整地存在硬盘和内存里,随时待命,因为下一个病人可能挂的是骨科或眼科。

映射到模型:推理时虽然只用了2个专家,但所有专家的参数都必须加载到显存(VRAM)中。所以MoE模型的显存占用,几乎等于同参数量的密集模型(Dense Model),而不是按激活比例缩小。


微调(Fine-tuning)为什么更难?

普通密集模型微调,只是让所有参数统一做小幅调整。

但MoE微调时,模型需要同时做两件相互矛盾的事:

  1. 路由器(Router)要重新学习:哪些专家适合新任务,门控权重需要大范围调整。
  2. 专家本身也要调整:每个专家内部的知识要适配新数据。

问题是,路由器的决策直接决定专家能否收到梯度信号。如果路由器一开始把某些专家“判了死刑”(分数极低),这些专家就得不到训练,形成专家闲置(Expert Dropping)。所以训练时必须额外加负载均衡损失(Load Balancing Loss),强行让所有专家都有活干——这增加了调参的难度和稳定性风险。


两个关键参数(你给的英文里提到了)

参数 含义 影响
num_local_experts(专家总数) 整个模型里总共有多少个专家,比如Mixtral 8x7B里有8个。 决定显存上限。这个数越大,模型总参数量越大,加载到显存时占用的VRAM就越高。
num_experts_per_tok(每个Token激活的专家数) 每个Token在每一层实际调用几个专家来处理,比如Mixtral里是2个。 决定计算速度和精度之间的权衡。 • 调大这个值(比如从2变4):效果可能略有提升,但收益递减(边际效益变小),计算量却翻倍。 • 调小这个值(比如1):推理和训练飞快,但可能因专家知识不足而损失精度。

一个直观的总结对比

维度 密集模型(Dense) 混合专家模型(MoE)
显存占用 等于总参数量 也等于总参数量(所有专家必须加载)
推理计算量 100%参数都算 只算 激活专家数/专家总数 的比例(比如2/8=25%)
微调难度 相对简单,统一调参 困难,需平衡路由器 + 专家 + 负载均衡
参数效率 低(增大模型,计算成本线性增长) 高(增大专家数,计算成本几乎不变,但显存成本线性增长)

一句话记住MoE的取舍

MoE用“显存换计算”:你把所有专家都装在显存里(贵),但每次推理只算一小部分(快)。适合显存大、推理量大、且需要超大规模参数的场景。

推荐阅读:

Fine-tune Mistral-7b with Direct Preference Optimization – Maxime Labonne