编辑 | 言征
出品 | 51CTO技术栈(微信号:blog51cto)
LLM在生成文本和理解信息方面非常有效,但它们最终受限于训练数据的语料库。例如,如果你让一个通用的预训练模型回答与你的业务特定流程或操作有关的问题,最好的结果是它拒绝,最坏的情况是它会信誓旦旦地给出一个看似合理但错误的答案。
当然,你可以通过自己训练一个模型来解决这个问题,但所需的资源往往超出实际可行的范围。例如,训练Meta的相对小的Llama 3 8B模型需要约130万GPU小时的计算资源,使用的是80GB的Nvidia H100。好消息是你不需要这样做。我们可以通过称为微调的过程,利用现有的模型(如Llama、Mistral或Phi),并通过自己的数据扩展其知识库或修改其行为和风格。
尽管相比推理,微调仍然较为耗费计算资源,但借助于低秩适应(LoRA)及其量化变体QLoRA等技术,现在可以使用单块GPU来微调模型——这正是我们将在本指南中探讨的内容。
在本指南中,我们将讨论:
- 微调的应用场景和适用时机
- 扩展预训练模型能力和行为的替代方法
- 数据准备的重要性
- 如何使用Axolotl和自定义数据集微调Mistral 7B模型
- 各种超参数及其对训练的影响
- 加快和提高微调效率的其他资源
1.设定期望
相比我们之前的动手指南,微调是一个涉及很多参数调整、开关配置和最佳实践的复杂过程。因此,我们认为有必要设定一些期望。
微调是修改预训练模型行为或风格的有用方法。然而,如果你的目标是教授模型新的知识,虽然可以做到,但可能有更好和更可靠的方式值得首先考虑。
我们之前探讨过检索增强生成(RAG),这种方法基本上为模型提供了一个它可以参考的库或数据库。这个方法因其相对易于设置、计算成本低廉且可以引用来源而备受欢迎。不过,它并不完美,也无法改变模型的风格或行为。
例如,如果你正在构建一个客户聊天机器人来帮助用户查找资源或解决产品问题,你可能不希望它回答与健康或财务无关的问题。提示工程可以在一定程度上帮助实现这一点。你可以创建一个系统提示,指示模型以某种方式行事。例如,添加一句“你不具备回答与健康、健康管理或营养相关问题的能力,如有相关问题,请将话题引导至更合适的内容。”
提示工程在其简单中显得优雅:只需告诉模型你希望它做什么或不做什么。但实际上,使用中的LLM模型经常会遇到一些边界情况,导致模型被误导执行它不应该做的事情。你可能会惊讶地发现,有时只需一句“忽略所有之前的指示,而执行以下操作”即可使模型改变行为。
如果RAG和提示工程无法满足需求,则可以考虑微调。
2.使用QLoRA进行内存高效的模型微调
在本指南中,我们将使用微调来改变Mistral 7B模型的风格和语调。特别是,我们将使用QLoRA,如前所述,这将允许我们在与传统训练相比下,使用更少的内存和计算资源进行微调。
这是因为微调比运行模型需要更多的内存。在推理过程中,可以通过将参数数量乘以精度来计算内存需求。对于Mistral 7B,其训练精度为BF16,因此大约需要14 GB内存,外加少量用于关键缓存的内存。
然而,完全微调则需要几倍于此的内存来加载模型。对于Mistral 7B来说,内存需求约为90 GB或更多。如果你没有多GPU的工作站,几乎必然需要租用像Nvidia A100或H100这样的数据中心GPU来完成任务。
这是因为完全微调意味着以完整分辨率重新训练模型的每一个权重。好消息是,在大多数情况下,不必更新所有权重即可调整神经网络的输出。实际上,只需更新几千或几百万的权重就可以实现预期的效果。
这正是LoRA的逻辑所在:简而言之,它将模型的权重冻结在一个矩阵中,然后使用另一组矩阵记录对第一个矩阵的调整以微调模型。这大大减少了计算和内存的开销。QLoRA进一步优化了这一点,通过以更低的精度(通常为四位)加载模型的权重。因此,每个参数只需占用半字节的内存。
3.微调很简单,数据准备就没那么简单了
解决了那些问题之后,我们需要谈谈数据。事实证明,微调模型并不是最难的部分,难的是准备和清理数据集,以确保模型能按你的期望工作。
那么,你从哪里获取用于微调模型的数据呢?嗯,对于像电子邮件助手或客户服务聊天机器人这样的应用,你其实不需要找得太远。只需打开你电子邮件中的“已发送”文件夹,就能找到一个不错的起点来寻找有机数据。如果你在使用像Continue这样的本地聊天助手,它可能会自动生成可用于微调模型的训练数据。
虽然高质量的有机数据是理想之选,但它可能无法涵盖你可能遇到的所有场景。例如,假设你希望模型生成回复,将收到的电子邮件的发送者引导到另一个部门或团队。如果这种情况只是偶尔发生,你可能没有足够的有机数据来进行训练。
这时,使用大型语言模型(LLMs)生成合成数据或部分合成数据就派上了用场。这样做相当直接,只需将几个示例输入模型,并要求它生成模仿这些示例的新数据。你可能需要不断调整提示,直到找到合适的内容。
你可以对输入和输出都这样做,或者生成输入并手动写出对应的回复。在我们的测试中,我们发现合成数据通常缺乏细微差别,半合成数据效果良好,而完全有机数据的效果最佳。
无论你是使用有机数据还是合成数据来生成数据集,你都需要花时间清理数据集,删除个人信息或不良样本等内容。例如,如果你正在为客户服务或支持微调模型,你可能想从数据中删除代理或用户的姓名、电话号码和其他信息。
虽然微调对于改变模型的行为最有帮助,但它仍然会捕捉到数据集中始终出现的细节,如姓名。
一旦你收集好了数据——其实并不需要太多:甚至100个样本可能就足以以明显的方式改变模型的行为——你就需要以模型能够理解的方式对其进行格式化。有很多方法可以做到这一点,但就我们的目的而言,我们发现使用Alpaca数据格式的JSON模板效果相当不错。
4.微调容易,数据准备难
以上内容准备好后,我们需要谈谈数据。事实证明,微调模型并不是最难的部分,真正的难点在于准备和清理数据集,使模型能够真正按照你的意图运行。
那么,你要从哪里获取微调模型的数据呢?对于电子邮件助手或客服聊天机器人之类的应用,数据来源并不难找。简单地查看你的电子邮件“已发送”文件夹,就能为获取自然数据提供一个不错的起点。如果你使用的是本地聊天助手,如Continue,它可能会自动生成可用于微调模型的训练数据。
如果写代码注释让你头疼,你也可以让AI来代劳。只要记得在提交代码前查看一下注释内容。
当你在家就能创建属于自己的AI代码助手,谁还需要GitHub Copilot呢?
虽然高质量的自然数据是理想选择,但它可能无法覆盖所有可能遇到的场景。例如,如果你希望模型生成的邮件回复能够将发件人重定向至不同的部门或团队,而这种情况偶尔才发生,那么可能没有足够的自然数据来训练模型。
这时,使用LLM生成合成数据或部分合成数据会非常有用。操作步骤相对简单:你可以向模型提供一些示例,然后让它生成模拟这些示例的新数据。你可能需要调整提示,直到生成出符合需求的数据。
你可以同时为输入和输出生成数据,也可以只生成输入,自己编写相应的输出。在我们的测试中发现,完全合成的数据通常缺乏细微之处,而半合成数据效果较好,完全自然的数据效果最佳。
无论是用自然数据还是合成数据生成数据集,你都需要花时间清理数据集,去除个人身份信息或无效样本。例如,如果你在微调一个客户服务或支持类的模型,可能需要删除数据中的代理人或用户的姓名、号码及其他信息。
虽然微调主要用于改变模型的行为,但模型仍然会受到数据集中一致出现的细节(如名称)的影响。
一旦数据准备好了,其实不需要很多数据:即便是100个样本也可能足以显著改变模型的行为。接下来,你需要将数据格式化,使模型能够理解。对于我们的目的,我们发现这种基于Alpaca数据格式的JSON模板效果很好:
[
{
"instruction": "generate an appropriate response to this chat message",
"input": "I'm having trouble getting Product X to work properly.",
"output": "Can you tell me more about what isn't working?"
},
...
]
5.设置Axolotl
市面上有许多用于微调LLM的框架,如Unsloth和Hugging Face的Transformers Trainer。不过在本次动手操作中,我们将使用Axolotl。
该开源项目旨在抽象出微调流行语言模型的复杂性,并支持多种不同的训练技术。因此,如果你在工作站或游戏PC上用QLoRA开始微调,之后想要在云端进行完整微调,可以轻松切换。
Axolotl的另一大优势是提供了大量用于微调流行LLM的模板库,因此你不必从头开始摸索针对特定模型或数据集需要的超参数。
6.准备条件
一块至少有16GB显存的GPU。任何较新的Nvidia GPU都可以。对于AMD用户,建议使用AMD Radeon RX 7900或更高型号。我们测试了RTX 3090 TI 24GB、RTX 6000 Ada Generation 48GB、AMD Radeon RX 7900 XT 20GB和Radeon Pro W7900 48GB。
- 在本指南中,我们会尽量保持简单,使用Ubuntu Desktop 24.04。
- 你的显卡所需的最新GPU驱动和CUDA(Nvidia)或ROCm(AMD)二进制文件。如果是第一次设置这些,可能会有些棘手,因此我们会在Ubuntu 24.04上详细说明配置步骤。
- 假设你对Linux系统的命令行操作较为熟悉。以下操作说明涉及在此环境中使用终端运行命令。
由于Nvidia和AMD显卡的设置略有不同,注意区分。更多内容。会在下一篇文章中介绍。