TT Lab

한국어 English 日本語 中文

开始
博客

博客

从 RLHF 到 DPO:LLM 对齐(Alignment)技术论文深度解析

对话收听 · 6分钟两位主持人为你讲解本文

LLM Alignment Survey

引言

大规模语言模型(LLM)通过学习海量语料获得了惊人的语言能力,但仅靠预训练无法保证输出符合人类的意图与价值观。生成有害内容、无视用户指示、或是自信满满地陈述不实信息,这些问题屡见不鲜。为弥合这一差距而生的研究领域,正是LLM 对齐(Alignment)。

自 2022 年 OpenAI 的 InstructGPT 论文将 RLHF(Reinforcement Learning from Human Feedback,基于人类反馈的强化学习)流水线体系化以来,Anthropic 的 Constitutional AI、Stanford 的 DPO(Direct Preference Optimization,直接偏好优化),以及 KTO、IPO、ORPO 等各种后续技术相继出现。本文将系统分析这些核心论文的数学基础、实现方式,以及实务应用时的注意事项。

LLM 对齐问题的定义

为什么需要对齐

预训练好的 LLM 优化的是互联网文本上的下一个词元预测(next-token prediction)。这一目标并不直接对应人类期望的「有用(Helpful)、诚实(Honest)、无害(Harmless)」输出。具体来说,存在三个核心问题。

  1. 有用性(Helpfulness):准确理解并执行用户指示的能力
  2. 诚实性(Honesty):承认自己不知道的事,并将幻觉降到最低的能力
  3. 无害性(Harmlessness):拒绝生成有害或带偏见内容的能力

对齐的数学框架

对齐问题被形式化为基于奖励函数 r(x, y) 的策略优化问题。给定提示词 x,在限制与预训练参考策略之间的偏离的同时,最大化策略 pi 生成的响应 y 所获得的奖励。

max⁡πEx∼D,y∼π(⋅∣x)[r(x,y)]−β KL[π(⋅∣x)∥πref(⋅∣x)]\max_{\pi} \mathbb{E}_{x \sim \mathcal{D}, y \sim \pi(\cdot|x)} \left[ r(x, y) \right] - \beta \, \text{KL}\left[\pi(\cdot|x) \| \pi_{\text{ref}}(\cdot|x)\right]

这里的 beta 是调节 KL 散度惩罚强度的超参数。beta 太小会发生奖励黑客(reward hacking),太大则训练会变慢。

RLHF 流水线深度分析

InstructGPT 的三阶段流水线

Ouyang 等人(2022)的 InstructGPT 论文将 RLHF 流水线体系化为三个阶段。

第一阶段:监督微调(SFT)

用人类标注者撰写的示范数据对基础模型进行微调。在这一阶段,模型学习到遵循指示的基本能力。

第二阶段:奖励模型(RM)训练

针对同一提示词生成多个响应,再由人类标注者对其排出偏好顺序。用这些数据训练奖励模型。

第三阶段:通过 PPO 进行强化学习

利用奖励模型的反馈,用 PPO 算法优化策略。

奖励模型训练实现

奖励模型基于 Bradley-Terry 模型,通过最大化偏好对(chosen、rejected)之间的对数概率差来训练。

import torch
import torch.nn as nn
from transformers import AutoModelForSequenceClassification, AutoTokenizer

class RewardModel(nn.Module):
    def __init__(self, model_name="gpt2"):
        super().__init__()
        self.model = AutoModelForSequenceClassification.from_pretrained(
            model_name, num_labels=1
        )

    def forward(self, input_ids, attention_mask):
        outputs = self.model(input_ids=input_ids, attention_mask=attention_mask)
        return outputs.logits.squeeze(-1)

def reward_model_loss(reward_model, chosen_ids, chosen_mask, rejected_ids, rejected_mask):
    """基于 Bradley-Terry 偏好模型的奖励模型损失函数"""
    r_chosen = reward_model(chosen_ids, chosen_mask)
    r_rejected = reward_model(rejected_ids, rejected_mask)

    # 训练使偏好响应的奖励高于非偏好响应
    loss = -torch.log(torch.sigmoid(r_chosen - r_rejected)).mean()
    accuracy = (r_chosen > r_rejected).float().mean()

    return loss, accuracy

偏好数据集构建

RLHF 流水线的核心在于构建高质量的偏好数据集。每个样本由提示词、偏好响应、非偏好响应三元组构成。

from datasets import Dataset

def build_preference_dataset(prompts, model, tokenizer, num_samples=4):
    """针对每个提示词生成多个响应并构建偏好对的流水线"""
    preference_data = []

    for prompt in prompts:
        inputs = tokenizer(prompt, return_tensors="pt")
        responses = []

        # 通过温度采样生成多样化响应
        for _ in range(num_samples):
            output = model.generate(
                **inputs,
                max_new_tokens=256,
                temperature=0.8,
                do_sample=True,
            )
            response = tokenizer.decode(output[0], skip_special_tokens=True)
            responses.append(response)

        # 实际流水线中由人类标注者排序
        # 此处以奖励模型分数代替
        scored = [(r, reward_model_score(prompt, r)) for r in responses]
        scored.sort(key=lambda x: x[1], reverse=True)

        # 用最高分与最低分构建偏好数据
        preference_data.append({
            "prompt": prompt,
            "chosen": scored[0][0],
            "rejected": scored[-1][0],
        })

    return Dataset.from_list(preference_data)

Constitutional AI:基于 AI 反馈的对齐

Anthropic 的方法

Bai 等人(2022)的 Constitutional AI,是为减少 RLHF 对人类标注依赖而提出的创新方法。其核心思想是让AI 自己批判并改进自身的输出,这一过程由预先定义的原则(Constitution,宪法)来引导。

两阶段流程

监督学习阶段(自我批判与修正):

  1. 模型生成一个可能有害的响应
  2. 依据宪法原则批判自己的响应
  3. 反映批判意见,生成修正后的响应
  4. 用修正后的响应执行 SFT

RL 阶段(RLAIF —— RL from AI Feedback):

  1. AI 判断两个响应中哪一个更符合原则
  2. 用这一 AI 偏好数据训练奖励模型
  3. 用奖励模型通过 PPO 优化策略

Constitutional AI 最大的优势在于,能在大幅削减人类标注成本的同时,实现基于原则、透明且可解释的对齐。

DPO:数学基础与实现

RLHF 目标函数的解析解

Rafailov 等人(2023)提出的 DPO,是 RLHF 最优雅的替代方案。其核心洞见是:带 KL 约束的奖励最大化问题存在解析解。

最优策略具有如下形式。

π∗(y∣x)=1Z(x)πref(y∣x)exp⁡(1βr(x,y))\pi^*(y|x) = \frac{1}{Z(x)} \pi_{\text{ref}}(y|x) \exp\left(\frac{1}{\beta} r(x, y)\right)

反解这一方程,可以将奖励函数表示为策略的比值。

r(x,y)=βlog⁡π∗(y∣x)πref(y∣x)+βlog⁡Z(x)r(x, y) = \beta \log \frac{\pi^*(y|x)}{\pi_{\text{ref}}(y|x)} + \beta \log Z(x)

将其代入 Bradley-Terry 模型,便得到无需奖励模型、直接优化策略的 DPO 损失函数。

LDPO(πθ;πref)=−E(x,yw,yl)[log⁡σ(βlog⁡πθ(yw∣x)πref(yw∣x)−βlog⁡πθ(yl∣x)πref(yl∣x))]\mathcal{L}_{\text{DPO}}(\pi_\theta; \pi_{\text{ref}}) = -\mathbb{E}_{(x, y_w, y_l)} \left[\log \sigma\left(\beta \log \frac{\pi_\theta(y_w|x)}{\pi_{\text{ref}}(y_w|x)} - \beta \log \frac{\pi_\theta(y_l|x)}{\pi_{\text{ref}}(y_l|x)}\right)\right]

DPO 训练循环实现

import torch
import torch.nn.functional as F
from transformers import AutoModelForCausalLM, AutoTokenizer

def compute_dpo_loss(
    policy_model,
    reference_model,
    chosen_ids,
    chosen_mask,
    rejected_ids,
    rejected_mask,
    beta=0.1,
):
    """DPO 损失函数:无需奖励模型,直接优化策略"""
    # 计算策略模型的对数概率
    policy_chosen_logps = get_log_probs(policy_model, chosen_ids, chosen_mask)
    policy_rejected_logps = get_log_probs(policy_model, rejected_ids, rejected_mask)

    # 计算参考模型的对数概率(不需要梯度)
    with torch.no_grad():
        ref_chosen_logps = get_log_probs(reference_model, chosen_ids, chosen_mask)
        ref_rejected_logps = get_log_probs(reference_model, rejected_ids, rejected_mask)

    # 计算 DPO 对数比率
    chosen_logratios = policy_chosen_logps - ref_chosen_logps
    rejected_logratios = policy_rejected_logps - ref_rejected_logps

    # DPO 损失:-log(sigmoid(beta * (chosen_logratio - rejected_logratio)))
    logits = beta * (chosen_logratios - rejected_logratios)
    loss = -F.logsigmoid(logits).mean()

    # 指标:偏好响应的隐式奖励更高的比例
    reward_accuracy = (logits > 0).float().mean()

    return loss, reward_accuracy

def get_log_probs(model, input_ids, attention_mask):
    """对序列的逐词元对数概率求和"""
    outputs = model(input_ids=input_ids, attention_mask=attention_mask)
    logits = outputs.logits[:, :-1, :]
    labels = input_ids[:, 1:]
    log_probs = F.log_softmax(logits, dim=-1)
    selected_log_probs = torch.gather(
        log_probs, dim=-1, index=labels.unsqueeze(-1)
    ).squeeze(-1)
    mask = attention_mask[:, 1:]
    return (selected_log_probs * mask).sum(dim=-1)

DPO 的优缺点

优点:

缺点:

PPO 训练稳定性

RLHF 中的 PPO:实现核心

PPO(Proximal Policy Optimization)是 RLHF 中使用最广泛的强化学习算法。其核心是裁剪机制(clipping),通过限制策略更新的幅度来保证训练稳定性。

import torch
import torch.nn.functional as F

def ppo_step(
    policy_model,
    value_model,
    old_log_probs,
    states,
    actions,
    rewards,
    advantages,
    clip_epsilon=0.2,
    value_clip=0.2,
    kl_coeff=0.1,
    ref_log_probs=None,
):
    """PPO 更新步骤(用于 LLM RLHF)"""
    # 当前策略的对数概率
    new_log_probs = policy_model.get_log_probs(states, actions)

    # 重要度比率计算
    ratio = torch.exp(new_log_probs - old_log_probs)

    # 裁剪后的代理目标函数
    surr1 = ratio * advantages
    surr2 = torch.clamp(ratio, 1.0 - clip_epsilon, 1.0 + clip_epsilon) * advantages
    policy_loss = -torch.min(surr1, surr2).mean()

    # 价值函数损失(应用裁剪)
    new_values = value_model(states)
    value_loss = F.mse_loss(new_values, rewards)

    # KL 散度惩罚(相对参考模型)
    kl_penalty = 0.0
    if ref_log_probs is not None:
        kl_div = (old_log_probs - ref_log_probs).mean()
        kl_penalty = kl_coeff * kl_div

    total_loss = policy_loss + 0.5 * value_loss + kl_penalty

    return total_loss, {
        "policy_loss": policy_loss.item(),
        "value_loss": value_loss.item(),
        "kl_penalty": kl_penalty if isinstance(kl_penalty, float) else kl_penalty.item(),
        "mean_ratio": ratio.mean().item(),
    }

PPO 训练的主要不稳定性来源

  1. 奖励黑客(Reward Hacking):利用奖励模型的弱点,让实际质量不佳的输出获得高奖励的现象
  2. KL 散度爆炸:与参考模型的距离急剧增大,生成无意义文本
  3. 价值函数估计误差:异常偏大的奖励估计值使训练变得不稳定
  4. 长序列问题:词元数越多,信用分配(credit assignment)问题越严重

最新对齐技术:KTO、IPO、ORPO

KTO(Kahneman-Tversky Optimization)

Ethayarajh 等人(2024)提出的 KTO 无需成对偏好数据即可完成对齐。它借用了行为经济学中的前景理论(Prospect Theory),仅凭每个响应「是否理想」的二元信号进行学习。

KTO 的核心在于反映了人类决策对损失更敏感这一损失厌恶(Loss Aversion)特性。它将对不理想响应的惩罚,设定得比对理想响应的奖励更大。

IPO(Identity Preference Optimization)

Azar 等人(2024)提出的 IPO,通过增加一个正则化项来解决 DPO 的过拟合(overfitting)问题。DPO 在对训练数据过拟合时,往往会将偏好响应的概率推向极端,IPO 则可以防止这一点。

LIPO=(log⁡πθ(yw∣x)πref(yw∣x)−log⁡πθ(yl∣x)πref(yl∣x)−12β)2\mathcal{L}_{\text{IPO}} = \left(\log \frac{\pi_\theta(y_w|x)}{\pi_{\text{ref}}(y_w|x)} - \log \frac{\pi_\theta(y_l|x)}{\pi_{\text{ref}}(y_l|x)} - \frac{1}{2\beta}\right)^2

ORPO(Odds Ratio Preference Optimization)

Hong 等人(2024)提出的 ORPO,将SFT 与偏好优化整合为单一阶段。由于不需要参考模型,能大幅降低内存与计算成本。其核心是基于优势比(Odds Ratio)的惩罚项。

import torch
import torch.nn.functional as F

def compute_orpo_loss(model, chosen_ids, chosen_mask, rejected_ids, rejected_mask, alpha=1.0):
    """ORPO 损失:SFT + 基于优势比的偏好优化的统一"""
    # SFT 损失(对偏好响应求 NLL)
    chosen_logits = model(input_ids=chosen_ids, attention_mask=chosen_mask).logits
    sft_loss = F.cross_entropy(
        chosen_logits[:, :-1, :].reshape(-1, chosen_logits.size(-1)),
        chosen_ids[:, 1:].reshape(-1),
        reduction="mean",
    )

    # 计算对数概率
    chosen_logps = get_sequence_log_probs(model, chosen_ids, chosen_mask)
    rejected_logps = get_sequence_log_probs(model, rejected_ids, rejected_mask)

    # 计算优势比
    chosen_odds = chosen_logps - torch.log1p(-torch.exp(chosen_logps))
    rejected_odds = rejected_logps - torch.log1p(-torch.exp(rejected_logps))
    log_odds_ratio = chosen_odds - rejected_odds

    # ORPO 最终损失
    orpo_loss = sft_loss - alpha * F.logsigmoid(log_odds_ratio).mean()

    return orpo_loss

对比分析

将各对齐技术的核心特性加以比较,结果如下。

技术数据需求模型数量计算成本稳定性性能
RLHF (PPO)成对偏好4(策略、参考、奖励、价值)非常高低(需要调优)高(充分调优时)
DPO成对偏好2(策略、参考)中等高高
KTO二元反馈(非成对)2(策略、参考)中等高中上
IPO成对偏好2(策略、参考)中等非常高中上
ORPO成对偏好1(仅策略)低高中上

核心权衡:

实务应用指南

技术选择标准

在实务中选择对齐技术时,需要考虑以下标准。

  1. 数据形态:是否有成对偏好数据?还是只能获取二元反馈?
  2. 计算资源:GPU 内存与训练时间的限制如何?
  3. 团队能力:是否有 PPO 调优经验?
  4. 模型规模:7B 以下考虑 DPO,70B 以上考虑 RLHF

评估指标实现

用于评估对齐结果的核心指标如下。

import numpy as np
from typing import List, Dict

def compute_alignment_metrics(
    model_responses: List[str],
    reference_responses: List[str],
    reward_model,
    tokenizer,
) -> Dict[str, float]:
    """用于评估对齐质量的综合指标计算"""
    metrics = {}

    # 1. 奖励模型分数
    rewards = []
    for response in model_responses:
        tokens = tokenizer(response, return_tensors="pt")
        score = reward_model(**tokens).item()
        rewards.append(score)
    metrics["mean_reward"] = np.mean(rewards)
    metrics["reward_std"] = np.std(rewards)

    # 2. 胜率(win rate)—— 相对参考模型
    wins = 0
    for model_resp, ref_resp in zip(model_responses, reference_responses):
        model_tokens = tokenizer(model_resp, return_tensors="pt")
        ref_tokens = tokenizer(ref_resp, return_tensors="pt")
        model_score = reward_model(**model_tokens).item()
        ref_score = reward_model(**ref_tokens).item()
        if model_score > ref_score:
            wins += 1
    metrics["win_rate"] = wins / len(model_responses)

    # 3. 响应长度分布(长度黑客检测)
    lengths = [len(r.split()) for r in model_responses]
    metrics["mean_length"] = np.mean(lengths)
    metrics["length_std"] = np.std(lengths)

    # 4. 多样性指标(模式崩溃检测)
    unique_bigrams = set()
    total_bigrams = 0
    for response in model_responses:
        words = response.split()
        for i in range(len(words) - 1):
            bigram = (words[i], words[i + 1])
            unique_bigrams.add(bigram)
            total_bigrams += 1
    metrics["distinct_2"] = len(unique_bigrams) / max(total_bigrams, 1)

    return metrics

失败案例与教训

1. 奖励黑客(Reward Hacking)

这是 RLHF 中最常见的失败模式。当奖励模型学到「响应越长 = 响应越好」这种虚假相关性时,策略模型就会不顾内容质量,生成过长的响应。InstructGPT 论文也报告过这一问题,并通过长度归一化与加强 KL 惩罚部分解决了它。

教训:需要持续监控奖励模型的偏差,并用多种代理指标进行交叉验证。

2. 模式崩溃(Mode Collapse)

在 PPO 训练过程中,策略只反复生成能在奖励模型上拿到高分的少数几种模式的现象。表现为对不同问题输出结构相同的响应,或过度重复某些特定表达。

教训:应当合理维持 KL 散度约束,并在训练过程中监控响应多样性指标。

3. DPO 的分布偏移(Distribution Shift)

由于 DPO 是在离线偏好数据上训练的,随着训练推进,当前策略生成的分布会与训练数据的分布逐渐产生偏离。这可能导致训练后期性能下降。

教训:应当采用迭代式(iterative)DPO,在每一轮用当前策略生成新的偏好数据,或者使用在线 DPO 变体。

4. Constitutional AI 的原则冲突

宪法中包含的各项原则之间有时会发生冲突。例如「要提供帮助」与「不要提供有害信息」这两条原则,在特定语境下可能相互抵触。

教训:应当明确定义各原则之间的优先级,并为边界情形(edge cases)另行制定指导方针。

参考资料

  1. Ouyang, L., et al. (2022). "Training language models to follow instructions with human feedback." NeurIPS 2022. https://arxiv.org/abs/2203.02155

  2. Rafailov, R., et al. (2023). "Direct Preference Optimization: Your Language Model is Secretly a Reward Model." NeurIPS 2023. https://arxiv.org/abs/2305.18290

  3. Bai, Y., et al. (2022). "Constitutional AI: Harmlessness from AI Feedback." Anthropic. https://arxiv.org/abs/2212.08073

  4. Ethayarajh, K., et al. (2024). "KTO: Model Alignment as Prospect Theoretic Optimization." https://arxiv.org/abs/2402.01306

  5. Hong, J., et al. (2024). "ORPO: Monolithic Preference Optimization without Reference Model." https://arxiv.org/abs/2403.07691

  6. Azar, M. G., et al. (2024). "A General Theoretical Paradigm to Understand Learning from Human Feedback." (IPO) https://arxiv.org/abs/2310.12036

  7. Schulman, J., et al. (2017). "Proximal Policy Optimization Algorithms." https://arxiv.org/abs/1707.06347

  8. Hugging Face Blog. "Preference Tuning LLMs with Direct Preference Optimization Methods." https://huggingface.co/blog/pref-tuning

登录后即可点赞

评论

还没有评论。

登录后即可发表评论