原文地址:create-mixtures-of-experts-with-mergekit
2024 年 3 月 27 日
由于 Mixtral 的发布,Mixture of Experts(MoE)架构近几个月开始流行。这种架构提供了一个有趣的权衡:以增加 VRAM 使用为代价获得更高的性能。虽然 Mixtral 和其他 MoE 架构是从头开始预训练的,但最近出现了另一种创建 MoE 的方法。感谢阿尔茜的MergeKit库,我们现在有了一种通过集成多个预训练模型来创建 MoE 的新方法。这些通常被称为frankenMoEs or MoErges,将它们与预先训练的 MoE 区分开来。
在本文中,我们将详细介绍 MoE 架构的工作原理以及 FrankenMoE 的创建方式。最后,我们将使用 MergeKit 制作我们自己的 FrankenMoE,并在几个基准上对其进行评估。该代码可在 Google Colab 上的名为LazyMergeKit的包装器中找到。
特别感谢MergeKit 的创建者Charles Goddard校对本文。
MoEs简介
专家混合是一种旨在提高效率和性能的架构。它使用多个专门的子网络,称为“专家”。与激活整个网络的密集模型不同,MoE 仅根据输入激活相关专家。这会带来更快的训练和更有效的推理。
MoE 模型的核心有两个组成部分:
- 稀疏 MoE 层:这些层取代了transformer架构中密集的前馈网络层。每个 MoE 层包含多个专家,并且只有这些专家的子集参与给定的输入。
- 门网络或路由器:该组件确定哪些令牌由哪些专家处理,确保输入的每个部分都由最合适的专家处理。
下面的示例展示了如何将 Mistral-7B 块转换为具有稀疏 MoE 层(前馈网络 1、2 和 3)和路由器的 MoE 块。此示例代表MoE拥有三名专家,其中目前有两名专家(FFN 1 和 FFN 3)。
MoE 也面临着自己的一系列挑战,特别是在微调和内存要求方面。由于模型的复杂性,微调过程可能很困难,需要在训练期间平衡专家的使用,以正确训练门控权重以选择最相关的权重。在内存方面,即使在推理过程中只使用了总参数的一小部分,但整个模型,包括所有专家,都需要加载到内存中,这需要很高的VRAM容量。
更具体地说,MoE 有两个基本参数:
- 专家数量(
num_local_experts
):这决定了架构中专家的总数(例如,Mixtral 为 8)。专家数量越多,VRAM 使用率越高。 - 专家/令牌的数量(
num_experts_per_tok
):这决定了每个令牌和每个层参与的专家数量(例如,Mixtral 为 2)。每个token的专家数量较多以提高准确性(但收益递减),而较少的专家数量则可实现快速训练和推理,需要进行权衡。
从历史上看,MoE 的表现不如密集模型。然而, Mixtral-8x7B于 2023 年 12 月的发布震撼了一切,并以其尺寸展现了令人印象深刻的性能。此外,据传 GPT-4 也是一个 MoE,这是有道理的,因为与密集模型相比,OpenAI 的运行和训练要便宜得多。除了这些最近优秀的 MoE 之外,我们现在还有一种使用 MergeKit 创建 MoE 的新方法:frankenMoEs,也称为 MoErges。
MoE 与 FrankenMoE
真正的 MoE 和 FrankenMoE 之间的主要区别在于它们的训练方式。在真正的 MoE 中,专家和路由器接受联合培训。对于 FrankenMoE,我们升级现有模型并随后初始化路由器。
换句话说,我们从基础模型中复制层归一化和自注意力层的权重,然后复制每个专家中找到的 FFN 层的权重。这意味着除了 FFN 之外,所有其他参数都是共享的。这解释了为什么具有八个专家的 Mixtral-8x7B 没有 8*7 = 56B 参数,而是大约 45B。这也是为什么每个令牌使用两名专家可以提供 12B 密集模型而不是 14B 的推理速度(FLOP)。
FrankenMoE 的目的是选择最相关的专家并正确初始化它们。 MergeKit 目前实现了三种初始化路由器的方法:
- 随机:随机权重。使用它时要小心,因为每次可能会选择相同的专家(它需要进一步微调 或
num_local_experts = num_experts_per_tok
,这意味着您不需要任何路由)。 - 廉价嵌入:它直接使用输入标记的原始嵌入,并在所有层上应用相同的转换。该方法计算成本低廉,适合在功能较弱的硬件上执行。
- 隐藏:它通过从LLMs的最后一层提取正面和负面提示列表来创建隐藏表示。对它们进行平均和标准化以初始化门。有关它的更多信息,请访问Charles Goddard 的博客。
正如您所猜测的,“隐藏”初始化是将令牌正确路由到最相关的专家的最有效方法。在下一节中,我们将使用这种技术创建我们自己的 FrankenMoE。
创建 FrankenMoE
为了创建我们的 FrankenMoE,我们需要选择n
专家。在这种情况下,我们将依靠 Mistral-7B,因为它很受欢迎且尺寸相对较小。然而,像 Mixtral 这样的 8 个专家相当多,因为我们需要将它们全部放入内存中。为了提高效率,我在此示例中仅使用四名专家,其中两名负责每个令牌和每个层。在这种情况下,我们最终将得到一个具有 24.2B 个参数的模型,而不是 4*7 = 28B 个参数。
在这里,我们的目标是创建一个全面的模型,它几乎可以做所有事情:写故事、解释文章、用 Python 编写代码等。我们可以将此需求分解为四个任务,并为每个任务选择最佳专家。我是这样分解的:
- 聊天模型:大多数交互中使用的通用模型。我使用的是mlabonne/AlphaMonarch-7B,它完全满足要求。
- 代码模型:能够生成好的代码的模型。我对基于 Mistral-7B 的代码模型没有太多经验,但我发现beowolx/CodeNinja-1.0-OpenChat-7B与其他模型相比特别好。
- 数学模型:数学对于LLMs来说很棘手,这就是为什么我们需要一个专门研究数学的模型。由于 MMLU 和 GMS8K 分数较高,我为此选择了mlabonne/NeuralDaredevil-7B 。
- 角色扮演模型:该模型的目标是编写高质量的故事和对话。我选择了SanjiWatsuki/Kunoichi-DPO-v2–7B,因为它具有良好的声誉和较高的 MT-Bench 分数(Mixtral 为 8.51 vs. 8.30)。
现在我们已经确定了要使用的专家,我们可以创建 MergeKit 将用来创建 FrankenMoE 的 YAML 配置。这使用了 MergeKit 的 mixtral 分支。您可以在此页面上找到有关如何编写配置的更多信息。这是我们的版本:
base_model: mlabonne/AlphaMonarch-7B
experts:
- source_model: mlabonne/AlphaMonarch-7B
positive_prompts:
- "chat"
- "assistant"
- "tell me"
- "explain"
- "I want"
- source_model: beowolx/CodeNinja-1.0-OpenChat-7B
positive_prompts:
- "code"
- "python"
- "javascript"
- "programming"
- "algorithm"
- source_model: SanjiWatsuki/Kunoichi-DPO-v2-7B
positive_prompts:
- "storywriting"
- "write"
- "scene"
- "story"
- "character"
- source_model: mlabonne/NeuralDaredevil-7B
positive_prompts:
- "reason"
- "math"
- "mathematics"
- "solve"
- "count"
对于每位专家,我提供了五个基本的积极提示。如果你愿意的话,你可以更花哨一点,写出整个句子。最好的策略包括使用应该触发特定专家的真实提示。您还可以添加负面提示来执行相反的操作。
准备就绪后,您可以将配置另存为config.yaml
.在同一文件夹中,我们将下载并安装mergekit库(mixtral 分支)。
git clone -b mixtral https://github.com/arcee-ai/mergekit.git
cd mergekit && pip install -e .
pip install -U transformers
如果您的计算机有足够的 RAM(大约 24–32 GB RAM),您可以运行以下命令:
mergekit-moe config.yaml merge --copy-tokenizer
如果您没有足够的 RAM,您可以按如下方式对模型进行分片(这将需要更长的时间):
mergekit-moe config.yaml merge --copy-tokenizer --allow-crimes --out-shard-size 1B --lazy-unpickle
此命令会自动下载专家并在目录中创建 FrankenMoE merge
。对于hidden
门模式,您还可以使用--load-in-4bit
和--load-in-8bit
选项以较低的精度计算隐藏状态。
或者,您可以将配置复制到LazyMergekit中,这是我为简化模型合并而制作的包装器。在此 Colab 笔记本中,您可以输入模型名称、选择分支mixtral
、指定您的 Hugging Face 用户名/令牌,然后运行单元格。创建 FrankenMoE 后,它还会将其上传到 Hugging Face Hub,并附上格式良好的模型卡。
我将我的模型命名为Beyonder-4x7B-v3并使用AutoGGUF创建了它的GGUF 版本。如果您无法在本地计算机上运行 GGUF 版本,您还可以使用此Colab Notebook执行推理。
为了更好地了解其功能,我们根据三个不同的基准对其进行了评估:Nous 基准套件、EQ-Bench 和 Open LLM Leaderboard。该模型的设计目的并不是在传统基准测试中表现出色,因为代码和角色扮演模型通常不适用于这些环境。尽管如此,由于强大的通用专家的帮助,它的表现非常出色。
Nous:Beyonder-4x7B-v3 是 Nous 基准测试套件中最好的模型之一(使用LLM AutoEval进行评估),并且显着优于 v2。在这里查看整个排行榜。
EQ-Bench:它也是EQ-Bench 排行榜上最好的 4x7B 模型,优于旧版本的 ChatGPT 和 Llama-2–70b-chat。 Beyonder 与 Mixtral-8x7B-Instruct-v0.1 和 Gemini Pro 非常接近,这两个模型(据说)要大得多。
Open LLM 排行榜:最后,它在 Open LLM 排行榜上也表现强劲,明显优于 v2 模型。
除了这些定量评估之外,我建议使用LM Studio上的 GGUF 版本以更定性的方式检查模型的输出。测试这些模型的常见方法是收集一组私人问题并检查其输出。通过这种策略,我发现与其他模型(包括 AlphaMonarch-7B)相比,Beyonder-4x7B-v3 对于用户和系统提示的变化相当稳健。这非常酷,因为它总体上提高了模型的实用性。
FrankenMoE 是一种很有前途但仍处于实验阶段的方法。较高的 VRAM 需求和较慢的推理速度等权衡使得很难看到它们相对于 SLERP 或 DARE TIES 等更简单的合并技术的优势。特别是,当您仅与两名专家一起使用 FrankenMoE 时,它们的性能可能不如您简单地合并两个模型那么好。然而,FrankenMoE 擅长保存知识,这可以产生更强大的模型,正如 Beyonder-4x7B-v3 所证明的那样。有了合适的硬件,这些缺点就可以得到有效缓解。
结论
在本文中,我们介绍了专家混合架构。与从头开始训练的传统 MoE 不同,MergeKit 有助于集成专家创建 MoE,提供创新方法来提高模型性能和效率。我们详细介绍了使用 MergeKit 创建 FrankenMoE 的过程,重点介绍了选择和组合不同专家以生成高质量 MoE 所涉及的实际步骤。
References
- Mixtral of Experts by Jiang et al. (2023)
- Mixture of Experts for Clowns by Charles Goddard (2023)
- Mixture of Experts Explained by Sanseviero et al. (2023)
- Adaptive Mixture of Local Experts by Jacobs et al. (1991)
- Sparse Upcycling: Training Mixture-of-Experts from Dense Checkpoints by Komatsuzaki et al. (2022)