Direct Preference Optimization (DPO)
为什么这篇论文重要
L4-01 / L6-02 我们讲过 RLHF 是怎么工作的—— 但它工程极复杂:
- 训奖励模型(reward model)
- PPO 强化学习
- 多个模型同时运行
- 不稳定,要调参
2023 年 Stanford 提出 DPO——
把 RLHF 简化成一个简单的交叉熵 loss。
不再需要:
- 奖励模型
- PPO 算法
- 复杂的训练 pipeline
效果接近 RLHF,工程简单 10×。
2023-2026 年,几乎所有开源 LLM 的对齐都用 DPO—— Llama 3、Mistral、Qwen、DeepSeek 都用。
核心思想
RLHF 的复杂流程:
偏好数据 → 训 reward model → PPO 优化主模型
DPO 的洞察:
数学上可以证明——RLHF 的最优解能直接用一个 closed-form loss 表达。
也就是:跳过中间的 reward model 和 PPO—— 直接从偏好数据训主模型。
损失函数
看着复杂——翻译一下:
- :偏好对里”赢”的回答
- :“输”的回答
- :当前训练的模型
- :原始 SFT 模型(不动)
- :超参数(约束当前模型不离原始太远)
意思:让主模型给”赢”回答的概率 比给”输”回答的高—— 带上对参考模型的约束。
一行代码总结
def dpo_loss(logits_w, logits_l, ref_logits_w, ref_logits_l, beta=0.1):
"""
logits_w: 当前模型对 winner 的 log prob
logits_l: 当前模型对 loser 的 log prob
ref_*: 参考模型的对应 log prob
"""
pi_logratios = logits_w - logits_l # 主模型偏好"赢"多少
ref_logratios = ref_logits_w - ref_logits_l # 参考模型偏好"赢"多少
return -F.logsigmoid(beta * (pi_logratios - ref_logratios)).mean()
就这一个公式—— 取代 RLHF 几百行的复杂训练流程。
实验结果
与 RLHF 对比
在 Anthropic HH 数据集上:
| 方法 | 胜率(vs SFT baseline) | 训练时间 |
|---|---|---|
| RLHF | 67% | 1× baseline |
| DPO | 66% | 0.1× baseline |
质量持平 + 训练快 10×。
在 GPT-4 Judge 评估上
| 模型 | 胜率 |
|---|---|
| SFT only | 50% |
| RLHF | 67% |
| DPO | 65% |
DPO 几乎等同 RLHF—— 但训练成本远低。
为什么 DPO 这么快
RLHF 的 PPO 训练要:
- 4 个模型同时在 GPU 上(policy、value、reward、reference)
- 每步生成新样本 → 算 reward → PPO 更新
- 不稳定,参数调起来麻烦
DPO 只要:
- 2 个模型(policy + reference)
- 静态偏好数据(不用生成)
- 标准监督学习
就像普通的 fine-tuning —— 远比 RL 简单。
论文之后
各种 DPO 变种
DPO 启发了一系列研究:
| 方法 | 改进 |
|---|---|
| DPO | 原版 |
| IPO(Identity Preference Optimization) | 避免过拟合 |
| KTO(Kahneman-Tversky Optimization) | 不需要偏好对,只需要”好/坏”标签 |
| ORPO(Odds Ratio PO) | 边 SFT 边对齐,一阶段 |
| SimPO | 不需要参考模型 |
| CPO(Contrastive PO) | 多对偏好 |
| APO(Anchored PO) | 防止退化 |
各家在 DPO 基础上找改进——整个”无 RL 对齐”领域被打开。
工业采用
2023 后期开始——几乎所有开源 LLM 用 DPO:
- Llama 3 —— SFT + DPO 流水线
- Mistral 系列 —— DPO
- Zephyr 7B —— 第一个广泛知名的纯 DPO 模型
- Qwen 2.5 —— DPO + 其它技巧
- DeepSeek V3 —— DPO 变种
- Mixtral Instruct —— DPO
开源生态选择 DPO —— RLHF 太贵,DPO 性价比高。
但是 OpenAI / Anthropic 仍用 RLHF
闭源大厂:
- OpenAI:仍用 RLHF(有钱、人力、且 PPO 经验积累)
- Anthropic:CAI + 各种方法混合
- Google:Gemini 也类似
他们的”质量上限” 可能 RLHF 略高—— 但开源生态的”性价比”是 DPO 赢。
几个反思
”RLHF 的本质是什么”
DPO 论文揭示了一个深刻的事实: RLHF 不是真的”reinforcement learning” —— 它本质是对一个特定 reward 函数的 supervised learning。
只是这个 reward 函数复杂——RLHF 需要先学它(reward model)然后优化。 DPO 直接 bypass 中间步骤。
类似数学上简化了一个复杂积分。
“RL 在 AI 里还有用吗”
DPO 让 RL 在 LLM 训练里地位下降—— 但 RL 在其它方向仍然关键:
- OpenAI o1 / o3 的推理训练(rule-based reward)
- AlphaGo 类应用
- 机器人控制
- 游戏 AI
不是 RL 没用——是 RLHF 的 RL 形式被简化了。
“DPO 是不是有缺陷”
是。研究者发现 DPO 的一些问题:
- 容易”过拟合偏好”——重复学训练数据
- 输出可能变啰嗦(偏好数据有 length bias)
- 在某些复杂任务上仍不如 RLHF
- 需要高质量偏好数据(垃圾进垃圾出)
后续变种(KTO、ORPO 等)部分解决—— 但 RLHF 时代的精细 polish 仍然有价值。
用代码做 DPO
HuggingFace TRL 库直接支持:
from trl import DPOTrainer
from transformers import AutoModelForCausalLM, AutoTokenizer
from datasets import Dataset
# 加载模型
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3-8B-SFT")
ref_model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3-8B-SFT") # 同样的 SFT 模型作为 reference
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3-8B-SFT")
# 偏好数据
dataset = Dataset.from_dict({
"prompt": ["What is 2+2?", "Explain gravity"],
"chosen": ["2+2=4", "Gravity is the force that..."], # 好回答
"rejected": ["I don't know", "Magic"], # 差回答
})
# DPO 训练
trainer = DPOTrainer(
model=model,
ref_model=ref_model,
tokenizer=tokenizer,
train_dataset=dataset,
beta=0.1,
)
trainer.train()
几十行代码 —— 完整 DPO pipeline。 比 RLHF 简单 10×。
推荐配套阅读
- HelloAI: L4-01 LLM 训练 + L6-02 RLHF/CAI
- DPO 论文(NeurIPS 2023 Best Paper)
- TRL 库(HuggingFace)—— 工程实现
- Zephyr 7B 报告 —— 第一个 DPO 大模型
2022 RLHF 论文发布—— 所有人觉得对齐 = RLHF。
2023 DPO 出现—— 12 个月时间,开源生态全部转向 DPO。
AI 领域的范式更替速度—— 一年一次。
这告诉我们:没有什么是”永远的最佳实践”—— 保持开放,持续学习。
想要更多论文精读
订阅每周精选 —— 下一篇论文笔记直接送邮箱。
讨论区
· 用 GitHub 账号登录评论src/components/Comments.astro 顶部填入
仓库 ID 和分类 ID(见组件注释里的配置步骤)。