📖 什么是DPO?
DPO(Direct Preference Optimization,直接偏好优化)是一种直接从人类偏好数据训练语言模型的方法,不需要训练单独的奖励模型。
由Stanford在2023年提出,是RLHF的简化替代方案,被Llama 2、Mistral等模型广泛采用。
💡 一句话理解
📚 比喻
跳过「考试评分」直接「模仿优秀」
RLHF是:先让模型答题 → 评分 → 根据分数调整(复杂);DPO是:直接告诉模型「这个答案比那个好」→ 模型学着选好的(简单直接)。
🆚 RLHF vs DPO 对比
🔄 RLHF流程
Step 1: 收集偏好数据
Step 2: 训练奖励模型
Step 3: PPO强化学习
Step 4: 迭代优化
⚠️ 需要多个模型
⚠️ 训练不稳定
⚠️ 超参数多
⚡ DPO流程
Step 1: 收集偏好数据
Step 2: 直接优化策略
(完成!)
✅ 只需一个模型
✅ 训练稳定
✅ 超参数少
⚙️ DPO核心原理
DPO的巧妙之处在于隐式学习奖励函数:
# RLHF目标:最大化奖励
max E[R(x, y)] # 需要先学R
# DPO目标:直接优化偏好
# 给定成对数据 (x, y_w, y_l)
# y_w = 被选中的回答(winner)
# y_l = 被拒绝的回答(loser)
# DPO Loss:
L_DPO = -log σ(β * (log π(y_w|x) - log π(y_l|x)
- log π_ref(y_w|x) + log π_ref(y_l|x)))
# 其中:
# π = 正在训练的模型
# π_ref = 参考模型(冻结)
# β = KL散度系数
# σ = sigmoid函数
💻 代码示例:DPO训练
from transformers import AutoModelForCausalLM, AutoTokenizer
from trl import DPOTrainer, DPOConfig
from datasets import load_dataset
# 加载模型
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-7B")
ref_model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-7B")
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2-7B")
# 加载偏好数据(格式:prompt, chosen, rejected)
dataset = load_dataset("Anthropic/hh-rlhf", split="train")
# DPO配置
training_args = DPOConfig(
output_dir="./dpo-output",
beta=0.1, # KL散度系数
learning_rate=5e-7,
per_device_train_batch_size=4,
num_train_epochs=1,
)
# 训练
trainer = DPOTrainer(
model=model,
ref_model=ref_model,
args=training_args,
train_dataset=dataset,
tokenizer=tokenizer,
)
trainer.train()
📊 偏好数据格式
{
"prompt": "解释什么是机器学习",
"chosen": "机器学习是AI的一个分支,让计算机能够从数据中学习...",
"rejected": "机器学习就是让机器学习东西"
}
人类标注者看到两个回答,选择更好的一个。DPO直接从这些选择中学习。
✅ DPO优势
🚀
训练简单
无需奖励模型和PPO
💪
稳定性高
避免RL的不稳定性
⚡
效率更高
计算资源需求更低
🔬
可解释性
直接看偏好学习