亚马逊AWS官方博客
炼石成丹:大语言模型微调实战系列(二)模型微调篇
模型的微调
在准备好高质量数据之后,我们就可以开始进入模型微调的环节。数据准备的环节往往是最消耗时间的环节,而模型微调环节往往是最消耗算力的一个环节。模型微调目前在开源社区有不同的工具和框架,微调本身也会有不同的方式,包括全参数微调、PEFT 等,他们之前有不同的最终效果和训练成本。每一次模型微调之后,往往算法科学家需要根据模型的一些指标来判别这一次模型微调的结果是否达到预期的结果,是否需要增加更多数据,或者调整模型超参数来达到最终微调出自己满意的结果。下面,我们来分解下这些过程。
1. 模型框架的选择
目前在开源社区有非常多不同的模型微调工具和框架,根据 Github 的 Star 指数从少到多,排名分别是 ms-swift、Firefly、DeepSpeedExamples、unsloth、LLaMA-Factory、FastChat。不同的工具对应的大语言模型的支持种类、工具的使用方式、开源社区的生态内容都是不一样的。不过综合来看,LLaMA-Factory 目前还是更为受欢迎。
LLaMA-Factory 涵盖了模型训练的各个阶段(预训练、指令监督微调 SFT、奖励模型训练、PPO、DPO、ORPO 训练),不同的训练方法(全参数微调、部分参数微调、LoRA、QLoRA)和不同的使用方式(CLI、WebUI、Python),支持多种大语言模型,包括国内的百川、ChatGLM3、GLM-4、Qwen2、Yi 等,以及海外的主流模型 Llama3、Phi 等。本文也将主要围绕 SageMaker 和 LLaMA-Factory 的微调方法进行展开。
另外,Amazon SageMaker 训练任务和推理都已经支持 LLaMA-Factory,我们因此开源了一个解决方案 ModelHub。因为文章篇幅的限制,在这里不太多展开。如果有兴趣的话,可以参考开源代码。当然,Amazon SageMaker 本身也可以通过 BYOC(Bring Your Own Container)或者 BYOS(Bring Your Own Script)的方式兼容几乎所有大语言模型的微调和部署,但是用这两种方式需要一定的适配工作,也需要了解 SageMaker 的工作机制,因此在可能的情况下还是直接用 ModelHub 更加方便。
2. 选择模型微调方法
在大型语言模型的参数微调中,全参数微调、PEFT(Parameter-Efficient Fine-Tuning)、LoRA 等方法各有特点和适用场景。在这里做一些简短的说明。
不同的微调方法:
微调方法 | 原理 | 优点 | 缺点 |
全参数微调(Full Fine-Tuning) | 对预训练模型的所有参数进行微调,以适应特定任务。 | 能够充分利用模型的表达能力,达到较好的性能。不受限于增量矩阵的秩特性,适用于各种任务和数据集。 | 需要大量的计算资源。训练时间较长,不利于快速迭代和优化。 |
PEFT(Parameter-Efficient Fine-Tuning) | 通过仅调整少量额外参数来适应新任务,保持大部分预训练模型参数不变。 | 减少了微调参数的数量,降低了训练时间和成本。适用于计算资源有限的情况。 | 可能无法完全发挥模型的潜力,性能可能略逊于全参数微调 |
LoRA(Low-Rank Adaptation) | 通过低秩矩阵分解的思想,将原始的高维权重矩阵分解为两个低秩矩阵的乘积,减少权重的数量和计算复杂度。 | 降低了存储需求和计算成本。提高了模型的训练速度和推理速度。 | 可能降低模型的准确性,因为使用了低精度权重。适用性受限,主要适用于具有低秩特性的增量矩阵。 |
其他方法:
- QLoRA(Quantized Low-Rank Adaptation):对 LoRA 的改进,引入高精度权重和可学习的低秩适配器,通过量化技术和低秩矩阵分解降低微调成本。
- Prefix Tuning:在模型输入层之前添加可训练的前缀嵌入,影响模型的输出。优点是减少需要更新的参数数量,提高训练效率。
- Adapter Tuning:在模型的每个层之间插入小型神经网络(称为 adapters),包含可训练的权重,而模型的原始参数保持不变。
在选择微调方法时,需要考虑任务的复杂性、可用的数据量、计算资源和期望的性能。例如,对于需要细粒度控制的复杂任务,可能更适合使用 P-Tuning v2 或基于 LSTM 的 P-Tuning。而对于计算资源有限的情况,可以选择 LoRA 或 Adapter Tuning 等方法。 在大部分的微调场景中,可以选择先用 LoRA 方式来进行模型微调,一方面它相对全参数微调的性能损失是比较小的(大致上差别不超过 5%);另一方面它对训练所需要的计算资源要求会比全参数微调低很多,往往一个 A100,L40S 机器就可以完成微调任务。
3. 模型微调所需要的算力
一般来说,模型微调所需要的算力和模型的参数、微调方法是直接相关的。模型参数量越大,训练算力需求越大;全参数微调的算力要求也比 LoRA 等参数微调的方法需求更大。
下面的表格可以作为模型微调的显存需求做一个参考。不同的 GPU 显卡的显存是不一样的,对于一些场景可能一张卡的显存不够,需要涉及到多个卡,甚至多台机器才能完成微调任务。
4. 模型微调
4.1 如何使用 SageMaker 进行微调
SageMaker Training Job 本身是一项非常灵活、按需的模型微调服务,我们一般通过 Jupyter Notebook 去调用 SageMaker Python SDK 来开启模型的微调任务。在微调的参数里面,我们可以指定要用多少台机器、什么类型的机器来进行微调。同时,SageMaker 只会收取在模型训练过程中的实例小时费率,当模型训练完毕后,实例就自动进行终止,停止额外的费用。另外,SageMaker Training Job 还可以集成 Spot 的实例类型进行模型训练,这样我们就可以以正常列表价的低至 3 折去开启我们的训练任务了。
最后,更重要的是,SageMaker Training Job 的资源池是和其他服务的资源池分割开来的,很多情况因为资源紧张的原因,我们没有办法申请到 A100,H100 的 EC2 实例,我们同样情况可以在 SageMaker Training Job 上面相对轻松地申请到这些资源。
一般来说我们要用 SageMaker Training Job 来训练自己的模型,SageMaker Training Job 本身支持有很多内置算法和预训练模型,比如图像分类、文本分类、对象检测、机器翻译、时间序列预测、异常检测等等,详细列表可以查看文档。而且本身也有很多打包好的容器镜像文件,比如不同的 CUDA、Pytorch、TensorFlow 和 Python 版本的镜像,具体景象列表可以参照链接。
对于大语言模型来说,比如前面说到的 LlamaFactory,我们需要以 BYOC(Bring your own Container)的形式进行集成。我们可以在这些镜像的基础之上,扩展我们需要的依赖和文件,这样对于我们用 SageMaker 集成自己的训练代码来说,可以节省很多时间和精力。因为文章篇幅的原因,在这里就不详细展开如何制作镜像和使用 SageMaker 进行模型训练了,如果想深入阅读这方面的内容,可以查看官方文档学习扩展预构建容器。
4.2 如何使用 ModelHub 进行微调
ModelHub 是亚马逊云科技中国的产品解决方案团队开发出来的方案,旨在将 SageMaker 模型训练的门槛降的更低,实际的底层资源用的依旧是前面提到的 SageMaker 的资源。ModelHub 基于 LLaMA-Factory on SageMaker,提供一站式模型微调、部署、调试无代码可视化平台,支持在亚马逊云科技全球区和宁夏区部署,可以帮助用户快速验证微调各类开源模型,方便快速实验,提升微调开源大模型的效率,降低上手门槛。
ModelHub 通过兼容 LLaMA-Factory 来兼容市面上几乎所有的主流大语言模型,比如 Llama、LLaVA、Mistral、Qwen、Yi、Baichuan、ChatGLM、Phi 等。
ModelHub 的整体流程:
ModelHub 的视频简介:https://mp.weixin.qq.com/s/PEl_-1CRAJvss5pMFcU31w
关于 ModelHub 如何部署和配置,可以参照博客《基于 Amazon SageMaker 和 LLaMA-Factory 打造一站式无代码模型微调部署平台 Model Hub》。
4.3 模型微调中的参数
在进行微调时,有几个关键的超参数需要关注,其中红色部分需要额外注意。
名称 | 描述 | |
1 | model_name_or_path | 模型名称或路径 |
2 | stage | 训练阶段,可选 rm(reward modeling)、pt(pretrain)、 sft(Supervised Fine-Tuning)、PPO、DPO、KTO、ORPO |
3 | do_train | true 用于训练,false 用于评估 |
4 | finetuning_type | 微调方式,可选:freeze、lora、full |
5 | lora_target | 采取 LoRA 方法的目标模块,默认值为 all |
6 | dataset | 使用的数据集,使用“,”分隔多个数据集 |
7 | template | 数据集模板,请保证数据集模板与模型相对应 |
8 | output_dir | 输出路径 |
9 | logging_steps | 日志输出步数间隔 |
10 | save_steps | 模型断点保存间隔 |
11 | overwrite_output_dir | 是否允许覆盖输出目录 |
12 | per_device_train_batch_size | 每个设备上训练的批次大小 |
13 | gradient_accumulation_steps | 梯度积累步数 |
14 | max_grad_norm | 梯度裁剪阈值 |
15 | learning_rate | 学习率 |
16 | lr_scheduler_type | 学习率曲线,可选 linear 、cosine 、polynomial 、constant 等 |
17 | num_train_epochs | 训练周期数 |
18 | bf16 | 是否使用 bf16 格式 |
19 | warmup_ratio | 学习率预热比例 |
20 | warmup_steps | 学习率预热步数 |
21 | push_to_hub | 是否推送模型到 HuggingFace |
可能刚开始接触这些模型的超参数的时候,会比较疑惑,也不知道应该怎么调整模型的超参数。一般的建议是,先按照默认的超参数配置进行一次试训练,然后根据模型的结果指标进行超参数的调整。调整的一些策略如下,可简单参考:
learning_rate
如果过大,可能会让模型最后找不到全局最优解,模型的参数迭代更新过大,可能会导致“梯度爆炸”现象,模型的 loss 值也会不稳定,会忽高忽低而不是持续变低的状态(loss 值理论上越低越好);learning_rate
如果过小,又可能最后模型找到的是“局部最优解”而不是全局最优解,从而模型的效果不是最好的。num_train_epochs
:这个超参数代表模型训练的总轮数(Epochs)。一轮训练是指模型对整个训练数据集进行一次完整的遍历。如果num_train_epochs
设置过小,模型可能未能充分学习数据集中的特征,导致欠拟合;而设置过大,则可能导致模型过拟合,即模型在训练集上表现很好,但在测试集上表现不佳。通常需要通过观察验证集上的性能指标来确定合适的迭代次数。per_device_train_batch_size
:这个超参数指的是每个设备上的训练批次大小(Batch Size)。它决定了每次梯度下降迭代中使用的训练样本数量。较大的per_device_train_batch_size
可以加速训练过程,因为可以并行处理更多的样本,但可能导致内存不足和泛化能力下降;较小的per_device_train_batch_size
可以引入更多的噪声,有助于模型跳出局部最优解,但训练过程可能不稳定且收敛速度较慢。- template:数据集的模板,比如 llama3、qwen2_vl 等,具体可以参考 Llama_Factory 的项目指导文件。
上面这些参数往往需要在微调过程中根据训练的效率、效果、资源占用情况来调整。
4.4 模型微调指标
不管是用 SageMaker Training Job 进行模型微调还是 ModelHub 进行模型微调,所有的日志和模型微调指标都会自动导出到 CloudWatch Log 中,我们可以通过 CloudWatch Log 实时查看模型微调的各种指标,比如 loss 等。
另外,往往模型微调工作不是一个一触而就的工作,很多情况下我们需要不断调整我们的数据集、超参数、得到若干个模型结果。这个时候我们需要对多个模型结果进行横向对比,并且能够溯源当时微调的环境和参数。这个情况下,类似模型指标监控工具 Weights&Bias 就很重要了。
Weights & Biases(简称 W&B)是一个专为机器学习和人工智能研究设计的综合性平台,它提供了实验管理和追踪、模型版本控制、性能可视化以及团队协作等功能。W&B 允许开发者记录和比较不同的机器学习实验,自动记录模型参数、性能指标和输出结果,使实验管理变得简单而高效。开发者可以使用 W&B 的可视化工具来分析实验结果,快速识别最佳模型和参数配置。提供了丰富的可视化工具,帮助开发者深入理解模型性能。通过直观的图表和仪表板,开发者可以轻松监控训练进度、比较不同模型的性能,并识别潜在的优化机会。
现在 ModelHub 方案里面要使用 Weights&Bias 来做指标监控,我们只需要在首次用 CloudFormation 部署时填入 WANDB_API_KEY 密钥,或者在部署后在 Backend/.env 中配置 WANDB_API_KEY,训练时就会自动把相关数据发送到 wandb。
这样,每一次训练过程和训练结束后,都可以登陆 W&B 的后台查看训练结果,观察 loss 值是否收敛。除了 loss 值,还可以关注准确度指标,如 F1 分数、精确度、召回率和 BLEU 等,这些都是衡量模型准确性的客观指标。此外,终端用户反馈和 A/B 测试也是非常重要的反馈来源,它们通常包括用户的直接反应以及表明用户偏好的隐式操作。
如果微调的指标和自己预想的结果偏差比较大,也可以通过以下方法进行指标的纠正。
- 数据增强:通过增加训练数据的多样性和覆盖范围来提高模型的泛化能力。
- 调整超参数:如学习率、批量大小等,以优化模型的训练过程。
- 使用更复杂的模型结构:如果模型过于简单,可能无法捕捉数据中的复杂模式。
- 集成学习:结合多个模型的预测结果,以提高整体性能。
- 引入人类反馈:通过强化学习技术,结合人类的偏好和反馈来训练模型,如近端政策优化(PPO)。
结论
本文介绍了大语言模型微调的关键步骤和注意事项。首先需要选择合适的模型微调框架,比如目前较受欢迎的 LLaMA-Factory,然后选择微调方法,包括全参数微调、PEFT、LoRA 等,微调过程中需要权衡计算资源和期望性能,接下来估算所需算力,模型参数越大微调方法越复杂,所需算力就越高。
在具体微调时,可利用 Amazon SageMaker Training Job 服务,通过 Python SDK 指定所需资源开启训练任务,也可使用 ModelHub 无代码平台,基于 LLaMA-Factory 在 SageMaker 上一站式完成微调、部署等。微调过程中,需实时监控指标如 loss、精确度等,可借助 CloudWatch Logs 和 Weights&Biases 等工具。如果指标不理想,可通过数据增强、调参、改进模型结构、集成学习、人类反馈等方式进行优化。总的来说,大模型微调是一个循环迭代的过程,需要根据具体任务和资源情况选择合适的方法和工具。
在微调完毕之后,我们会得到微调后的模型权重文件和配置文件等,一般进行 Lora 微调是一个比较小的参数文件,在有的情况下使用需要和 Base model 进行合并才能使用。在微调后我们往往需要做一个很重要的事情:评估模型的效果,以及进行模型的部署,我们将会在后面的文章介绍相关内容。
*前述特定亚马逊云科技生成式人工智能相关的服务仅在亚马逊云科技海外区域可用,亚马逊云科技中国仅为帮助您了解行业前沿技术和发展海外业务选择推介该服务。
参考链接
- https://amzn-chn.feishu.cn/docx/QniUdr7FroxShfxeoPacLJKtnXf
- https://github.com/aws-samples/llm_model_hub/