Transformer 中的专家混合模型 (MoEs)

Hugging Face Blog 论文

摘要

Hugging Face 的博客文章,介绍 Transformer 中的专家混合模型 (MoEs) 架构,涵盖从密集模型到稀疏模型的转变、权重加载优化、专家并行计算以及基于 MoE 的语言模型训练技术。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/04/20 17:27

Transformer 中的专家混合模型 (MoEs)

来源:https://huggingface.co/blog/moe-transformers 返回文章 (https://huggingface.co/blog)

目录

  • 介绍 (https://huggingface.co/blog/moe-transformers#introduction)
  • 从稠密到稀疏:什么是 MoEs?(https://huggingface.co/blog/moe-transformers#from-dense-to-sparse-what-are-moes)
  • Transformer 和 MoEs (https://huggingface.co/blog/moe-transformers#transformers-and-moes)
  • 权重加载重构 (https://huggingface.co/blog/moe-transformers#weight-loading-refactor)
  • 使用 WeightConverter 进行动态权重加载 (https://huggingface.co/blog/moe-transformers#dynamic-weight-loading-with-weightconverter)
  • 张量的延迟实例化 (https://huggingface.co/blog/moe-transformers#lazy-materialization-of-tensors)
  • 基准测试:权重加载管道改进 (https://huggingface.co/blog/moe-transformers#benchmark-weight-loading-pipeline-improvements)
  • 结果 (https://huggingface.co/blog/moe-transformers#results)
  • 量化的作用 (https://huggingface.co/blog/moe-transformers#where-quantization-fits-in)
  • 专家后端 (https://huggingface.co/blog/moe-transformers#expert-backend)
  • 专家并行 (https://huggingface.co/blog/moe-transformers#expert-parallelism)
  • 使用 Transformers 训练 MoEs (https://huggingface.co/blog/moe-transformers#training-moes-with-transformers)
  • 总结 (https://huggingface.co/blog/moe-transformers#conclusion)

介绍

过去几年,扩展稠密语言模型推动了大语言模型的大部分进展。从早期的 ULMFiT (https://nlp.fast.ai/classification/2018/05/15/introducing-ulmfit.html)(约 3000 万参数)或 GPT-2(15 亿参数,当时被认为“太危险而无法发布“ 🧌),到今天的数千亿参数系统,方法很简单:

更多数据 + 更多参数 = 更好的性能。

扩展法则 (https://huggingface.co/papers/2001.08361)强化了这一趋势,但稠密扩展有实际限制:

  • 训练变得越来越昂贵。
  • 推理延迟不断增长。
  • 部署需要大量内存和硬件。

这正是专家混合模型(MoEs)发挥作用的地方。

如果你已经熟悉 MoEs,想直接跳到在 Transformers 中的工程工作,可以直接前往 Transformer 和 MoEs (https://huggingface.co/blog/moe-transformers#transformers-and-moes)。

从稠密到稀疏:什么是 MoEs?

专家混合模型保持了 Transformer 骨干,但用一组专家替换某些稠密的前馈层。“专家“不是一个特定领域的模块(例如“数学专家”、“代码专家”)。它只是一个可学习的子网络。对于每个令牌,一个路由器选择一个小的专家子集来处理它。

不同的令牌根据它们的隐藏表示激活不同的专家。

模型容量取决于总参数,但推理速度取决于活跃参数。

这是关键思想。

例如,以 gpt-oss-20b (https://huggingface.co/openai/gpt-oss-20b) 为例。它有 210 亿总参数,但每个令牌使用 4 个活跃专家(总共 32 个专家中的)。考虑到共享组件加上活跃专家,该模型每个令牌使用约 36 亿个活跃参数。在具有约 800 GB 内存带宽的 M3 Ultra Mac 上运行此模型,我们可以估计生成速度为 800 / (3.6 * 2)bfloat16 中(每个参数占用 2 字节)。这产生约每秒 111 个令牌。我们获得的实际性能数字约为 115 tok/s,非常接近粗略计算。

您的浏览器不支持视频标签。

这个超快速度确认该模型大约作为一个 36 亿参数的模型工作,但它具有与 210 亿参数模型相同的容量(或质量)。

(注:如果我们为模型使用的原生 mxfp4 量化使用内核,速度会更快。)

MoEs 吸引人的原因有:

  1. 更好的计算效率 在固定训练 FLOP 预算下,MoEs 通常优于稠密模型。这意味着更快的迭代和更好的扩展效率。
  2. 自然的并行化轴 专家在计算图中提供了结构边界。由于不同的令牌使用不同的专家,我们可以跨专家并行化(我们稍后在专家并行中讨论这个)。
  3. 行业采用 过去几周发生的开放模型的主要 MoE 版本包括 Qwen 3.5 (https://huggingface.co/collections/Qwen/qwen35)、MiniMax M2 (https://huggingface.co/collections/MiniMaxAI/minimax-m2)、GLM-5 (https://huggingface.co/collections/zai-org/glm-5) 或 Kimi K2.5 (https://huggingface.co/collections/moonshotai/kimi-k25)。在 2025 年 1 月 DeepSeek R1 (https://huggingface.co/deepseek-ai/DeepSeek-R1) 成功后,趋势加快,基于更早的系统如 DeepSeek V2 (https://huggingface.co/deepseek-ai/DeepSeek-V2)。另一个早期 MoE 是 Mixtral-8x7B (https://huggingface.co/mistralai/Mixtral-8x7B-v0.1),于 2023 年 12 月发布。

MoE 模型添加到 Transformers 包的 2 年时间线 (https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/moe-transformers/moe_2y_timeline.png)

图 3:MoE 模型添加到 transformers 库的 2 年时间线。DeepSeek R1 标志着一个明确的拐点。

闭源实验室也使用 MoEs。ChatGPT 长期以来被传言 (https://x.com/soumithchintala/status/1671267150101721090)使用稀疏架构,而 OpenAI 的 gpt-oss 模型 (https://huggingface.co/collections/openai/gpt-oss)确实使用。

如果你想更多地了解 MoEs,我们强烈建议阅读 (https://huggingface.co/blog/moe)和观看我们最近关于路由的 YouTube 视频 (https://youtu.be/CDnkFbW-uEQ)。

Transformer 和 MoEs

生态系统中的大多数工具,包括模型加载、设备放置、量化和后端执行,最初都是为稠密模型设计的。MoEs 挑战了这些假设。

使 MoEs 成为 transformers 中的一等公民意味着重新设计加载管道、执行模型和分布式抽象的部分内容,而不仅仅是添加新的模型类。我们将重点关注 transformers 库如何演进以支持跨以下方面的稀疏架构:

  • 权重加载重构 (https://huggingface.co/blog/moe-transformers#weight-loading-refactor)
  • 专家后端 (https://huggingface.co/blog/moe-transformers#expert-backend)
  • 专家并行 (https://huggingface.co/blog/moe-transformers#expert-parallelism)
  • 使用 Transformers 训练 MoEs (https://huggingface.co/blog/moe-transformers#training-moes-with-transformers)

权重加载重构

AutoModelForCausalLM.from_pretrained("model_id") (https://huggingface.co/docs/transformers/main/en/model_doc/auto#transformers.AutoModelForCausalLM.from_pretrained) 下载模型权重并将其加载到 PyTorch 模型中。对于稠密模型,加载相对简单,检查点中的每个张量都一一映射到运行时模块中的参数。

对于 MoEs,情况更复杂。在大多数 MoE 检查点中,每个专家都是独立序列化的。如果你查看 DeepSeek-V3 检查点索引 (https://huggingface.co/deepseek-ai/DeepSeek-V3/raw/main/model.safetensors.index.json),你会看到这样的键:

model.layers.3.mlp.experts.0.gate_proj.weight
...
model.layers.3.mlp.experts.255.gate_proj.weight

每个专家都有自己的权重矩阵集合,本质上是 256 个(以 DeepSeek-V3 为例,从 0 到 255)小前馈网络并排保存。但在运行时,GPU 执行优化的内核。现代 MoE 内核如分组 GEMM 和融合 MoE 实现 (https://huggingface.co/kernels-community/megablocks) 被设计为在单个操作中处理所有专家,而不是一次循环一个。

为了高效地做到这一点,它们需要专家权重被打包到单个连续张量中。

所以我们遇到了不匹配:

  • 检查点: 256 个独立张量
  • 运行时: 1 个打包张量

系统地桥接这个差距正是权重加载重构 (https://github.com/huggingface/transformers/pull/41580) 所实现的。

随着通用 WeightConverter 的引入,思维模式从:

检查点已经与我的运行时布局匹配;加载主要是逐键复制。

转变为:

检查点只是张量的序列化源。加载是一个转换管道,将它们转换为我们想要的运行时布局。

使用 WeightConverter 进行动态权重加载

此重构引入的中心抽象是通过 WeightConverter (https://huggingface.co/docs/transformers/main/en/internal/weight_converter) 进行的动态权重加载

WeightConverter 允许我们定义:

源键模式 → 目标键(们)+ 操作

原始操作(块、连接等)是可组合的。对于 MoEs 特别有用的两个:

  • MergeModulelist (https://github.com/huggingface/transformers/blob/main/src/transformers/core_model_loading.py) 将张量列表合并为单个张量。例如,你可以组合 MergeModulelistConcatenate 来堆叠 MoE 中的专家并将它们打包到一个张量中。
WeightConverter(
    ["block_sparse_moe.experts.*.w1.weight", "block_sparse_moe.experts.*.w3.weight",],
    "mlp.experts.gate_up_proj",
    operations=[
        MergeModulelist(dim=0),
        Concatenate(dim=1),
    ],
)
  • SplitModulelist (https://github.com/huggingface/transformers/blob/b71de73468429eb02da18caa50e9b5200400a4ed/src/transformers/core_model_loading.py#L208) 将张量分割回张量列表。例如,你可以将堆叠的专家分割回各个专家。
WeightConverter(
    "mlp.experts.down_proj",
    "block_sparse_moe.experts.*.w2.weight",
    operations=[SplitModulelist(dim=0)],
)

张量的延迟实例化

重构改进的不仅是什么转换存在,还有如何安排它们。

加载程序扫描检查点键一次,将它们与转换器模式匹配,并按转换器对张量分组。一旦标识了所需的键,它就被注册为future,并通过线程池实例化。转换操作仅在其依赖项准备就绪时运行。例如,MergeModulelist 等待直到层的所有专家都加载。

这避免了重复扫描并减少了内存峰值。

基准测试:权重加载管道改进

为了评估新权重加载管道引入的改进,我们对 Transformers 的 v4 和 v5 版本进行了基准测试。重点是加载大型 MoE 模型的速度,这通常是训练和推理的瓶颈。

我们使用以下内容对 v4 和 v5 进行了基准测试:

  • v4 分支:https://github.com/ariG23498/transformers/tree/bench-v4
  • v5 分支:https://github.com/ariG23498/transformers/tree/bench-v5

示例:

from transformers import AutoModelForCausalLM

model_id = "Qwen/Qwen1.5-110B-Chat"
model = AutoModelForCausalLM.from_pretrained(model_id)

两个相关的环境变量:

  • HF_ENABLE_PARALLEL_LOADING:通过线程启用并行分片加载。
  • HF_DEACTIVATE_ASYNC_LOAD:禁用新异步管道(v5 逃生舱)。

结果

模型: Qwen/Qwen1.5-110B-Chat GPU: 1× A100(80GB)

版本策略加载模式时间
v4.57.6device_map="auto"线程池66.24s
v4.57.6device_map="auto"顺序67.29s
v4.57.6TPOOM
v5device_map="auto"异步(默认)20.71s
v5device_map="auto"同步45.3s
v5TP异步10.1s
v5TP同步19.28s

加载基准测试 (https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/moe-transformers/loading_benchmark.png)

图 4:加载基准测试(v4 对比 v5)

加速不仅仅是“更多线程“。

它是单遍路由异步实例化转换感知调度的结合,这些共同避免了不必要的实例化和内存峰值,同时在加载时启用专家打包和投影融合。

量化的作用

通过此重构,我们现在可以首先创建运行时模块结构,然后将权重转换为该结构。我们现在可以选择在转换管道内附加量化,使量化成为权重加载管道本身的一部分。这很关键,因为“按专家“量化只有在专家以可预测的打包布局存在时才有意义。

这个端到端管道之前是不可能的,现在以公开的 API 形式提供给用户。

专家后端

一旦专家被打包到单个运行时张量中,另一个问题出现了:

你实际上如何高效地通过它们进行路由?

在专家混合模型中,每个令牌被路由到不同的专家。这意味着运行时必须将令牌分发到其选定的专家权重,高效地执行投影,应用路由权重,然后收集和重新排序结果。

这正是专家后端系统 (https://huggingface.co/docs/transformers/experts_interface)(在 PR #42697 (https://github.com/huggingface/transformers/pull/42697) 中引入)所处理的。专家后端引入了可插拔执行架构,将专家计算与模型实现解耦。与其在每个 MoE 模型内部硬编码一个分发策略,该系统允许专家层在运行时动态选择后端。

这通过装饰器模式实现:

@use_experts_implementation

装饰器包装专家类并自动将计算分发到选定的后端。

目前提供三个后端:

  1. eager 循环遍历选定的专家并逐个专家应用投影。这用于正确性参考和调试。
  2. batched_mm 使用 torch.bmm (https://docs.pytorch.org/docs/stable/generated/torch.bmm.html) API。这为每个令牌复制选定的专家权重并执行单个批量 GEMM。此后端非常适合内存充足的小批量、GPU 密集型工作负载。
  3. grouped_mm 使用 torch._grouped_mm (https://docs.pytorch.org/docs/stable/generated/torch.nn.functional.grouped_mm.html) API。这里我们按专家 ID 对令牌进行排序,将它们分组,然后执行单个分组 GEMM。此后端在大批量或内存受限的设置中表现出色。

图:专家后端示意图

专家并行

专家混合模型可能具有数千亿个参数(远超过单个 GPU 能容纳的参数)。专家并行(EP)通过在多个设备上分布专家来解决这个问题。每个设备只加载其分配的专家子集,为那些专家计算,然后参与结果聚合。这种方法可以将模型扩展到远更大的参数数量,而无需增加计算

相似文章

EMO:用于涌现模块化的专家混合模型预训练

Hugging Face Daily Papers

EMO 是一种专家混合模型(Mixture-of-Experts),通过将相似领域的词元与共享专家分组实现模块化部署,在保持与标准 MoE 相当的性能的同时,支持显著的专家剪枝(保留 25% 的专家即可保留 99% 的性能)且不会导致性能下降。