如何用 Hugging Face 微调 LLM

大型语言模型(LLM)在去年取得了很大进展。我们从没有 ChatGPT 的竞争对手变成了一整套 LLM 动物园,包括 Meta AI 的 Llama 2、Mistrals Mistral 和 Mixtral 模型、TII Falcon 等等。 这些 LLM 可用于各种任务,包括聊天机器人、问答、总结,无需任何额外培训。但是,如果要为应用程序自定义模型。您可能需要对数据进行微调,以获得更高质量的结果,而不是通过训练更小的模型来提示或节省成本,更高效的模型。

这篇博文将引导您了解如何在 2024 年使用 Hugging Face TRLTransformer 和数据集微调开放 LLM。在博客中,我们将:

  1. 定义我们的用例
  2. 设置开发环境
  3. 创建和准备数据集
  4. 使用 trl 和 SFTTrainer 微调 LLM
  5. 测试和评估法学硕士
  6. 为生产部署 LLM

注意:本博客旨在在消费级 GPU (24GB) 上运行,例如 NVIDIA A10G 或 RTX 4090/3090,但可以轻松适应在更大的 GPU 上运行。

1. 定义我们的用例

在微调 LLM 时,了解您的用例和想要解决的任务非常重要。这将帮助您选择正确的模型或帮助您创建数据集来微调模型。如果您尚未定义用例。您可能想回到绘图板。 我想提一下,并非所有用例都需要微调,始终建议在微调自己的模型之前评估和试用已经微调的模型或基于 API 的模型。

例如,我们将使用以下用例:

我们想要微调一个模型,该模型可以基于自然语言指令生成 SQL 查询,然后可以将其集成到我们的 BI 工具中。目标是减少创建 SQL 查询所需的时间,并使非技术用户更容易创建 SQL 查询。

文本转 SQL 可能是微调 LLM 的一个很好的用例,因为它是一项复杂的任务,需要大量关于数据和 SQL 语言的(内部)知识。

2. 搭建开发环境

我们的第一步是安装 Hugging Face Libraries 和 Pytorch,包括 trl、transformer 和数据集。如果您还没有听说过 trl,请不要担心。它是 transformer 和数据集之上的新库,可以更轻松地微调、rlhf、对齐开放 LLM。

如果您使用的是具有 Ampere 架构的 GPU(例如 NVIDIA A10G 或 RTX 4090/3090)或更新版本,则可以使用 Flash 注意。Flash Attention 是一种对注意力计算进行重新排序的方法,并利用经典技术(平铺、重新计算)来显着加快速度,并将序列长度从二次减少到线性的内存使用量。The TL;博士;将训练速度提高 3 倍。如需了解更多信息,请访问FlashAttention

注意:如果您的计算机的 RAM 少于 96GB 且 CPU 内核很多,请减少MAX_JOBS的数量。在 g5.2xlarge 上,我们使用了 4

安装 flash-attn 可能需要相当长的时间(10-45 分钟)。

我们将使用 Hugging Face Hub 作为远程模型版本控制服务。这意味着我们将在训练期间自动将模型、日志和信息推送到中心。您必须为此在 Hugging Face 上注册。在您拥有帐户后,我们将使用huggingface_hub软件包中登录我们的帐户并将我们的令牌(访问密钥)存储在磁盘上。

3. 创建并准备数据集

一旦确定微调是正确的解决方案,我们就需要创建一个数据集来微调我们的模型。数据集应该是要解决的任务的一组多样化的演示。有几种方法可以创建此类数据集,包括:

  • 使用现有的开源数据集,例如 Spider
  • 使用 LLM 创建综合数据集,例如 Alpaca
  • 使用人类创建数据集,例如 Dolly
  • 使用上述方法的组合,例如Orca

每种方法都有自己的优点和缺点,取决于预算、时间和质量要求。例如,使用现有数据集是最简单的,但可能无法根据您的特定用例进行定制,而使用人工可能是最准确的,但可能既耗时又昂贵。也可以结合几种方法来创建指令数据集,如 Orca: Progressive Learning from Complex Explanation Traces of GPT-4 中所示。

在我们的示例中,我们将使用一个名为 sql-create-context 的现有数据集,其中包含自然语言指令、架构定义和相应 SQL 查询的示例。

trl最新版本中,我们现在支持流行的指令和对话数据集格式。这意味着我们只需要将数据集转换为支持的格式之一,其余的trl将负责。这些格式包括:

  • 对话格式(conversational format)
  • 指令格式(instruction format)

在我们的示例中,我们将使用 🤗 Datasets 库加载开源数据集,然后将其转换为对话格式,其中我们将架构定义包含在助手的系统消息中。然后,我们将数据集保存为 jsonl 文件,然后我们可以使用它来微调我们的模型。我们将数据集随机抽样到仅 10,000 个样本。

注意:此步骤可能因您的用例而异。例如,如果您已经有一个数据集,例如使用 OpenAI,您可以跳过此步骤并直接进入微调步骤。

4. 使用trlSFTTrainer微调LLM

我们现在准备微调我们的模型。我们将使用来自trlSFTTrainer 来微调我们的模型。这使得SFTTrainer监督微调开放 LLM 变得直接。该SFTTrainer是来自transformersTrainer的子类库,支持所有相同的功能,包括日志记录、评估和检查点,但添加了额外的生活质量功能,包括:

  • 数据集格式,包括对话和指令格式
  • 仅针对完成情况进行训练,忽略提示
  • 打包数据集以实现更高效的训练
  • PEFT(参数高效微调)支持,包括 Q-LoRA
  • 准备用于对话微调的模型和分词器(例如,添加特殊令牌)

在我们的示例中,我们将使用数据集格式、打包和 PEFT 特征。作为 peft 方法,我们将使用 QLoRA 技术来减少微调期间大型语言模型的内存占用,而不会因使用量化而牺牲性能。如果您想了解有关 QLoRA 及其工作原理的更多信息,请查看使用位沙字节、4 位量化和 QLoRA 博客文章使 LLM 更易于访问

现在,让我们开始吧!🚀 让我们从磁盘加载 json 数据集。

接下来,我们将加载我们的 LLM。对于我们的用例,我们将使用 CodeLlama 7B。CodeLlama 是一个经过训练的 Llama 模型,用于一般代码合成和理解。 但是我们可以通过更改变量model_id轻松地将模型换成另一个模型,例如 Mistral 或 Mixtral 模型、TII Falcon 或任何其他 LLM。我们将使用 bitsandbytes 将我们的模型量化为 4 位。

注意:请注意,模型越大,所需的内存就越多。在我们的示例中,我们将使用 7B 版本,它可以在 24GB GPU 上进行调整。如果您的 GPU 较小。

正确地准备用于训练聊天/对话模型的模型和分词器至关重要。我们需要向分词器和模型添加新的特殊令牌,以教他们在对话中的不同角色。在 trl 我们有一个方便的setup_chat_format方法:

  • 向分词器添加特殊令牌,例如<|im_start|><|im_end|>,指示对话的开始和结束。
  • 调整模型嵌入层的大小以容纳新标记。
  • 设置 chat_template 分词器 ,用于将输入数据格式化为类似聊天的格式。默认值 chatml 来自 OpenAI。

SFTTrainer支持与peft的本机集成,这使得使用 QLoRA 等 LLM 的高效调整变得非常容易。我们LoraConfig只需要创建我们的并将其提供给培训师。我们LoraConfig的参数是根据 qlora 论文和 sebastian 的博客文章定义的。

在开始训练之前,我们需要定义要使用的超参数(TrainingArguments)。

现在,我们拥有了创建 SFTTrainer 模型并开始训练模型的所有构建块。

我们可以通过在 Trainer 实例上调用train()方法来开始训练模型。这将启动训练循环并训练我们的模型 3 个周期。由于我们使用的是PEFT方法,因此我们只会保存自适应的模型权重,而不是完整的模型。

使用 Flash Attention 对 3 个 epoch 的训练,数据集为 10k 个样本,在 g5.2xlarge 实例成本1.212$/h,使我们的总成本仅为1.8$

可选:将 LoRA 适配器合并到原始模型中

使用 QLoRA 时,我们只训练适配器,而不是完整模型。这意味着在训练期间保存模型时,我们只保存适配器权重,而不是完整模型。如果要保存完整模型,以便更轻松地与文本生成推理一起使用,则可以使用 merge_and_unload 方法将适配器权重合并到模型权重中,然后使用 save_pretrained 方法保存模型。这将保存一个默认模型,该模型可用于推理。

注意:您可能需要> 30GB CPU 内存。

5. 测试和评估 LLM

训练完成后,我们要评估和测试我们的模型。我们将从原始数据集中加载不同的样本,并使用简单的循环和准确性作为我们的指标,在这些样本上评估模型。

注意:评估生成式 AI 模型并非易事,因为 1 个输入可以有多个正确的输出。如果您想了解有关评估生成模型的更多信息,请查看使用 Langchain 和 Hugging Face 的实例评估 LLM 和 RAG 博客文章。

让我们加载我们的测试数据集,尝试生成一条指令。

好!我们的模型能够根据自然语言指令生成 SQL 查询。让我们在测试数据集的全部 2,500 个样本上评估我们的模型。注意:如上所述,评估生成模型并非易事。在我们的示例中,我们使用基于真实 SQL 查询生成的 SQL 的准确性作为我们的指标。另一种方法是自动执行生成的 SQL 查询,并将结果与实际情况进行比较。这将是一个更准确的指标,但需要更多的工作来设置。

我们在评估数据集中的 1000 个样本上评估了我们的模型,并得到了79.50%的准确度,这需要 ~25 分钟。

这很好,但如前所述,您需要对这个指标持保留态度。如果我们可以通过对真实数据库运行查询来评估我们的模型并比较结果,那就更好了。因为同一指令可能有不同的“正确”SQL 查询。还有几种方法可以提高性能,方法是使用少样本学习,使用 RAG、自我修复来生成 SQL 查询。

6. 为生产部署 LLM

现在可以将模型部署到生产环境。为了将开放 LLM 部署到生产环境中,我们建议使用文本生成推理 (TGI)。TGI 是用于部署和服务大型语言模型 (LLM) 的专用解决方案。TGI 支持使用张量并行和连续批处理为最流行的开放 LLM(包括 Llama、Mistral、Mixtral、StarCoder、T5 等)生成高性能文本。文本生成推理被 IBM、Grammarly、Uber、Deutsche Telekom 等公司使用。有几种方法可以部署模型,包括:

如果安装了 docker,则可以使用以下命令启动推理服务器。

注意:请确保有足够的 GPU 内存来运行容器。重新启动内核以从笔记本电脑中删除所有已分配的 GPU 内存。

容器运行后,可以发送请求。

太棒了,完成后不要忘记停止容器。

结论

大型语言模型和工具TRL的可用性使其成为公司投资开放式LLM技术的理想时机。针对特定任务微调开放 LLM 可以显著提高效率,并为创新和改进服务开辟新的机会。随着可访问性和成本效益的提高,现在是开始使用开放式 LLM 的最佳时机。


感谢您的阅读!如果您有任何问题,请随时在TwitterLinkedIn上与我联系。

参考连接:https://www.philschmid.de/fine-tune-llms-in-2024-with-trl?WT.mc_id=academic-105485-koreyst

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部