LLM 微调
第4章LLM 微调 —— 完整详解4.1 概述微调的定义微调 在预训练好的大模型基础上用自己的数据继续训练让它适配具体任务。打个比方预训练模型是一个读了万卷书的学霸知识丰富但不听你指挥。微调就是用你的数据再教他一遍让他专门干你的活儿。微调的三大价值价值解释举例增强任务能力让模型在特定任务上更准更可靠医疗问答更准确定制输出行为按你想要的语气、格式、风格输出让模型用专业但友好的语气回答注入领域知识把专业术语和业务规则塞进模型法律条文、金融术语重要原则能不微调就不微调优先尝试 Prompt Engineering提示词工程和 RAG检索增强生成。只有当这些轻量方法搞不定时才考虑微调。4.2 整体流程模型选择 → 数据准备 → 微调训练 → 模型验证第一步模型选择Instruct Model vs Base ModelInstruct Model推荐优先已做过指令微调和偏好对齐“情商在线”微调更容易上手Base Model原始预训练模型“只有知识没有情商”适合高度定制场景模型规模参考任务场景推荐模型类型推荐规模意图识别、文本分类Instruct Model1B-7B智能客服FAQ/工单辅助Instruct Model7B-14B企业知识库问答/RAGInstruct Model7B-14B起步复杂场景14B-32BNL2SQLInstruct Model简单7B-14B复杂14B-32B边缘设备轻量部署Instruct Model0.5B-4B经验法则先从 7B/8B 的 Instruct Model 做基线实验不够再加。第二步数据准备公开数据集Hugging Face Hub数千个数据集按任务类型、语言筛选ModelScope阿里的模型开放平台覆盖NLP、CV、多模态私有数据企业内部文档产品手册、技术文档、会议纪要用户反馈与客服数据咨询、投诉、工单业务系统数据订单记录、交易流水、设备日志私有数据使用前需要清洗、结构化、标注可以用 Easy Dataset 等工具辅助。核心原则数据质量决定模型质量垃圾进垃圾出。第三步微调训练按训练目标分方法数据形式特点SFT监督微调指令-回答标准答案最基础学习标准答案DPO偏好对齐好答案 vs 差答案对比学习相对偏好关系RLHF人类反馈强化学习奖励模型强化学习流程最复杂效果最好按参数更新方式分全参数微调更新所有参数训练自由度最高但资源消耗也最大参数高效微调PEFT仅更新少量参数显著降低资源消耗。代表方法LoRA、QLoRA第四步模型验证不光看训练 loss 有没有降还要在验证集上测指标用真实案例做推理测试同时评估任务能力和通用能力避免偏科发现过拟合、指令跟随能力不足、回答质量不稳定等问题4.3 微调实现手写 SFT 和 DPO4.3.1 SFT监督微调目标把 Qwen3-0.6B-Base 微调成能遵循人类指令、进行多轮对话的模型。数据HuggingFaceH4/ultrachat_200k多轮对话数据集数据处理关键点1. Chat Template对话模板模型不直接看你一句我一句的对话而是要转成固定格式。tokenizer 自带的apply_chat_template方法可以把对话列表转成模型能理解的文本。推理时同样需要用 chat template 封装输入消息让模型基于预测下一个 token的方式实现多轮对话。2. Assistant Answer 掩码最关键的区别SFT 和预训练最本质的区别SFT 只对 assistant 回答部分计算损失不对用户输入的 prompt 部分计算损失。为什么因为 SFT 的目的是教模型如何回答而不是教它如何提问。如果对 prompt 部分也计算损失模型就会浪费精力去学怎么生成用户的问题这不是我们想要的。实现方式构造一个与 input_ids 同形状的掩码矩阵找到 assistant 回答的起止位置将对应位置设为1其余为0。损失计算SFT 的训练目标是在给定 prompt 的前提下让模型输出更接近训练数据中的标准答案。数学上就是最大似然估计Loss -1/N * Σ log P(target_token | previous_tokens)取对数将乘法变加法加负号将最大化变最小化除以 token 数取平均。训练流程张量准备遍历数据对 input_ids 进行 padding构建 input_ids 和 labels前向传播输入模型获取 logits损失计算用掩码只计算 assistant 部分的损失反向传播计算梯度参数更新用 AdamW 优化器更新参数训练中还使用了余弦衰减学习率和warmup策略前几步学习率从小逐渐增大warmup之后按余弦曲线逐渐减小到最小值SFT 存在的问题灾难性遗忘如果训练轮次过多、学习率过高、或数据规模小且分布单一模型可能过度拟合微调数据导致通用能力下降。这叫灾难性遗忘。解决方案控制训练轮次1-2个epoch结合验证集做早停构造混合数据除任务数据外混入通用能力数据同时评估任务能力和通用能力避免只优化特定任务4.3.2 DPO直接偏好优化核心思想不需要单独训练奖励模型也不用强化学习直接利用优答 vs 差答的偏好数据训练模型。DPO 的数据格式一条 DPO 样本由三部分组成prompt用户问题或上下文chosen更符合人类偏好的回答好的rejected质量较低的回答差的数据的核心不在绝对正确而在相对偏好是否清晰。DPO 损失函数的核心逻辑当前模型对 chosen 的对数概率 - 对 rejected 的对数概率 偏好差值参考模型ref_model对 chosen 和 rejected 的偏好差值 基线差值DPO 损失 -log(sigmoid(beta * (当前偏好差值 - 基线差值)))为什么要引入参考模型给训练提供稳定基线。DPO 不只是要求模型更喜欢 chosen而是要求它比参考模型更明显地喜欢 chosen这样既能利用偏好数据优化又能保持原有模型的语言能力和输出风格。训练流程与 SFT 的区别需要加载两个模型训练模型 参考模型参考模型只做前向传播no_grad不更新参数每个 batch 需要分别计算 chosen 和 rejected 的前向传播4.4 微调中的工程问题4.4.1 显存消耗构成微调时显存主要由五部分消耗组成部分说明占比模型参数所有可训练权重参数量 × 每参数字节数梯度反向传播产生的梯度与参数量相当优化器状态AdamW 的一阶矩二阶矩约参数量的 8 倍FP32激活值前向传播的中间结果与 batch_size × seq_len × hidden_dim 相关其他开销CUDA 内核临时内存等较小重点优化器状态是显存消耗的大头AdamW 为每个参数维护两个状态变量一阶矩和二阶矩都用 FP32 存储所以是参数量的 8 倍。4.4.2 单 GPU 训练优化1. 梯度累积Gradient Accumulation显存不够放大的 batch那就把大 batch 拆成多个小 batch每个小 batch 做完前向反向后先不更新参数等多个小 batch 都算完了再一起更新。例如batch_size4, gradient_accumulation3 → 等价于 batch_size122. CPU 卸载CPU Offload把暂时不用的数据从 GPU 显存搬到 CPU 内存需要时再搬回来。用传输开销换显存空间。3. 梯度检查点Gradient Checkpointing前向传播时不保存所有中间结果只保存少数检查点。反向传播需要时再重新算一遍。以时间换空间。4. 混合精度训练Mixed Precision Training核心思想尽可能用低精度FP16/BF16做计算只在关键步骤用高精度FP32保稳定。类型精度特点Float161510位所有GPU支持但数值范围小Float321823位范围大最稳定BFloat16187位范围等同FP32仅Ampere及以上GPU支持训练时维护两份权重FP32 主权重用于参数更新 FP16/BF16 工作权重用于计算。5. 其他优化FlashAttention优化 attention 计算效率Liger Kernel优化 LLM 训练的多个算子4.4.3 多 GPU 训练与分布式优化1. 数据并行Data Parallelism每张 GPU 放一份完整模型副本各 GPU 处理不同数据子集算完后AllReduce 汇总梯度各 GPU 用相同梯度更新参数。优点提升训练吞吐量。缺点每张卡都要存完整模型显存浪费。2. 流水线并行Pipeline Parallelism把模型按层纵向切分不同层放不同 GPU。前向从第一个 GPU 逐级传到最后一个反向则反过来。问题GPU 之间有气泡等待时间。解决方案引入微批次Micro-batches和流水线调度策略让 GPU 尽量不闲着。3. 张量并行Tensor Parallelism把单层内的权重矩阵切分到多张 GPU 上每张卡只算一部分矩阵乘法最后通信聚合结果。适合单层参数量特别大的情况。4. 专家并行Expert Parallelism专门针对 MoE 模型把不同专家分配到不同 GPU 上天然适合并行。5. ZeROZero Redundancy Optimizer对数据并行的深度增强。核心思想分片存储、按需加载。三个逐级递进的阶段阶段分片内容显存节省通信开销ZeRO-1优化器状态中等较小ZeRO-2优化器状态 梯度较大中等ZeRO-3优化器状态 梯度 模型参数最大较大阶段越高单卡显存占用越低但通信成本上升。可根据硬件资源灵活选择。4.4.4 参数高效微调PEFTLoRALow-Rank Adaptation核心思想微调时不要更新原始权重 W而是学一个低秩增量矩阵BA其中 B 和 A 的维度远小于 W。W W ΔW W α * B × A 其中 rank r 远小于原始维度 d为什么有效作者观察到微调时的权重变化 ΔW 往往具有低秩结构——有效自由度远低于表面维度。所以可以用两个小矩阵的乘积来近似。参数量对比全参数微调4096×4096 16M 个参数LoRAr84096×8 8×4096 65536 个参数仅占0.4%插入位置通常插入注意力层的q_proj和v_proj因为 Query 和 Value 对任务语义最敏感且仅插这两处就能接近全参微调性能。关键工程组件缩放系数 alpha控制 LoRA 增量在训练初期的影响力通常设 alpha rLoRA Dropout对 LoRA 层输入做 dropout防止过拟合推理时低秩增量可以无缝合并回原始权重不引入额外计算开销。QLoRAQuantized LoRA核心思想先对预训练模型做 4-bit 量化压缩显存再在其上应用 LoRA 微调。三大关键技术1. NF44-bit NormalFloat量化大模型权重近似正态分布中间密、两头稀。传统均匀量化在中间精度不够、两头浪费。NF4 按正态分布的累积概率均分15个区间中间密两头疏完美匹配权重分布。2. 双重量化Double Quantization每64个权重共享一个 FP32 缩放因子这些缩放因子本身也占空间。双重量化就是对这些缩放因子再做一次 8-bit 量化进一步省空间。3. 分页优化器Paged Optimizer把优化器状态拆成小块按需加载/卸载。显存只容纳当前正在使用的部分。效果数十亿参数的模型可以在单张消费级 GPU如 RTX 3090/4090上完成微调。4.5 基于库的微调实现工具库一览库作用开发组织TRL封装了 SFT/DPO/PPO 等 TrainerHugging FacePEFT参数高效微调方法LoRA、P-Tuning等Hugging FaceBitsandbytes模型量化结合 PEFT 做 QLoRAHugging FaceUnsloth底层训练加速降低显存占用和时间UnslothAccelerate分布式训练与 TRL 高度集成Hugging FaceLLaMA-Factory可视化界面微调兼容多种模型和算法个人开发者4.5.1 TRLSFT 全参微调TRL 的 SFTTrainer 封装了整个微调流程。使用步骤准备数据转成 TRL 要求的格式LanguageModeling 类型或对话格式配置SFTConfig学习率、batch_size、epoch 数等创建SFTTrainer传入 model、tokenizer、数据集、配置调用trainer.train()训练调用trainer.save_model()保存TRL 支持多种数据格式标准格式、对话格式和数据类型LanguageModeling、Prompt-only、Preference 等。4.5.2 PEFTSFT-LoRA 微调在 TRL 基础上加 LoRA只需三步frompeftimportLoraConfig,get_peft_model peft_configLoraConfig(r4,lora_alpha8,lora_dropout0.05,biasnone,target_modulesall-linear,task_typeCAUSAL_LM)lora_modelget_peft_model(model,peft_config)# 然后把 lora_model 传给 SFTTrainer 即可训练完成后用peft_model.merge_and_unload()将 LoRA 权重合并回基座模型。4.5.3 BitsandbytesQLoRA 微调fromtransformersimportBitsAndBytesConfigfrompeftimportprepare_model_for_kbit_training quantization_configBitsAndBytesConfig(load_in_4bitTrue,bnb_4bit_quant_typenf4,bnb_4bit_use_double_quantTrue,bnb_4bit_compute_dtypetorch.bfloat16,)modelAutoModelForCausalLM.from_pretrained(model_name,quantization_configquantization_config)modelprepare_model_for_kbit_training(model)# 后续与 LoRA 微调一致4.5.4 Unsloth加速微调Unsloth 的核心价值同样的训练流程跑得更快、更省显存。通过手动优化反向传播把关键模块改写成 Triton 内核TRL 负责训练范式Unsloth 负责加速落地提供FastLanguageModel加载模型train_on_responses_only设置只对 assistant 回答计算损失支持一键导出合并模型model.save_pretrained_merged()4.5.5 Accelerate分布式训练通过accelerate config交互式配置分布式环境GPU 数量、DeepSpeed 阶段、混合精度等然后用accelerate launch train.py启动多卡训练。训练脚本本身不需要任何修改。使用 ZeRO-3 微调后如果zero3_save_16bit_modelFalse需要手动合并多卡参数python zero_to_fp32.py././full_params--safe_serialization4.5.6 LLaMA-Factory可视化微调零代码微调平台通过 Web UI 完成git clone下载源码安装依赖llamafactory-cli webui启动可视化界面配置模型路径、LoRA 参数、训练轮数、输出目录一键训练一键导出合并模型支持 Alpaca 和 ShareGPT 两种数据格式兼容上百种预训练模型。核心知识点速查表知识点关键内容SFT vs 预训练SFT 只对 assistant 部分计算损失DPO vs SFTDPO 学习相对偏好需要 chosen/rejected 成对数据灾难性遗忘控制轮次、混合数据、双维度评估显存消耗大头优化器状态 模型参数 梯度单卡优化梯度累积、CPU卸载、梯度检查点、混合精度分布式数据并行、流水线并行、张量并行、专家并行、ZeROLoRA低秩分解 ΔWBA只训练 B 和 A推理时合并QLoRA4-bit NF4量化 LoRA消费级GPU可跑SwiGLUFFN 双分支门控结构当前主流MoE多专家稀疏激活高容量低计算全章一句话总结LLM 微调的核心流程是选模型→备数据→训练→验证。SFT 学标准答案DPO 学偏好对比。工程上通过 LoRA/QLoRA 降低门槛通过分布式训练扩展规模。