DPO(Direct Preference Optimization)

Jul 26, 2024
1 views
Reinforcement Learning

背景

RLHF 通常包括三个阶段:

  • 有监督微调(SFT)
  • 奖励建模阶段 (Reward Model)
  • RL微调阶段

直接偏好优化(DPO)

传统的RLHF方法分两步走:

  1. 先训练一个奖励模型来判断哪个回答更好
  2. 然后用强化学习让语言模型去最大化这个奖励
    这个过程很复杂,就像绕了一大圈:先学习"什么是好的",再学习"如何做好"。

DPO发现了一个数学上的捷径:

  1. 关键发现:对于任何奖励函数,都存在一个对应的最优策略(语言模型);反过来说,任何语言模型也隐含着一个它认为最优的奖励函数
  2. 直接优化:与其先训练奖励模型再训练语言模型,不如直接训练语言模型,让它自己内化"什么是好的"
  3. 数学转换:DPO将"学习判断好坏"和"学习生成好内容"这两个任务合二为一,通过一个简单的数学变换,把原本需要用于训练奖励模型的偏好数据直接用来训练语言模型
    想象你在学习做菜:
  • 传统方法(RLHF):先找一个美食评论家(奖励模型)学会评价菜的好坏,然后你根据这个评论家的反馈不断调整自己的烹饪方法
  • DPO方法:直接观察人们对不同菜品的喜好(偏好数据),自己同时学习"什么是好菜"和"如何做好菜",一步到位
    本质上,DPO让语言模型自己成为了隐含的奖励模型,省去了中间环节,使整个训练过程更简单、更直接、更高效。

DPO推导

我们从与先前工作相同的RL目标开始,根据一般奖励函数 \(r\)。遵循先前的工作,可以证明KL约束的奖励最大化目标的最优解具有以下形式:

\[ \begin{equation}\pi_r(y|x) = \frac{1}{Z(x)} \pi_{ref}(y|x) \exp\left(\frac{1}{\beta}r(x, y)\right)\end{equation} \]

其中,\(Z(x) = \sum_y \pi_{ref}(y|x) \exp\left(\frac{1}{\beta}r(x, y)\right)\)是分区函数。

🧾 (4)式证明如下:

我们可以重新排列(4)式,以根据其对应的最优策略 \(\pi_r\)、参考策略 \(\pi_{ref}\) 和未知分区函数\(Z(\cdot)\) 表达奖励函数;另一个角度来说,由 \(\pi_r\) 的公式,我们相当于是得到了 \(r_\phi\) 和 \(\pi_r\) 的关系,那么是否我们可以把训练 \(r_\phi\) 转化成直接去训练 \(\pi_r\) 呢:

\[ \begin{equation}r(x, y) = \beta \log \frac{\pi_r(y|x)}{\pi_{ref}(y|x)} + \beta \log Z(x)\end{equation} \]

这里因为公式中分区函数\(Z(x)\)的估计很难,幸运的是,Bradley-Terry模型仅依赖于两个response之间的奖励差异,即\(p^*(y_1 \succ y_2|x) = \sigma(r^*(x, y_1) - r^*(x, y_2))\)当我们计算两个输出的奖励差时,常数项 \(\beta \log Z(x)\) 会被消除:

\[ \begin{equation}\begin{aligned} p^*(y_1 \succ y_2|x) &=\sigma\left(r^*(x, y_1) - r^*(x, y_2)\right) \\ &= \sigma\left(\beta \log \frac{\pi^*(y_1|x)}{\pi_{ref}(y_1|x)} - \beta \log \frac{\pi^*(y_2|x)}{\pi_{ref}(y_2|x)}\right)\\ &=\frac{1}{1 + \exp\left(\beta \log \frac{\pi^*(y_2|x)}{\pi_{ref}(y_2|x)} - \beta \log \frac{\pi^*(y_1|x)}{\pi_{ref}(y_1|x)}\right)} \end{aligned}\end{equation} \]

既然我们已经有了人类偏好的概率表达式, 我们可以构建一个最大似然目标函数来直接优化策略 \(\pi_\theta\)

\[ \begin{equation}\mathcal{L}_{\text{DPO}}(\pi_\theta; \pi_{ref}) = -\mathbb{E}_{(x,y_w,y_l) \sim \mathcal{D}} \left[ \log \sigma \left( \beta \log \frac{\pi_\theta(y_w|x)}{\pi_{ref}(y_w|x)} - \beta \log \frac{\pi_\theta(y_l|x)}{\pi_{ref}(y_l|x)} \right) \right]\ \ \ \ \end{equation} \]

这个目标函数与奖励建模的目标函数(公式1)在形式上非常相似,但关键区别在于:

  • 奖励建模目标函数优化的是奖励模型 \(r_\phi\)
  • DPO目标函数优化的是策略模型 \(\pi_\theta\)
    这就是 DPO 的 loss。DPO 通过以上的公式转换把 RLHF 无损地转化为了 SFT,在训练的时候不再需要同时跑 4 个模型(reward model, ref model, critic, actor),而是只用跑 actor 和 ref 2 个模型,甚至由于不再在线采数据,ref model 的输出可以预先存下来,训练的时候重复使用。

DPO梯度更新

DPO(Direct Preference Optimization)的核心在于其梯度更新机制。通过分析DPO损失函数的梯度,我们可以深入理解其工作原理。

DPO损失函数相对于参数 \(\theta\) 的梯度可以表示为:

\[ \nabla_\theta L_{DPO}(\pi_\theta; \pi_{ref}) = -\beta E_{(x,y_w,y_l)\sim D} \left[\sigma(\hat{r}_\theta(x, y_l) - \hat{r}_\theta(x, y_w)) \cdot \left[\nabla_\theta \log \pi(y_w | x) - \nabla_\theta \log \pi(y_l | x)\right]\right] \]

其中:

  • \(\hat{r}_\theta(x, y) = \beta \log \frac{\pi_\theta(y|x)}{\pi_{ref}(y|x)}\) 是由语言模型 \(\pi_\theta\) 和参考模型 \(\pi_{ref}\) 隐式定义的奖励函数
  • \((x,y_w,y_l)\)是从偏好数据集 \(D\) 中采样的三元组,包含提示 \(x\)、偏好response \(y_w\) 和非偏好response \(y_l\)
  • \(\sigma\)是sigmoid函数
    梯度公式可以分解为三个关键部分:
  1. 加权系数\(\sigma(\hat{r}_\theta(x, y_l) - \hat{r}_\theta(x, y_w))\)
  2. 增加偏好response的似然\(\nabla_\theta \log \pi(y_w | x)\)
  3. 减少非偏好response的似然\(\nabla_\theta \log \pi(y_l | x)\)
    实验表明,加权系数在DPO中起着至关重要的作用:
  • 没有这个加权系数的朴素版本可能导致语言模型退化
  • 加权确保了更有效的学习,因为它使模型专注于当前评估最不准确的样本
  • 这种加权机制与强化学习中的优势函数类似,但在DPO中是隐式定义的

DPO 流程

DPO的一般实施流程包括两个主要步骤:

  1. 构建偏好数据集
  2. 优化语言模型
    在实际应用中,我们通常希望重用公开可用的偏好数据集,而不是生成新样本并收集人类偏好。由于这些偏好数据集通常是使用SFT模型(\(\pi_{SFT}\))采样的:
  • \(\pi_{SFT}\) 可用时,我们初始化 \(\pi_{ref} = \pi_{SFT}\)
  • \(\pi_{SFT}\)不可用时,我们通过最大化偏好response的似然来初始化 \(\pi_{ref}\)
    $$
    \pi_{ref} = \arg\max_\pi E_{x,y_w\sim D} [\log \pi(y_w | x)]
    $$

这种初始化过程有助于缓解真实参考分布(不可用)与DPO使用的 \(\pi_{ref}\) 之间的分布偏移。

💡 这个公式的含义是找到一个模型 \(\pi\),使得它在偏好数据集 \(D\) 上对偏好response \(y_w\) 的对数似然期望值最大化

具体实现

DPO的实现相对简单,核心是计算损失函数:

def dpo_loss(pi_logps, ref_logps, yw_idxs, yl_idxs, beta):
    """
    pi_logps: 策略对数概率,形状 (B,)
    ref_logps: 参考模型对数概率,形状 (B,)
    yw_idxs: 偏好完成索引,形状 (T,)
    yl_idxs: 非偏好完成索引,形状 (T,)
    beta: 控制KL惩罚强度的温度参数
    """
    pi_yw_logps, pi_yl_logps = pi_logps[yw_idxs], pi_logps[yl_idxs]
    ref_yw_logps, ref_yl_logps = ref_logps[yw_idxs], ref_logps[yl_idxs]

    pi_logratios = pi_yw_logps - pi_yl_logps
    ref_logratios = ref_yw_logps - ref_yl_logps

    losses = -F.logsigmoid(beta * (pi_logratios - ref_logratios))
    rewards = beta * (pi_logps - ref_logps).detach()

    return losses, rewards

DPO理论基础(Option)

"语言模型其实是个奖励模型"

DPO的关键理论突破在于发现语言模型本身可以被视为一个隐式的奖励模型。这一洞见使我们能够绕过传统RLHF中的两步过程(先学习奖励,再优化策略),直接从人类偏好中学习最优策略。

DPO理论首先引入了奖励函数的等价关系:

  • 如果两个奖励函数只相差一个仅依赖于提示\(x\) 的函数,则它们被视为等价的
  • 重要的是,同一等价类中的奖励函数在Bradley-Terry偏好模型下产生相同的偏好分布,并在约束RL问题下产生相同的最优策略
    这意味着我们只需要找到每个等价类中的一个代表性奖励函数,而不必担心具体选择哪一个。

DPO的核心定理证明了所有与Bradley-Terry模型兼容的奖励类都可以通过以下形式表示:

$$
r(x,y) = β log\frac{π(y|x)}{π_{ref}(y|x)}

$$

这个参数化的关键优势在于:

  1. 它不会限制可学习的奖励模型类别
  2. 它允许我们直接提取对应的最优策略,无需强化学习
  3. 它为每个等价类选择了一个特定的奖励函数,使得最优策略计算变得简单[8][9]

Actor-Critic算法的不稳定性与DPO的优势

传统RLHF方法(如使用PPO)面临的主要挑战是训练不稳定性,这源于以下问题

  • 归一化项的挑战
    DPO通过其特殊参数化巧妙地避开了这些问题:
  1. 不需要显式估计归一化项
  2. 不需要学习单独的值函数
  3. 不需要在训练循环中从语言模型采样
  4. 使用简单的分类损失函数直接优化策略

理论对实践的指导

这些理论分析为DPO的实际实现提供了重要指导:

  1. 简化实现:理解DPO的数学基础使我们能够用一个简单的二元交叉熵损失函数替代复杂的RL算法
  2. 梯度加权的重要性:理论解释了为什么DPO梯度中的加权系数(\(σ(r̂_θ(x,y_l) - r̂_θ(x,y_w))\))至关重要 - 它确保模型关注当前评估最不准确的样本
  3. \(β\)参数的选择:理论阐明了\(β\) 参数控制KL约束强度的作用,指导了不同任务的参数设置
  4. 参考模型初始化:理论解释了为什么在原始SFT模型不可用时,我们需要通过最大化偏好完成的似然来初始化参考模型
    DPO的理论基础不仅证明了方法的合理性,还解释了为什么这种简单的方法能够如此有效。通过巧妙的数学重参数化,DPO实现了与传统RLHF相同的目标,但方法更简单、更稳定、计算成本更低。这些理论洞见直接转化为实践优势,使DPO成为从人类偏好中训练语言模型的强大工具。

DPO的缺点

DPO面临 “distribution shift”的问题,即分布偏移问题,偏好数据在训练过程中是静态的,而模型输出分布正在不断变化

  1. 静态偏好数据 vs. 动态模型输出
  2. 偏移的具体表现
  3. 后果
    举例说明

假设我们有一个偏好数据对:

  • 回答A(被标记为"好"):相对清晰但不够全面的解释
  • 回答B(被标记为"坏"):混乱或不准确的解释