RLHF / DPO / GRPO / PPO 面试 Cheat Sheet
公式推导 + From-Scratch 代码 + 25 高频题(L1 必会 · L2 进阶 · L3 顶级 lab)
§0 TL;DR Cheat Sheet
一页拿下面试核心要点(详见后文 §2–§9 推导)。
- RLHF pipeline (Ouyang 2022 InstructGPT):SFT → RM (Bradley-Terry pairwise) → PPO + per-token KL;价值模型 (value head) 单独训练,policy 与 reference policy 通过 KL 约束。
- 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}$ 平衡偏差/方差。
- 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)})$。
- 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。
- 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,进一步省)。
- PRM vs ORM (Lightman 2023 arXiv / 2024 ICLR):Process-reward 监督每步 reasoning,Math-Shepherd (Wang 2024 ACL) 自动标 PRM;Outcome-reward 只看最终答案。PRM 在数学推理上稳压 ORM,但标注成本高。
- 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 训练分成三段:
- Pretraining:next-token prediction on 万亿 token 语料 —— 学世界知识与语言模式
- SFT (Supervised Fine-Tuning):在 instruction-response pair 上做 next-token —— 学指令格式与基础能力
- Alignment / RL post-training:让模型输出与人类偏好对齐(helpful / harmless / honest)—— 学"哪个回答更好"
为什么 SFT 不够?因为 SFT 只能模仿正例("做得好的样子"),无法显式学对比信号("A 比 B 好")。RL post-training 提供了三种范式:
| 范式 | 信号 | 代表 | 一句话 |
|---|---|---|---|
| RLHF + PPO | 学一个 RM 模仿偏好,再 RL 优化 RM | InstructGPT, ChatGPT, Claude | RM-in-the-loop on-policy RL |
| DPO 系 | 跳过 RM,直接在偏好数据上做 contrastive 损失 | DPO, IPO, SimPO, KTO, ORPO | offline,无需 sampling |
| GRPO 系 | RM 在线打分但省 value model,组内归一化算 advantage | DeepSeek-R1, Kimi-K1.5 | 数学/代码任务首选 |
如果你直接 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 末尾) |
| 环境 | 独立 simulator | RM(也是个神经网络,会被 hack) |
| on/off-policy | on-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]\;}$$
直觉:
- 若 $A_t > 0$(这个 action 比 baseline 好),希望提升 $\pi_\theta(a_t|s_t)$,但最多提升到 $r_t = 1+\epsilon$(防止一次更新太激进)。
- 若 $A_t < 0$(这个 action 比 baseline 差),希望降低 $\pi_\theta(a_t|s_t)$,但最多压到 $r_t = 1-\epsilon$。
min选两者较小者 → 悲观估计(pessimistic bound):当我们想"加分"时,clip 上限;想"扣分"时,clip 下限。
典型 $\epsilon = 0.1 \sim 0.2$。LLM RLHF 实践中通常用 $0.1 \sim 0.2$,过大易爆 KL。
原论文还有一种 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}\;}$$
边界情况:
- $\lambda = 0$ → $A_t = \delta_t$,纯 TD(0),偏差大方差小
- $\lambda = 1$ → $A_t = \sum_l \gamma^l r_{t+l} - V(s_t)$,纯 Monte Carlo(advantage 等于实际 return 减 baseline),偏差小方差大
- 典型 $\lambda = 0.95$,$\gamma = 0.99$
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()}
approx_kl用 $\mathbb{E}[r - 1 - \log r] \ge 0$(Schulman 2020 blog),比 $\mathbb{E}[\log r]$ 更稳,不会负。- 每 epoch 多次 PPO update(典型 4 次),但要监控
approx_kl:超过target_kl(如 0.02)就 early stop。 - Advantage 务必做 batch-level normalization(减均值除标准差),否则 scale 会让 learning rate 失效。
- 用 reference policy 算 KL penalty 时,KL 是 token-level(不是 sequence-level);写错维度容易梯度爆炸。
c_v=0.5只是经验值;若 value loss 远大于 policy loss,会"吃掉"梯度。可以用 separate optimizer 或对 value 单独 lr。
§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)\;}$$
实现细节:
- 一般用 SFT model 初始化 RM(共享 backbone),最后 token 的 hidden state 过线性层得到 scalar reward。
- 训练完后 RM 参数冻结。
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_φ
没有 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 个模型:
- Policy $\pi_\theta$(trainable)
- Reference policy $\pi_\text{ref}$(frozen,算 KL)
- Reward model $r_\psi$(frozen,算 reward)
- 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)\;}$$
- 它没有显式 reward model,但隐式 reward = $\beta \log(\pi/\pi_\text{ref})$。
- 它不需要 sampling(不像 PPO 要 on-policy rollouts),整个训练就是 offline contrastive learning。
- KL 约束是隐式写进 loss 的(通过 $\pi_\text{ref}$ 在 log-ratio 分母里)。
- 整个流水线变成 SFT-style:监督学习一遍就完事。
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。直觉:
- 系数 $\sigma(\hat{r}_l - \hat{r}_w)$ 是"当前模型对 $y_l \succ y_w$ 的错误置信度"——错得越自信,权重越大(hard-example mining 效应)。
- 接着提升 $\log \pi_\theta(y_w | x)$ 并降低 $\log \pi_\theta(y_l | x)$。
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()}
- Likelihood decreases for both $y_w$ and $y_l$(Pal et al. 2024, Saeidi et al.):DPO 只要求 $\log\pi(y_w) - \log\pi(y_l)$ 涨,没强制 $\log\pi(y_w)$ 涨。实测中两者经常一起降,只是 $y_l$ 降得更多——可能导致模型"什么都不愿意说"。
- 对 $\beta$ 敏感:$\beta$ 太小→失去 KL 约束→reward hacking;太大→学不动。常用 $0.05 \sim 0.5$。
- 数据质量决定一切:偏好对噪声大时 DPO 比 PPO 更脆弱(PPO 通过 RM ensemble 缓冲,DPO 直接吃原数据)。
- off-policy bias:偏好数据是 $\pi_\text{SFT}$ 采的,但 $\pi_\theta$ 在训练中漂移,存在分布偏移。
§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 上很难训:
- LLM token-level value 没有明确语义(中间 token 通常 reward = 0,只有 terminal 才有)
- Value model 与 policy 同等大小 → 显存双倍
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 算组相对优势)。
把 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 基础上做了两件事:
- R1-Zero:从 pretrain base 直接跑 GRPO,无 SFT 阶段,纯靠 rule-based reward(数学正确性 + 格式奖励)。emergent 长 CoT。
- R1:加少量 SFT cold-start + 多阶段 RL(reasoning RL → SFT → general RL)。开源 32B/70B 在数学推理上对标 o1。
- Rule-based reward:数学有唯一答案、代码有单元测试,绕过 neural RM,reward hacking 风险显著降低(reward signal 接近地面真相,但 policy 仍可能找 grader 漏洞,例如猜答案、不写推理只写"42"、利用 test 覆盖盲区等,所以"完全没有 hacking"不严谨)。
- 组内归一化:同一道题采 $G=16$ 个 solution,自动找出"哪些 reasoning path 更好",不需要绝对 scale。
- 省 value model:数学 prompt 多、reasoning 长,省一半显存能跑更大 batch。
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()}
- $G$ 一般取 8/16/32:太小组内统计噪声大,太大显存爆。
std为 0 的退化情况(组内 reward 全相同,all-pass / all-fail):加 $\epsilon$ 或丢掉该组。- DAPO (ByteDance Seed, 2025 arXiv 2503.14476) 对 GRPO 做了多项改进:clip higher (打破对称 clip)、dynamic sampling(丢全对全错 group)、token-level loss、overlong shaping,是 GRPO 的工业级进阶。
- DeepSeek 在 R1 报告中也讨论了 GRPO 的限制:组内 baseline 在 reward 方差小或 group size 小的情况下会失效;后续工作(如 VAPO、CISPO)尝试改进。
§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 overfitting | Azar 2024 AISTATS |
| KTO | per-sample sigmoid loss,only need binary good/bad,不需 pair | Kahneman-Tversky 启发,desirable/undesirable | Ethayarajh 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 一阶段,无需 reference | Hong 2024 EMNLP |
| RLOO | REINFORCE + leave-one-out baseline 从 $k$ 个 sample | online RL,无 value,强 baseline | Ahmadian 2024 ACL |
| ReMax | REINFORCE + greedy baseline(同 prompt greedy decode 作 baseline) | 进一步省 sample | Li 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)。
- 训练时无需 $\pi_\text{ref}$,省一份模型权重的显存。
- Length-normalization 缓解 DPO 的 length bias(DPO 倾向选长答案,因为它们 log-prob 更负,差更大)。
- 实验上 AlpacaEval-2 / Arena-Hard 上 SimPO 经常优于 DPO;但 reward-free 形式没有 KL 锚定,对 $\beta, \gamma$ 调参更敏感。
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:
- RLOO:对每 prompt 采 $k$ 个 response,每个的 baseline = 其余 $k-1$ 个的平均 reward(leave-one-out),$\hat{A}_i = r_i - \frac{1}{k-1}\sum_{j\ne i} r_j$。
- ReMax (Li et al. 2024 ICML):baseline 直接用同 prompt 的 greedy decode reward,每次只需 1 sample + 1 greedy。
两者都无 value model,与 GRPO 同源——本质都是用多 sample 或 greedy 的 baseline 替代 critic。
- GRPO:组内 mean+std 归一化($z$-score)+ PPO-clip。
- RLOO:组内 leave-one-out 均值做 baseline + REINFORCE。
- ReMax:greedy decode 做 baseline + REINFORCE。
- 三者哲学一致:绕过 value model,用 sample baseline;区别只在 baseline 形式。
§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:
- PRM800K:80 万 step-level 标注(每步标 ✓ / ⚠️ / ✗)。
- 在 GPT-4 generator 上,PRM 重排 1860 个候选时 MATH 准确率 78.2%,明显高于 ORM 的 72.4%。
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:
- SL stage:让 AI 根据"宪法"原则自己改写 harmful response。
- 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 设计良好。
如果评委 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 核心缓解机制
- KL penalty ($\beta \log\pi/\pi_\text{ref}$):最基础的 anchor。
- Early stopping by KL budget:跑到 $\text{KL}(\pi || \pi_\text{ref}) > K_\text{target}$ 时停。
- Reward model ensemble (Coste 2024 ICLR Reward Model Ensembles Help Mitigate Overoptimization):多个 RM 取 min 或 mean - std。
- Reward shaping:把 reward 拆成多个项(helpfulness + length + diversity),单独 cap 每项。
- 离线 + 在线混合:先 DPO / KTO 拿 70 分,再 PPO + 强 RM 跑最后一公里。
- 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:
- Proxy reward (RM score) 随 KL 单调上升,但 gold reward 先升后降 (inverted-U)。
- Best-of-N 的 over-optimization 与 PPO 形式略不同:BoN 的 gold reward 在 $\sqrt{\text{KL}}$ 上接近线性 -减 + 线性,PPO 多了高阶项。
- 给出 RM 越大、过优化越慢的 scaling law,论文中也讨论了不同函数形式拟合。
面试 takeaway:reward hacking 不是 bug,是 RL 本质——proxy 与真目标分离的不可避免现象。
§9 复杂度 / 资源 对比
9.1 四种范式资源对比
| 维度 | PPO RLHF | DPO 系 | GRPO | RLOO/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, Claude | Llama-3 instruct, Zephyr | DeepSeek-R1, Kimi-K1.5 | Cohere Command R |
9.2 LLM RLHF 训练显存粗算
以 7B base、fp16 forward + fp32 master、AdamW 为例(典型 RLHF):
| 副本 | 用途 | bf16 weights | fp32 optimizer state | 合计 |
|---|---|---|---|---|
| Policy $\pi_\theta$ | trainable | 14 GB | 28+14+14=56 GB | 70 GB |
| Value $V_\phi$ | trainable | 14 GB | 56 GB | 70 GB |
| Reference $\pi_\text{ref}$ | frozen | 14 GB | — | 14 GB |
| Reward $r_\psi$ | frozen | 14 GB | — | 14 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 报告):
- PPO:~50-100 token/s/GPU(瓶颈:on-policy generation + 4 副本)
- DPO:~500-1000 token/s/GPU(纯监督,无 generation)
- GRPO:~100-200 token/s/GPU(需要 generation,但少一个模型)
- SimPO:~600-1200 token/s/GPU(DPO 进一步去 reference)
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 起)。
- 目标:$\max_\pi \mathbb{E}[r] - \beta \text{KL}(\pi || \pi_\text{ref})$
- Lagrangian + 对 $\pi$ 求导 $\Rightarrow \pi^*(y|x) = \frac{1}{Z(x)}\pi_\text{ref}(y|x)\exp(r/\beta)$
- 反解 $r(x, y) = \beta\log(\pi^*/\pi_\text{ref}) + \beta\log Z(x)$
- 代入 Bradley-Terry $P(y_w \succ y_l) = \sigma(r_w - r_l)$,$\log Z$ 消掉
- 把 $\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_logp和rejected_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?
抽象出三层:
- Data layer:preference pair (DPO) / prompt + group (GRPO) / prompt only (PPO) → 统一 batch interface
Trajectory layer:on-policy rollout (PPO/GRPO) vs offline (DPO)
- PPO/GRPO 需要 vLLM/sgl 推理加速 + 异步 trajectory queue
- DPO 完全 dataloader
Loss layer:插件化
- PPO: clipped surrogate + value + entropy + GAE
- DPO: log-ratio sigmoid
- GRPO: clipped surrogate + group-normalized advantage + K3 KL
- Reference 管理:DPO/PPO/GRPO 都需 $\pi_\text{ref}$,统一封装为 frozen + lazy load
- 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 基础
- Schulman et al. 2017 arXiv 1707.06347 Proximal Policy Optimization Algorithms
- Schulman et al. 2016 ICLR High-Dimensional Continuous Control Using GAE
- Schulman 2020 blog Approximating KL Divergence(K3 estimator 来源)
RLHF
- Christiano et al. 2017 NeurIPS Deep Reinforcement Learning from Human Preferences(pairwise preference + RM 第一篇)
- Stiennon et al. 2020 NeurIPS Learning to Summarize from Human Feedback(OpenAI summarization 报告)
- Ouyang et al. 2022 NeurIPS Training Language Models to Follow Instructions with Human Feedback(InstructGPT)
- Bai et al. 2022 Anthropic arXiv 2204.05862 Training a Helpful and Harmless Assistant with RLHF
- Bai et al. 2022 Anthropic arXiv 2212.08073 Constitutional AI
- Lee et al. 2023 Google arXiv 2309.00267 RLAIF: Scaling RLHF with AI Feedback
DPO 系
- Rafailov et al. 2023 NeurIPS Direct Preference Optimization
- Azar et al. 2024 AISTATS A General Theoretical Paradigm to Understand Learning from Human Preferences(IPO)
- Ethayarajh et al. 2024 ICML KTO: Model Alignment as Prospect Theoretic Optimization
- Meng et al. 2024 NeurIPS SimPO: Simple Preference Optimization with a Reference-Free Reward
- Hong et al. 2024 EMNLP ORPO: Monolithic Preference Optimization without Reference Model
- Tang et al. 2024 ICML Generalized Preference Optimization (统一 DPO/IPO/SLiC 框架)
Critic-free RL
- Ahmadian et al. 2024 ACL Back to Basics: Revisiting REINFORCE Style Optimization (RLOO)
- Li et al. 2024 ICML ReMax: A Simple, Effective, and Efficient Reinforcement Learning Method
- Shao et al. 2024 arXiv 2402.03300 DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models(GRPO 提出)
- DeepSeek-AI 2025 arXiv 2501.12948 DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning
- Yu et al. 2025 ByteDance arXiv 2503.14476 DAPO: An Open-Source LLM Reinforcement Learning System at Scale
Reward Modeling
- Lightman et al. 2024 ICLR / OpenAI arXiv 2305.20050 (2023) Let's Verify Step by Step(PRM800K, PRM vs ORM)
- Wang et al. 2024 ACL Math-Shepherd: Verify and Reinforce LLMs Step-by-Step without Human Annotations
- Coste et al. 2024 ICLR Reward Model Ensembles Help Mitigate Overoptimization
- Eisenstein et al. 2024 COLM (arXiv 2312.09244, 2023) Helping or Herding? Reward Model Ensembles Mitigate but do not Eliminate Reward Hacking
- Gao, Schulman, Hilton 2023 ICML Scaling Laws for Reward Model Overoptimization
Iterative / Self-rewarding
- Xu et al. 2023 arXiv 2312.16682 Some things are more CRINGE than others: Iterative Preference Optimization with the Pairwise Cringe Loss
- Yuan et al. 2024 ICML Self-Rewarding Language Models
- Pal et al. 2024 arXiv 2402.13228 Smaug: Fixing Failure Modes of Preference Optimisation with DPO-Positive
代码框架:TRL (HuggingFace)、OpenRLHF、verl (ByteDance Seed)、Axolotl、LLaMA-Factory、SimplePO。verl 是当前 GRPO/RLOO/DAPO 主流实现,DeepSeek 系工作多基于 verl 复现。