核心内容摘要
AI应用架构师视角:企业AI技术栈如何选?
原文towardsdatascience.com/merge-large-language-models-with-mergekit-2118fb392b54?sourcecollection_archive---------0-----------------------#
轻松创建你自己的模型无需 GPUhttps://medium.com/mlabonne?sourcepost_page---byline--2118fb392b54--------------------------------https://towardsdatascience.com/?sourcepost_page---byline--2118fb392b54-------------------------------- Maxime Labonne·发表于 Towards Data Science ·阅读时间11 分钟·2024 年 1 月 8 日–https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/3250f7b46dc7b58c13e186d2b0230d
png图片由作者提供模型合并是一种将两个或更多 LLM 模型合并为单个模型的技术。
这是一种相对较新且实验性的方法用于以低成本无需 GPU创建新模型。
模型合并效果出乎意料地好并且产生了许多在Open LLM 排行榜上排名靠前的顶尖模型。
在本教程中我们将使用mergekit库来实现。
更具体地我们将回顾四种合并方法并提供配置示例。
然后我们将使用 mergekit 创建我们自己的模型Marcoro14–7B-slerp该模型在 Open LLM 排行榜2024 年 1 月 2 日上表现最佳。
代码可在GitHub和Google Colab上找到。
我推荐使用我的自动化笔记本来轻松运行 mergekit LazyMergekit。
特别感谢Charles Goddardmergekit 库的作者感谢他审阅本文。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/c43a26493b1d996b35c6c341845a3a
png图片由作者提供 合并算法在本节中我们将重点介绍mergekit中目前实现的四种方法。
请注意还有其他方法如线性插值和任务算术。
如果你对模型合并的论文感兴趣推荐查看这个优秀的合集。
SLERP球面线性插值SLERP是一种在两个向量之间平滑插值的方法。
它保持恒定的变化速率并保留向量所处球面空间的几何属性。
有几个理由更倾向于使用 SLERP 而不是传统的线性插值。
例如在高维空间中线性插值可能会导致插值向量的大小减小即减少权重的尺度。
此外权重的方向变化通常代表了更有意义的信息如特征学习和表示而不是变化的大小。
SLERP 的实现步骤如下将输入向量标准化为单位长度确保它们表示的是方向而非大小。
使用它们的点积计算这些向量之间的角度。
如果向量几乎共线则默认使用线性插值以提高效率。
否则SLERP 会根据插值因子tt0 100%的第一个向量t1 100%的第二个模型和向量之间的角度计算缩放因子。
这些因素用于加权原始向量然后将其求和以得到插值向量。
SLERP 目前是最流行的合并方法但它仅限于一次合并两个模型。
仍然可以层次化地合并多个模型如在Mistral-7B-Merge-14-v
1中所示。
配置示例slices:-sources:-model:OpenPipe/mistral-ft-optimized-1218layer_range:[0,32]-model:mlabonne/NeuralHermes-
5-Mistral-7B layer_range:[0,32]merge_method:slerp base_model:OpenPipe/mistral-ft-optimized-1218parameters:t:-filter:self_attn value:[0,
5,
3,
7,1]-filter:mlp value:[1,
5,
7,
3,0]-value:
5dtype:bfloat16这是一个经典的 SLERP 配置应用于两个模型的每一层。
请注意我们输入一个值梯度作为插值因子t。
自注意力层和 MLP 层的参数将使用OpenPipe/mistral-ft-optimized-1218和mlabonne/NeuralHermes-
5-Mistral-7B的不同组合。
其他层则是两个模型的 50/50 混合。
你可以在 Hugging Face Hub 上找到最终模型mlabonne/NeuralPipe-7B-slerp。
TIES在Yadav 等人的论文中提出的TIES-Merging旨在高效地将多个任务特定的模型合并为一个多任务模型。
它解决了模型合并中的两个主要挑战模型参数中的冗余它识别并消除任务特定模型中的冗余参数。
通过关注微调过程中所做的变化识别最重要的前 k%变化并丢弃其余部分。
参数符号之间的分歧当不同模型对同一参数提出相反调整时会产生冲突。
TIES-Merging 通过创建一个统一的符号向量来解决这些冲突表示所有模型中最主导的变化方向。
TIES-Merging 分为以下三个步骤修剪通过仅保留最重要参数密度参数的部分重置其余部分为零从而减少任务特定模型中的冗余。
选择符号通过基于累积大小的最主导方向正或负创建统一符号向量解决不同模型之间的符号冲突。
不相交合并平均与统一符号向量对齐的参数值排除零值。
与 SLERP 不同TIES 可以一次合并多个模型。
配置示例models:-model:mistralai/Mistral-7B-v
1# no parameters necessary for base model-model:OpenPipe/mistral-ft-optimized-1218parameters:density:
5weight:
5-model:mlabonne/NeuralHermes-
5-Mistral-7B parameters:density:
5weight:
3merge_method:ties base_model:mistralai/Mistral-7B-v
1parameters:normalize:true dtype:float16使用此配置我们使用 Mistral-7B 作为基础模型来计算增量权重。
我们合并相同的两个模型mistral-ft-optimized-121850%和NeuralHermes-
5-Mistral-7B30%并进行归一化。
这里的密度表示我们只保留每个模型 50%的参数另一半来自基础模型。
请注意配置中的权重总和不等于 1但normalize: true参数会自动在内部对其进行归一化。
该配置灵感来自于OpenHermes-
5-neural-chat-7b-v3–1–7B作者提供的参数。
您可以在 Hugging Face Hub 上找到最终模型mlabonne/NeuralPipe-7B-ties。
DARE由 Yu 等人2023 年提出的DARE采用了类似于 TIES 的方法主要有两个不同之处剪枝DARE 将微调后的权重随机重置为其原始值即基础模型的值。
重新缩放DARE 通过重新缩放权重来保持模型输出的期望值大致不变。
它将两个或多个模型的重新缩放权重与基础模型的权重通过一个缩放因子相加。
Mergekit 对此方法的实现有两种形式一种是带有 TIES 符号选择步骤dare_ties另一种是没有的dare_linear。
配置示例models:-model:mistralai/Mistral-7B-v
1# No parameters necessary for base model-model:samir-fama/SamirGPT-v1 parameters:density:
53weight:
4-model:abacusai/Slerp-CM-mist-dpo parameters:density:
53weight:
3-model:EmbeddedLLM/Mistral-7B-Merge-14-v
2parameters:density:
53weight:
3merge_method:dare_ties base_model:mistralai/Mistral-7B-v
1parameters:int8_mask:true dtype:bfloat16在此配置中我们基于 Mistral-7B 合并了三种不同的模型使用了dare_ties。
这次我选择了权重之和为 1 的组合权重和应该在
9 到
1 之间。
密度参数比论文中推荐的值
5稍高但看起来它 consistently 给出了更好的结果参见这个讨论。
你可以在 Hugging Face Hub 上找到它地址是mlabonne/Daredevil-7B。
它也是本文中表现最好的合并模型甚至超过了 Marcoro14–7B-slerp。
透传透传方法与之前的几种方法有显著不同。
通过将来自不同大语言模型LLM的层级进行拼接它可以生成具有独特参数数量的模型例如两个 7B 参数模型合并生成 9B 模型。
这些模型通常被社区称为“弗兰肯合并”或“弗兰肯斯坦模型”。
这个技术非常实验性但它成功地创造了令人印象深刻的模型比如使用两个 Llama 2 70B 模型合并的goliath-120b。
最近发布的SOLAR-
1
7B-v
0也采用了相同的理念称为深度向上扩展详见他们的论文这里。
配置示例slices:-sources:-model:OpenPipe/mistral-ft-optimized-1218layer_range:[0,32]-sources:-model:mlabonne/NeuralHermes-
5-Mistral-7B layer_range:[24,32]merge_method:passthrough dtype:bfloat16结果的弗兰肯合并将拥有来自第一个模型的所有 32 层以及来自第二个模型的 8 层。
这创建了一个总共 40 层和
99B 参数的弗兰肯合并模型。
此配置灵感来自于GML-Mistral-merged-v1。
你可以在 Hugging Face Hub 上找到最终模型地址是mlabonne/NeuralPipe-9B-merged。
合并你自己的模型在这一部分中我们将使用 mergekit 加载合并配置运行它并将合并后的模型上传到 Hugging Face Hub。
首先我们直接从源代码安装 mergekit如下所示!git clone https://github.com/cg123/mergekit.git !cd mergekitpip install-q-e.在接下来的代码块中我们加载合并配置文件YAML 格式。
我们还指定了合并后模型的名称以供以后使用。
你可以将上一节中的任何配置复制/粘贴到这里。
这次我们将使用两个不同的模型Marcoroni-7B-v3 和 Mistral-7B-Merge-14-v
1并使用 SLERP 方法将它们合并。
我们将配置保存为 yaml 文件以便作为输入使用在合并命令中。
importyaml MODEL_NAMEMarcoro
B-slerpyaml_config slices: - sources: - model: AIDC-ai-business/Marcoroni-7B-v3 layer_range: [0, 32] - model: EmbeddedLLM/Mistral-7B-Merge-14-v
1 layer_range: [0, 32] merge_method: slerp base_model: AIDC-ai-business/Marcoroni-7B-v3 parameters: t: - filter: self_attn value: [0,
5,
3,
7, 1] - filter: mlp value: [1,
5,
7,
3, 0] - value:
5 dtype: bfloat16 # Save config as yaml filewithopen(config.yaml,w,encodingutf-
asf:f.write(yaml_config)我们使用以下参数运行合并命令--copy-tokenizer用于从基础模型复制分词器--allow-crimes和--out-shard-size用于将模型分割成较小的分片以便在低内存的 CPU 上计算。
--lazy-unpickle以启用实验性的懒加载解包器从而减少内存使用。
此外一些模型可能需要--trust_remote_code标志Mistral-7B 不需要此标志。
这个命令将下载合并配置中列出的所有模型的权重并运行选定的合并方法大约需要 10 分钟。
# Merge models!mergekit-yaml config.yaml merge--copy-tokenizer--allow-crimes--out-shard-size 1B--lazy-unpickl模型现在已经合并并保存在merge目录中。
在上传之前我们可以创建一个包含所有可复现性所需信息的 README 文件。
以下代码块定义了一个 Jinja 模板并自动填充来自合并配置的数据。
!pip install-qU huggingface_hubfromhuggingface_hubimportModelCard,ModelCardDatafromjinja2importTemplate usernamemlabonnetemplate_text --- license: apache-
0 tags: - merge - mergekit - lazymergekit {%- for model in models %} - {%- endfor %} --- # is a merge of the following models using [mergekit](https://github.com/cg123/mergekit): {%- for model in models %} * [](https://huggingface.co/) {%- endfor %} ## Configuration yaml py # Create a Jinja template objectjinja_templateTemplate(template_text.strip())# Get list of models from configdatayaml.safe_load(yaml_config)ifmodelsindata:models[data[models][i][model]foriinrange(len(data[models]))ifparametersindata[models][i]]elifparametersindata:models[data[slices][0][sources][i][model]foriinrange(len(data[slices][0][sources]))]elifslicesindata:models[data[slices][i][sources][0][model]foriinrange(len(data[slices]))]else:raiseException(No models or slices found in yaml config)# Fill the templatecontentjinja_template.render(model_nameMODEL_NAME,modelsmodels,yaml_configyaml_config,usernameusername,)# Save the model cardcardModelCard(content)card.save(merge/README.md)现在我们有了模型卡片可以将整个文件夹推送到 Hub。
fromgoogle.colabimportuserdatafromhuggingface_hubimportHfApi usernamemlabonne# Defined in the secrets tab in Google ColabapiHfApi(tokenuserdata.get(HF_TOKEN))api.create_repo(repo_idf{username}/{MODEL_NAME},repo_typemodel)api.upload_folder(repo_idf{username}/{MODEL_NAME},folder_pathmerge,)该模型现在可以在 Hugging Face Hub 上获取链接为mlabonne/Marcoro14–7B-slerp。
在另一个笔记本中我们可以使用以下代码在免费的 T4 GPU 上尝试该模型!pip install-qU transformers acceleratefromtransformersimportAutoTokenizerimporttransformersimporttorch modelmlabonne/Marcoro
B-slerpmessages[{role:user,content:What is a large language model?}]tokenizerAutoTokenizer.from_pretrained(model)prompttokenizer.apply_chat_template(messages,tokenizeFalse,add_generation_promptTrue)pipelinetransformers.pipeline(text-generation,modelmodel,torch_dtypetorch.float16,device_mapauto,)outputspipeline(prompt,max_new_tokens256,do_sampleTrue,temperature
7,top_k50,top_p
0.
我们提出了“什么是大语言模型”这个问题并获得了以下输出大语言模型是一种人工智能AI系统它通过大量的文本数据进行训练。
其设计目的是理解和生成类似人类的语言预测句子或文档中接下来可能出现的单词或短语。
这些模型使用复杂的算法和神经网络架构从数据中学习并随着时间的推移提高其表现。
一些著名的大语言模型包括 OpenAI 的 GPT-3 和 Google 的 BERT。
一切看起来不错但我们需要更全面的评估。
对于这种通用模型有一些有趣的基准测试Chatbot Arena它根据人类投票编制了一个基于 Elo 的 LLM 排行榜。
MT-bench同一个链接它使用 GPT-4 作为裁判基于一组多轮问题对模型的回答进行评分。
NousResearch 基准套件它汇集了四个基准测试AGIEval、GPT4ALL、TruthfulQA 和 Bigbench。
GPT4ALL 本身包括 HellaSwag、OpenBookQA、Winogrande、ARC-Easy、ARC-Challenge、BoolQ 和 PIQA。
Open LLM 排行榜它汇集了六个基准测试ARC、HellaSwag、MMLU、Winogrande、GSM8K 和 TruthfulQA。
不幸的是我们无法将模型提交到 Chatbot Arena。
相反我选择使用 Open LLM 排行榜和 NousResearch 基准测试来评估它。
我将我们的模型提交到了Open LLM 排行榜“ Submit here!”标签。
如介绍所示它在排行榜中排名为最佳 7B 参数模型。
以下是完整的结果https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f4226bad511e593527bd4a16b408aca
png作者提供的图像Open LLM Leaderboard 的问题在于这些基准是公开的。
这意味着人们可以在测试数据上训练 LLMs 以获得更好的结果。
通过合并最佳模型我们也污染了自己的结果。
可以安全地假设Marcoro14–7B-slerp 已被污染并且本次合并中使用的某些模型可能已在测试集上进行过训练。
如果您想创建最好的模型而不是操控排行榜我建议仅使用非合并模型来创建您自己的合并模型。
这就是为什么我们不想仅依赖 OpenLLM Leaderboard。
对于 NousResearch 基准测试套件我使用了 LLM AutoEval通过简单的 Colab 笔记本自动计算分数。
以下是与优秀的OpenHermes-
5-Mistral-7B相比的结果https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/dccb0dc2b74086db79fae8ace4c1bad
png图片由作者提供我们在每个基准测试上都取得了显著的提升。
请注意NousResearch 基准测试套件与 Open LLM Leaderboard 共享一些任务ARC-Challenge、TruthfulQA、HellaSwag 和 Winogrande。
据我所知Bigbench 是唯一一个 100% 不同的基准如果不是请随时与我联系。
然而我们在此合并中使用的某些模型仍然可能在 Bigbench 上进行了训练。
结论在本文中我们介绍了将 LLMs 合并的四种不同方法。
我们详细讲解了 SLERP、TIES、DARE 和 passthrough 的工作原理并提供了配置示例。
最后我们使用 mergekit 运行 SLERP创建了Marcoro14–7B-slerp并将其上传至 Hugging Face Hub。
我们在两个基准测试套件上取得了优秀的表现Open LLM Leaderboard表现最好的 7B 模型和 NousResearch。
如果您想创建自己的合并模型我推荐使用我的自动化笔记本 LazyMergekit。
另一种合并多个模型的方法是将它们合并在 Mixture of Experts (MoE) 架构中。
在下一篇文章中我们将详细讨论如何执行此操作并创建我们自己的类似 Mixtral 的模型。
如果您喜欢本文请在 Medium 和 Twitter 上关注我maximelabonne。
通过点击一次了解更多关于机器学习的信息并支持我的工作——在这里成为 Medium 会员[## 通过我的推荐链接加入 Medium — Maxime Labonne作为 Medium 会员您的一部分会员费用将用于支持您阅读的作家同时您可以完全访问每个故事…medium.com](https://medium.com/mlabonne/membership?sourcepost_page-----2118fb392b54--------------------------------)