基于 transformers 与 peft 对 Qwen1.5-7B-Chat 进行 LoRA 指令微调全流程指南(self-llm 开源大模型食用指南系列) 基于 transformers 与 peft 对 Qwen1.5-7B-Chat 进行 LoRA 指令微调全流程指南self-llm 开源大模型食用指南系列【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm本文以《开源大模型食用指南》仓库中的 04-Qwen1.5-7B-chat Lora 微调.md 为核心骨架结合同目录下的 Qwen1.5-7B-Chat Lora.ipynb 完整运行记录与 dataset/huanhuan.json 真实微调数据集系统讲解从环境搭建、指令集构建、数据格式化、LoRA 配置到训练与推理加载的完整闭环。读者完成本文后将具备独立复现将 Qwen1.5-7B-Chat 微调为指定人设/风格对话模型的完整实战能力并理解 LoRA 各核心参数对训练的实际影响。一、前置准备环境配置与依赖安装本文基础运行环境如下出自原文档---------------- ubuntu 22.04 python 3.12 cuda 12.1 pytorch 2.3.0 ----------------默认学习者已安装好以上 PyTorch(cuda) 环境如未安装请自行安装。在确认基础环境后通过pip换源加速下载并安装依赖包pip install --upgrade pip # 更换 pypi 源加速库的安装 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple pip install modelscope1.16.1 pip install transformers4.43.2 pip install accelerate0.32.1 pip install peft0.11.1 pip install datasets2.20.0其中各依赖的角色如下modelscope用于下载与管理 Qwen1.5 系列模型权重也可直接从 Hugging Face 下载后放置于本地目录transformers提供AutoTokenizer、AutoModelForCausalLM、Trainer、TrainingArguments、DataCollatorForSeq2Seq等核心训练/推理组件accelerate支撑device_mapauto的自动设备分配与多卡加速peft提供LoraConfig、get_peft_model、PeftModel等 LoRA 参数高效微调组件datasets用于读取并转换微调数据集Dataset。在 Qwen1.5-7B-Chat Lora.ipynb 中环境导入部分即对应如下语句from datasets import Dataset import pandas as pd from transformers import AutoTokenizer, AutoModelForCausalLM, DataCollatorForSeq2Seq, TrainingArguments, Trainer, GenerationConfig仓库文档中还提到考虑到部分同学配置环境可能遇到问题在 AutoDL 平台准备了 Qwen1.5 的环境镜像该镜像适用于该仓库除 Qwen-GPTQ 和 vLLM 外的所有部署环境可通过原文档指引直接创建 AutoDL 示例。二、指令集构建面向目标人设的指令微调数据LLM 的微调一般指指令微调Instruction Tuning过程。所谓指令微调是指我们使用的微调数据形如{ instruction: 回答以下用户问题仅输出答案。, input: 11等于几?, output: 2 }其中instruction用户指令告知模型其需要完成的任务input用户输入是完成用户指令所必须的输入内容可为空字符串output模型应该给出的输出即期望模型学习到的标准答案。核心训练目标是让模型具有理解并遵循用户指令的能力。因此在指令集构建时应针对目标任务针对性构建任务指令集。例如本文使用由社区合作开源的甄嬛对话项目作为示例目标是构建一个能够模拟甄嬛对话风格的个性化 LLM因此构造的指令形如{ instruction: 你是谁, input: , output: 家父是大理寺少卿甄远道。 }本文使用的全部指令数据集位于仓库根目录的 dataset/huanhuan.json。该数据集为 JSON 数组格式每条样本均包含instruction、input、output三个字段内容为甄嬛传风格的宫廷对话语料。在 notebook 中通过如下方式将 JSON 文件转换为datasets.Dataset对象df pd.read_json(./huanhuan.json) ds Dataset.from_pandas(df)notebook 的运行记录显示该数据集共包含3729 条样本num_rows: 3729例如{ instruction: 小姐别的秀女都在求中选唯有咱们小姐想被撂牌子菩萨一定记得真真儿的——, input: , output: 嘘——都说许愿说破是不灵的。 }三、数据格式化process_func 与 ChatML 模板编码LoRA 训练的数据需要经过格式化、编码之后再输入给模型进行训练。熟悉 PyTorch 训练流程的同学都知道我们一般需要将输入文本编码为input_ids将输出文本编码为labels编码之后的结果都是多维向量。首先定义一个预处理函数该函数对每一个样本编码其输入、输出文本并返回一个编码后的字典def process_func(example): MAX_LENGTH 384 # 分词器会将一个中文字切分为多个token因此需要放开一些最大长度保证数据的完整性 input_ids, attention_mask, labels [], [], [] instruction tokenizer(f|im_start|system\n现在你要扮演皇帝身边的女人--甄嬛|im_end|\n|im_start|user\n{example[instruction] example[input]}|im_end|\n|im_start|assistant\n, add_special_tokensFalse) # add_special_tokens 不在开头加 special_tokens response tokenizer(f{example[output]}, add_special_tokensFalse) input_ids instruction[input_ids] response[input_ids] [tokenizer.pad_token_id] attention_mask instruction[attention_mask] response[attention_mask] [1] # 因为eos token咱们也是要关注的所以 补充为1 labels [-100] * len(instruction[input_ids]) response[input_ids] [tokenizer.pad_token_id] if len(input_ids) MAX_LENGTH: # 做一个截断 input_ids input_ids[:MAX_LENGTH] attention_mask attention_mask[:MAX_LENGTH] labels labels[:MAX_LENGTH] return { input_ids: input_ids, attention_mask: attention_mask, labels: labels }该函数的几个关键设计点模板拼接将system提示现在你要扮演皇帝身边的女人--甄嬛、user指令、assistant输出拼接成一条完整的 ChatML 格式对话文本add_special_tokensFalse不额外在开头添加特殊 token因为模板中已显式包含了|im_start|、|im_end|labels 掩码指令部分system user的 labels 全部置为-100在损失计算时被忽略仅对assistant输出部分计算损失——这是指令微调只学答案、不学提问的关键机制MAX_LENGTH 截断MAX_LENGTH 384当序列超长时对三个字段统一截断保证 batch 内张量形状一致末尾 token在序列末尾补tokenizer.pad_token_id作为结束位并将对应的attention_mask置为1。Qwen1.5采用的 Prompt TemplateChatML格式如下|im_start|system You are a helpful assistant.|im_end| |im_start|user 你是谁|im_end| |im_start|assistant 我是一个有用的助手。|im_end|在 notebook 中对全部样本执行映射转换并移除原始列tokenized_id ds.map(process_func, remove_columnsds.column_names) tokenized_id其运行输出确认数据集被转换为[input_ids, attention_mask, labels]三个特征列共 3729 行。notebook 中还通过tokenizer.decode做了编码正确性验证tokenizer.decode(tokenized_id[0][input_ids]) # 还原为: |im_start|system\n现在你要扮演皇帝身边的女人--甄嬛|im_end|\n|im_start|user\n小姐别的秀女都在求中选唯有咱们小姐想被撂牌子菩萨一定记得真真儿的——|im_end|\n|im_start|assistant\n嘘——都说许愿说破是不灵的。|endoftext| tokenizer.decode(list(filter(lambda x: x ! -100, tokenized_id[1][labels]))) # 还原为: 你们俩话太多了我该和温太医要一剂药好好治治你们。|endoftext|第一条验证了完整模板拼接正确第二条验证了 labels 中-100掩码被过滤后恰好还原出模型需要学习的答案文本说明数据格式化链路完全正确。四、加载 tokenizer 与半精度模型模型以半精度形式加载如果显卡比较新可以用torch.bfloat16形式加载。对于自定义模型一定要指定trust_remote_code参数为True。tokenizer AutoTokenizer.from_pretrained(./qwen/Qwen1.5-7B-Chat/, use_fastFalse, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained(./qwen/Qwen1.5-7B-Chat/, device_mapauto, torch_dtypetorch.bfloat16)notebook 的运行记录揭示了该模型的底层细节可作为理解参考tokenizerQwen2Tokenizervocab_size151643model_max_length32768padding_sideright特殊 token 包含eos_token|endoftext|、pad_token|endoftext|以及额外注册的|im_start|、|im_end|对应 token id 151644、151645模型结构Qwen2ForCausalLM内嵌 32 层Qwen2DecoderLayer每层包含Qwen2Attentionq_proj/k_proj/v_proj/o_proj输入输出维度 4096与Qwen2MLPgate_proj/up_proj升维至 11008、down_proj降回 4096激活函数 SiLU总参数量约 74 亿。由于后续会开启梯度检查点notebook 在创建模型后还执行了model.enable_input_require_grads() # 开启梯度检查点时要执行该方法五、定义 LoraConfig核心参数逐项解析LoraConfig中可以设置很多参数但主要参数并不多核心包括task_type模型类型此处为因果语言模型TaskType.CAUSAL_LMtarget_modules需要训练的模型层名字主要是 attention 部分以及 MLP 部分的层不同模型对应层的名字不同可以传入数组、字符串也可以传正则表达式rLoRA 的秩rank具体原理参见 LoRA 论文lora_alphaLoRA alpha 缩放系数具体作用参见 LoRA 原理lora_dropoutLoRA 层的 Dropout 比例。需要特别强调 LoRA 的缩放机制缩放系数不是r秩而是lora_alpha / r。在本节配置中缩放为32 / 8 4倍。config LoraConfig( task_typeTaskType.CAUSAL_LM, target_modules[q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj], inference_modeFalse, # 训练模式 r8, # Lora 秩 lora_alpha32, # Lora alaph具体作用参见 Lora 原理 lora_dropout0.1 # Dropout 比例 )这里target_modules覆盖了注意力的全部四个投影层q/k/v/o_proj和 MLP 的全部三个投影层gate/up/down_proj与 notebook 中打印出的Qwen2DecoderLayer结构一一对应。在 notebook 中通过get_peft_model将 LoRA 适配器挂载到基础模型上from peft import LoraConfig, TaskType, get_peft_model model get_peft_model(model, config) model.print_trainable_parameters()其运行输出为trainable params: 19,988,480 || all params: 7,741,313,024 || trainable%: 0.2582052933143348即在 77.4 亿总参数中仅约2000 万参数0.258%参与训练这正是 LoRA 高效微调以极低参数量实现高质量适配的直观体现——绝大多数基础模型权重被冻结只有低秩增量矩阵被优化。六、自定义 TrainingArguments训练超参数配置TrainingArguments的源码中详细介绍了每个参数的具体作用这里讲解常用的几个output_dir模型的输出路径checkpoint 保存目录per_device_train_batch_size即单设备上的batch_sizegradient_accumulation_steps梯度累加步数。如果显存较小可以把batch_size调小、把梯度累加调大用时间换显存logging_steps每多少步输出一次 lognum_train_epochs训练轮数epochsave_steps每多少步保存一次 checkpointlearning_rate学习率save_on_each_node在每个节点上均保存 checkpoint适用于多节点训练gradient_checkpointing梯度检查点。一旦开启模型就必须执行model.enable_input_require_grads()其原理是通过在前向传播中丢弃中间激活、反向传播时重新计算来大幅节省显存。args TrainingArguments( output_dir./output/Qwen1.5-7B-Chat, per_device_train_batch_size4, gradient_accumulation_steps4, logging_steps10, num_train_epochs3, save_steps100, learning_rate1e-4, save_on_each_nodeTrue, gradient_checkpointingTrue )显存换算参考在gradient_checkpointingTrue且未开启use_cache的前提下per_device_train_batch_size4配合gradient_accumulation_steps4相当于每 4 步做一次真实参数更新等效 batch size 为 16。如果你的显卡显存较小可先降低per_device_train_batch_size并同步提高gradient_accumulation_steps。七、使用 Trainer 训练完整训练流程使用transformers的Trainer将模型、训练参数、数据集和 DataCollator 组装起来即可开始训练trainer Trainer( modelmodel, argsargs, train_datasettokenized_id, data_collatorDataCollatorForSeq2Seq(tokenizertokenizer, paddingTrue), ) trainer.train()其中DataCollatorForSeq2Seq(tokenizertokenizer, paddingTrue)负责在批处理时对不等长序列做右侧 padding使同一 batch 内的input_ids、attention_mask、labels长度对齐。notebook 中的真实训练日志可作为过程佐证训练开始时transformers自动提示use_cacheTrue与梯度检查点不兼容已自动将use_cache置为False这是开启gradient_checkpointing时的预期行为训练进度显示[134/699 ... Epoch 0.57/3]即 3729 条样本在 batch size 4 下每个 epoch 约 233 步3 个 epoch 共约 699 步每 10 步记录的 Training Loss 从第 10 步的4.153500逐步下降至第 130 步的2.935700附近验证了 LoRA 微调正常收敛训练过程中每save_steps100步在./output/Qwen1.5/checkpoint-100等目录保存一次 LoRA checkpoint。八、加载 LoRA 权重推理验证微调效果训练完成后使用如下方式加载 LoRA 权重进行推理from transformers import AutoModelForCausalLM, AutoTokenizer import torch from peft import PeftModel model_path ./qwen/Qwen1.5-7B-Chat/ lora_path lora_path # 加载tokenizer tokenizer AutoTokenizer.from_pretrained(model_path) # 加载模型 model AutoModelForCausalLM.from_pretrained(model_path, device_mapauto, torch_dtypetorch.bfloat16) # 加载lora权重 model PeftModel.from_pretrained(model, model_idlora_path, configconfig) prompt 你是谁 messages [ {role: system, content: 现在你要扮演皇帝身边的女人--甄嬛}, {role: user, content: prompt} ] text tokenizer.apply_chat_template(messages, tokenizeFalse, add_generation_promptTrue) model_inputs tokenizer([text], return_tensorspt).to(cuda) generated_ids model.generate( model_inputs.input_ids, max_new_tokens512 ) generated_ids [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response tokenizer.batch_decode(generated_ids, skip_special_tokensTrue)[0] print(response)几个关键点基础模型加载与训练阶段一致仍以torch.bfloat16半精度加载原始Qwen1.5-7B-Chat权重LoRA 权重合并通过PeftModel.from_pretrained(model, model_idlora_path, configconfig)将训练产出的 LoRA 适配器保存在lora_path指向的 checkpoint 目录中挂载到基础模型之上其中config需与训练时使用的LoraConfig保持一致r8、lora_alpha32等Chat Template 重建推理时通过tokenizer.apply_chat_template将 messages 重新组织为 ChatML 格式文本并用add_generation_promptTrue追加assistant起始标记与训练时的模板格式保持一致增量解码generated_ids减去输入部分的input_ids只保留模型新生成的 token再通过skip_special_tokensTrue解码得到纯文本回答。对你是谁这一测试 prompt微调后的模型将输出甄嬛风格的回复如家父是大理寺少卿甄远道。从而验证个性化人设已成功注入基础模型。九、常见问题与调优建议基于上述流程与 notebook 的实际运行记录总结几点实操建议显存不足优先降低per_device_train_batch_size、提高gradient_accumulation_steps并确保gradient_checkpointingTrue同时执行model.enable_input_require_grads()必要时可将模型加载精度从bfloat16降到 4-bit 量化参考仓库中其他模型的 QLoRA 教程LoRA 效果不达预期可尝试增大r如 16、32同时按比例调整lora_alpha注意实际缩放因子为lora_alpha / r改动任一参数都会影响增量权重的生效强度数据质量优先指令微调的核心是指令-答案配对质量instruction input拼接后作为提问、output作为唯一学习目标labels 掩码已排除提问部分因此数据集中出现噪声答案会直接影响微调效果过拟合监控本文示例训练 3 个 epoch、约 699 步notebook 显示 loss 已降至 2.9 附近。若样本量更大或训练更久建议配合eval_strategy、logging_steps等参数持续观察也可参考仓库同目录下的 08-Qwen1.5-7B-chat LoRA微调接入实验管理.md 接入 SwanLab 进行实验跟踪与可视化。十、总结本文完整复现了Qwen1.5-7B-Chat 人设化 LoRA 指令微调的全链路环境与依赖Ubuntu CUDA PyTorch 环境上安装transformers/peft/accelerate/datasets/modelscope数据构建以 dataset/huanhuan.json3729 条甄嬛对话样本为例理解instruction/input/output三段式指令结构数据格式化通过process_func将样本按 ChatML 模板编码为input_ids/attention_mask/labels并用-100掩码保证只学习答案部分模型与配置以bfloat16半精度加载模型配置LoraConfig仅 0.258% 参数可训练与TrainingArguments训练与推理通过Trainer完成训练并用PeftModel加载 LoRA 权重进行人设对话验证。这套流程的核心方法论可平滑迁移到其他 ChatML 格式的开源模型如 Qwen 系列后续版本只需替换模型路径、target_modules层名与数据集即可。读者可结合同目录 Qwen1.5-7B-Chat Lora.ipynb 逐步运行验证也可以进一步参考仓库中 models/Qwen2、models/Qwen2.5 等目录下的同类微调教程横向对比。【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考