Transformer 中的专家混合模型 (MoEs)
摘要
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 吸引人的原因有:
- 更好的计算效率 在固定训练 FLOP 预算下,MoEs 通常优于稠密模型。这意味着更快的迭代和更好的扩展效率。
- 自然的并行化轴 专家在计算图中提供了结构边界。由于不同的令牌使用不同的专家,我们可以跨专家并行化(我们稍后在专家并行中讨论这个)。
- 行业采用 过去几周发生的开放模型的主要 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) 将张量列表合并为单个张量。例如,你可以组合MergeModulelist和Concatenate来堆叠 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.6 | device_map="auto" | 线程池 | 66.24s |
| v4.57.6 | device_map="auto" | 顺序 | 67.29s |
| v4.57.6 | TP | — | OOM |
| v5 | device_map="auto" | 异步(默认) | 20.71s |
| v5 | device_map="auto" | 同步 | 45.3s |
| v5 | TP | 异步 | 10.1s |
| v5 | TP | 同步 | 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
装饰器包装专家类并自动将计算分发到选定的后端。
目前提供三个后端:
eager循环遍历选定的专家并逐个专家应用投影。这用于正确性参考和调试。batched_mm使用torch.bmm(https://docs.pytorch.org/docs/stable/generated/torch.bmm.html) API。这为每个令牌复制选定的专家权重并执行单个批量 GEMM。此后端非常适合内存充足的小批量、GPU 密集型工作负载。grouped_mm使用torch._grouped_mm(https://docs.pytorch.org/docs/stable/generated/torch.nn.functional.grouped_mm.html) API。这里我们按专家 ID 对令牌进行排序,将它们分组,然后执行单个分组 GEMM。此后端在大批量或内存受限的设置中表现出色。
图:专家后端示意图
专家并行
专家混合模型可能具有数千亿个参数(远超过单个 GPU 能容纳的参数)。专家并行(EP)通过在多个设备上分布专家来解决这个问题。每个设备只加载其分配的专家子集,为那些专家计算,然后参与结果聚合。这种方法可以将模型扩展到远更大的参数数量,而无需增加计算
相似文章
@jbhuang0604: Huge! It’s amazing how often Noam’s papers end up at the center of the field. In many tutorial videos I’ve made, they’v…
The article provides a detailed explanation of Mixture of Experts (MoE) in transformers, covering routing, load balancing, and recent innovations like fine-grained experts. It also highlights the significance of Noam Shazeer's research contributions and his move from Google to OpenAI.
Mix-MoE:通过混合专家混合提升大语言模型的多语言机器翻译
Mix-MoE提出了一种混合专家混合框架,通过专门的专家组和傅里叶变换增强的路由机制来缓解多语言机器翻译中的参数干扰,相比基线方法取得了显著改进。
XPERT:通过专家知识迁移实现语言模型的高效训练
本文介绍了 XPERT,这是一个从预训练混合专家(MoE)语言模型中提取和复用专家知识的框架,旨在提高下游模型的训练效率和性能。
除了更快之外,MoE 模型的意义何在?
讨论混合专家(MoE)模型在速度之外相对于密集模型的优势,考虑内存限制和扩展限制。
EMO:用于涌现模块化的专家混合模型预训练
EMO 是一种专家混合模型(Mixture-of-Experts),通过将相似领域的词元与共享专家分组实现模块化部署,在保持与标准 MoE 相当的性能的同时,支持显著的专家剪枝(保留 25% 的专家即可保留 99% 的性能)且不会导致性能下降。