前言

在上一篇文章中,我完成了 SFT(监督微调)阶段。通过 523 条高质量指令数据,模型学会了如何组织完整、结构化的回答——至少在部分问题上表现惊艳。

按照三段式微调的蓝图,接下来是 DPO(直接偏好优化) 阶段。目标很清晰:让模型的回答更符合人类的偏好——更专业、更准确、更安全。

然而,这次 DPO 训练的结果却给了我当头一棒:模型不仅没有变得更好,反而在多个问题上出现了深度倒退,整体趋向平庸。

本文将完整记录我从 偏好数据构建DPO 训练 到 四级模型评估 的全过程,并重点复盘这次“翻车”背后的根因。希望能给同样在消费级显卡上折腾大模型的朋友们一些真实的参考——失败的经验往往比成功更有价值。


一、DPO 偏好数据构建:74 条“黄金样本”的诞生

DPO 的核心是偏好数据:对于同一个问题,需要提供一个“优选回答(chosen)”和一个“劣选回答(rejected)”。模型通过最大化两者之间的概率差异来学习人类偏好。

1.1 构建流程

步骤 具体操作 产出
1. 抽取 prompt 从 SFT 数据集 storage_sft_final.jsonl 中随机抽取 100 条 instruction dpo_prompts.txt
2. 生成候选回答 用 SFT 模型对每个 prompt 生成 2~3 个候选回答,使用不同温度参数(0.7、1.0、1.3)增加多样性 dpo_candidates.jsonl
3. 自动标注偏好 调用阿里云百炼 qwen3-vl-flash API,根据“专业性、安全性、完整性”三个维度标注出最优和最差回答 dpo_data.jsonl(100 条)
4. 数据清洗 人工抽检 + 规则过滤(领域相关性、回答长度、敷衍词等) dpo_data_clean.jsonl(74 条)

1.2 清洗策略

我们使用了保守的清洗策略,只剔除明显不合格的样本:

  • JSON 格式错误

  • chosen 或 rejected 长度过短(<20 字符)

  • 问题与存储领域明显无关(如涉及版权、商标、Ubuntu 系统操作等)

最终从 100 条中保留了 74 条,剔除 26 条。事后复盘,这个数量和清洗策略埋下了隐患。

1.3 数据样例

json

{
  "prompt": "在NVM子系统擦除操作中,主机如何通过Sanitize命令启动不同类型的擦除?",
  "chosen": "根据NVM Express® Base Specification Revision 2.3,Sanitize命令(命令22h)用于在NVM子系统擦除操作中...",
  "rejected": "在NVM Subsystem中的Erasure Operation(擦除操作),主机通过执行特定的Sanitize命令来控制不同类型的擦除行为..."
}
可以看到,

chosen 回答包含了具体的命令号、擦除类型枚举,而 rejected 回答则相对笼统。这种差异是 DPO 希望学习的信号。


二、DPO 训练:2 分钟的“快速对齐”

2.1 训练配置

为了节省显存,我选择了 ORPO 损失函数,它无需独立的参考模型,能在单卡上直接训练。

配置项 说明
基座模型 Qwen3-4B-Instruct
检查点路径 SFT LoRA 权重 在指令微调基础上对齐
训练阶段 dpo
损失函数 orpo 无需参考模型
pref_beta 0.1 控制偏离程度
学习率 5e-7 DPO 学习率极低
训练轮数 1 epoch 74 条数据,约 10 步
批处理大小 1 × 梯度累积 8 等效 batch=8

2.2 训练过程

训练异常快速,仅用约 2 分钟就完成了 1 个 epoch。

Loss 曲线

Loss 从 1.086 微降至 1.072,降幅极小。这是 DPO 在小数据集上的典型表现——它本身是微调过程,loss 大幅下降反而意味着过拟合。

Rewards Accuracy 曲线

准确率从 0.83 降至 0.59。这看起来像是“退步”,但实际上是 DPO 生效的信号——模型不再一味模仿 chosen,而是学会了在 chosen 和 rejected 之间权衡。同时,日志显示 chosen 的奖励始终高于 rejected,证明偏好信号成功注入。


三、四级模型统一评估:期望与现实的落差

3.1 评估方案

为了公平对比,我重新设计了评估方案:

  • 将 max_new_tokens 统一调大到 1024,确保回答完整输出

  • 固定温度、top_p、随机种子等生成参数

  • 对 基座、CPT、SFT、DPO 四个模型,用相同的 5 道存储核心测试题 重新生成回答

3.2 四级模型表现速览

模型 核心特点 最佳表现 核心问题
基座 领域知识扎实,回答完整 全部问题均有不错表现 风格偏文档,结构不够精炼
CPT 术语最专业、深度最深 QLC、OP 问题分析最透彻 回答偏长,部分截断
SFT 结构化能力最强(局部) NVMe 问题堪称典范 灾难性遗忘,V-NAND/OP 严重敷衍
DPO 中庸的平衡者 无明显突出 深度不足,结构平庸

3.3 典型回答对比

案例一:FusionStorage 融合架构

CPT 模型回答(节选)

FusionStorage 8.0 的融合架构主要体现在:1. 硬件与软件深度融合... 2. 分布式架构与高可用融合... 3. 资源池化与弹性扩展融合... 4. 管理与运维融合... 5. 多业务场景融合支持... 6. 高并发与低延迟融合...

SFT 模型回答(节选)

FusionStorage 8.0 的融合架构主要体现在以下方面:① 硬件融合... ② 软件融合... ③ 服务融合... 这三者共同构建了高效、灵活、可扩展的融合架构。

DPO 模型回答(节选)

FusionStorage 8.0 的融合架构主要体现在以下三个方面:1. 融合存储资源... 2. 融合服务架构... 3. 融合业务场景...

从 CPT 的六个维度,到 SFT 的三个维度高度归纳,再到 DPO 的三个维度泛化表述,深度层层递减。

案例二:预留空间(OP)
  • CPT 模型:详细分析了 OP 对写放大、垃圾回收效率的影响,给出了最佳 OP 区间建议,甚至补充了“OP 过高带来的成本与空间浪费”这一工程权衡视角。

  • SFT 模型:仅用一段笼统的话概括,严重敷衍。

  • DPO 模型:比 SFT 稍详细,但深度仍远不如 CPT。

DPO 似乎成了“中庸的平衡者”——它部分纠正了 SFT 的敷衍,却未能恢复 CPT 的深度,也未能保持 SFT 的结构化优势。


四、踩坑复盘:三个核心问题的根因分析

坑一:SFT 模型的选择性灾难性遗忘

现象:SFT 在 NVMe 问题上结构化飞跃,但在 V-NAND、OP 等主题上回答长度和深度断崖式下跌。

根因

  1. SFT 数据长度分布不均衡:自动生成的数据中,不同主题的回答长度差异显著,模型学会了“主题-长度”的隐性映射。

  2. 主题覆盖不全:SFT 数据过度集中于 NVMe 相关主题,V-NAND、OP 等样本稀缺。

  3. 缺乏“强制详述”样本:未在指令中显式要求模型在薄弱主题上输出详尽回答。

坑二:DPO 模型的效果倒退与中庸化

现象:DPO 在多个问题上深度和结构均不如 SFT,整体趋向平庸。

根因

  1. 偏好数据量过小:74 条对于稳定对齐处于临界值。

  2. 标注噪声:API 自动标注未经全面人工复核,存在 chosen/rejected 差异不显著的样本。

  3. 主题覆盖与 SFT 不匹配:偏好数据 prompt 过度集中于 NVMe 细节,V-NAND、OP 等薄弱主题几乎缺失。

  4. ORPO 在小数据集上过拟合pref_beta=0.1 对于 74 条数据仍偏小,导致过度调整。

坑三:评估体系滞后与不完整

现象:直到全部训练完成后才发现 SFT 和 DPO 的问题,错失中途纠偏机会。

根因

  1. 缺少分阶段评估:SFT 完成后未立即用标准测试题评估,直接进入 DPO。

  2. 缺少验证集监控:训练时未预留验证集,无法实时发现过拟合或遗忘趋势。

  3. 评估指标单一:PPL 无法衡量结构化、完整性等生成质量维度。


五、优化方向:如果再来一次,我会怎么做

短期优化(可立即执行)

问题 优化措施 预期收益
SFT 选择性遗忘 针对薄弱主题人工补充 10~20 条“强制详述”样本,统一输出格式 恢复 V-NAND、OP 深度,结构化一致性提升
DPO 效果倒退 扩充偏好数据至 150~200 条,人工复核剔除噪声,补充薄弱主题偏好对 DPO 产生正向增益,安全性提升
评估体系 建立固定测试题的阶段评估机制,预留 10% 验证集 及时发现问题,避免事后补救

长期改进方向

  • 扩充 CPT 语料:增加 SNIA 白皮书、三星技术博客等更多权威文档,提升领域知识覆盖度。

  • 引入 RAG 评估:用检索增强生成的方式验证模型是否真正“理解”而非“背诵”。

  • 部署阶段优化:完成模型量化 + vLLM 推理加速,形成“训练→部署”完整闭环。


六、写在最后:失败是更真实的技术故事

这次 DPO 实验没有产生预期中的正向增益,反而暴露了数据工程、评估体系和训练流程中的多个短板。但正是这些“踩坑”经历,让我对三段式微调的理解从理论走向了实战。

我深刻认识到:

  • 数据质量决定模型上限:SFT 的长度分布不均衡、DPO 的标注噪声,是本次实验中两个最致命的短板。

  • 分阶段评估是不可或缺的工程质量保障:没有阶段评估,问题会累积到最后才暴露。

  • 小规模 DPO 对数据质量极度敏感:74 条噪声数据比没有数据更糟糕。

  • 坦诚面对失败比虚构成功更有说服力:这段经历恰恰证明了我具备完整的分析、定位和迭代能力。

如果你也在消费级显卡上尝试大模型微调,希望我的“翻车”经历能让你少走一些弯路。完整代码和数据集已整理到 GitHub,欢迎交流讨论。


附:DPO 阶段关键文件

text

~/KnowledgeForge/
├── dpo_candidates.jsonl         # SFT 模型生成的候选回答
├── dpo_data.jsonl               # API 自动标注的原始偏好数据(100 条)
├── dpo_data_clean.jsonl         # 清洗后的偏好数据(74 条)
├── dpo_config.yaml              # DPO 训练配置
├── eval_all_models_unified_1024.py  # 四级模型统一评估脚本
├── all_models_eval_unified_1024.json # 四级模型评估结果
└── checkpoints/dpo/             # DPO LoRA 权重
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐