DPO(Direct Preference Optimization) 是一种用于训练大语言模型的直接偏好优化方法,它相比于 PPO(Proximal Policy Optimization)无需显式构建奖励模型,而是基于人类反馈的“选优对比”直接学习偏好。
假设我们有成对的回答:一个用户 prompt 和两个模型回答:
我们希望模型对 chosen 的回答给出更高的概率(LogLik),对 rejected 的回答给出较低概率,从而学习人类偏好。
使用 softmax 概率建模:
P h e t a ( y c ≻ y r ∣ x ) = exp ( β log π θ ( y c ∣ x ) ) exp ( β log π θ ( y c ∣ x ) ) + exp ( β log π θ ( y r ∣ x ) ) P_{ heta}(y_c \succ y_r | x) = \frac{\exp(\beta \log \pi_\theta(y_c|x))}{\exp(\beta \log \pi_\theta(y_c|x)) + \exp(\beta \log \pi_\theta(y_r|x))} Pheta(yc≻yr∣x)=exp(βlogπθ(yc∣x))+exp(βlogπθ(yr∣x))exp(βlogπθ(yc∣x))
其中:
最终优化目标:
L DPO = − E x , y c , y r [ log P θ ( y c ≻ y r ∣ x ) ] \mathcal{L}_{\text{DPO}} = - \mathbb{E}_{x, y_c, y_r} \left[ \log P_\theta(y_c \succ y_r | x) \right] LDPO=−Ex,yc,yr[logPθ(yc≻yr∣x)]
{
"prompt": "请解释黑洞的形成。",
"chosen": "黑洞是由大质量恒星在耗尽核燃料后坍缩形成的。",
"rejected": "黑洞是一种宇宙现象,跟火山爆发类似。"
}
该格式只需要人类判断哪个更好,而无需精确打分。
pip install trl transformers datasets
from datasets import Dataset
samples = [
{
"prompt": "介绍一下狮子和老虎的区别",
"chosen": "狮子生活在草原,雄狮有鬃毛;老虎生活在森林,体型更大。",
"rejected": "狮子和老虎其实是同一种动物的两个名字。"
}
]
dataset = Dataset.from_list(samples)
from trl import DPOTrainer, DPOConfig
from transformers import AutoTokenizer, AutoModelForCausalLM
model_name = "gpt2"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)
ref_model = AutoModelForCausalLM.from_pretrained(model_name)
config = DPOConfig(
beta=0.1,
learning_rate=5e-6,
batch_size=4,
max_prompt_length=128,
max_length=512,
label_pad_token_id=-100
)
trainer = DPOTrainer(
model=model,
ref_model=ref_model,
tokenizer=tokenizer,
args=config,
train_dataset=dataset
)
trainer.train()
特性 | DPO |
---|---|
是否需奖励模型 | ❌ 不需要 |
是否需 Ref Model | ✅ 需要(对比稳定性) |
数据格式 | prompt + chosen + rejected |
优点 | 简洁、稳定、无需 reward |
缺点 | 无法利用连续奖励信号 |
推荐使用场景 | 微调大模型以更好符合人类偏好 |
DPO 是一种更实用、直接的人类偏好学习方法,适用于没有 reward model 的场景,同时训练效果稳定、实现简单,适合大多数 RLHF 项目落地。
trl
库:https://github.com/huggingface/trl