大模型微调实战:从 SFT 到 RLHF/DPO,如何用单卡炼出“听话”的 AI?
目录
- 微调概述
- 监督微调 SFT
- 人类反馈强化学习 RLHF
- 直接偏好优化 DPO
- 方法对比与选型
- 微调工程实践
- 实践建议与最佳实践
摘要
本文拆解 SFT、RLHF 与 DPO 三条微调路线的原理、实现、成本与选型依据。SFT 以 1K 到 100K 条示范数据建立指令遵循能力,RLHF 用奖励模型加 PPO 逼近人类偏好,DPO 以闭式损失在同等偏好数据上达到 RLHF 约 95% 的效果。一个 7B 模型的 LoRA 微调可在单卡 24GB 显存上完成,SFT 约 3 到 10 小时,DPO 约 1 到 2 天,RLHF 完整流程需要 4 到 8 张 A100 运行数天。
1. 微调概述
1.1 微调的必要性
预训练通过自回归目标让模型吸收海量文本中的语言结构与世界知识,目标是学会预测下一个词。基座模型在续写任务上表现优秀,却不会主动遵循指令,也不会按对话格式输出。微调解决的是分布迁移问题,把续写分布拉向指令响应分布。
预训练的成本极高。以 LLaMA-2 的 7B 模型为例,训练语料约 2 万亿 token,按前向与反向合计约 6 倍参数量乘 token 数估算,浮点运算量约 8.4e22。相比之下,SFT 阶段的数据量通常只有数千万 token,成本比预训练低三到四个数量级,这决定了微调是绝大多数团队实际能触及的环节。
微调的杠杆效应在 InstructGPT 的实验中最直接。Ouyang 等人 2022 年的报告显示,1.3B 参数的 RLHF 模型在人类偏好评估中以约 72% 的胜率击败 175B 的 SFT 模型。模型尺寸不再是决定对话质量的第一变量,训练方法的权重被显著放大。
从能力维度看,预训练提供事实记忆、推理基元与语法能力,微调负责把这三者组织成可用的行为。GSM8K 上的典型曲线是,基座 7B 模型直接作答的准确率不足 15%,加入 SFT 后提升到 40% 以上,叠加思维链数据后可以超过 50%。这组数据说明微调激活的是预训练阶段已经沉淀的能力,而不是凭空注入新知识。
微调的必要性还来自评估口径的变化。预训练用困惑度衡量,而困惑度下降与指令遵循能力之间没有稳定的映射关系。生产系统关心的是遵循率、安全拒绝率与格式正确率,这些指标必须由微调阶段直接优化。
工程上的分工同样清晰。预训练通常需要大规模集群与昂贵的数据管线,微调则可以在单卡到数卡的环境内完成。一个 7B 模型以 LoRA 方式做 SFT 仅需一块 24GB 显存的 GPU,而预训练该模型所需的资源是其数百倍。时效上,预训练一次动辄数月,微调以天为周期,可以在模型能力与业务需求之间快速对齐。
上图给出完整流水线:预训练产出基座,SFT 建立指令遵循能力,RLHF 或 DPO 完成偏好对齐,评估门禁决定是否交付生产。三个数据阶段的数据量级依次递减,单条数据的技术含量却依次递增。
对齐税是理解必要性的必修课。对齐过程会轻微牺牲知识基准分,换取更高的偏好胜率,这种权衡在预训练阶段不存在。部分模型在 SFT 加 DPO 后,MMLU 相对基座下降 1 到 3 个百分点,而偏好胜率上升 10 个百分点以上。换算到单位收益,对齐的性价比依然显著高于纯预训练扩展。
微调不是所有问题的答案。指令足够简单时,零样本提示与上下文学习就够用,强行微调反而引入过拟合风险。判断是否需要微调的标准是错误代价,格式与领域术语错误容忍度低的场景才值得投入微调。基座模型的选择同样属于定位问题,开源基座意味着微调可完全自控,闭源 API 模型只能通过提示词间接影响行为。
1.2 微调的挑战
微调的第一类挑战是灾难性遗忘。微调数据分布与预训练差异大时,模型会迅速遗忘通用能力,典型表现是数学题与知识问答明显变差。缓解手段包括降低学习率、混合预训练语料以及限制训练时长,7B 模型上把 epoch 控制在 3 以内是最常见的起点。
第二类挑战是对齐税。偏好对齐在提升对话质量的同时,可能让 MMLU 类知识基准下降 1 到 3 个百分点。对齐税无法消除,只能通过 KL 约束与数据配比控制其幅度,评估时必须把知识与偏好分开看,不能笼统归因于微调失败。
第三类挑战是数据质量。偏好数据的标注一致性通常要求达到 80% 以上,低于 70% 的批次会显著拖低奖励模型准确率与 DPO 收敛质量。标注风格漂移是隐蔽问题,一致性会随标注者疲劳与任务复杂度变化,需要持续监控。
第四类挑战是奖励黑客。RLHF 阶段模型会学会刷奖励分数而产出语法正确但语义空洞的文本,根因是 KL 约束不足或奖励模型存在可钻漏洞。Gao 等人 2022 年的研究显示,奖励分数随优化步数持续上升,但真实人类偏好会在某个临界点后下降,两者出现剪刀差。
第五类挑战是资源预算。全量微调 7B 模型在 Adam 优化器下,模型、梯度与优化器状态合计超过 80GB,单卡 A100 80GB 才勉强容纳。LoRA 只更新低秩适配器,基座 14GB 即可在 fp16 下驻留,加上适配器与激活值后,24GB 显存的消费级 GPU 也能完成训练。
第六类挑战是复现性。多卡训练时数据顺序、dropout 与优化器状态都影响结果,只固定 torch 的随机种子远远不够,需要同时固定数据集顺序、流水线并行种子与评估时的温度采样种子。
微调挑战的类型可以汇总为下表:
| 挑战 | 典型表现 | 量化参考 | 缓解手段 |
|---|---|---|---|
| 灾难性遗忘 | 基准分骤降 | MMLU 下降 1 到 3 分 | 混合预训练语料、低学习率 |
| 对齐税 | 知识与偏好背离 | 偏好胜率上升 10 分以上 | KL 约束、数据配比 |
| 数据噪声 | 收敛质量差 | 一致性低于 70% | 一致性过滤、抽检返工 |
| 奖励黑客 | 输出空洞冗长 | KL 散度超出预算 | 监控 KL 与响应长度 |
| 显存不足 | 训练无法启动 | 全量 7B 超 80GB | LoRA、梯度检查点 |
| 不可复现 | 同配置结果漂移 | 种子间胜率差 3 到 5 分 | 固定全部随机源 |
表中量化参考是社区公开实践与论文报告中的常见区间,用于建立预期。实际项目应先跑小规模实验确认某个挑战是否突出,再决定治理投入,避免一次性全量治理的浪费。
第七类挑战是标注与评估成本。一条人工偏好标注的价格在数美分到数美元之间,而偏好数据需要数千到数万条,医学与法律领域单条标注可达 1 美元以上。标注预算不足时,RLAIF 这类基于 AI 反馈的路线值得考虑,但需要抽检对冲系统偏差。
第八类挑战是推理侧约束。量化与推理框架会改变输出分布,训练用 bf16 混合精度,推理用 fp16 或 INT8 量化,输出分布偏移在格式遵循上表现明显。量化前要在同一评估集上跑一致性对照,偏差超标则调整量化方案,INT4 量化后显存可从 16GB 降至 4GB。
挑战之间还会互相放大。数据噪声会加剧奖励黑客的探测空间,显存不足会压缩 batch 而提高梯度方差,评估集与训练集同源会掩盖前两类问题。排查时按数据、训练、评估三层归因,逐层下钻,比一次性怀疑所有环节更高效。
预算约束是挑战的最终上限。显存预算决定参数更新方式,训练时长预算决定方法选择,标注预算决定数据质量。预算估算的意义不在于精确预测,而在于快速排除不可行方案,例如在单卡环境下规划全量 RLHF。
第九类挑战是模板一致性。训练用模板 A、评估用模板 B 时,格式遵循率会虚低,被误判为训练失败。模板必须全局唯一配置,训练与评估从同一配置读取,禁止两处手写模板字符串。多轮对话的模板更复杂,历史轮次与分隔符的拼接顺序出错会直接破坏上下文。
第十类挑战是评测污染。用模型评估模型时,judge 对冗长回答与位置顺序有系统性偏好,胜率虚高。对策是盲评、顺序打乱与长度控制,必要时对 judge 的评估结果做人工抽检校准。评测数据混入训练集同样危险,换分布后模型提升立刻现形。
挑战清单的维护责任要落到人。每条挑战记录现象、根因与修复,沉淀成清单,新的训练项目启动时逐条对照。多数踩坑属于已知清单,复盘机制的价值在于让团队只踩一次同一个坑。
多轮退化是对话模型的专属挑战。单轮 SFT 数据训练出的模型在多轮对话中上下文混乱,历史轮次被当成新指令处理。对策是混入合成多轮数据,把历史轮次作为上下文的一部分参与训练与评估,多轮评估集应单独构建,不要用单轮结果外推。
检查点损坏与回滚失败属于运维侧挑战。训练中断后检查点可能半写入,加载时报错或静默损坏。对策是原子写入加校验和,加载时验证张量形状与损失连续性,回滚演练应定期执行。训练与推理的精度不一致也会放大问题,量化前要在同一评估集上跑一致性对照。
长尾与分布漂移属于数据侧挑战。训练分布与线上分布不一致时,模型在分布外提示上的行为不可控,通常表现为拒绝率骤升或语气突变。缓解手段是在数据构造阶段混合线上采样提示,并在上线两周后重新抽样评估一次,把漂移数据纳入下一轮样本池。
上下文长度预算是推理侧与训练侧共有的约束。7B 模型在 4096 长度下训练,激活值与 KV cache 占用明显上升,batch 被迫缩小。长度与 batch 的权衡应按显存余量动态调整,超出硬件预算时优先压缩长度而不是压缩数据质量。
算力利用率是最后一类约束。分布式训练的理论吞吐乘以 MFU 才是实际产出,MFU 通常只有 30% 到 50%,通信与数据加载会吃掉一半以上算力。预算估算必须按实际 MFU 打折,否则工期排期会普遍低估一到两倍。
挑战的应对顺序建议按投入产出排序:先修数据质量,再锁模板与评估口径,然后调训练配置,最后才考虑换方法。顺序颠倒时,多数调参投入会被数据或评估问题抵消,这一判断来自一线项目的复盘数据:约 40% 的微调返工源于数据问题被误判为训练问题。因此排查应遵循"先数据、再评估、后训练"的固定顺序,把最常见且最便宜的根因先排除。
挑战的量化影响:数据质量问题可使指令遵循准确率下降 10 到 20 个百分点,评估口径不一致会让两次实验的对比结论反转,训练配置不当则表现为收敛慢或过拟合。三类挑战的修复成本差异显著:数据清洗约 5 到 10 人天,评估体系搭建约 10 到 20 人天,训练调参约 3 到 5 人天。按成本排序投入,先做收益高成本低的修复项。
挑战管理的团队协作:数据、评估与训练三块责任归属明确,数据问题由数据团队负责,评估口径由评估负责人维护,训练配置由训练工程师调优。问题跨领域时需要三方联调,联调会议按周固定排期,避免问题在团队间推诿。挑战清单按季度评审,识别新挑战并评估缓解措施的落地情况。
1.3 方法分类
微调方法按优化信号分为两类:基于示范数据的监督学习,以及基于偏好数据的对齐优化。SFT 属于前者,RLHF 与 DPO 属于后者。示范数据告诉模型应该怎么说,偏好数据告诉模型哪个回答更好,两者解决的是不同层面的问题。
时间线上,SFT 的方法论来自 2022 年的 InstructGPT 工作,它证明了几千条人工示范就能把基座模型转化为可用的指令模型。RLHF 的雏形可追溯到 2017 年 Christiano 等人的偏好强化学习工作,在 2022 年与 InstructGPT 结合后成为对话模型的标准管线。DPO 由 Rafailov 等人在 2023 年提出,把偏好优化压缩为单阶段监督式训练。
RLHF 与 DPO 的关系常被误读为新旧替代,实际是同一目标的两条实现路线。RLHF 显式训练奖励模型,再用 PPO 优化策略;DPO 从 Bradley-Terry 模型出发,把最优策略的闭式解代回偏好损失,绕开了奖励模型与强化学习循环。两者共享同一套偏好假设,数学联系在论文中有完整推导。
DPO 之后涌现了一批变体。IPO 弱化了对参考模型的依赖,KTO 支持无配对数据,ORPO 把 SFT 与偏好优化合并为单阶段,SimPO 同时去掉参考模型与长度归一化,GRPO 在组内归一化奖励并用于数学推理对齐。这些变体并非都要取代 DPO,而是针对 DPO 的已知弱点做修补。
各方法的适用边界可以用下表概括:
| 方法 | 优化信号 | 代表工作 | 提出年份 | 数据量级 |
|---|---|---|---|---|
| SFT | 示范对 | InstructGPT | 2022 | 1K-100K 条 |
| RLHF | 偏好对加奖励模型 | InstructGPT、LLaMA-2 | 2022-2023 | 1K-10K 对 |
| DPO | 偏好对 | Direct Preference Optimization | 2023 | 1K-10K 对 |
| ORPO | 偏好对单阶段 | ORPO | 2024 | 1K-10K 对 |
表中数据量级是社区实践的常见区间。SFT 数据规模弹性最大,几十万条与几千条都有成功案例,差异体现在任务覆盖面上。偏好数据规模相对收敛,因为人工标注成本限制了上限。
选择方法前先分清目标。仅需提升任务能力时 SFT 足够,需要调整语气、拒绝策略与价值观倾向时再引入偏好优化。把偏好方法当作万能药,在数据量不足时往往得到比纯 SFT 更差的结果。
# 来源:自实现 / method_taxonomy.pydefclassify_method(method):taxonomy={"sft":{"signal":"demonstration","stage":1,"requires_rm":False},"rlhf":{"signal":"preference","stage":3,"requires_rm":True},"dpo":{"signal":"preference","stage":2,"requires_rm":False},}returntaxonomy.get(method,None)deftraining_flops(num_params,num_tokens):# 前向与反向合计约 6 倍参数量乘训练 token 数return6.0*num_params*num_tokensif__name__=="__main__":formin["sft","rlhf","dpo"]:info=classify_method(m)print(m,info["stage"],"requires_rm:",info["requires_rm"])flops=training_flops(7_000_000_000,100_000_000_000)print("7B 模型训练 100 亿 token 的浮点运算量:",flops)classify_method 用于快速核对方法的阶段数与是否依赖奖励模型,stage 与 requires_rm 两个字段足以筛掉一批不匹配的候选。training_flops 给出统一的算力估算公式,工程上用于在开工前排除不可行方案,例如在单卡环境下规划全量 RLHF。
方法谱系的成熟度差异也值得注意。SFT 的工程生态最完整,工具链与数据集最丰富,几乎任何框架都能直接跑通。RLHF 的成熟度次之,主流框架均提供奖励模型与 PPO 的参考实现,但调参经验仍分散在论文与博客中。DPO 的生态发展最快,两年内出现了大量变体与支持库。
判断新方法是否值得跟进,可以看三个信号:是否有可复现的官方实现、是否在多个独立基准上复现、是否解决了已知方法的可量化短板。缺少任一信号时,观望是比冒险更理性的选择。
2. 监督微调 SFT
2.1 SFT 原理
SFT 的优化目标是从示范数据中学习条件分布。每个训练样本由指令与回答拼接而成,模型只在回答部分计算损失,指令部分的 token 不参与梯度更新。这个只对回答计损的设计是 SFT 与预训练在工程实现上的核心差异。
从原理上看,损失函数仍是标准的自回归交叉熵,但掩码改变了其作用域。若不对指令部分掩码,模型会学习到预测指令的下一个词,这既浪费算力,还会把指令分布的错误知识注入参数。实践中,回答 token 的占比通常在 40% 到 70% 之间,取决于指令的长度。
掩码的构造依赖分词器的输出结构。指令与回答通常以特殊分隔符拼接,例如 LLaMA 对话模板中的分隔标记。答案从分隔符之后开始,掩码从分隔符后的第一个 token 置 1,其余保持 0。拼接后按最大长度截断,过长的样本应整体丢弃而非硬截断,否则答案尾部会丢失监督信号。
损失计算有两个实现细节。其一,标签需要整体右移一位,位置 t 的预测目标是对位置 t+1 的 token,掩码也要同步右移。其二,归一化分母应使用掩码和而不是序列长度,否则 batch 内长短样本的损失尺度不一致,互相干扰。
学习率的选择对 SFT 影响显著。全量微调常用的峰值学习率在 2e-5 到 3e-5,LoRA 微调则提高一个量级,常见区间为 1e-4 到 2e-4。学习率过大会导致指令遵循能力上升但通用能力快速退化,过小则新知识注入不足,验证集遵循率长期停滞。
SFT 的 epoch 数通常控制在 1 到 3。与预训练的重看不同,SFT 数据量小且质量高,多 epoch 复读会让模型记住训练样本的措辞,在验证集上表现为模板化的重复输出。社区实践中,1 到 2 个 epoch 加早停是出现频率最高的组合。