资讯动态

大模型微调实战:训练阶段、PEFT与数据类型选型避坑指南

发布时间:2026/10/15 5:56:07 来源:尧图企业网站定制
最近在做一个垂直领域问答系统的落地项目同行问得最多的三个问题基本是训练阶段到底怎么划分、微调用什么数据类型、为什么大家都在折腾PEFT参数高效微调体系。这些问题听起来基础但真到动手配置的时候坑一个接一个。这篇文章把训练阶段划分、数据类型选择、PEFT参数高效微调体系这三件事串起来讲透顺便把我实测过的参数组合和踩坑记录列出来方便你直接照着抄。如果你是刚开始接触大模型微调或者已经跑过一两个脚本但不太理解为什么要那样配置读完应该能理清不少头绪。1. 训练阶段划分预训练、监督微调与对齐到底在做什么1.1 预训练阶段让模型掌握语言的基本规律大模型训练的第一个阶段是预训练。这个阶段输入的是海量纯文本数据来源可能是网页、书籍、论文、代码仓库规模一般按TB计算。模型通过自回归或掩码语言建模的方式不断预测下一个词最终学到的是词与词之间的统计规律、句法结构、基础事实和一部分推理能力。预训练产出的基座模型本质上只是一个“语言通”。你说什么它都能接但它并不知道什么是“回答问题”也不存在指令遵循的概念。很多人第一次拿到预训练权重直接对话会觉得输出前言不搭后语就是因为这个模型只见过“接着往下写”的任务没有见过“你说一句我答一句”的任务。预训练阶段消耗的算力非常夸张通常需要大规模集群连续训练几十天普通团队基本不会自己去碰。实操中你需要关心的只有一件事你拿到的基座模型是否已经经过指令微调或对齐。如果拿一个已经带对话能力的模型继续做任务微调新数据会和固有行为产生冲突效果不一定更好有时反而变差。所以在开始任何微调之前先确认基座的状态这个信息通常会写在模型卡或README里不要想当然。1.2 监督微调阶段让模型学会“按指令办事”监督微调SFT是日常落地和我个人项目中使用最多的阶段。它的输入是“指令-回答”对有时会带上下文目标很直接让模型在给定指令时输出期望的回答。数据规模通常从几千条到几十万条不等单机单卡就能完成训练。这也是PEFT参数高效微调体系最适合发挥的地方。SFT阶段最大的特点是少量高质量数据就能改变模型行为。我之前做过一个垂直领域问答项目只用大概两万条人工清洗过的数据就把一个开源基座模型改造成基本能用的领域助手。反过来堆十万条低质量数据效果反而更差。SFT的本质是教模型“该说什么”不是教它“学会新知识”。一条错误示范会被模型当作标准答案学进去这比不教更糟。所以数据清洗、去重、格式统一在这个阶段比模型结构本身更影响最终效果。1.3 对齐阶段让模型输出更安全、更符合偏好对齐阶段通常指RLHF或DPO这一类方法目标不是继续提高准确率而是让模型输出符合人类偏好。比如用户问危险问题模型需要拒绝用户给开放性问题模型需要给出更有帮助的回答。对齐依赖奖励模型或偏好数据实现复杂度比SFT高不少。对绝大多数业务场景而言真正需要的是SFT阶段。对齐应该在模型已经稳定“听懂指令”之后再做。如果SFT没做好模型连基础格式都不规范直接上对齐会浪费大量时间。阶段划分的核心逻辑是预训练把语言能力补齐SFT把任务能力补上对齐调风格和安全边界。用PEFT做业务的同学99%的精力放在SFT就可以了。三阶段对比如下阶段数据形式训练目标算力消耗PEFT适用性预训练海量纯文本预测下一个词极高一般不适用监督微调指令-回答对学习指令遵循中等非常适用对齐偏好数据/奖励模型符合人类偏好较高部分适用2. 数据类型选型FP32、FP16、BF16、INT8、INT4如何组合使用2.1 浮点精度基础指数位和尾数位的关系先讲最基础的浮点表示。FP32是单精度浮点1位符号8位指数23位尾数FP16是半精度1位符号5位指数10位尾数BF16是1位符号8位指数7位尾数。乍看只是位宽不同实际影响很大。FP16的指数位只有5位能表示的最大值大约65504。训练时一旦梯度或中间激活超过这个值就会直接变成inf。BF16的指数位和FP32一样是8位所以范围内基本不会溢出但尾数只有7位数值精度有限。这个差别解释了为什么很多新手在FP16下训练时loss会突然变成nan——不是学习率问题而是数据一波动就溢出了。改成BF16之后问题基本消失。2.2 混合精度训练主权重高精度计算用低精度大模型训练通常用混合精度。具体做法是主权重和优化器状态保存为FP32前向和反向计算使用BF16或FP16。这样显存占用大约减半数值稳定性也好。现在的训练框架基本把逻辑封装好了设置bf16True就能用不需要手动处理梯度缩放。但有一点很多人没意识到AdamW优化器本身要保存一阶动量和二阶动量这两个都是FP32主权重也是FP32。所以在BF16训练流程里权重其实各有一个BF16副本计算用和一个FP32主副本更新用。这也是为什么全参数微调显存需求很大而PEFT只更新少量参数就能省下大量优化器状态的显存。2.3 训练量化与推理量化不要混为一谈INT8和INT4量化通常用于推理部署比如把模型权重从FP16压到INT8甚至INT4显存占用和推理速度都有明显改善。但是在训练中常规的INT4权重没法直接做反向传播所以出现了QLoRA这一类方法用NF4的4bit格式存基座模型权重同时保留高精度的可训练LoRA参数。这相当于把量化训练和PEFT结合在一起。我的建议是微调阶段优先用BF16LoRA或NF4量化LoRA推理部署阶段再用INT8或INT4量化。不要在训练阶段为了省显存直接把基座模型加载成FP16尤其是老显卡很容易遇到精度溢出的问题。另一个经验是只要显卡支持BF16训练就不要用FP16收益非常明显。常用精度对比精度类型符号位指数位尾数位典型用途注意事项FP321823主权重、优化器状态显存占用大FP161510老显卡混合精度训练容易溢出需要loss缩放BF16187新显卡混合精度训练大模型训练默认选择INT8---推理量化精度损失较小INT4 (NF4)---推理量化、QLoRA训练适合显存受限场景3. PEFT参数高效微调体系三种主流技术路线与选型3.1 为什么需要参数高效微调全参数微调有多奢侈全参数微调在大模型时代非常奢侈。一个7B模型的全参微调单张24G显存基本跑不动即使跑得动每个任务都会产出一整套完整权重部署维护成本极高。更麻烦的是全量微调容易造成“灾难性遗忘”模型在学新任务的同时把原有通用能力丢掉。PEFT的思路是只更新极少量参数同时尽量保留基座模型的原有能力。可训练参数占比通常在0.1%到1%之间显存需求大幅降低单卡微调大模型成为可能。这也是PEFT参数高效微调体系在社区里迅速普及的根本原因。3.2 LoRA低秩分解思路LoRA是当前最主流的PEFT方案。它把权重增量写成两个低秩矩阵B和A的乘积训练时冻结原始权重只优化B和A。假设一个模块的维度是2048x2048全量权重参数超过400万个而LoRA用r8的话参数量大约是2乘2048再乘8约3万个差距上百倍。LoRA有几个关键超参必须理解。r是秩太小表达能力不足太大又退化成近似全量更新常规从8开始试复杂任务可以到16或32alpha是缩放系数通常设成r的1到2倍dropout用在LoRA矩阵上防止过拟合经验值0.05左右。target_modules决定LoRA挂在哪些模块常见选择是注意力模块的q/k/v/o有些场景把mlp也加进去效果更好。需要注意的是r不是越大越好。我实测过一些分类任务r16反而比r8差多出来的参数量没什么收益还更容易过拟合。3.3 QLoRA量化与LoRA的结合QLoRA解决的是显存不够的问题。基座模型用NF4格式量化到4bit存储显存大幅缩水前向计算时再反量化为BF16。这套方案能在保持接近全参数微调效果的同时把微调门槛降到单卡可跑。我自己在12G显存的环境里用QLoRA微调过7B级别的模型per_device_batch_size只能设1配合梯度累积到等效batchsize16训练基本稳定。QLoRA还有一个容易忽略的细节它对基座模型本身是有损的量化4bit会丢失一部分信息。少数任务上QLoRA效果明显不如纯LoRA建议在效果和显存之间做权衡。如果显卡能跑纯LoRA优先纯LoRA实在跑不动再上QLoRA。3.4 前缀学习和Adapter两种不同的思路Prefix-Tuning和P-Tuning v2是另一类PEFT方案它们在输入序列前插入可学习的“虚拟token”或前缀向量冻结模型主体权重。参数量很小在部分自然语言理解任务上效果不错尤其适合序列标注、分类这类结构化任务。缺点是会让训练序列变长占用额外显存生成式任务上表现通常不如LoRA。Adapter的做法是在Transformer层之间插入小型前馈网络训练时只更新Adapter。好处是参数少、任务隔离性好多个任务可以共享基座模型各挂各的Adapter。坏处是引入额外顺序计算推理延迟会增加。如果对推理时延敏感需要好好评估。三类PEFT方案对比方案可训练参数推理影响推荐任务缺点LoRA很低0.1%左右几乎无生成式对话、指令微调选择target_modules有技巧QLoRA很低几乎无显存受限的大模型微调4bit量化有信息损失Prefix/P-Tuning极低输入序列变长NLU分类、序列标注生成任务效果一般Adapter低推理延迟增加多任务多适配器场景推理路径非标准选型建议很简单做生成式助手首选LoRA或QLoRA做轻量NLU任务P-Tuning v2值得试试要在一个基座上挂多个任务Adapter的多路复用有天然优势。4. 实操项目基于LoRA和QLoRA完成一次指令微调4.1 环境准备与依赖版本开始前先确认环境。Python版本建议3.9以上然后依次装PyTorch、Transformers、PEFT、bitsandbytes这几个库版本尽量保持稳定不要全装最新版否则经常出现接口不兼容。特别是bitsandbytes老版本加载4bit模型时经常报错建议装最近几月内有维护的版本。装完依赖后先验证显卡是否支持BF16。用一个很小的Tensor测试如果支持配置里直接开bf16True省很多事。很多环境问题其实都出在这里先确认依赖再跑数据预处理不要一上来就训练完整模型定位问题会容易很多。4.2 数据准备从JSON到Token序列SFT数据常见的格式是JSON每条记录包含instruction、input、output三部分。有input就拼在instruction后面没有就只保留instruction。加载后要转换成模型认识的token序列核心是把文本拼接成固定格式然后tokenizer编码。这个环节有三个关键点。第一max_length不要随便设太长128到2048之间按任务复杂程度选设太长浪费显存设太短答案会被截断。第二padding策略要注意训练时右侧padding是常规做法但推理生成时建议改成左侧padding避免模型被迫生成padding部分。第三tokenizer必须有pad_token很多基座模型没有设置需要手动将pad_token设置为eos_token否则训练时会告警。强烈建议在正式训练前做一次小样本过拟合测试。拿100条数据用稍大的学习率跑几十个step如果loss能压到很低说明数据pipeline没装错。这个习惯帮我排查了至少三次莫名其妙的问题比直接投诉训练框架有用得多。4.3 加载基座模型并配置QLoRA加载4bit模型的代码示意如下from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig import torch bnb_config BitsAndBytesConfig( load_in_4bitTrue, bnb_4bit_quant_typenf4, bnb_4bit_compute_dtypetorch.bfloat16, bnb_4bit_use_double_quantTrue, ) tokenizer AutoTokenizer.from_pretrained(your_model_path) model AutoModelForCausalLM.from_pretrained( your_model_path, quantization_configbnb_config, device_mapauto, trust_remote_codeTrue, )加载后立刻设置pad_token并开启gradient_checkpointing。然后构造LoRA配置并包装模型from peft import LoraConfig, get_peft_model, TaskType lora_config LoraConfig( task_typeTaskType.CAUSAL_LM, r8, lora_alpha16, lora_dropout0.05, target_modules[q_proj, k_proj, v_proj, o_proj], ) model get_peft_model(model, lora_config)包装完打印一下可训练参数量确认LoRA参数占总参数的比例正常一般在0.1%左右。如果比例异常高多半是target_modules写错了多写了一些不是注意力投影的模块名。4.4 训练参数设置与Trainer训练参数直接影响效果下面是一组经过验证的配置from transformers import TrainingArguments, Trainer training_args TrainingArguments( output_dir./lora_output, num_train_epochs3, per_device_train_batch_size1, gradient_accumulation_steps8, learning_rate2e-4, warmup_ratio0.03, lr_scheduler_typecosine, bf16True, gradient_checkpointingTrue, logging_steps20, save_steps200, save_total_limit2, )几个关键参数说下原因。learning_rate用2e-4左右比全参数微调的1e-5到3e-5高一个数量级因为LoRA只更新少量参数可更新的参数少了步长自然可以更大。gradient_accumulation_steps用来扩大等效batch size显存不够时是标配。gradient_checkpointing开启后显存占用会降低但训练速度会变慢需要自己取舍。save_total_limit设成2避免磁盘被checkpoint塞满。4.5 推理、合并与导出训练完成后直接用LoRA权重做推理时需要同时加载基座模型和adapter。如果想把模型部署成完整权重需要先合并再保存model model.merge_and_unload() model.save_pretrained(./merged_model) tokenizer.save_pretrained(./merged_model)合并操作建议在CPU上做显存不足时可以换内存跑。合并后的权重等于原始权重加增量可以直接当普通模型用。这里有个容易踩的坑很多人训练完直接加载未合并的原始模型做测试效果当然没有变化以为是训练失败。先确认adapter有没有正确加载再怀疑模型没训练好。5. 常见问题与排查技巧显存溢出、Loss异常与效果不佳5.1 显存溢出先定位瓶颈再优化显存溢出是最常见的问题原因无非这么几类max_length太长、batch_size太大、没开gradient_checkpointing、数据加载时每条padding到相同长度造成无谓浪费。排查思路是先用一条最短样本测试显存占用然后逐项放宽。有一个冷门但常见的原因训练参数里设置了eval集但没关评估时的显存翻倍。Trainer在训练过程中会周期性地跑评估如果评估数据量比较大显存压力会骤然上升。降低评估频率或把eval关掉OOM问题可能就消失了。5.2 Loss变成NaN或一直不下降Loss变NaN先检查精度FP16改成BF16大概率解决问题。再检查学习率如果你拿全参数微调的5e-6来跑LoRAloss会下降极慢但2e-4用在LoRA上是常规操作。然后检查数据样本里有没有空字符串、有没有截断后output为空的情况这些会在batch里制造异常的padding。Loss不下降则先看小样本过拟合测试能不能跑通。如果小样本也降不下去多半是数据拼接或标签位置写错了重点检查input_ids和labels的对齐关系尤其是offset的处理。5.3 训练完成但生成效果不理想效果不好先验证推理配置。很多人把temperature设成0.7甚至更高模型输出发散设得太低又容易重复。常规做法是temperature设在0.1到0.3之间top_p设在0.9。另一个常见问题是do_sample设False时模型只用贪心解码输出会比较机械但它至少应该能正确回答训练集里的问题。如果训练集里都答不对那说明模型没有学到模式回查数据格式。如果训练集里答得对但测试集不行大概率是数据分布太单一90%的训练样本都是同一个模板模型只会照葫芦画瓢换个说法就崩。解决办法是增加数据多样性而不是单纯增加数量。5.4 过拟合与灾难性遗忘SFT过拟合的表现是loss很低但生成时词汇重复、没有多样性。对策是增加数据多样性、适当调高lora_dropout到0.1、减少训练轮次到2或3。遇到过拟合时先降epoch再调dropout不要一上来就动rank。灾难性遗忘则是另一种体验模型学会了新任务但忘了原来的通用能力。解决方法是训练数据里混入10%到20%的通用指令数据让模型在学习新技能的同时保留已有能力。问题排查速查表现象典型原因处理建议显存溢出batch过大或序列过长开gradient_checkpointing减max_lengthLoss变成NaNFP16精度溢出换成BF16关闭loss缩放Loss不下降数据标签错位用小样本过拟合测试验证pipeline训练完没效果没加载adapter权重推理前确认是否加载或合并adapter输出重复过拟合减少epoch调高dropout通用能力下降灾难性遗忘混入通用指令数据6. 进阶经验与避坑清单到这里训练阶段、数据类型、PEFT体系的核心内容基本覆盖完了。最后分享几条实操中积累的经验不算总结就是一些日常能用到的小习惯。第一每次实验先记录三样东西显存占用、单step耗时、loss曲线。这三项能快速定位绝大多数问题。不要嫌麻烦等出问题再回忆就晚了。第二不要盲目追求大的rank。LoRA的r从8开始几乎是通用做法任务变复杂先加数据质量再加r。我在多个任务上对比过r16并没有稳定优于r8而训练时间和显存倒是实打实增加了。第三混入通用指令数据是缓解灾难性遗忘最有效的技巧之一。我通常按9比1的比例混也就是九份领域数据配一份通用指令数据模型既学得到新任务也不至于忘记老本领。第四如果你准备长期做模型微调把数据预处理脚本和评估脚本固化下来做成模板。每次新项目只是换数据、换任务文本其他逻辑不动。这套流程跑顺之后从拿到数据到完成一次LoRA微调基本能在半天内完成。第五关于模型能力的天花板PEFT能改变的是行为、格式、风格很难凭空塞入大量模型原来不具备的知识。如果任务需要大量新知识优先考虑检索增强或继续预训练把希望全压在SFT微调上通常会失望。我个人在实际操作中的体会是先把pipeline跑通用最小资源验证数据质量再逐步放大模型规模和数据量。这个思路让我少走了很多弯路。希望这篇文章对你有帮助也欢迎带着你的踩坑记录来交流。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑