ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

BlueLM-7B-Chat LoRA 微调实战:基于 transformers 与 peft 的高效指令微调完整指南

BlueLM-7B-Chat LoRA 微调实战:基于 transformers 与 peft 的高效指令微调完整指南 BlueLM-7B-Chat LoRA 微调实战基于 transformers 与 peft 的高效指令微调完整指南【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/datawhalechina/self-llm导读本文围绕 Datawhale self-llm 仓库中 models/BlueLM/04-BlueLM-7B-Chat Lora 微调.md 的核心脉络展开系统讲解如何基于transformers、peft等框架对 vivo AI 开源的 BlueLM-7B-Chat 模型进行 LoRA 高效微调并用甄嬛风格的指令数据将模型改造成角色扮演式对话助手。读完本文你将掌握指令数据集格式化、tokenizer 与模型加载、LoraConfig 与 TrainingArguments 配置、Trainer 训练以及微调后模型推理的完整实战链路并能直接运行仓库提供的.py脚本与 Jupyter Notebook 复现全过程。一、LoRA 微调概述与前置准备1.1 LoRA 是什么LoRALow-Rank Adaptation是一种参数高效微调PEFT方法它冻结预训练模型的全部原始权重仅在需要适配的线性层旁注入低秩分解矩阵对$A \in \mathbb{R}^{r \times d}$ 与 $B \in \mathbb{R}^{d \times r}$训练时只更新这些极小的低秩矩阵从而以极少的可训练参数量完成领域适配显著降低显存占用与训练成本。训练完成后可以将低秩增量合并回原始权重推理时零额外开销。本节教程基于transformers、peft框架完成对 BlueLM-7B-Chat 的 LoRA 微调仓库在 models/BlueLM/04-BlueLM-7B-Chat Lora 微调.ipynb 提供了逐 Cell 讲解的 Notebook并在 models/BlueLM/04-BlueLM-7B-Chat Lora 微调.py 提供了等价的完整可执行脚本建议两者对照学习。1.2 环境配置在完成基础环境配置和本地模型部署的前提下还需要安装以下第三方库pip install transformers4.35.2 pip install peft0.4.0 pip install datasets2.10.1 pip install accelerate0.20.3 pip install tiktoken pip install transformers_stream_generator其中transformers4.35.2提供AutoTokenizer、AutoModelForCausalLM、Trainer、DataCollatorForSeq2Seq等核心训练组件peft0.4.0提供LoraConfig、TaskType、get_peft_model是 LoRA 微调的关键库datasets2.10.1用于加载与映射微调数据集accelerate0.20.3Trainer底层依赖的分布式/混合精度加速库tiktoken、transformers_stream_generatorBlueLM 分词与流式生成相关的辅助库。提示若更换 pip 镜像源或需下载模型权重可参考仓库 models/General-Setting/01-pip、conda换源.md 与 models/General-Setting/03-模型下载.md。1.3 微调数据集本教程将微调数据集放置在仓库根目录下的 dataset/huanhuan.json此外 dataset/huanhuan-100.json 提供了 100 条小规模子集适合快速验证流程dataset/huanhuan.jsonl 是等价的 JSON Lines 版本。数据内容为《甄嬛传》风格的宫廷对话用于将通用聊天模型微调成甄嬛角色扮演助手。二、指令集构建从通用指令到 BlueLM 对话格式LLM 的微调一般指指令微调Instruction Tuning即使用指令—输入—输出三元组数据监督模型学会按要求作答。数据形态如下{ instruction: 解释什么是人工智能。\n, input: , output: 人工智能是一种利用计算机程序和算法创造出类似人类智能的技术可以让计算机在解决问题、学习、推理和自然语言处理等方面表现出类似人类的能力。 }字段含义instruction用户指令告知模型需要完成的任务input用户输入是完成用户指令所必须的上下文内容可为空字符串output模型应当给出的标准输出。上述格式是通用的数据集描述而真正送入 BlueLM 训练的目标格式必须符合其自身的对话模板。从仓库配套脚本 models/BlueLM/04-BlueLM-7B-Chat Lora 微调.py 与 Notebook 的 tokenizer 打印信息可以看到BlueLM 的 tokenizer 额外注册了[|Human|]:、[|AI|]:、[SEH]、[SEA]四个特殊 token其对话模板仅包含Human与AI两个角色。因此目标格式是{ inputs: [|Human|]:解释什么是人工智能。\n[|AI|]:, targets: 人工智能是一种利用计算机程序和算法创造出类似人类智能的技术可以让计算机在解决问题、学习、推理和自然语言处理等方面表现出类似人类的能力。 }其中inputs是指令 角色标记拼接而成的模型输入前缀targets是期望模型续写的标准回答。理解这一点是后续数据格式化函数编写的依据。三、数据格式化process_func 逐行拆解LoRA 训练的数据需要经过格式化、编码之后才能输入模型。熟悉 PyTorch 训练流程的同学知道我们需要把输入文本编码为input_ids把输出文本编码为labels编码结果都是多维向量。仓库定义了一个预处理函数对每个样本编码其输入、输出文本并返回编码后的字典def process_func(example): MAX_LENGTH 384 input_ids [] labels [] instruction tokenizer(textf[|Human|]:现在你要扮演皇帝身边的女人--甄嬛\n\n {example[instruction]}{example[input]}[|AI|]:, add_special_tokensFalse) response tokenizer(textf{example[output]}, add_special_tokensFalse) input_ids [tokenizer.bos_token_id] instruction[input_ids] response[input_ids] [tokenizer.eos_token_id] labels [tokenizer.bos_token_id] [-100] * len(instruction[input_ids]) response[input_ids] [tokenizer.eos_token_id] if len(input_ids) MAX_LENGTH: input_ids input_ids[:MAX_LENGTH] labels labels[:MAX_LENGTH] return { input_ids: input_ids, labels: labels }3.1 关键设计点角色扮演前缀输入前缀为现在你要扮演皇帝身边的女人--甄嬛\n\n将模型锚定为甄嬛角色之后拼接instruction input最后以[|AI|]:结尾引导模型以 AI 角色续写add_special_tokensFalse分段编码时先不追加特殊 token由后续拼接逻辑统一管理input_ids组装[bos_token_id] instruction_ids response_ids [eos_token_id]即整条样本以s开头、以/s结尾。BlueLM 的 tokenizer 中bos_token为s、eos_token为/s、pad_token为padlabels掩码指令部分对应的 label 全部置为-100而回答部分保留真实 token id。这是 HuggingFace 训练器约定的忽略索引——计算损失时-100位置不参与 loss 计算从而保证模型只学习输出部分的生成能力不惩罚对指令本身的复述MAX_LENGTH 384对超长样本做截断input_ids与labels同步裁剪保证二者长度一致。经过格式化的每条数据都是一个包含input_ids、labels两个键的字典。从 Notebook 的实际运行记录看decode 之后样本形态如下s [|Human|]: 现在你要扮演皇帝身边的女人--甄嬛\n\n 这个温太医啊也是古怪谁不知太医不得皇命不能为皇族以外的人请脉诊病他倒好十天半月便往咱们府里跑。 [|AI|]: 你们俩话太多了我该和温太医要一剂药好好治治你们。/s为什么是这个形态因为不同模型对应的格式化输入各不相同BlueLM 只有[|Human|]和[|AI|]两个角色所以数据格式自然如此。Notebook 中还通过tokenizer.decode(list(filter(lambda x: x ! -100, ...)))验证了labels去除-100后恰好还原为模型的回答部分说明掩码设置正确。3.2 数据映射到 Dataset借助datasets库先将 JSON 转为Dataset再批量应用预处理函数Notebook 中可见处理结果为 3729 条样本特征为[input_ids, labels]from datasets import Dataset import pandas as pd df pd.read_json(./huanhuan.json) ds Dataset.from_pandas(df) tokenizer AutoTokenizer.from_pretrained(vivo-ai/BlueLM-7B-Chat, use_fastFalse, trust_remote_codeTrue) tokenized_id ds.map(process_func, remove_columnsds.column_names)注意AutoTokenizer加载时使用use_fastFalseBlueLM 使用基于trust_remote_code的自定义分词实现并建议显式设置tokenizer.padding_side right与 Notebook 保持一致。四、加载 tokenizer 与模型模型加载使用AutoModelForCausalLM以半精度torch.half加载并自动分配到可用设备import torch from transformers import AutoModelForCausalLM, GenerationConfig model AutoModelForCausalLM.from_pretrained(vivo-ai/BlueLM-7B-Chat, trust_remote_codeTrue, torch_dtypetorch.half, device_mapauto) model.generation_config GenerationConfig.from_pretrained(vivo-ai/BlueLM-7B-Chat) model.generation_config.pad_token_id model.generation_config.eos_token_id要点说明trust_remote_codeTrueBlueLM 的模型结构与分词器均通过远程代码modeling_blueLM.py等加载必须开启torch_dtypetorch.half以 FP16 加载权重兼顾显存与训练效率device_mapauto由accelerate自动将各层分配到 GPU/CPUmodel.generation_config同步加载官方生成配置并将pad_token_id对齐为eos_token_id避免生成时的 padding 歧义。从 Notebook 打印的模型结构可以看到 BlueLM-7B 的骨干为 32 层BlueLMDecoderLayer每层由BlueLMAttention含q_proj、k_proj、v_proj、o_proj四个 4096×4096 的线性层与rotary_emb旋转位置编码和BlueLMMLP含gate_proj、down_proj、up_proj中间维度 11008激活函数 SiLU组成词表大小为 100008。这一结构信息是下一步确定 LoRAtarget_modules的直接依据。五、定义 LoraConfigLoraConfig可设置很多参数核心参数如下参数含义本教程取值task_type任务类型此处为因果语言建模TaskType.CAUSAL_LMtarget_modules需要注入 LoRA 的模块名主要是 attention 与 MLP 中的线性层可传数组、字符串或正则见下rLoRA 的秩低秩分解的维度8lora_alphaLoRA 缩放因子32lora_dropoutLoRA 层随机失活比例0.1inference_mode是否为推理模式False训练模式一个常见的误解是LoRA 的缩放是秩 r实际缩放系数是lora_alpha / r本例中即32 / 8 4倍。需要特别说明target_modules的取值。文档正文给出的示例是config LoraConfig( task_typeTaskType.CAUSAL_LM, target_modules[c_attn, c_proj, w1, w2], inference_modeFalse, # 训练模式 r8, # Lora 秩 lora_alpha32, # Lora alaph具体作用参见 Lora 原理 lora_dropout0.1# Dropout 比例 )但仓库配套的 .py 脚本 与 .ipynb Notebook 中实际使用的是另一组模块名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 比例 )结合上一节 Notebook 输出的模型结构可以推断BlueLM 实际使用的是 LLaMA 风格命名q_proj/k_proj/v_proj/o_proj/gate_proj/up_proj/down_proj而c_attn/c_proj/w1/w2属于 GPT-2 风格命名与本模型结构并不匹配。因此实际运行时请以仓库.py/.ipynb中的模块名列表为准这也提醒我们在复刻他人 LoRA 教程时务必先打印模型结构核对真实模块名否则target_modules匹配不到任何层会导致训练无效。将 LoRA 配置应用到模型上from peft import LoraConfig, TaskType, get_peft_model model.enable_input_require_grads() # 开启梯度检查点时必须执行该方法 model get_peft_model(model, config) model.print_trainable_parameters()Notebook 的运行记录显示trainable params: 19,988,480 || all params: 7,315,533,824 || trainable%: 0.27323337545681203即整个 73 亿参数的模型中仅约 1998 万参数约 0.27%参与训练——这正是 LoRA 高效微调的核心体现。六、自定义 TrainingArguments 参数TrainingArguments源码对每个参数均有说明这里梳理常用参数参数含义本教程取值output_dir模型输出目录checkpoint 保存路径./output/BlueLMper_device_train_batch_size单卡 batch size8gradient_accumulation_steps梯度累加步数显存不足时可调小 batch_size、调大该值2logging_steps每多少步输出一次 log10num_train_epochs训练轮数3gradient_checkpointing梯度检查点以计算换显存开启后必须调用model.enable_input_require_grads()Truesave_steps每多少步保存一次 checkpoint100learning_rate学习率1e-4save_on_each_node多节点训练时各节点均保存Trueargs TrainingArguments( output_dir./output/BlueLM, per_device_train_batch_size8, gradient_accumulation_steps2, logging_steps10, num_train_epochs3, save_steps100, learning_rate1e-4, save_on_each_nodeTrue, gradient_checkpointingTrue )补充说明梯度累加当显存较小、无法容纳较大 batch 时可将per_device_train_batch_size调小、gradient_accumulation_steps调大二者乘积近似等效于更大的 batch size本例等效 batch ≈ 8 × 2 16梯度检查点开启后模型会在前向传播中丢弃中间激活、反向时重新计算从而大幅降低显存峰值代价是训练变慢同时use_cacheTrue与梯度检查点不兼容Trainer 会自动将其关闭Notebook 运行日志中有对应提示enable_input_require_grads()梯度检查点场景下输入嵌入需要保留梯度因此必须在get_peft_model之前调用该方法仓库.py与 Notebook 均严格遵循这一顺序。七、使用 Trainer 训练将模型、参数与数据集一并交给Trainer配合DataCollatorForSeq2Seq做动态 padding即可开始训练from transformers import DataCollatorForSeq2Seq, Trainer trainer Trainer( modelmodel, argsargs, train_datasettokenized_id, data_collatorDataCollatorForSeq2Seq(tokenizertokenizer, paddingTrue), ) trainer.train() # 开始训练data_collatorDataCollatorForSeq2Seq(tokenizertokenizer, paddingTrue)对 batch 内长度不一的input_ids/labels做右侧 padding 对齐padding 使用padtokentrainer.train()内部由Trainer统一调度前向、反向、优化器更新、日志与 checkpoint 保存。从 Notebook 的完整训练记录可以看到本次微调的实际运行结果共 699 个训练步3 个 epoch训练 loss 从初期的约 4.76 逐步下降中后期稳定在 2.0 以下末段 step 约 1.93~1.94最终train_loss约 2.99训练耗时约 1156 秒每步约 0.605 步/秒。这说明在per_device_train_batch_size8、gradient_accumulation_steps2、learning_rate1e-4的配置下该任务能够稳定收敛若显存不足可下调 batch size 并同步上调梯度累加步数。八、模型推理训练完成后使用最常用的model.generate方式进行推理注意输入同样要套上 BlueLM 的对话模板text 小姐别的秀女都在求中选唯有咱们小姐想被撂牌子菩萨一定记得真真儿的—— inputs tokenizer(f[|Human|]:{text}[|AI|]:, return_tensorspt) outputs model.generate(**inputs.to(model.device), max_new_tokens100) result tokenizer.decode(outputs[0], skip_special_tokensTrue) print(result)要点输入必须以[|Human|]:开头、以[|AI|]:结尾与训练时的数据格式保持一致否则微调效果无法正确触发max_new_tokens100限制生成的新 token 数量skip_special_tokensTrue在 decode 时去掉s、/s等特殊标记。Notebook 中该样本的实际推理输出为小姐别的秀女都在求中选唯有咱们小姐想被撂牌子菩萨一定记得真真儿的—— 姐姐您别急咱们还有机会的。可以看到模型已经学会了以甄嬛的口吻进行符合语境的应答说明 LoRA 微调取得了预期的角色扮演效果。九、完整代码与进一步阅读9.1 完整脚本仓库在 models/BlueLM/04-BlueLM-7B-Chat Lora 微调.py 提供了端到端可运行的完整脚本其整体流程为读取 dataset/huanhuan.json → 转换为Dataset→ 加载 tokenizer → 用process_func映射编码 → 加载模型并enable_input_require_grads()→get_peft_model注入 LoRA → 构造Trainer并训练。注意脚本中以if __name__ __main__:组织主流程数据集文件需放置在与脚本同级目录或按需修改读取路径。9.2 Notebook 逐 Cell 学习推荐配合 models/BlueLM/04-BlueLM-7B-Chat Lora 微调.ipynb 学习它保留了每一步的真实输出tokenizer 信息、模型结构、训练 loss 曲线与推理结果便于对照验证每个环节的正确性。9.3 BlueLM 系列其他实战文档如需将微调后的模型投入实际使用可进一步阅读本仓库中 BlueLM 的其他部署文档01-BlueLM-7B-Chat FastApi 部署以 FastAPI 封装模型服务02-BlueLM-7B-Chat langchain 接入将模型接入 LangChain 框架03-BlueLM-7B-Chat WebDemo 部署搭建可交互的 Web Demo。十、总结本文完整复现了 BlueLM-7B-Chat 的 LoRA 微调链路从指令数据集构建、BlueLM 双角色对话模板适配到process_func的编码与掩码设计再到模型加载、LoraConfig/TrainingArguments配置、Trainer训练与推理验证。仓库源码实证了三个关键事实BlueLM 实际可注入 LoRA 的模块名为q_proj/k_proj/v_proj/o_proj/gate_proj/up_proj/down_proj与打印的模型结构一一对应开启梯度检查点前必须调用model.enable_input_require_grads()LoRA 仅训练约 0.27% 的参数即可在 3 epoch 内稳定收敛并产出符合语境的角色扮演回答。掌握这套方法论后你可以将其迁移到任意基于 transformers 架构的开源模型只需替换模型名、核对目标模块名并适配其对话模板即可。【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/datawhalechina/self-llm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表