Overview
1.DPO 核心思想: 模型生成概率比近似人类偏好比
2.DPO 的推导过程: Boltzmann 分布带入生成-偏好匹配公式
3.DPO 的执行流程: 计算 DPO Loss
4.DPO v.s. PPO 如何比较 ?
Recap: RLHF Reward Modeling
RLHF 中 Reward Modeling 的目标是: 建模一个标量打分函数,这个函数能满足对于任何偏好对,都能能够满足对齐的人类偏好偏序, 形式化如下:假设有 Reward model
有同一个 prompt $x$ 下生成的偏好对
我们希望
也就是希望接受概率大于拒绝概率, 换句话说当我们在建模偏好时,Reward model 的建模目标是
有很多建模偏好的概率方法,通常选择选择 Bradley-Terry (BT, 常见翻译作布拉德利–特里模型) 概率模型作为建模这个 $p$ 的概率模型, 得到
似然函数
上式取对数似然
训练过程相当于最大化对数似然,也就是最小化负对数似然
intuitively,
1.训练偏好模型,其实就是在训练集上,约等于最大化所有偏好差值
2.为什么式子 (3) 里面 $\log\frac{e^a}{e^a+e^b}=\log \sigma(a-b)$ ? 这就是 Bradely-Terry 模型的精妙之处, 翻译成直觉形式,当我们想建模一个偏好概率函数,我们就是在建模一个函数差值 (外加 sigma 归一化处理的) 值
Recap: RLHF Fine-tuning
RLHF 的一般目标是用上面的 Reward Model 指导反馈,最大化 policy model 在 RL 阶段的 RM 的打分, 形式化就是如下定义, 这里面的 $y$ 默认是一个序列
另外还得增加一个策略模型不偏离参考模型的约束,这种约束最简单的方法就是用 KL 散度这种指标,衡量概率分布的变化
直觉上看,如果 $\pi{\theta}(y|x)$ 和 $\pi{ref}(y|x)$ 相等,那么不做任何惩罚;如果 $\pi{\theta}(y|x)-\pi{ref}(y|x)>0$ 当前策略比参考策略更加的大胆, 需要进行 reward 惩罚;惩罚的幅度增加个 $\beta$ 参数控制
因此,完整的 RLHF 的目标 formulation 如下:
对应强化学习过程中的 reward function 也不仅仅是 reward function 本身,而是构造为
DPO 核心思想: 模型生成概率比近似人类偏好比
思考原点:PPO 单独训练一个 RM 模型是间接操作, 能不能直接去通过找模型和偏好之间的关系直接优化? 或者说能不能直接学习偏好数据去优化模型?
可以的,但怎么能做到呢?核心思想是 “用策略模型生成概率比近似人类偏好比”, 或者说 “直接优化策略模型使生成的输出概率分布匹配人类偏好”
对于一个 pairwise
数据, DPO 假设模型
要模拟人类的偏好, 直觉上就是模型生成的结果概率比 (“好” 比 “坏”),等于人类 (数据) 偏好比, 形式化满足如下比例一致性:
intuitively,
1.左边是模型输出的概率比,衡量模型 “更倾向于生成哪个 response”
2.右边是人类偏好概率比,也就是在 pair 里面选 winner 的倾向性有多大?
3.”强行让左边 == 右边”的意思是, 我们希望模型在相对偏好上尽量对齐人类的偏好
4.为什么用 “概率比” 而不是 “绝对概率” ? (i). pairwise 的数据只能告诉我们相对的好坏 (ii). 和 Boltzmann 假设是一致的
5.举个例子体会下 “模型生成概率比近似人类偏好比” 的思想, 我们有 prompt: “写一段祝福”, 现在有 $y_w$: “祝你天天开心”, $y_l$: “天气很好”
人类标注结果
DPO 的训练目标
DPO 模型训练目标最求生成的相对比例约等于 $4.0$ 这样, 因此训练下来 winner 的概率相对比 loser 提高,符合人类偏好
DPO 的推导过程: Boltzmann 分布带入生成-偏好匹配公式
DPO 的推导过程: 基于 Boltzmann 分布带入生成偏好等于人类偏好公式做推导
有一个完整推导过程,需要有点耐心,慢慢来我们一步一步走下
Boltzmann 分布: 从能量分布应用到人类偏好分布
物理学中 Boltzmann 分布是描述系统在能量状态下出现概率的公式
其中,
1.$E(y)$ 是状态 $y$ 的能量
2.$\beta$ 是温度的倒数, 叫温度参数;当 $\beta \to 0$, 趋于均匀随机选择; $\beta \to \infty$ 趋于确定性选择最高能量状态
为什么用 Boltzmann 分布能建模人类偏好 ?
人类在面对多个候选答案的时候,选择概率越高的答案,其实就是隐含的 reward 越高
Boltzmann 建模人类偏好的数学 formulation: 假设我们有一个 prompt $x$ 和一组答案 $y_1,y_2,\ldots,y_n$ 人类偏好的概率定义为
其中,
1.$\pi_{ref}(y|x)$ 是参考模型给答案的概率, 参考模型给了一个先验的概率
2.$r^{\ast}$ response 的隐含真实 reward
3.$\beta$ 是控制人类选择的锐利度, 如果 $\beta$ 很大,那就是人类总选择最优的答案,一点不随机; $\beta$ 很小,那么就是人类选答案很随机,reward 之间差异不大
人类偏好假设满足 Boltzmann 分布带入人类偏好比
然后开始我们的推导, 先基于假设让左边等于右边:
看见右边有个 $e$ 很不爽, 两边取个对数
再把和 $\pi$ 相关的放一边,和 $r$ 相关的放一边, 看起来就更清爽了,看看能得出来什么有趣的关系
竟然有一项是 $r^{\ast}$ 的差值,左边 reward 作差这种我们想要的偏好偏序关系再得搞得再清爽点呢? 把 $\beta$ 放到右边, 然后右边观察出来一个对数减法, 想着换换除法形式呢? 竟然能出来更符合直觉的
这种形式 (策略模型相对于参考模型的放大或者缩小相关的数学形式), 得到如下
我们停下来看下这个 pairwise reward 差值公式,左边是 pairwise reward 的差值, 也就是相比垃圾回复,优质回复好多少; 右边忽略 $\frac{1}{\beta}$ 和 $\log$ 等于一个 [策略模型在 winner 样本相对于参考模型的变化] 减去 [策略模型在 loser 样本相对于参考模型的变化]
我直觉上的理解是:
偏好的相对程度 == 策略模型在好样本上 “模型好了” 多少减去策略模型在差样本上 “坏了多少”
上面这个 pairwise reward 差值公式,只说明了一种 reward 的一种相对关系是怎么定义的, 但我们想得到一个绝对的公式去形式化 reward,应该如何构建 ? 可以参考 pairwise reward 差值公式的定义,定义出来一种绝对的 reward 公式
这个公式是是说存在一种绝对 reward function 的定义,能满足 pairwise reward 公式,定义里面含有常数项 $C(x)$, 这个常数项 $C(x)$ 是一个依赖于 prompt 的量,作用是让所有的 reward 发生 $C(x)$ 的平移,但不会改变 pairwise 的 reward 差值
这个形式定义出来之后,发现和 paper, 中的不太一致, paper 中使用的是
差别在于 $\beta$ 是否放在 reward 的内部, 刚才的推导针对的是单位 reward, paper 中定义 reward 包含了 $\beta$ 放大
DPO 实际计算 reward 公式
在实际计算 reward 的时候, 会忽略掉常数项, reward 按照如下计算
这是因为 DPO 最终损失函数只依赖 reward 的差值,而不需要依赖常数项
DPO 最终损失函数的定义
DPO 的执行流程: 计算 DPO Loss
1.准备 pairwise 偏好数据集. 形式都是
准备策略模型 $\pi{\theta}$ 和 参考模型 $\pi{ref}$, 来自于同一个 SFT 模型, 然后参考模型冻结参数
2.计算 DPO Loss
DPO Loss 计算过程详细拆解
(i). 分别计算策略模型和参考模型对 chosen 和 reject 的概率,这里给出一个模拟结果
| resp | π_{ref}(y of given x) | π_{θ}(y of given x) |
|---|---|---|
| $y_w=\text{“你好,世界!”}$ | 0.5 | 0.7 |
| $y_l=\text{“哈喽,世界!”}$ | 0.5 | 0.2 |
这里有个细节,模型每次输出的是生成 token 概率,计算的是生成句子概率, 句子概率本质是用 token 概率的乘积实现的; 但乘积不太稳定,实际的实现是通过对数概率累加的
我们为了描述整体流程,暂时不拆解到 token 这么细节, 继续计算后续的损失
(ii). 分别计算对数概率比
(iii). 计算 reward 差值
假设 $\beta=1$, 经验上看 $\beta$ 范围取值是 $0.1\sim 1.0$, 默认取值 $1.0$
(iv). 计算 Sigmoid
直观理解:模型认为有 77.7 % 概率被选中偏好
(v). 计算 DPO loss
3.反向传播并优化梯度
DPO 执行流程抽象成代码块如下
for step, batch in enumerate(train_loader):
# 1. 准备输入数据
x = torch.cat([x_chosen, x_rejected], dim=0)
y = torch.cat([y_chosen, y_rejected], dim=0)
# 2. 计算参考模型的概率
with torch.no_grad():
ref_outputs = ref_model(x)
ref_logits = ref_outputs.logits
ref_probs = logits_to_probs(ref_logits, y)
# 3. 计算策略模型的概率
outputs = model(x)
logits = outputs.logits
probs = logits_to_probs(logits, y)
# 4. 计算DPO损失
loss = dpo_loss(ref_probs, probs, mask, beta=0.1)
# 5. 反向传播与优化
loss.backward()
optimizer.step()
DPO v.s. PPO 如何比较 ?
DPO 作为一种简单有效学习人类偏好的的方式, 是完全不能替代 PPO 的
DPO 的优势: 成本低
1.训练成本显著低,只要组 pairwise preference 数据就能训练,无需 rollout, critic, advantage 计算流程,训练过程近似于监督学习,收敛稳定
DPO 的劣势: 静态数据优化带来的泛化不足
1.完全依赖于已有 pairwise 数据训练,如果训练数据覆盖不足,那么效果可能不理想
2.RL面对的关键问题都没有较好的处理机制: 对于稀疏奖励或者延迟奖励难以学到, 举个例子: 如果训练数据中出现 reward=1 的情况很少,那么 pairwise 组对也是很少的
3.对多目标的优化支持能力有限,PPO 可以对多个 reward 加权 ensemble, 但 DPO 面对多个 reward 的时候需要额外构造
Reference
[1]. Direct Preference Optimization: Your Language Model is Secretly a Reward Model.
转载请注明来源 goldandrabbit.github.io