Interview Prep · Post-Training Alignment

RLHF / DPO / GRPO / PPO 面试 Cheat Sheet

公式推导 + From-Scratch 代码 + 25 高频题(L1 必会 · L2 进阶 · L3 顶级 lab)

Source: docs/tutorials/rlhf_dpo_grpo_ppo_tutorial.md SHA256: 67ea410d68e2 Rendered: 2026-05-19 10:00 UTC

§0 TL;DR Cheat Sheet

7 句话搞定 post-training alignment

一页拿下面试核心要点(详见后文 §2–§9 推导)。

  1. RLHF pipeline (Ouyang 2022 InstructGPT):SFT → RM (Bradley-Terry pairwise) → PPO + per-token KL;价值模型 (value head) 单独训练,policy 与 reference policy 通过 KL 约束。
  2. PPO 核心 (Schulman 2017):clipped surrogate $L^{\text{CLIP}}(\theta) = \mathbb{E}[\min(r_t A_t,\; \text{clip}(r_t, 1-\epsilon, 1+\epsilon) A_t)]$,重要性比 $r_t = \pi_\theta / \pi_{\theta_\text{old}}$;advantage 用 GAE $A_t^{\text{GAE}} = \sum_{l \ge 0} (\gamma\lambda)^l \delta_{t+l}$ 平衡偏差/方差。
  3. DPO 闭式 (Rafailov 2023 NeurIPS):KL-regularized RLHF 的最优策略 $\pi^*(y|x) \propto \pi_\text{ref}(y|x)\exp(r(x,y)/\beta)$,反解得 $r = \beta\log(\pi^*/\pi_\text{ref}) + \beta\log Z(x)$;代入 Bradley-Terry,$\log Z$ 在 pairwise 差中消掉,留下纯 SFT-style 损失 $-\log\sigma(\beta\log\frac{\pi(y_w)}{\pi_\text{ref}(y_w)} - \beta\log\frac{\pi(y_l)}{\pi_\text{ref}(y_l)})$。
  4. GRPO (DeepSeekMath 2024, R1 2025):对每个 prompt 采样一组 $G$ 个回答,advantage 用组内归一化 $\hat{A}_i = (r_i - \text{mean}(\mathbf{r}))/\text{std}(\mathbf{r})$;省掉 value model,省一半显存,特别适合 LLM 数学/代码 RL。
  5. DPO 变体生态:KTO(仅需 thumbs up/down,无需 pair)、IPO(防 reward overfit 的 $\ell_2$ 形式)、SimPO(去 reference,length-normalized)、ORPO(SFT + odds-ratio 一阶段融合)、RLOO(多采样 leave-one-out baseline,无需 value)、ReMax(greedy baseline,进一步省)。
  6. PRM vs ORM (Lightman 2023 arXiv / 2024 ICLR):Process-reward 监督每步 reasoning,Math-Shepherd (Wang 2024 ACL) 自动标 PRM;Outcome-reward 只看最终答案。PRM 在数学推理上稳压 ORM,但标注成本高。
  7. Reward hacking 是核心痛点:模型 over-optimize proxy reward 导致答案变长、谄媚、风格异常;缓解手段 = KL penalty、reward clipping、length penalty、ensemble RM、Constitutional AI / RLAIF(Bai 2022, Lee 2023)。

§1 Post-Training Alignment 直觉

把 LLM 训练分成三段:

为什么 SFT 不够?因为 SFT 只能模仿正例("做得好的样子"),无法显式学对比信号("A 比 B 好")。RL post-training 提供了三种范式:

范式信号代表一句话
RLHF + PPO学一个 RM 模仿偏好,再 RL 优化 RMInstructGPT, ChatGPT, ClaudeRM-in-the-loop on-policy RL
DPO 系跳过 RM,直接在偏好数据上做 contrastive 损失DPO, IPO, SimPO, KTO, ORPOoffline,无需 sampling
GRPO 系RM 在线打分但省 value model,组内归一化算 advantageDeepSeek-R1, Kimi-K1.5数学/代码任务首选
为什么不用纯 reward?

如果你直接 maximize reward,model 会找 RM 的捷径(reward hacking)。KL penalty $\beta \cdot \text{KL}(\pi || \pi_\text{ref})$ 是"防漂移"的核心机制:让 RL 后的策略不要离 SFT base 太远,相当于一个隐式正则。

1.1 语言任务 RL 的特殊性

经典游戏 RL(Atari、Go)和 LLM RL 差异很大,面试时常被反问:

维度游戏 RL(PPO 经典场景)LLM RL
状态空间图像 / 棋盘token 序列,可 $\sim 10^4$ 长
动作空间数十到数百离散动作vocab 大($\sim 10^5$)
轨迹长度数千步通常 1 个 response(整段 generation 后给一次 reward)
Reward 稀疏度中间也有 reward通常只有 terminal reward(response 末尾)
环境独立 simulatorRM(也是个神经网络,会被 hack
on/off-policyon-policy(PPO)RLHF: on-policy;DPO: 完全 offline

因为只有 terminal reward,LLM RL 的 advantage 估计常常用粗粒度方案:PPO+GAE 在每个 token 上分配 advantage(但 reward 大多数 token 是 0);GRPO 直接用整段 response 的 reward,给所有 token 同一个组内归一化 advantage。

§2 PPO 核心

2.1 Vanilla policy gradient 复盘

策略梯度定理:

$$\nabla_\theta J(\theta) = \mathbb{E}_{\tau \sim \pi_\theta}\!\left[\sum_t \nabla_\theta \log \pi_\theta(a_t | s_t)\, A^{\pi_\theta}(s_t, a_t)\right]$$

REINFORCE 是 $A \leftarrow R_t$(return),方差大;Actor-Critic 用 $A^{\pi}(s, a) = Q^\pi(s,a) - V^\pi(s)$ 减方差。

2.2 PPO clipped surrogate(必考公式)

定义重要性比:

$$r_t(\theta) = \frac{\pi_\theta(a_t | s_t)}{\pi_{\theta_\text{old}}(a_t | s_t)}$$

PPO-Clip 的目标函数:

$$\boxed{\;L^{\text{CLIP}}(\theta) = \mathbb{E}_t\!\left[\min\!\Big(r_t(\theta) A_t,\; \text{clip}(r_t(\theta), 1-\epsilon, 1+\epsilon) A_t\Big)\right]\;}$$

直觉:

典型 $\epsilon = 0.1 \sim 0.2$。LLM RLHF 实践中通常用 $0.1 \sim 0.2$,过大易爆 KL。

PPO-Clip vs PPO-Penalty

原论文还有一种 PPO-Penalty 形式:$L = \mathbb{E}[r_t A_t] - \beta\, \text{KL}(\pi_{\theta_\text{old}} \| \pi_\theta)$,并 adaptively 调 $\beta$。生产中clipped 形式更常用(rl4lms / TRL / OpenRLHF 默认)。

2.3 GAE:generalized advantage estimation

定义 TD residual:

$$\delta_t = r_t + \gamma V(s_{t+1}) - V(s_t)$$

GAE 是不同步长 advantage 的指数加权平均

$$\boxed{\;A_t^{\text{GAE}(\gamma, \lambda)} = \sum_{l=0}^{\infty} (\gamma\lambda)^l \delta_{t+l}\;}$$

边界情况:

LLM 中 GAE 的退化:在 RLHF 中通常 $\gamma = 1$(不折扣),且只有 terminal reward,所以 $\delta_t = -V(s_t) + V(s_{t+1})$ 对中间 token、$\delta_T = R_T - V(s_T)$ 对终止 token。这种情况下 GAE 等价于做了"value baseline + reward 回传"。

2.4 PPO 在 RLHF 中的完整目标

LLM 中每个 timestep $t$ 对应生成第 $t$ 个 token,state = $(x, y_{\lt t})$,action = $y_t$。reward 一般加 KL penalty:

$$\tilde{r}_t = \mathbb{1}[t = T] \cdot R(x, y) - \beta \log \frac{\pi_\theta(y_t | x, y_{\lt t})}{\pi_\text{ref}(y_t | x, y_{\lt t})}$$

最终目标:

$$L^{\text{PPO}}(\theta) = L^{\text{CLIP}}(\theta) - c_v \cdot \underbrace{\mathbb{E}_t (V_\phi(s_t) - V_t^\text{target})^2}_{\text{value loss}} + c_e \cdot \underbrace{\mathbb{E}_t \mathcal{H}[\pi_\theta(\cdot | s_t)]}_{\text{entropy bonus}}$$

典型 $c_v = 0.5$,$c_e = 0.01$(LLM 中 entropy bonus 一般很小或为 0,因为 vocab 大本就高熵)。

代码块约定

后文 PPO / RM / DPO / GRPO 四块为教学伪代码,每块独立可读(已各自 import torch / torch.nn.functional as F)。生产实现需要额外补:(1) HF transformer forward 传 attention_mask;(2) decode-time position_ids 处理 padding;(3) gather 前对 targets clip 到 vocab;(4) RM 取 last-token 时按 attention_mask 找真实末尾。本文聚焦核心 loss 推导。

2.5 代码(核心 60 行)

import torch
import torch.nn as nn
import torch.nn.functional as F

def compute_gae(rewards, values, dones, gamma=1.0, lam=0.95):
    """
    rewards: [B, T]    per-token reward (含 KL penalty)
    values:  [B, T+1]  value at s_0...s_T (s_T = terminal, V=0)
    dones:   [B, T]    1 if terminal, 0 otherwise
    returns advantages [B, T], returns [B, T]
    """
    B, T = rewards.shape
    advantages = torch.zeros_like(rewards)
    gae = 0.0
    for t in reversed(range(T)):
        non_term = 1.0 - dones[:, t]
        delta = rewards[:, t] + gamma * values[:, t + 1] * non_term - values[:, t]
        gae = delta + gamma * lam * non_term * gae
        advantages[:, t] = gae
    returns = advantages + values[:, :T]
    return advantages, returns


def ppo_step(policy, value, batch, eps_clip=0.2, c_v=0.5, c_e=0.01):
    """
    batch: dict with keys
      input_ids:    [B, L]     prompt + response tokens
      action_mask:  [B, L]     1 for response tokens, 0 for prompt/pad
      old_log_probs:[B, L]     log π_θold(y_t | s_t) at sample time
      advantages:   [B, L]     GAE advantages (already normalized)
      returns:      [B, L]     GAE returns (V target)
    """
    logits = policy(batch["input_ids"]).logits          # [B, L, V]
    # log-prob of taken action y_t at position t (shifted by 1: predict t+1 from t)
    log_probs = F.log_softmax(logits[:, :-1], dim=-1)
    targets   = batch["input_ids"][:, 1:].unsqueeze(-1)
    new_log_probs = log_probs.gather(-1, targets).squeeze(-1)  # [B, L-1]
    new_log_probs = F.pad(new_log_probs, (1, 0))               # 对齐 [B, L]

    mask = batch["action_mask"].float()
    ratio = torch.exp(new_log_probs - batch["old_log_probs"])  # r_t

    # ── PPO-Clip 核心 ──
    A = batch["advantages"]
    surr1 = ratio * A
    surr2 = torch.clamp(ratio, 1.0 - eps_clip, 1.0 + eps_clip) * A
    policy_loss = -((torch.min(surr1, surr2) * mask).sum() / mask.sum())

    # ── Value loss ──
    V = value(batch["input_ids"]).squeeze(-1)                  # [B, L]
    value_loss = (((V - batch["returns"]) ** 2) * mask).sum() / mask.sum()

    # ── Entropy bonus ──
    probs = log_probs.exp()                                    # [B, L-1, V]
    entropy = -(probs * log_probs).sum(-1)                     # [B, L-1]
    entropy = F.pad(entropy, (1, 0))
    entropy_bonus = (entropy * mask).sum() / mask.sum()

    loss = policy_loss + c_v * value_loss - c_e * entropy_bonus

    # 监控(不参与反传)
    with torch.no_grad():
        approx_kl = ((ratio - 1) - torch.log(ratio.clamp_min(1e-8)))
        approx_kl = (approx_kl * mask).sum() / mask.sum()
        clip_frac = (((ratio < 1 - eps_clip) | (ratio > 1 + eps_clip)).float() * mask).sum() / mask.sum()

    return loss, {"policy": policy_loss.item(), "value": value_loss.item(),
                  "entropy": entropy_bonus.item(),
                  "approx_kl": approx_kl.item(), "clip_frac": clip_frac.item()}
PPO 工程踩坑 top 5

§3 RLHF Pipeline(InstructGPT 范式)

Ouyang et al. 2022 NeurIPS 论文 Training language models to follow instructions with human feedback 是 ChatGPT 的前身论文,定义了今天 RLHF 的标准三阶段:

3.1 Stage 1 — SFT(监督微调)

给定 instruction-response pair $\{(x, y)\}$(高质量人工撰写),做 next-token:

$$\mathcal{L}_\text{SFT}(\phi) = -\mathbb{E}_{(x, y) \sim \mathcal{D}_\text{SFT}}\left[\sum_t \log \pi_\phi(y_t | x, y_{\lt t})\right]$$

输出 $\pi_\text{SFT}$(也叫 $\pi_\text{ref}$,因为下游 RL 拿它做 KL anchor)。

3.2 Stage 2 — RM(Reward Model)

对同一 prompt $x$ 用 $\pi_\text{SFT}$ 采样多个回答,让人两两比较得到偏好对 $(x, y_w, y_l)$,$y_w \succ y_l$。

Bradley-Terry 偏好模型

$$P(y_w \succ y_l | x) = \sigma(r^*(x, y_w) - r^*(x, y_l))$$

其中 $r^*$ 是未知的"真实"奖励函数。我们用 $r_\psi$(一个 transformer,最后一层接 scalar head)拟合:

$$\boxed{\;\mathcal{L}_\text{RM}(\psi) = -\mathbb{E}_{(x, y_w, y_l)} \log \sigma\!\big(r_\psi(x, y_w) - r_\psi(x, y_l)\big)\;}$$

实现细节:

import torch
import torch.nn.functional as F

def rm_loss(reward_model, batch):
    """
    batch:
      chosen_ids:   [B, L]     prompt + y_w
      rejected_ids: [B, L]     prompt + y_l
    """
    r_w = reward_model(batch["chosen_ids"])      # [B]  scalar at last token
    r_l = reward_model(batch["rejected_ids"])    # [B]
    # Bradley-Terry NLL
    loss = -F.logsigmoid(r_w - r_l).mean()
    accuracy = (r_w > r_l).float().mean()
    return loss, accuracy

3.3 Stage 3 — PPO + KL(Policy Optimization)

目标:

$$\boxed{\;\max_{\pi_\theta} \mathbb{E}_{x \sim \mathcal{D},\, y \sim \pi_\theta(\cdot|x)} \big[r_\psi(x, y)\big] - \beta\, \mathbb{E}_x\, \text{KL}\!\big(\pi_\theta(\cdot|x) \,\big\|\, \pi_\text{ref}(\cdot|x)\big)\;}$$

实现时把 KL 拆到每个 token 上,与 RM reward 合并成 per-token reward $\tilde{r}_t$(见 §2.4),然后跑 PPO。


prompt x
   │
   │   π_θ generates response y
   ↓
(x, y)
   │
   │   r_ψ(x, y) → scalar reward       (Stage 2 RM, frozen)
   │   KL(π_θ || π_ref)               (per-token, on the fly)
   ↓
r̃_t = R · 1[t=T] − β log(π_θ/π_ref)
   │
   │   GAE on r̃_t → advantages
   ↓
PPO update on π_θ and V_φ
为什么需要 reference policy?

没有 KL anchor,policy 会严重 over-optimize RM(reward hacking):输出越来越长、重复废话、谄媚("As an AI...")、风格漂移到 RM 的偏见样本上。$\beta = 0.01 \sim 0.1$ 是 InstructGPT 常用范围;太小漂移,太大学不到东西。

3.4 实际工程:4 个模型同时驻留

PPO RLHF 训练时显存里同时有 4 个模型

  1. Policy $\pi_\theta$(trainable)
  2. Reference policy $\pi_\text{ref}$(frozen,算 KL)
  3. Reward model $r_\psi$(frozen,算 reward)
  4. Value model $V_\phi$(trainable,PPO 需要)

这是 RLHF 显存大的根本原因;4 倍 base model + optimizer state + gradient = 容易爆。这也是 DPO / GRPO 在 LLM RL 中被广泛接受的根本原因——它们各自砍掉了某些模型。

§4 DPO:闭式直接偏好优化

Rafailov et al. 2023 NeurIPS Direct Preference Optimization: Your Language Model is Secretly a Reward Model 是 RLHF 简化的里程碑。核心观察:KL-regularized RL 问题的最优解有闭式形式,可以反解得到隐式奖励,于是 PPO 步骤被替换成纯监督学习。

4.1 KL-regularized 最优策略(关键步骤)

考虑 RLHF 目标(公式 §3.3):

$$\max_{\pi} \mathbb{E}_{x \sim \mathcal{D}, y \sim \pi(\cdot|x)}\big[r(x, y)\big] - \beta\, \text{KL}\!\big(\pi(\cdot|x) \| \pi_\text{ref}(\cdot|x)\big)$$

对单个 $x$ 求最优 $\pi^*(\cdot | x)$(Lagrangian):

$$\mathcal{L}_x[\pi] = \sum_y \pi(y|x) r(x, y) - \beta \sum_y \pi(y|x) \log \frac{\pi(y|x)}{\pi_\text{ref}(y|x)} + \mu\!\left(1 - \sum_y \pi(y|x)\right)$$

对 $\pi(y|x)$ 求偏导并令 = 0:

$$r(x, y) - \beta\!\left(\log \frac{\pi(y|x)}{\pi_\text{ref}(y|x)} + 1\right) - \mu = 0$$

整理:

$$\log \pi^*(y|x) = \log \pi_\text{ref}(y|x) + \frac{r(x, y)}{\beta} - \frac{\mu + \beta}{\beta}$$

记 $\log Z(x) = (\mu + \beta)/\beta$(partition function 的 log),得:

$$\boxed{\;\pi^*(y|x) = \frac{1}{Z(x)} \pi_\text{ref}(y|x) \exp\!\left(\frac{r(x, y)}{\beta}\right), \quad Z(x) = \sum_y \pi_\text{ref}(y|x) \exp\!\left(\frac{r(x, y)}{\beta}\right)\;}$$

4.2 反解:implicit reward

把上式取 log 反解 $r$:

$$r(x, y) = \beta \log \frac{\pi^*(y|x)}{\pi_\text{ref}(y|x)} + \beta \log Z(x)$$

关键洞察:reward 是 $\pi^*$ 与 $\pi_\text{ref}$ 的 log-ratio(再加一个不依赖 $y$ 的项 $\beta \log Z(x)$)。所以一旦我们有 $\pi^*$,就有 reward;反之亦然。

4.3 代入 Bradley-Terry 得到 DPO 损失

Bradley-Terry 给出偏好概率:

$$P(y_w \succ y_l | x) = \sigma\!\big(r(x, y_w) - r(x, y_l)\big)$$

代入 §4.2 的反解(注意 $\beta \log Z(x)$ 不依赖 $y$,在 $r(x, y_w) - r(x, y_l)$ 中消掉!):

$$r(x, y_w) - r(x, y_l) = \beta \log \frac{\pi^*(y_w|x)}{\pi_\text{ref}(y_w|x)} - \beta \log \frac{\pi^*(y_l|x)}{\pi_\text{ref}(y_l|x)}$$

把要学的 $\pi^*$ 改记为可学的 $\pi_\theta$,得到 DPO 损失

$$\boxed{\;\mathcal{L}_\text{DPO}(\theta) = -\mathbb{E}_{(x, y_w, y_l) \sim \mathcal{D}}\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)\;}$$

为什么 DPO 这么"反直觉地"有效?

4.4 DPO 梯度的隐含意义

对 $\theta$ 求梯度(推导细节略,原论文 Appendix):

$$\nabla_\theta \mathcal{L}_\text{DPO} = -\beta \mathbb{E}\big[\sigma(\hat{r}_l - \hat{r}_w)\big(\nabla_\theta \log \pi_\theta(y_w|x) - \nabla_\theta \log \pi_\theta(y_l|x)\big)\big]$$

其中 $\hat{r} = \beta \log(\pi_\theta/\pi_\text{ref})$ 是 implicit reward。直觉

4.5 代码(DPO loss 核心 30 行)

import torch
import torch.nn.functional as F

def dpo_loss(policy, ref_policy, batch, beta=0.1):
    """
    batch:
      chosen_ids:    [B, L]     prompt + y_w
      rejected_ids:  [B, L]     prompt + y_l
      chosen_mask:   [B, L]     1 for y_w response tokens, 0 elsewhere (prompt + pad)
      rejected_mask: [B, L]
    """
    # log π(y | x) = sum_t log π(y_t | x, y_<t) over response tokens
    def log_prob_sum(model, ids, mask):
        logits = model(ids).logits[:, :-1]                  # [B, L-1, V]
        logp = F.log_softmax(logits, dim=-1)
        tgt = ids[:, 1:].unsqueeze(-1)                      # [B, L-1, 1]
        token_logp = logp.gather(-1, tgt).squeeze(-1)       # [B, L-1]
        token_mask = mask[:, 1:]                            # 对齐 next-token 预测
        return (token_logp * token_mask).sum(dim=-1)        # [B]

    pi_w  = log_prob_sum(policy,     batch["chosen_ids"],   batch["chosen_mask"])
    pi_l  = log_prob_sum(policy,     batch["rejected_ids"], batch["rejected_mask"])
    with torch.no_grad():
        ref_w = log_prob_sum(ref_policy, batch["chosen_ids"],   batch["chosen_mask"])
        ref_l = log_prob_sum(ref_policy, batch["rejected_ids"], batch["rejected_mask"])

    # log-ratios
    logits_w = pi_w - ref_w        # = log(π/π_ref)(y_w)
    logits_l = pi_l - ref_l
    diff = beta * (logits_w - logits_l)

    loss = -F.logsigmoid(diff).mean()
    # implicit reward margin (用来做监控)
    chosen_reward   = beta * logits_w.detach()
    rejected_reward = beta * logits_l.detach()
    margin = (chosen_reward - rejected_reward).mean()
    accuracy = (chosen_reward > rejected_reward).float().mean()
    return loss, {"loss": loss.item(), "margin": margin.item(),
                  "accuracy": accuracy.item()}
DPO 已知失败模式

§5 GRPO:组相对优势

DeepSeekMath (Shao et al. 2024 arXiv 2402.03300) 提出 Group Relative Policy Optimization,DeepSeek-R1 (DeepSeek-AI 2025 arXiv 2501.12948) 把它推到 reasoning 旗舰位置。

5.1 动机

PPO 的 value model 在 LLM 上很难训:

GRPO 的核心 idea:对每个 prompt $x$ 采样一组 $G$ 个回答 $\{y_1, \dots, y_G\}$,用 RM 打 $G$ 个 reward $\{r_1, \dots, r_G\}$,advantage 直接用组内归一化

$$\boxed{\;\hat{A}_{i, t} = \frac{r_i - \text{mean}(\{r_1, \dots, r_G\})}{\text{std}(\{r_1, \dots, r_G\}) + \epsilon}\;}$$

整段 response 内所有 token 共享同一个 $\hat{A}_i$(因为没有 value model 给 per-token baseline,只用 sequence-level reward 算组相对优势)。

GRPO 的精髓

把 PPO 的 "$A_t = Q - V$"(Critic 出 $V$)换成 "$A_i = (r_i - \bar{r}) / \sigma$"(组内统计出 baseline)。省掉 value model,省下一半显存;同时组内 baseline 自动做了 variance reduction。

5.2 GRPO 目标

GRPO 保留 PPO-Clip 的形式,但加 KL penalty 进 loss(不是进 reward):

记 importance ratio $\rho_{i, t}(\theta) = \pi_\theta(y_{i,t}|x_i, y_{i,\lt t}) / \pi_{\theta_\text{old}}(y_{i,t}|x_i, y_{i,\lt t})$(避免与 sequence-level reward $r_i$ 混淆):

$$L^\text{GRPO}(\theta) = \mathbb{E}\!\left[\frac{1}{G}\sum_{i=1}^G \frac{1}{|y_i|}\sum_{t=1}^{|y_i|} \Big(\min(\rho_{i, t} \hat{A}_{i, t},\, \text{clip}(\rho_{i, t}, 1\!-\!\epsilon, 1\!+\!\epsilon) \hat{A}_{i, t}) - \beta\, \text{KL}_{i, t}(\pi_\theta \| \pi_\text{ref})\Big)\right]$$

其中 KL 用 K3 estimator (Schulman blog 2020):

$$\text{KL}_{i, t} = \frac{\pi_\text{ref}(y_{i,t}|\cdot)}{\pi_\theta(y_{i,t}|\cdot)} - \log\frac{\pi_\text{ref}(y_{i,t}|\cdot)}{\pi_\theta(y_{i,t}|\cdot)} - 1$$

该 estimator 保证非负、低方差,相比直接 $\log(\pi_\theta/\pi_\text{ref})$ 更稳定。

5.3 DeepSeek-R1 的关键改造

DeepSeek-R1 (Jan 2025) 在 GRPO 基础上做了两件事:

  1. R1-Zero:从 pretrain base 直接跑 GRPO,无 SFT 阶段,纯靠 rule-based reward(数学正确性 + 格式奖励)。emergent 长 CoT。
  2. R1:加少量 SFT cold-start + 多阶段 RL(reasoning RL → SFT → general RL)。开源 32B/70B 在数学推理上对标 o1。
为什么 GRPO 在数学/代码 RL 上特别有效?

5.4 代码(GRPO advantage + loss 核心 50 行)

import torch
import torch.nn.functional as F

def grpo_loss(policy, ref_policy, batch, eps_clip=0.2, beta=0.04):
    """
    batch:
      input_ids:     [N, L]       N = sum_b G_b samples in the batch
      action_mask:   [N, L]
      old_log_probs: [N, L]
      rewards:       [N]          sequence-level reward (rule-based or RM)
      group_id:      [N]          which prompt each sample belongs to (long tensor)
    """
    rewards = batch["rewards"]
    gid = batch["group_id"].long()
    N = rewards.shape[0]

    # ── 组内归一化 (GRPO 核心) ──
    # 用 scatter 聚合每个 group 的 mean / std,不假设 group_id 已排序或等大小。
    num_groups = int(gid.max().item()) + 1
    counts = torch.zeros(num_groups, device=rewards.device).scatter_add_(
        0, gid, torch.ones_like(rewards))                              # [num_groups]
    sums = torch.zeros(num_groups, device=rewards.device).scatter_add_(
        0, gid, rewards)                                                # [num_groups]
    group_mean = sums / counts.clamp_min(1.0)                          # [num_groups]
    diff_sq = (rewards - group_mean[gid]) ** 2
    sq_sums = torch.zeros(num_groups, device=rewards.device).scatter_add_(
        0, gid, diff_sq)                                                # [num_groups]
    group_var = sq_sums / counts.clamp_min(1.0)
    group_std = group_var.sqrt()                                       # [num_groups]

    A = (rewards - group_mean[gid]) / (group_std[gid] + 1e-8)          # [N]
    A = A.unsqueeze(-1)                                                # [N, 1] 整段共享

    # ── log-prob ratio ──
    logits = policy(batch["input_ids"]).logits[:, :-1]
    log_probs = F.log_softmax(logits, dim=-1)
    tgt = batch["input_ids"][:, 1:].unsqueeze(-1)
    new_log_probs = log_probs.gather(-1, tgt).squeeze(-1)
    new_log_probs = F.pad(new_log_probs, (1, 0))        # [B*G, L]
    mask = batch["action_mask"].float()

    ratio = torch.exp(new_log_probs - batch["old_log_probs"])

    # ── PPO-Clip surrogate(advantage 整段共享)──
    surr1 = ratio * A                                    # [N, L]
    surr2 = torch.clamp(ratio, 1.0 - eps_clip, 1.0 + eps_clip) * A

    # ── KL penalty (K3 estimator: KL ≈ exp(Δ) - Δ - 1) ──
    with torch.no_grad():
        ref_logits = ref_policy(batch["input_ids"]).logits[:, :-1]
        ref_log_probs = F.log_softmax(ref_logits, dim=-1)
        ref_token_lp = ref_log_probs.gather(-1, tgt).squeeze(-1)
        ref_token_lp = F.pad(ref_token_lp, (1, 0))
    delta = ref_token_lp - new_log_probs                 # log(π_ref / π_θ)
    kl_per_token = torch.exp(delta) - delta - 1.0        # K3, non-negative [N, L]

    # 公式: (1/G) Σ_i (1/|y_i|) Σ_t [ min(...) - β·KL_{i,t} ]
    # 实现: 每个 sample 先按 response 长度 |y_i| 归一化, 再对 batch 取均值
    token_obj = torch.min(surr1, surr2) - beta * kl_per_token   # [N, L]
    seq_len = mask.sum(dim=-1).clamp_min(1.0)            # [N] = |y_i|
    per_seq = (token_obj * mask).sum(dim=-1) / seq_len   # [N]
    loss = -per_seq.mean()                               # 负号: 最大化 -> 最小化

    # 监控
    with torch.no_grad():
        policy_term = -(torch.min(surr1, surr2) * mask).sum(dim=-1) / seq_len
        kl_term = (kl_per_token * mask).sum(dim=-1) / seq_len
    return loss, {"policy": policy_term.mean().item(),
                  "kl": kl_term.mean().item(),
                  "reward_mean": rewards.mean().item(),
                  "advantage_std": A.squeeze(-1).std().item()}
GRPO 工程要点

§6 DPO 变体生态

DPO 之后 2024–2025 出现一大波改进,面试时常被问"X 和 Y 区别"。下表对核心损失差异做对比;记号统一为:$\pi$ = current policy, $\pi_\text{ref}$ = SFT model, $\beta$ = inverse temperature, $r$ = implicit reward。

方法损失关键变化论文
DPO$-\log\sigma(\beta\log\tfrac{\pi(y_w)}{\pi_\text{ref}(y_w)} - \beta\log\tfrac{\pi(y_l)}{\pi_\text{ref}(y_l)})$基础Rafailov 2023 NeurIPS
IPO$(\log\tfrac{\pi(y_w)/\pi_\text{ref}(y_w)}{\pi(y_l)/\pi_\text{ref}(y_l)} - \tfrac{1}{2\beta})^2$sigmoid → squared loss,防止 reward overfittingAzar 2024 AISTATS
KTOper-sample sigmoid loss,only need binary good/bad,不需 pairKahneman-Tversky 启发,desirable/undesirableEthayarajh 2024 ICML
SimPO$-\log\sigma(\beta\cdot\tfrac{1}{\lvert y_w\rvert}\log\pi(y_w) - \beta\cdot\tfrac{1}{\lvert y_l\rvert}\log\pi(y_l) - \gamma)$去 reference、length-normalized、加 margin $\gamma$Meng 2024 NeurIPS
ORPO$\mathcal{L}_\text{SFT}(y_w) + \lambda\cdot\mathcal{L}_\text{OR}$,odds-ratio 偏好SFT + preference 一阶段,无需 referenceHong 2024 EMNLP
RLOOREINFORCE + leave-one-out baseline 从 $k$ 个 sampleonline RL,无 value,强 baselineAhmadian 2024 ACL
ReMaxREINFORCE + greedy baseline(同 prompt greedy decode 作 baseline)进一步省 sampleLi 2024 ICML

6.1 IPO:防止 reward overfit

Azar et al. 2024 A General Theoretical Paradigm to Understand Learning from Human Preferences 指出:Bradley-Terry + DPO 在偏好 deterministic("$y_w$ 总是赢")时会让 implicit reward 无限放大,过拟合。IPO 把 sigmoid 换成 squared loss

$$\mathcal{L}_\text{IPO} = \mathbb{E}\!\left[\left(\log\frac{\pi(y_w)/\pi_\text{ref}(y_w)}{\pi(y_l)/\pi_\text{ref}(y_l)} - \frac{1}{2\beta}\right)^2\right]$$

直觉:希望 log-ratio 等于一个固定 margin $1/(2\beta)$,而不是越大越好。

6.2 KTO:no need for pairs

Ethayarajh et al. 2024 ICML KTO: Model Alignment as Prospect Theoretic Optimization。生产数据常常是 single label("这条好"/"这条不好"),不是 pair。KTO 启发自前景理论(Kahneman-Tversky),对 desirable / undesirable 两类样本对称地推开 reference point

记 implicit reward $\hat{r}_\theta(x, y) = \beta \log \tfrac{\pi_\theta(y|x)}{\pi_\text{ref}(y|x)}$,reference point $z_0 = \mathbb{E}_{x',\, y' \sim \pi_\theta(\cdot | x')}\!\big[\beta \cdot \text{KL}\!\big(\pi_\theta(\cdot | x') \,\|\, \pi_\text{ref}(\cdot | x')\big)\big]$(用 batch 内 mismatched pair 估计、且不参与反传——只当常数)。KTO 损失为:

$$\boxed{\;\mathcal{L}_\text{KTO}(\theta) = \mathbb{E}_{(x, y) \sim \mathcal{D}} \big[\, w(y)\big(1 - v(x, y)\big)\,\big]\;}$$

其中 piecewise 定义(hat r 和 z0 已含 $\beta$,sigmoid 内不再外乘 $\beta$):

$$v(x, y) = \begin{cases}\sigma\!\big(\hat{r}_\theta(x, y) - z_0\big) & y \text{ desirable}\\[2pt] \sigma\!\big(z_0 - \hat{r}_\theta(x, y)\big) & y \text{ undesirable}\end{cases}$$

$$w(y) = \begin{cases}\lambda_D & y \text{ desirable}\\ \lambda_U & y \text{ undesirable}\end{cases}$$

直觉:desirable 样本希望 $\hat{r} > z_0$(推上去),undesirable 样本希望 $\hat{r} < z_0$(压下去);$\sigma$ 给出"距离 reference point 多远"的概率打分。$\lambda_D, \lambda_U$ 是不平衡数据下的权重(如 desirable 多则 $\lambda_U > \lambda_D$)。当数据只有 single thumb up/down 时 KTO 比 DPO 实用。详细形式见 Ethayarajh et al. 2024 ICML、HuggingFace TRL KTOTrainer 实现。

6.3 SimPO:去 reference

Meng et al. 2024 NeurIPS SimPO: Simple Preference Optimization with a Reference-Free Reward。SimPO 观察:DPO 推理时不用 $\pi_\text{ref}$,但训练时存(占显存)。SimPO 直接把 implicit reward 改成 length-normalized log-prob:

$$r_\text{SimPO}(x, y) = \frac{\beta}{|y|}\log\pi(y|x)$$

损失:

$$\boxed{\;\mathcal{L}_\text{SimPO} = -\mathbb{E}\log\sigma\!\left(\frac{\beta}{|y_w|}\log\pi(y_w|x) - \frac{\beta}{|y_l|}\log\pi(y_l|x) - \gamma\right)\;}$$

其中 $\gamma$ 是 target reward margin(鼓励 $r_w - r_l \ge \gamma$,超出才不算 loss)。

SimPO 优势

6.4 ORPO:SFT + 偏好一阶段

Hong et al. 2024 EMNLP ORPO: Monolithic Preference Optimization without Reference Model。ORPO 取消"先 SFT 再 DPO"两阶段,一次训练同时做 SFT 和偏好

$$\mathcal{L}_\text{ORPO} = \mathcal{L}_\text{SFT}(y_w) - \lambda \cdot \log\sigma\!\left(\log\frac{\text{odds}_\theta(y_w|x)}{\text{odds}_\theta(y_l|x)}\right)$$

其中 odds = $p / (1 - p)$。无需 reference model,但需要 chosen response 是高质量的(SFT 部分驱动)。

6.5 RLOO / ReMax

Ahmadian et al. 2024 ACL Back to Basics: Revisiting REINFORCE Style Optimization。在 LLM RLHF 上,简单的 REINFORCE + 多采样 baseline 实测优于 PPO

两者都无 value model,与 GRPO 同源——本质都是用多 sample 或 greedy 的 baseline 替代 critic

GRPO vs RLOO vs ReMax 区分

§7 Reward Modeling 进阶

7.1 PRM vs ORM

维度ORM (Outcome RM)PRM (Process RM)
打分粒度只看最终答案每步 reasoning 都打分
标注成本低(只看结果)高(每步都要标)
奖励信号sparse(轨迹末尾)dense(每步)
数学推理表现
典型用法Best-of-N + ORM 重排PRM 用于 step-level search / RL
代表论文InstructGPT (Ouyang 2022)Let's Verify Step by Step (Lightman 2023 arXiv / 2024 ICLR)

Lightman et al. Let's Verify Step by Step (OpenAI arXiv 2305.20050, 2023; ICLR 2024) 在 MATH 数据集上对比 ORM 和 PRM:

Math-Shepherd (Wang et al. 2024 ACL Math-Shepherd: Verify and Reinforce LLMs Step-by-Step without Human Annotations) 用 rollout-based 自动标注 PRM:从每步出发跑 $K$ 次后续 generation,根据正确率自动给每步打 soft label,省去人工。

7.2 Constitutional AI / RLAIF

Constitutional AI (Bai et al. 2022 Anthropic) Constitutional AI: Harmlessness from AI Feedback

  1. SL stage:让 AI 根据"宪法"原则自己改写 harmful response。
  2. RL stage:用 AI(而非人)做偏好标注 → 训 RM → PPO(即 RLAIF)。

整个 harmless 训练无需人工偏好标注,靠 LLM 自我评估。

RLAIF (Lee et al. 2023 Google) RLAIF: Scaling RLHF with AI Feedback:在 summarization、helpful dialogue 等任务上系统验证 AI feedback ≈ human feedback 效果。条件:LLM 评委足够强(GPT-4 / Claude-3 级),且 prompt 设计良好。

RLAIF 风险

如果评委 LLM 自己有偏见(如 sycophancy、长度偏好),偏见会被放大到 student model。生产中通常混合使用:rule-based(数学/代码)+ RM(一般质量)+ RLAIF(safety)。

7.3 Reward model ensemble & uncertainty

近几年(Coste 2024, Eisenstein 2024)发现:single RM 容易被 hacking,ensemble of RMs(5-7 个不同 seed 的 RM)配合 conservative aggregation(min / mean - $k\cdot$std)可以显著缓解 reward hacking 且不损失性能。代价是显存翻倍——所以工业部署多用 lightweight RM(如 6B 评 70B policy)。

§8 Reward Hacking & 工程经验

Reward hacking 是 RL post-training 的核心痛点:model 找到 RM 的盲点拿高分,但人类觉得变差。常见症状:

现象原因缓解
答案变长长答案在 RM 训练数据里通常分高(信息量、礼貌套话)length penalty / length normalize (SimPO) / 长度回归校准
谄媚 (sycophancy)用户喜欢被认同 → RM 学到"agree better"sycophancy probe + 对抗数据
重复 / 套话句尾"Hope this helps!" 类型在 RM 数据里高分n-gram repetition penalty / 多样性 reward
拒绝过度安全 RM 学到"拒绝就安全"helpfulness vs harmlessness 双 RM 平衡
格式 hack用 markdown / bullet / emoji 拿分格式 normalization
数字操作数学题硬编码常见答案分布rule-based reward 替代 RM

8.1 核心缓解机制

  1. KL penalty ($\beta \log\pi/\pi_\text{ref}$):最基础的 anchor。
  2. Early stopping by KL budget:跑到 $\text{KL}(\pi || \pi_\text{ref}) > K_\text{target}$ 时停。
  3. Reward model ensemble (Coste 2024 ICLR Reward Model Ensembles Help Mitigate Overoptimization):多个 RM 取 min 或 mean - std。
  4. Reward shaping:把 reward 拆成多个项(helpfulness + length + diversity),单独 cap 每项。
  5. 离线 + 在线混合:先 DPO / KTO 拿 70 分,再 PPO + 强 RM 跑最后一公里。
  6. Composite reward:rule-based + RM-based 加权,rule 部分不能被 hack。

8.2 Gao 2023 scaling law

Gao, Schulman, Hilton 2023 ICML Scaling Laws for Reward Model Overoptimization

面试 takeaway:reward hacking 不是 bug,是 RL 本质——proxy 与真目标分离的不可避免现象。

§9 复杂度 / 资源 对比

9.1 四种范式资源对比

维度PPO RLHFDPO 系GRPORLOO/ReMax
需要 RM?✅ frozen❌ implicit✅ frozen 或 rule✅ frozen 或 rule
需要 value model?✅ trainable
需要 reference policy?✅ frozen✅ frozen (SimPO/ORPO 除外)✅ frozen✅ frozen 或不需
Online sampling?✅ on-policy❌ offline✅ on-policy✅ on-policy
模型副本数4 (π, π_ref, RM, V)2 (π, π_ref)3 (π, π_ref, RM)3
KL anchor显式 reward 中隐式 in loss显式 loss 中显式 reward 或 loss
主要瓶颈显存 + on-policy 慢偏好数据质量sampling 多倍sampling 多倍
调参难度 ($\beta, \epsilon, \lambda, c_v, c_e$)中 ($\beta$)中 ($\beta, G$)低 ($\beta, k$)
代表InstructGPT, ClaudeLlama-3 instruct, ZephyrDeepSeek-R1, Kimi-K1.5Cohere Command R

9.2 LLM RLHF 训练显存粗算

以 7B base、fp16 forward + fp32 master、AdamW 为例(典型 RLHF):

副本用途bf16 weightsfp32 optimizer state合计
Policy $\pi_\theta$trainable14 GB28+14+14=56 GB70 GB
Value $V_\phi$trainable14 GB56 GB70 GB
Reference $\pi_\text{ref}$frozen14 GB14 GB
Reward $r_\psi$frozen14 GB14 GB
合计~170 GB

加上 activation、KV cache、generation buffer,单卡 80GB 极难放下;通常用 ZeRO-3 + offload 或多机分片。

DPO 同 base:只需 $\pi_\theta$ + $\pi_\text{ref}$ = 70 + 14 = 84 GB(少一半)。

GRPO 同 base:$\pi_\theta$ + $\pi_\text{ref}$ + RM = 70 + 14 + 14 = 98 GB(省 value 一份)。

9.3 训练吞吐对比

实测(开源 7B、8×H100,TRL/OpenRLHF 报告):

DPO 训练快是因为完全 offline,几乎是 SFT 速度;PPO 慢主要在 rollout(generate 一段 response 才能算一次梯度)。

§10 25 高频面试题

按难度分 3 档:L1 = 任何 LLM 工程岗都会问;L2 = research/alignment 团队会问;L3 = 顶级 lab / DeepSeek 量级团队的硬核题。每题点开看答案要点 + 易踩坑。

L1 必会题(10 题)

Q1.RLHF 的三个阶段是什么?
  • Stage 1: SFT(监督微调)
  • Stage 2: RM(用 Bradley-Terry 训 reward model,frozen)
  • Stage 3: PPO + KL penalty(policy 优化 RM 分,受 reference policy KL 约束)

跳掉 SFT 直接说"RM + PPO";或漏掉 KL penalty。

Q2.PPO clipped surrogate 的公式是什么?
  • $r_t = \pi_\theta / \pi_{\theta_\text{old}}$ 是重要性比
  • $L^\text{CLIP} = \mathbb{E}[\min(r_t A_t,\, \text{clip}(r_t, 1-\epsilon, 1+\epsilon) A_t)]$
  • 取 min 是悲观估计 (pessimistic bound);advantage 为正时上限 $1+\epsilon$,为负时下限 $1-\epsilon$

说"clip 的是 reward";或漏说 min 的作用。

Q3.GAE 是什么?$\lambda$ 怎么取?
  • $A_t^\text{GAE} = \sum_l (\gamma\lambda)^l \delta_{t+l}$,$\delta_t = r_t + \gamma V(s_{t+1}) - V(s_t)$
  • $\lambda = 0$ → TD(0),偏差大方差小
  • $\lambda = 1$ → Monte Carlo,偏差小方差大
  • 典型 $\lambda = 0.95$,$\gamma = 0.99$

把 GAE 当成 advantage 本身(它是估计器);或忘了 $\gamma\lambda$ 是联合衰减系数。

Q4.RM 的损失函数是什么?
  • Bradley-Terry pairwise: $\mathcal{L} = -\mathbb{E}\log\sigma(r(x, y_w) - r(x, y_l))$
  • 用 SFT model 初始化 backbone,最后接 scalar head
  • 训完冻结,给 PPO 用

说 RM 用 BCE / MSE;或写成绝对 reward 监督。

Q5.DPO 损失公式?跟 RM 损失什么关系?
  • $\mathcal{L}_\text{DPO} = -\log\sigma(\beta\log\frac{\pi_\theta(y_w)}{\pi_\text{ref}(y_w)} - \beta\log\frac{\pi_\theta(y_l)}{\pi_\text{ref}(y_l)})$
  • 形式跟 Bradley-Terry RM loss 一样,但implicit reward 是 $\beta\log(\pi/\pi_\text{ref})$,不是单独的 RM
  • 起源:KL-regularized RLHF 最优解 $\pi^* \propto \pi_\text{ref}\exp(r/\beta)$,反解得到 $r = \beta\log(\pi/\pi_\text{ref}) + \beta\log Z$,$\log Z$ 在 pairwise 差里消掉

只背公式不知道闭式推导;或说"DPO 不需要 reference"(错,需要 $\pi_\text{ref}$ 算 log-ratio)。

Q6.DPO 训练时需要哪些数据?
  • 偏好对 $(x, y_w, y_l)$:同一 prompt 下,人或 AI 评判 $y_w \succ y_l$
  • 需要 $\pi_\text{ref}$(一般是 SFT model)
  • 不需要 RM、value model、online sampling

说要 reward scalar 标注;或忘了 $\pi_\text{ref}$。

Q7.GRPO 比 PPO 省了什么?
  • 省掉 value model:advantage 用组内归一化 $\hat{A}_i = (r_i - \bar{r}) / \sigma_r$
  • 显存少一份;调参少一组 ($c_v$、value lr 不需要)
  • 适合 LLM RL,因为 LLM 的 per-token value 很难学

说省了 RM(错,GRPO 还要 RM 或 rule-based reward);或说 GRPO 是 offline(错,它是 on-policy)。

Q8.RLHF 中 KL penalty 起什么作用?
  • Reward 上加 $-\beta\log\pi/\pi_\text{ref}$(per-token KL)
  • 防止 policy 偏离 SFT 太远,缓解 reward hacking
  • $\beta$ 太小 → 漂移,$\beta$ 太大 → 学不到东西
  • 在 DPO 中通过 $\pi_\text{ref}$ 隐式实现

说 KL 是 RM 的一部分(错,KL 是 policy 与 ref 之间的,不涉及 RM)。

Q9.为什么 SFT 之后还要 RL/DPO?
  • SFT 只能模仿正例,学不到对比信号(A 比 B 好)
  • RM 把"哪个好"显式建模,policy 优化"获得高 RM 分"
  • DPO 跳过 RM 但保留了同样的对比信号
  • 实测 RLHF/DPO 后 helpfulness、harmlessness、honesty 都有显著提升(InstructGPT 报告)

只说"RL 比 SFT 强";或不知道对比信号这一点。

Q10.Reward hacking 是什么?怎么缓解?
  • Policy over-optimize RM,找到 RM 盲点拿高分,但人类觉得变差
  • 典型症状:答案变长、谄媚、重复套话、过度拒绝
  • 缓解:KL penalty、RM ensemble、length penalty、composite reward (rule + RM)、early stopping by KL budget

只说"加 KL",不知道其他缓解;或不知道 length bias。

L2 进阶题(10 题)

Q11.推导 DPO loss(从 KL-regularized RLHF 起)。
  1. 目标:$\max_\pi \mathbb{E}[r] - \beta \text{KL}(\pi || \pi_\text{ref})$
  2. Lagrangian + 对 $\pi$ 求导 $\Rightarrow \pi^*(y|x) = \frac{1}{Z(x)}\pi_\text{ref}(y|x)\exp(r/\beta)$
  3. 反解 $r(x, y) = \beta\log(\pi^*/\pi_\text{ref}) + \beta\log Z(x)$
  4. 代入 Bradley-Terry $P(y_w \succ y_l) = \sigma(r_w - r_l)$,$\log Z$ 消掉
  5. 把 $\pi^*$ 替换为可学 $\pi_\theta$,对偏好数据做 NLL → DPO loss

直接背公式,问"$\log Z$ 为什么消掉"答不上来(因为它不依赖 $y$,差掉)。

Q12.PPO 的重要性比 $r_t = \pi_\theta/\pi_\text{old}$ 为什么需要?
  • 标准 PG 是 on-policy 的,但 PPO 在同一 batch 上做多次 update(K 个 epoch)
  • 第 2 次开始 $\pi_\theta \ne \pi_\text{old}$(即采样分布),需要 importance sampling 校正
  • $\nabla \mathbb{E}_{\pi_\theta}[A] = \mathbb{E}_{\pi_\text{old}}[(\pi_\theta/\pi_\text{old}) \nabla\log\pi_\theta A]$
  • Clip 是为了防止 ratio 在多次 update 中飘太远

不知道 PPO 多次 update;或不清楚 IS 的角色。

Q13.DPO vs IPO 区别?什么时候用 IPO?
  • DPO 用 sigmoid loss:偏好越极端,implicit reward 越大(无界)
  • IPO 用 squared loss + 固定 margin $1/(2\beta)$:reward 有界
  • 当偏好数据 deterministic(每对都 $y_w$ 总赢)时 DPO 容易过拟合,IPO 更稳
  • Azar et al. 2024 AISTATS 给出统一框架($\Psi$PO)

说 IPO 是改进 DPO 的 hyperparameter;或不知道 sigmoid 在 deterministic preference 下的 issue。

Q14.SimPO 相比 DPO 改了什么?
  • 去 reference:$r = (\beta / |y|) \log\pi(y)$,不需要 $\pi_\text{ref}$
  • Length normalize:除以 $|y|$,缓解 DPO 的长度偏好
  • Reward margin $\gamma$:要求 $r_w - r_l \ge \gamma$,超出才停止 loss
  • 显存省一倍;但失去 KL anchor,需要更小心调 $\beta, \gamma$

只说"去 reference",不说 length-norm 和 margin;或不知道 SimPO 也是 contrastive。

Q15.GRPO 的 advantage 公式?为什么这样设计?
  • $\hat{A}_i = (r_i - \text{mean}_g(r)) / (\text{std}_g(r) + \epsilon)$,$g$ 是同 prompt 的 group
  • 整段 response 内所有 token 共享同一 $\hat{A}_i$
  • 设计理由:LLM token-level value 难学;用 sequence-level reward + 组内统计直接做 variance reduction
  • 哲学和 RLOO(leave-one-out 均值)、ReMax(greedy baseline)一致:用 sample baseline 替代 critic

写成 per-token advantage(错,GRPO 整段共享);或不知道 GRPO/RLOO/ReMax 的共性。

Q16.PRM vs ORM 差在哪?什么时候用 PRM?
  • ORM 只在最终答案打分;PRM 每步 reasoning 打分
  • PRM 在多步推理任务(数学、code)上明显更好(Lightman 2023, MATH 数据集 78% vs 72%)
  • PRM 标注成本高 → Math-Shepherd 用 rollout-based 自动标
  • PRM 既能做 search 重排,也能做 step-level RL(dense reward)

说 PRM 在所有任务都更好(不对,简单任务 ORM 足够);或不知道 Math-Shepherd 的自动标注。

Q17.Constitutional AI / RLAIF 关键 idea?
  • 用 AI(而非人)做偏好标注,省人工
  • Constitutional AI (Bai 2022 Anthropic):SL stage AI 自我改写 harmful → RL stage AI 偏好打分 → PPO
  • RLAIF (Lee 2023 Google):在 summarization 等任务系统验证 AI ≈ human
  • 风险:评委 LLM 有偏见会放大;通常和 rule-based / human RM 混合

说 RLAIF 就是 GPT-4 来标数据(不全对,CAI 强调"按宪法"自我评估);或不知 CAI 早于 RLAIF 一年。

Q18.PPO 训练时为什么要在 reward 上加 KL,而不是在 loss 上?
  • 加在 reward 上 → 通过 advantage 自然进入 PPO-clip surrogate,per-token 控制
  • 加在 loss 上 → 整体 KL 约束,但失去 token-level resolution
  • GRPO 反而把 KL 放在 loss 上(用 K3 estimator),因为 GRPO 不展开 per-token advantage
  • 两种放法本质都是 KL anchor,但实现细节不同

混淆两种放法;或不知道 GRPO 的 K3 estimator。

Q19.RLHF 中 value model 怎么初始化?为什么?
  • 通常用 RM 或 SFT model 初始化 value backbone,加新 value head
  • 用 RM 初始化的好处:RM 已经"理解 reward",value 收敛更快
  • 用 SFT 初始化的好处:value 与 policy 共享底层表征
  • DeepSpeed-Chat 默认用 RM 初始化;TRL 默认用 SFT
  • 共享 trunk vs 独立模型是 trade-off:A3C/A2C 等经典 actor-critic 共享 trunk 省显存,但 policy 与 value loss scale 不同容易相互干扰;LLM RLHF 主流(DeepSpeed-Chat / TRL / OpenRLHF)选独立模型 + separate optimizer,稳定性优先

随机初始化 value(实践中不可行,太慢);或说"value 必须共享 trunk"/"绝对不能共享",两个极端都不对——是 trade-off 不是定理。

Q20.DPO 训练崩了(margin 不涨 / loss 不降),怎么诊断?
  • chosen_logprejected_logp 是否同时下降(典型 DPO 退化)
  • 看 reference policy 是否正确加载(forgot to load → log-ratio 变成 raw log-prob)
  • 看 $\beta$:太小(< 0.01)loss 几乎 = sigmoid 常数,太大 ($> 1$) 容易 collapse
  • 看数据:$y_w$ 和 $y_l$ 是否真的差异显著
  • 看 length:DPO 偏好长 response,若 $y_w$ 系统性比 $y_l$ 短就有 bug

只说"调 lr";或不知道 likelihood-decrease-for-both 问题。

L3 顶级 lab 题(5 题)

Q21.DeepSeek-R1 vs R1-Zero 的差异?为什么需要 cold-start?
  • R1-Zero:从 pretrain base 直接跑 GRPO + rule-based reward(数学正确 + 格式),无 SFT

    • 优点:emergent 长 CoT,证明 RL 能自激发 reasoning
    • 缺点:可读性差、混语言、格式不稳定
  • R1:cold-start SFT (几千条高质量 reasoning) → reasoning RL → SFT → general RL(多阶段)

    • 修复 R1-Zero 的可读性问题
    • SOTA 数学 / 代码推理
  • R1-Zero 重要性:证明 RL 单独能激发 reasoning,不必先 SFT;后续 self-play / pure-RL 路线的基础

只说 R1 是 R1-Zero 的改进;或不知道 cold-start 修的是什么(可读性,不是性能)。

Q22.GAE 中 $\gamma$ 和 $\lambda$ 谁更重要?LLM RLHF 中通常怎么取?
  • $\gamma$ 是 reward 折扣(任务级),$\lambda$ 是 TD 估计的 trace-decay(算法级)
  • LLM RLHF 中 $\gamma = 1$(不折扣,因为 reward 只在 terminal,折扣会让 early token 收到信号过小)
  • $\lambda = 0.95$ 仍然有用:在 token 维度做 bias-variance 折中
  • $\gamma\lambda$ 联合衰减是 GAE 的有效 trace-decay;$\gamma=1, \lambda=0.95$ 时实际 trace 约 20 token
  • 若 $\gamma = 1, \lambda = 1$ → GAE 退化为 MC,与"reward-to-go - V baseline" 等价

不假思索照搬 game RL 的 $\gamma = 0.99$,不知道 LLM 中 $\gamma = 1$ 是更主流选择(在 terminal-reward + 短上下文 generation 下更合理);或反过来认定 $\gamma$ 必须为 1——具体仍取决于 reward 是否 dense / 是否长 horizon,是工程选择不是定理。

Q23.如何设计一个 RL 框架同时支持 DPO / PPO / GRPO?

抽象出三层:

  1. Data layer:preference pair (DPO) / prompt + group (GRPO) / prompt only (PPO) → 统一 batch interface
  2. Trajectory layer:on-policy rollout (PPO/GRPO) vs offline (DPO)

    • PPO/GRPO 需要 vLLM/sgl 推理加速 + 异步 trajectory queue
    • DPO 完全 dataloader
  3. Loss layer:插件化

    • PPO: clipped surrogate + value + entropy + GAE
    • DPO: log-ratio sigmoid
    • GRPO: clipped surrogate + group-normalized advantage + K3 KL
  4. Reference 管理:DPO/PPO/GRPO 都需 $\pi_\text{ref}$,统一封装为 frozen + lazy load
  5. RM/rule reward:插件化 reward backend(neural RM、unit-test、math checker)

参考:TRL、OpenRLHF、verl (字节)、SimplePO。verl 是 GRPO/RLOO/DAPO 的主流实现框架

只列 PPO;或没考虑 trajectory queue 和异步 rollout。

Q24.如果 RM 和 policy 一起训会怎样?为什么主流 RLHF 不这么做?
  • 直觉:让 RM 也在线学,给 RM 更多新分布的数据 → adversarial training
  • 问题 1:RM 训练目标和 policy 训练目标耦合,loss landscape 不稳定(GAN-like)
  • 问题 2:RM 训练需要 fresh human label,否则会被 policy 拖着 drift
  • 问题 3:RM 信号变化太快 → policy 学到的"什么是好" 不一致
  • 折中方案:iterative preference optimization (Xu et al. 2023 arXiv 2312.16682 Some things are more CRINGE than others: Iterative Preference Optimization with the Pairwise Cringe Loss)、self-rewarding LM (Yuan et al. 2024 Self-Rewarding Language Models) — 每轮用最新 policy 生成响应 + 重新打分(同模型 / 人 / GPT-4),让 RM 隐式更新
  • OpenAI / Anthropic 主流:固定 RM,多轮 PPO;可视化解释更稳定

只说"会不稳定",不给具体原因;或不知道 iterative DPO / self-rewarding 这条 emerging path。

Q25.如果让你设计 next-gen 后训练算法,你会怎么改进 GRPO?

可能的方向(任答 2-3 个,且要有 trade-off 讨论):

  • Adaptive group size:reward variance 大时小 $G$,小时大 $G$(DAPO dynamic sampling)
  • Token-level credit assignment:GRPO 整段共享 advantage → 长 response 信号稀释。可以引入 lightweight critic(VAPO)或基于 step-level reward(PRM)的 partial credit
  • Off-policy correction:GRPO 是 on-policy,rollout 慢;引入 V-trace / Retrace 让 stale samples 也能用
  • Multi-task reward:rule + RM + style 合成 reward,每个维度独立归一化避免 reward scale 不平衡
  • Reward model uncertainty:用 ensemble RM 的 min 或 mean - std 防止 over-optimization
  • Process reward integration:PRM 给 step-level dense advantage,与 group baseline 联合(Math-Shepherd + GRPO 路线)
  • CISPO / 截断 IS (Minimax 2025):解决 GRPO 在 negative advantage 大 ratio 时的稳定性
  • DAPO (ByteDance 2025):clip higher + dynamic sampling + token-level loss + overlong shaping,已开源 verl 实现

只罗列"加 attention / 加更多模型",没 trade-off;或不知道 DAPO / VAPO / CISPO 等 GRPO 后续工作。

§A 附录:参考文献清单

按章节分组,全部经过 codex (gpt-5.5 xhigh) reviewer 验证作者-年份-会议正确:

PPO / RL 基础

RLHF

DPO 系

Critic-free RL

Reward Modeling

Iterative / Self-rewarding

代码框架:TRL (HuggingFace)、OpenRLHF、verl (ByteDance Seed)、Axolotl、LLaMA-Factory、SimplePO。verl 是当前 GRPO/RLOO/DAPO 主流实现,DeepSeek 系工作多基于 verl 复现。