Qwen2.5 大模型微调实践指南
1、基础概念
1.1、什么是微调(Fine-tuning)?
大模型微调,也称为 Fine-tuning,是指在已经预训练好的大型语言模型基础上(一般称为'基座模型'),使用特定的数据集进行进一步的训练,让模型适应特定任务或领域。
经过预训练的基座模型其实已经可以完成很多通用任务,比如回答问题、总结数据、编写代码等。但是,并没有一个模型可以解决所有的问题,尤其是行业内的专业问答、关于某个组织自身的信息等,是通用大模型所无法触及的。在这种情况下,就需要使用特定的数据集,对合适的基座模型进行微调,以完成特定的任务、回答特定的问题等。
假设医院希望使用大模型来帮助医生从文本笔记生成患者报告或者辅助治疗。虽然通用模型能理解和创建一般文本,但它可能没有针对复杂的医学术语和特定医疗术语进行优化。这时医院可以用包含医疗报告和患者笔记的数据集上对模型进行微调,这样模型变得更加熟悉医学术语、临床语言的微妙之处和典型的报告结构,微调后的模型才有可能成为医生的好助手。
总的来说,需要微调是因为如下几点:
任务特定性能提升:预训练语言模型通过大规模的无监督训练学习了语言的统计模式和语义表示。然而它在特定任务下的效果可能并不令人满意。通过在任务特定的有标签数据上进行微调,模型可以进一步学习任务相关的特征和模式,从而提高性能。
领域适应性:预训练语言模型可能在不同领域的数据上表现不一致。通过在特定领域的有标签数据上进行微调,可以使模型更好地适应该领域的特殊术语、结构和语义,提高在该领域任务上的效果。
数据稀缺性:某些任务可能受制于数据的稀缺性,很难获得大规模的标签数据。监督微调可以通过使用有限的标签数据来训练模型,从而在数据有限的情况下取得较好的性能。
防止过拟合:在监督微调过程中,通过使用有标签数据进行有监督训练,可以减少模型在特定任务上的过拟合风险。这是因为监督微调过程中的有标签数据可以提供更具体的任务信号,有助于约束模型的学习,避免过多地拟合预训练过程中的无监督信号。
成本效益:与 prompt 提示相比,微调通常可以更有效且更高效地引导大型语言模型的行为。在一组示例上训练模型不仅可以缩短精心设计的 prompt,还可以节省宝贵的输入 token,同时不会牺牲质量。另外,你可以使用一个更小的模型,这反过来会降低延迟和推断的成本。例如,与 GPT-3.5 这类的现成模型相比,经过微调的 Llama 7B 模型在每个 token 基础上的成本效益更高,并且性能相当。
1.2、模型微调有哪些常见方法?
大模型微调的方法多样,随着技术的发展,涌现出越来越多的大语言模型,且模型参数越来越多。除了传统的 SFT(Supervised Fine-Tuning,有监督微调)外,还有 Adapter Tuning、PET、Prefix Tuning、P-Tuning、LoRA、QLoRA 等。这些方法各有优缺点,适用于不同的场景和需求。
例如,LoRA(Low-Rank Adaptation)和 QLoRA 是目前主流的大模型微调方法之一,它们通过冻结预训练模型的大部分参数,只微调一小部分额外的参数,从而避免灾难性遗忘,并且快速迁移到新的任务上。此外,还有 PEFT(Parameter-Efficient Fine-Tuning,参数高效调整)和 FFT(Full Fine-Tuning,全参数调整)两种微调方法,前者主要针对预训练模型中的某些部分参数进行调整,后者则是对所有层都参与微调。
本文侧重介绍下 SFT(有监督微调) 结合 LoRA 技术。
有监督微调意味着使用标记数据更新预先训练的语言模型来完成特定任务。所使用的数据已提前检查过。这与不检查数据的无监督方法不同。通常语言模型的初始训练是无监督的,但微调是有监督的。
接下来将介绍大模型微调具体流程:
- 数据准备:有许多开源数据集可以提供关于用户行为和偏好的洞察,即使它们没有直接格式化为指令性数据。例如,我们可以利用亚马逊产品评论的大量数据集,将其转化为微调的指令提示数据集。提示模板库包含了许多针对不同任务和不同数据集的模板。
- 执行微调:将数据集分为训练、验证和测试部分。在微调过程中,你会从训练数据集中选择提示,并将它们传递给 LLM,然后模型会生成完整的文本。
- 具体来说,当模型接触到针对目标任务的新标记数据集时,它会计算其预测与实际标签之间的误差或差异。
- 然后,模型使用这个误差来调整其权重,通常通过梯度下降等优化算法。
- 权重调整的幅度和方向取决于梯度,梯度指示了每个权重对误差的贡献程度。对误差贡献更大的权重会被更多地调整,而贡献较小的则调整较少。
- 迭代调整:在数据集的多次迭代(或称为周期)中,模型继续调整其权重,逐渐找到一种配置,以最小化特定任务的误差。目标是将之前学到的一般知识适应到新数据集中的细微差别和特定模式,从而使模型在目标任务上更加专业化和有效。
- 模型更新:在这个过程中,模型会根据标记数据进行更新。它根据其猜测与实际答案之间的差异进行改变。这有助于模型学习标记数据中的细节。通过这样做,模型在微调的任务上的表现会得到提升。
2、实操微调 qwen2.5
通过上文的介绍,只能建立对模型微调的大概认知,要想真正理解大模型微调,还是得要实操。可能对入门者来说,大模型微调本身是一件非常复杂且技术难度很高的任务,但当下有很多工具可以低门槛地实操。常见的工具是 llama factory、阿里的魔塔社区。
为了让小白也能明白大模型微调过程,本文选了阿里的魔塔社区来作为实践对象。魔塔社区给新用户提供免费 GPU 资源进行使用,非常适合用来学习大模型的微调。
话不多说,直接开始。
2.1、账号和环境准备
首先你需要注册和登录魔塔的账号:https://modelscope.cn/home
在模型库找到 qwen2.5 大模型,当然了,还可以试试其他大模型,魔塔集合了很多大模型,都能直接下载使用。
本文使用阿里最新的 qwen2.5 大模型,为了减少下载等待时间,用的是 7B 模型。
Qwen 是阿里巴巴集团 Qwen 团队研发的大语言模型和大型多模态模型系列。目前,大语言模型已升级至 Qwen2.5 版本。无论是语言模型还是多模态模型,均在大规模多语言和多模态数据上进行预训练,并通过高质量数据进行后期微调以贴近人类偏好。Qwen 具备自然语言理解、文本生成、视觉理解、音频理解、工具使用、角色扮演、作为 AI Agent 进行互动等多种能力。
最新版本 Qwen2.5 有以下特点:
- 易于使用的仅解码器稠密语言模型,提供 0.5B、1.5B、3B、7B、14B、32B 和 72B 共 7 种参数规模的模型,并且有基模型和指令微调模型两种变体。
- 利用最新的数据集进行预训练,包含多达 18T tokens。
- 在遵循指令、生成长文本(超过 8K tokens)、理解结构化数据(例如,表格)以及生成结构化输出特别是 JSON 方面有了显著改进。
- 支持最多达 128K tokens 的上下文长度,并能生成多达 8K tokens 的文本。
- 支持超过 29 种语言,包括中文、英文、法文、西班牙文、葡萄牙文、德文、意大利文、俄文、日文、韩文、越南文、泰文、阿拉伯文等。
在模型介绍页,选择 Notebook 快速开发,然后选择方式二(GPU 环境)后,点击启动。
启动大概需要 2 分钟,等 GPU 环境启动好以后点击查看 Notebook 进入。
魔塔社区内置了 JupyterLab 的功能,你进入之后,可以找到 Notebook 标签,新建一个 Notebook(当然你在 terminal 里执行也没问题)。
增添一个代码块,并且执行以下命令(点击左侧的运行按钮运行该代码块,下同,这一步是安装依赖库)。
!pip3 install --upgrade pip
!pip3 install bitsandbytes>=0.39.0
输入如下代码拉取 LLaMA-Factory,过程大约需要几分钟。
!git clone --depth 1 https://github.com/hiyouga/LLaMA-Factory.git
LLaMA Factory 是一款开源低代码大模型微调框架,集成了业界广泛使用的微调技术,git 上提供很详细的操作攻略,想深入了解 llamafactory 的可以在这里查看:https://github.com/hiyouga/LLaMA-Factory
接下来需要去 Launcher > Terminal 执行(按照图片剪头指示操作)。安装依赖的软件,这步需要的时间比较长。
⚠️下面两行命令在刚启动的 Terminal 中执行
⚠️cd LLaMA-Factory
pip3 install -e ".[torch,metrics]"
等以上所有步骤完成后,再进行下面的操作。
2.2、下载模型
按照下图操作,找到模型的下载地址。我使用的是 Git 下载,下载速度会比较快,还有其他下载方式,也可以尝试。
在终端输入 git 链接,notebook 会自动创建一个模型文件夹,然后同步拉取模型文件。
一开始是看到其他已经下载好的文件,model 文件较大,会等十分钟左右才能完全下载,一共有四个主 model。
2.3、微调模型
a. 创建微调训练相关的配置文件
在左侧的文件列表,Llama-Factory 的文件夹里,打开 examples\train_qlora(注意不是 train_lora)下提供的 llama3_lora_sft_awq.yaml,复制一份并重命名为 qwen_lora_sft_bitsandbytes.yaml。
这个文件里面写着和微调相关的关键参数。打开这个文件,将第一行 model_name_or_path 更改为你下载模型的位置。
### model
model_name_or_path: Qwen2.5-7B-Instruct
同样修改其他行的内容,下面是我的修改,你可以逐行对比一下,有不一致或缺少的就添加一下。
详细的参数解释如下:
模型基础信息:
model_name_or_path: Qwen2.5-7B-Instruct:指定了要微调的基础模型的路径或名称。这里表明基础模型是存放在 Qwen2.5-7B-Instruct 路径下的 qwen 模型。quantization_bit: 4:表示将模型的权重进行量化的位数为 4 位。量化是一种压缩技术,可以减少模型的存储和计算需求,但可能会对模型的精度产生一定影响。通过将权重量化到 4 位,可以在一定程度上提高模型的运行效率。
微调方法:
stage: sft:这里的sft代表'Supervised Fine-Tuning'(有监督微调),即使用有标注的数据对模型进行微调训练。do_train: true:表示要进行训练操作。finetuning_type: lora:使用'LoRA'(Low-Rank Adaptation)方法进行微调。LoRA 是一种高效的微调技术,它通过在原始模型的基础上添加一些低秩矩阵来实现对模型的微调,从而减少了训练的参数数量和计算成本。lora_target: all:表示对模型的所有部分都应用 LoRA 微调。
数据集相关:
dataset: identity:指定了使用的数据集 identity。template: qwen:指定了数据的模板或格式与 qwen 模型相匹配。这有助于将数据集转换为适合模型输入的格式。cutoff_len: 1024:设置输入文本的截断长度为 1024。如果输入文本超过这个长度,会被截断以适应模型的处理能力。max_samples: 1000:限制数据集中使用的最大样本数量为 1000。这可能是出于训练时间或资源限制的考虑。overwrite_cache: true:表示如果缓存存在,将覆盖缓存。这意味着每次运行时都会重新处理数据集,而不是使用之前缓存的数据。preprocessing_num_workers: 16:指定了用于数据预处理的工作进程数为 16。增加工作进程数可以加快数据预处理的速度,但也会消耗更多的系统资源。
输出设置:
output_dir: saves/qwen-7b/lora/sft:指定了微调后的模型输出路径。训练后的模型将保存在 saves/qwen-7b/lora/sft 文件夹中。logging_steps: 10:表示每 10 步记录一次训练日志,以便跟踪训练过程中的指标和进度。save_steps: 500:每 500 步保存一次模型的中间状态,以便在训练过程中可以随时恢复或检查模型的进展。plot_loss: true:表示绘制训练过程中的损失曲线,以便直观地观察模型的训练效果。overwrite_output_dir: true:如果输出目录已经存在,将覆盖该目录。这确保了每次训练的结果都会保存在指定的输出目录中。
训练参数:
per_device_train_batch_size: 1:每个设备上的训练批次大小为 1。这意味着每次只处理一个样本进行训练,通常在资源有限或模型较大时使用较小的批次大小。gradient_accumulation_steps: 8:梯度累积的步数为 8。梯度累积是一种技术,通过多次前向传播和反向传播累积梯度,然后再进行一次参数更新,以等效于使用较大的批次大小进行训练。learning_rate: 1.0e-4:学习率为 0.0001。学习率决定了模型在训练过程中参数更新的步长,较小的学习率可能导致训练速度较慢,但可以提高模型的稳定性和准确性。num_train_epochs: 3.0:训练的轮数为 3 轮。一轮是指对整个数据集进行一次完整的遍历。lr_scheduler_type: cosine:使用余弦退火(cosine annealing)的学习率调度策略。这种策略可以在训练过程中逐渐降低学习率,有助于提高模型的收敛速度和性能。warmup_ratio: 0.1:热身比例为 0.1。在训练开始时,使用较小的学习率进行热身,然后逐渐增加到指定的学习率,以帮助模型更好地适应训练。bf16: true:表示使用 BF16(Brain Floating Point 16)数据类型进行训练。BF16 是一种半精度浮点数格式,可以减少内存占用和计算时间,但可能会对精度产生一定影响。ddp_timeout: 180000000:分布式数据并行(DDP)的超时时间为 180000000 毫秒(约 50 小时)。这是在分布式训练中等待其他进程的最长时间,如果超过这个时间,训练将被终止。
评估设置:
val_size: 0.1:将数据集的 10% 作为验证集。在训练过程中,会使用验证集来评估模型的性能,以便及时调整训练策略。per_device_eval_batch_size: 1:每个设备上的评估批次大小为 1。与训练批次大小类似,评估时每次只处理一个样本。eval_strategy: steps:按照指定的步数进行评估。这意味着在训练过程中,每隔一定的步数就会对模型进行一次评估。eval_steps: 500:每 500 步进行一次评估。这与 eval_strategy 配合使用,确定了评估的频率。
从上面的配置文件中可以看到,本次微调的数据集是 identity。修改原有的 json 数据,就可以微调一个属于你自己的大模型。比如你可以将 identity.json 中的 {{name}} 字段替换为你的名字来微调一个属于自己的大模型。
保存刚才对于 qwen_lora_sft_bitsandbytes.yaml 文件的更改,回到终端 terminal。
在 LLaMA-Factory 目录下,输入以下命令启动微调脚本 (大概需要 10 分钟)。
llamafactory-cli train examples/train_qlora/qwen_lora_sft_bitsandbytes.yaml
看到进度条就是开始微调了。运行过程大概需要 10 分钟,当你看到下面这个界面的时候,微调过程就结束了。
b. 推理测试
参考 Llama-Factory 文件夹中,examples\inference 下提供的 llama3_lora_sft.yaml,复制一份,并重命名为 qwen_lora_sft.yaml。
将内容更改为,并且保存(一定记得保存)。
model_name_or_path: <和之前一样,你下载的模型位置,比如我的 Qwen2.5-7B-Instruct>
adapter_name_or_path: saves/qwen-7b/lora/sft
template: qwen
finetuning_type: lora
回到刚刚结束微调的终端 Terminal,运行下面的推理命令 (同样在 Llama-Factory 目录下运行)。
llamafactory-cli chat examples/inference/qwen_lora_sft.yaml
稍微等待一下模型加载,然后就可以聊天了。可以看到模型的自我身份认知被成功的更改了。
基于本实验,你就完成了一个简单的微调,完整的走了一遍模型的微调过程。
3、常见问题与进阶
3.1、显存不足(OOM)怎么办?
如果在训练过程中遇到 Out Of Memory (OOM) 错误,可以尝试以下方法:
- 减小
per_device_train_batch_size到 1 或更小。 - 增大
gradient_accumulation_steps以保持有效的 batch size。 - 启用
bf16或fp16混合精度训练。 - 使用
quantization_bit: 4进行 4bit 量化加载模型。 - 关闭
flash_attention_2如果驱动不支持,改用标准 attention。
3.2、如何合并 LoRA 适配器?
训练完成后,生成的 LoRA 权重是独立的。如果你需要将微调后的模型合并回基座模型以便单独部署,可以使用以下命令:
llamafactory-cli export \
--model_name_or_path Qwen2.5-7B-Instruct \
--adapter_name_or_path saves/qwen-7b/lora/sft \
--template qwen \
--finetuning_type lora \
--export_dir saves/qwen-7b/merged \
--export_size 2 \
--export_legacy_format false
这将把 LoRA 权重合并到基座模型中,生成一个新的完整模型文件夹,可以直接用于推理服务。
3.3、数据集格式要求
微调数据通常采用 JSONL 格式,每一行是一个样本。对于指令微调(SFT),建议格式如下:
{"instruction": "请介绍一下 Python 的列表推导式", "input": "", "output": "Python 的列表推导式是一种简洁的语法..."}
确保 instruction、input、output 字段符合所选模板的要求。如果数据集中缺少 input,可以留空字符串。
通过上述步骤,你已经掌握了 Qwen2.5 大模型微调的核心流程。在实际生产中,建议根据业务需求调整超参数,并持续监控验证集上的 Loss 变化,以防止过拟合。

