论文题目

DeepSeekMoE: Towards Ultimate Expert Specialization in Mixture-of-Experts Language Models

这篇论文是 DeepSeek 基础模型路线里很关键的一环。DeepSeek LLM 证明团队可以训练标准 dense LLM;DeepSeekMoE 则开始回答另一个问题:如果 dense 模型继续扩大太贵,能不能用 MoE 让模型拥有更大的总参数,同时只激活较少参数?

论文的核心结论可以先概括成一句话:

DeepSeekMoE 通过“细粒度专家切分”和“共享专家隔离”,让 routed experts 更专门化,从而用更少激活计算接近更大 dense 模型或更大 GShard 模型的效果。

背景:MoE 想解决什么问题

标准 Transformer 的每一层通常包含 self-attention 和 FFN 两个主要模块。对于大语言模型来说,FFN 参数占比很大。如果继续扩大 dense 模型,每个 token 都要经过全部参数,训练和推理成本都会随模型规模上升。

MoE(Mixture-of-Experts)的做法是把 FFN 替换成多个 expert FFN。每个 token 不再经过所有专家,而是通过 router 选择少数几个专家计算。这样可以形成一个很有吸引力的结构:

  • 总参数多:模型有很多 expert,容量更大。
  • 激活参数少:每个 token 只用少数 expert,计算成本相对低。
  • 稀疏计算:不同 token 可以走不同 expert,理论上可以形成分工。

GShard 这类常规 MoE 通常是 top-\(K\) routing:给定 \(N\) 个专家,每个 token 选择得分最高的 \(K\) 个专家。用论文里的记号,一个 MoE 层可以写成:

\[h_t^l=\sum_{i=1}^{N}(g_{i,t}FFN_i(u_t^l))+u_t^l\]

其中 \(g_{i,t}\) 是第 \(t\) 个 token 到第 \(i\) 个 expert 的 gate value。因为只有 top-\(K\) 个 \(g_{i,t}\) 非零,所以每个 token 只计算少数专家。

问题在于:有 MoE,不等于专家真的专门化。

论文认为常规 MoE 有两个限制:

  1. Knowledge Hybridity:专家数量有限时,一个 expert 会被迫接收很多类型的 token,于是一个专家里混着很多不同知识。
  2. Knowledge Redundancy:不同 expert 都可能需要通用知识,比如语法、常识、基础模式,于是多个专家重复学习相同内容。

这两个问题都会削弱 expert specialization。DeepSeekMoE 的设计目标就是让专家更少混杂、更少重复。

核心设计一:Fine-Grained Expert Segmentation

第一个设计是细粒度专家切分。

假设常规 MoE 有 \(N\) 个专家,每个 token 激活 \(K\) 个专家。DeepSeekMoE 把每个专家切成 \(m\) 个更小的专家,于是总专家数变成 \(mN\)。为了保持计算量大致不变,每个 token 激活的专家数量也从 \(K\) 增加到 \(mK\)。

论文中的公式是:

\[h_t^l=\sum_{i=1}^{mN}(g_{i,t}FFN_i(u_t^l))+u_t^l\]

\[g_{i,t}= \begin{cases} s_{i,t}, & s_{i,t} \in Topk(\{s_{j,t}|1 \leq j \leq mN\}, mK) \\ 0, & otherwise \end{cases}\]

这里的关键不是单个专家变小,而是组合空间变大

论文给了一个很直观的例子:如果 \(N=16\),常规 top-2 routing 的组合数是:

\[\binom{16}{2}=120\]

如果把每个专家切成 4 个小专家,总专家数变成 64,每次激活 8 个小专家,组合数变成:

\[\binom{64}{8}=4,426,165,368\]

这个数字不表示模型真的会平均使用所有组合,而是说明细粒度切分后,router 有更灵活的选择空间。原来一个大专家可能同时包含“代码 + 数学 + 英文语法 + 某类事实”,切分后这些知识有机会分散到更细的专家里。每个 token 激活多个小专家,相当于按需拼装一组更精细的知识模块。

核心设计二:Shared Expert Isolation

第二个设计是共享专家隔离。

DeepSeekMoE 把一部分专家设为 shared experts。它们不经过 router 选择,而是对每个 token 都固定激活。其余专家仍然是 routed experts,由 router 动态选择。

论文里的完整 DeepSeekMoE 层可以写成:

\[h_t^l= \sum_{i=1}^{K_s}FFN_i(u_t^l) + \sum_{i=K_s+1}^{mN}(g_{i,t}FFN_i(u_t^l)) + u_t^l\]

其中 \(K_s\) 是 shared experts 数量。为了保持计算成本不变,加入 shared experts 后,activated routed experts 数量会相应减少。也就是说,计算预算从:

1
全部给 routed experts

变成:

1
2
一部分给总是激活的 shared experts
一部分给动态选择的 routed experts

这个设计的直觉很清楚:语言模型里有很多通用知识每个 token 都可能需要。如果没有 shared experts,多个 routed experts 都会重复学习这些通用知识。把通用知识集中到 shared experts 后,routed experts 就可以更专注于差异化知识。

这也是论文标题里 “Ultimate Expert Specialization” 的含义:不是让所有专家都平均分担所有知识,而是让共享专家负责共性,让路由专家负责特性。

负载均衡:不是只追求专家专门化

MoE 还有一个工程问题:router 可能总是选择少数专家,导致 routing collapse。这样一部分专家训练不足,另一些专家过载。如果专家分布在不同设备上,负载不均还会导致设备等待和通信瓶颈。

DeepSeekMoE 使用两类 balance loss:

  1. Expert-level balance loss:防止专家层面的路由坍缩。
  2. Device-level balance loss:在专家分布到不同设备时,促进设备间计算均衡。

Expert-level balance loss

Expert-level balance loss 只针对 routed experts,不包括 shared experts。因为 shared experts 是每个 token 都固定激活的,不存在 router 偏向问题。

论文中的公式是:

\[L_{ExpBal}=\alpha_1 \frac{1}{N'} \sum_{i=1}^{N'} f_iP_i\]

其中 \(N'\) 是 routed experts 数量,\(K'\) 是每个 token 激活的 routed experts 数量,\(T\) 是当前序列或 batch 中参与统计的 token 数。\(f_i\) 和 \(P_i\) 分别定义为:

\[f_i=\frac{N'}{K'T}\sum_{t=1}^{T}\mathbf{1}(\text{Token }t\text{ selects Expert }i)\]

\[P_i=\frac{1}{T}\sum_{t=1}^{T}s_{i,t}\]

这里 \(s_{i,t}\) 是第 \(t\) 个 token 对第 \(i\) 个 expert 的 router softmax 概率。\(\mathbf{1}(\text{Token }t\text{ selects Expert }i)\) 表示第 \(t\) 个 token 的 top-\(K'\) routed experts 中是否包含第 \(i\) 个 expert。

可以把 \(f_i\) 理解成“实际选择负载”。如果所有 routed experts 被均匀使用,每个 expert 理论上会被选中 \(K'T/N'\) 次。论文用 \(\frac{N'}{K'T}\) 做归一化,所以平均负载时 \(f_i=1\):

  • \(f_i>1\):第 \(i\) 个 expert 被选得偏多。
  • \(f_i<1\):第 \(i\) 个 expert 被选得偏少。

\(P_i\) 则是“router 的概率倾向”。它不关心 expert 是否进入 top-\(K'\),只统计 softmax 后分配给第 \(i\) 个 expert 的平均概率。

一个简单例子:假设 \(N'=4\),\(K'=2\),\(T=3\),三个 token 的 routed experts 选择结果是:

1
2
3
token1 -> E1, E2
token2 -> E1, E3
token3 -> E1, E4

那么 E1 被选中 3 次。均匀情况下,每个 expert 应该被选中:

\[\frac{K'T}{N'}=\frac{2\times3}{4}=1.5\]

所以:

\[f_1=\frac{3}{1.5}=2\]

也就是说 E1 的实际负载是平均值的 2 倍。如果 E1 的平均 router 概率 \(P_1\) 也很高,那么 \(f_1P_1\) 就会较大,balance loss 会给 router 一个信号:不要继续把过多概率质量集中到 E1。

这里同时使用 \(f_i\) 和 \(P_i\) 是有原因的。\(f_i\) 来自 top-\(K'\) 后的实际选择,能反映真实负载;但 top-\(K'\) indicator 本身不适合直接提供平滑梯度。\(P_i\) 来自 softmax 概率,更容易给 router 提供可优化的梯度。因此这个 loss 的直觉是:被选得越多的 expert,不应该继续获得过高的 router 概率;低负载 expert 应该获得更多机会。

Device-level balance loss

Expert-level balance 关注单个 expert 是否过热;device-level balance 关注多卡训练时设备是否过热。对于大规模 MoE,如果 routed experts 分布在不同设备上,即使 expert 层面不是完全坍缩,也可能出现某些设备组负载更高,拖慢整体训练。

假设把所有 routed experts 分成 \(D\) 个设备组:

\[\mathcal{E}_1,\mathcal{E}_2,\ldots,\mathcal{E}_D\]

第 \(i\) 个设备组的平均实际负载和概率质量定义为:

\[f'_i=\frac{1}{|\mathcal{E}_i|}\sum_{j\in \mathcal{E}_i}f_j\]

\[P'_i=\sum_{j\in \mathcal{E}_i}P_j\]

对应的 device-level balance loss 是:

\[L_{DevBal}=\alpha_2\sum_{i=1}^{D}f'_iP'_i\]

这个 loss 不要求每个 expert 完全平均,而是从设备组角度压制“某台设备承载过多 token”的情况。论文中的设置也体现了这一点:2B 验证实验没有跨设备 expert parallelism,所以不用 device-level balance;16B 的并行策略里每层 experts 放在同一设备上,也不用 device-level balance;145B 使用 expert parallelism,把 routed experts 分布到多个设备上,因此加入 device-level balance。

模型 Expert-level balance factor Device-level balance factor
2B 验证实验 0.01 不使用
16B 0.001 不使用
145B 0.003 0.05

论文中特别强调,负载均衡约束不能太强。过强的平衡会损害模型性能,因为它会强迫 router 为了均衡而牺牲本来更合适的专家选择。DeepSeekMoE 的做法是:用较小的 expert-level balance factor 防止坍缩,同时在需要跨设备部署时用较大的 device-level balance factor 保证设备负载。

这一点也能看出 DeepSeekMoE 的目标不是“让每个专家被一样多地使用”,而是“在不坍缩、不拖慢设备的前提下,尽量让专家自然分工”。

2B 验证实验:先证明架构有效

论文先在约 2B 总参数规模上验证架构。这个实验比较重要,因为它把 DeepSeekMoE 和 Hash Layer、Switch Transformer、GShard 放在同一训练语料和超参下比较。

2B 验证实验的主要配置如下:

项目 配置
训练 tokens 100B
Transformer 层数 9
hidden size 1280
attention heads 10
vocab size 8K
sequence length 2048
batch size 2048 sequences,即每 batch 约 4M tokens
DeepSeekMoE 配置 1 个 shared expert + 63 个 routed experts
每 token 激活 1 个 shared expert + 7 个 routed experts
总参数 2.0B
激活参数 约 0.3B

这个配置里,每个 expert 是标准 FFN 大小的 0.25 倍。也就是说,它不是简单地把专家数量加多,而是把专家变细,然后激活更多小专家。

Table 1 的结果很直接:在同样 2.0B 总参数、相近激活参数和同样 100B 训练 tokens 下,DeepSeekMoE 明显超过 GShard。例如:

指标 GShard DeepSeekMoE
Pile loss 1.867 1.808
HellaSwag 50.5 54.8
PIQA 70.6 72.3
ARC-challenge 31.6 34.3
TriviaQA 10.2 16.6
NaturalQuestions 3.2 5.7

论文还把 DeepSeekMoE 和 GShard×1.5 比较。GShard×1.5 有 1.5 倍 expert 参数和 expert 计算,但 DeepSeekMoE 仍能达到相近表现。更强的是,DeepSeekMoE 接近 Dense×16 的表现,而 Dense×16 可以看成 MoE 在模型容量上的严格上界:因为它相当于每个 token 都使用 16 份 FFN 参数,不再做稀疏路由。

这里的解释要小心:论文不是说 DeepSeekMoE 在所有意义上等于 dense 上界,而是说在约 2B 参数、100B tokens 的实验设置下,它的结果非常接近这个上界。

消融实验:两个设计都有效

论文的 ablation 主要回答三个问题。

共享专家有没有用

论文在 GShard 基础上隔离一个 shared expert。结果显示,相比原始 GShard,加入 shared expert 后多数 benchmark 都提升。这说明 shared expert 不只是工程上的便利,而是对模型性能有帮助。

更强的证据来自专家分析:论文把 DeepSeekMoE 的 shared expert 关掉,同时多激活一个 routed expert,以保持计算成本不变。Pile loss 从 1.808 显著上升到 2.414。这个结果说明 shared expert 学到的不是普通 routed expert 可以轻易替代的内容,而是比较基础、通用的知识。

细粒度切分有没有用

论文把专家进一步切细,比较 32 个专家和 64 个专家配置。结果显示,专家粒度越细,整体表现持续增强。也就是说,在总参数和激活参数相同的情况下,让专家更细、组合更灵活,是有效的。

shared/routed 比例怎么选

论文在 64 个总专家的条件下尝试 1、2、4 个 shared experts。三者 Pile loss 分别是 1.808、1.806、1.811,差异不大。考虑到 1:3 的 shared experts 与 activated routed experts 比例有略好的 Pile loss,后续扩展时采用这个比例。

需要注意,这里的“后续扩展”是论文内部从 2B 扩展到 16B/145B 的设置,不是在做额外推断。

专家专门化分析:DeepSeekMoE 的 routed experts 更不可替代

论文还做了几个很有意思的专家分析。

第一个分析是禁用 top routed experts。具体做法是:对每个 token,先把路由概率最高的一部分 experts mask 掉,再从剩余 experts 里选 top-\(K\)。如果模型对禁用高分 expert 不敏感,说明专家之间可能有较多冗余;如果 loss 明显变差,说明这些专家更不可替代。

结果是:DeepSeekMoE 比 GShard×1.5 更敏感。这说明 DeepSeekMoE 的 routed experts 冗余更低,每个专家更像在承担独特功能。

第二个分析是减少激活 routed experts 数量。论文把 activated routed experts 从 7 减到 3 到 7 之间观察 Pile loss。结果显示,即使只激活 4 个 routed experts,DeepSeekMoE 也能达到接近 GShard 的 Pile loss。论文还训练了一个从零开始的新模型:1 个 shared expert + 63 个 routed experts,但只激活 3 个 routed experts。即使激活 expert 参数只有 GShard 的一半,这个模型仍然超过 GShard。

这组实验支撑了论文的一个判断:DeepSeekMoE 不只是“专家更多”,而是 activated experts 中有效参数比例更高。

16B 扩展:从验证实验走向可用模型

2B 实验证明架构有效后,论文训练了 DeepSeekMoE 16B。这个模型也是公开发布的重点模型。

16B 模型配置如下:

项目 配置
训练 tokens 2T
vocab size 100K
Transformer 层数 28
hidden size 2048
attention heads 16
sequence length 4096
batch size 4608 sequences,即每 batch 约 18M tokens
MoE 层 除第一层外,所有 FFN 替换为 MoE
MoE 配置 2 个 shared experts + 64 个 routed experts
每 token 激活 2 个 shared experts + 6 个 routed experts
总参数 16.4B
激活参数 约 2.8B

论文为什么保留第一层 FFN 不替换成 MoE?原因是作者观察到第一层的 load balance 收敛特别慢,所以除第一层外再使用 MoE。

DeepSeekMoE 16B 和 DeepSeek 7B 的比较尤其重要,因为二者使用相同语料、同样 2T tokens。论文报告 DeepSeekMoE 16B 只用 40.5% 的 FLOPs,就达到接近 DeepSeek 7B 的表现:

项目 DeepSeek 7B DeepSeekMoE 16B
总参数 6.9B 16.4B
激活参数 6.9B 2.8B
FLOPs per 4K tokens 183.5T 74.4T
训练 tokens 2T 2T

在具体任务上,DeepSeekMoE 16B 在 Pile、HellaSwag、TriviaQA、NaturalQuestions 等语言建模和知识密集任务上较强;但在 MMLU、CEval、CMMLU 等多选任务上落后 DeepSeek 7B。论文给出的解释是:DeepSeekMoE 16B 的 attention 参数约 0.5B,而 DeepSeek 7B 的 attention 参数约 2.5B,多选任务可能更依赖 attention capacity。

这个解释很有价值,因为它提醒我们:MoE 主要扩的是 FFN 容量,不等于所有能力都会等比例提升。知识记忆类任务更容易受益于 FFN 参数扩展;某些选择题、复杂匹配或跨 token 交互任务,则可能受 attention 容量限制。

论文还比较了 LLaMA2 7B。DeepSeekMoE 16B 用 39.6% 的计算,在多数 benchmark 上超过 LLaMA2 7B,并在代码、数学和中文 benchmark 上优势明显。这里要注意,DeepSeekMoE 的训练语料包含更多中英、代码和数学材料,因此这部分结果既反映架构效率,也受到数据构成影响。

SFT:MoE 也能做 chat 对齐

论文还对 DeepSeekMoE 16B 做了监督微调,得到 DeepSeekMoE Chat 16B。SFT 数据是内部构造的 1.4M examples,覆盖数学、代码、写作、问答、推理、摘要等类别,主要是中英文。

SFT 配置:

  • batch size:1024 examples。
  • 训练 8 epochs。
  • maximum sequence length:4K。
  • constant learning rate:\(10^{-5}\)。

结果显示,DeepSeekMoE Chat 16B 在约 40% 计算量下,与 LLaMA2 SFT 7B、DeepSeek Chat 7B 在多数任务上接近或更好。它在 HumanEval、MBPP 等代码任务上表现突出;但在 MMLU、CEval、CMMLU 等多选任务上仍落后 DeepSeek Chat 7B,这和 base model 的观察一致。

这部分的意义是:论文不仅证明 MoE base model 可以训练,也证明它可以接受常规 SFT,并没有因为稀疏专家结构而不能做对齐。

145B 初步实验:规模扩大后优势还在

论文最后做了 DeepSeekMoE 145B 的初步实验。注意这是 ongoing / initial study,不是完整训练完成后的最终模型。

145B 配置如下:

项目 配置
训练 tokens 245B
Transformer 层数 62
hidden size 4096
attention heads 32
sequence length 4096
batch size 4608 sequences,即每 batch 约 18M tokens
MoE 配置 4 个 shared experts + 128 个 routed experts
每 token 激活 4 个 shared experts + 12 个 routed experts
总参数 144.6B
激活参数 约 22.2B

Table 6 中,DeepSeekMoE 145B 与 DeepSeek 67B、GShard 137B、DeepSeekMoE 142B Half Activated 比较。几个关键数字如下:

模型 总参数 激活参数 FLOPs per 4K tokens 训练 tokens
DeepSeek 67B dense 67.4B 67.4B 2057.5T 245B
GShard 137B 136.5B 21.6B 572.7T 245B
DeepSeekMoE 145B 144.6B 22.2B 585.6T 245B
DeepSeekMoE 142B Half Activated 142.3B 12.2B 374.6T 245B

论文结论是:DeepSeekMoE 145B 在总参数和计算量相近时明显超过 GShard 137B;用 28.5% 的计算量达到接近 DeepSeek 67B 的表现。Half Activated 版本只激活约 12.2B 参数,用 18.2% 的计算量,也能接近 DeepSeek 67B,并超过 GShard 137B。

这部分给 DeepSeek-V2/V3 的路线埋下伏笔:如果 MoE 在 145B 级别仍能保持优势,那么继续把 MoE 和更强的 attention/KV cache 设计结合起来,就有很高的工程价值。

我的理解:DeepSeekMoE 的关键不是“专家更多”

DeepSeekMoE 最容易被误解成“把专家切小、数量变多”。但论文真正想证明的是:

  1. 细粒度专家提高组合灵活性,让 token 可以用更精细的专家组合表达需求。
  2. shared experts 承担通用知识,减少 routed experts 之间的重复。
  3. routed experts 因此更不可替代,专家冗余更低。
  4. 在相同激活计算下,DeepSeekMoE 比 GShard 更接近 dense 上界。

换句话说,DeepSeekMoE 不是单纯改变 MoE 的宽度,而是在改变专家的分工方式。

从 DeepSeek 基础模型线路看,这篇论文的地位也很清楚:

  • 它为 DeepSeek-V2/V3 的 MoE 结构提供了直接基础。
  • 它解释了为什么 DeepSeek 后续模型会采用 shared experts + routed experts 的设计。
  • 它也暴露了 MoE 的局限:FFN 容量扩张不等于 attention 容量扩张,所以多选、复杂交互类任务可能仍然受 attention 侧限制。

小结

DeepSeekMoE 这篇论文可以看成 DeepSeek 从 dense LLM 走向高效基础模型的第一块关键拼图。它没有解决所有问题,也不是完整的 DeepSeek-V2/V3 形态;但它给出了一个重要方向:通过更好的专家分工,让总参数扩大带来的容量尽量转化为有效能力,而不是变成重复参数。

下一篇继续读 DeepSeek-V2 时,重点就会自然转向另一个瓶颈:MoE 解决的是 FFN 计算效率,MLA 解决的是长上下文解码中的 KV Cache 成本。DeepSeek-V2 的关键,就是把这两条线合在一起。

参考资料

  1. DeepSeekMoE: Towards Ultimate Expert Specialization in Mixture-of-Experts Language Models
  2. DeepSeekMoE GitHub
  3. GShard: Scaling Giant Models with Conditional Computation and Automatic Sharding
  4. Switch Transformers: Scaling to Trillion Parameter Models with Simple and Efficient Sparsity
  5. DeepSpeed-MoE: Advancing Mixture-of-Experts Inference and Training