RLHF 深度解析:从人类反馈到 PPO/GRPO/DPO 的对齐革命

5129 字
26 分钟
RLHF 深度解析:从人类反馈到 PPO/GRPO/DPO 的对齐革命

1. 引言:为什么需要”对齐”?#

1.1 从 SFT 到 RLHF 的进化#

如果说预训练给学生灌输了整个互联网的知识,SFT 教会学生”听人话做事”,那么RLHF 就是让学生学会**“做正确的事”**——不仅按指令,还要符合人类的价值观、偏好与安全约束。

训练范式的演进:
预训练 (Pre-training)
↓ 学习"语言 + 世界知识"
↓ 能力:续写、模仿
SFT (Supervised Fine-Tuning)
↓ 学习"指令 → 回答"
↓ 能力:助手、对话
RLHF (Reinforcement Learning from Human Feedback)
↓ 学习"偏好 + 价值观"
↓ 能力:有用 (Helpful) + 无害 (Harmless) + 诚实 (Honest)

1.2 SFT 解决不了的问题#

即使做完 SFT,模型仍会表现出:

问题表现例子
胡编乱造一本正经说错信息编造不存在的论文
有害输出教用户做危险的事制造武器、绕过安全
过度冗长不必要的客套话”作为 AI 助手…”
风格不适配不符合期望语气客服场景过于正式
幻觉 + 自信错误但充满信心错误医学建议

这些问题是主观偏好价值观判断,无法用”标准答案”完全标注——SFT 的最大似然损失没有偏好信号

一个关键洞见

SFT 优化的是 p(answerquestion)p(\text{answer} | \text{question}),但 RLHF 优化的是 p(answerquestion,preference)p(\text{answer} | \text{question}, \text{preference})。后者编码了”哪一个更好”这一隐性知识。

1.3 RLHF 的核心思想#

两阶段训练

  1. 奖励建模(Reward Modeling):学习一个人类偏好的”打分器”
  2. 策略优化(Policy Optimization):用 RL 让 LLM 生成高分回答
┌──────────────────────────────────────────────────────────────┐
│ RLHF 流程总览 │
├──────────────────────────────────────────────────────────────┤
│ │
│ ① 收集偏好数据 │
│ prompt + response_A + response_B + 人类标注 A>B │
│ ↓ │
│ ② 训练奖励模型 RM(y|x) │
│ loss = -log σ( RM(y_w|x) - RM(y_l|x) ) │
│ ↓ │
│ ③ 用 PPO 优化 SFT 模型 │
│ reward = RM(y|x) - β·KL(π_θ || π_ref) │
│ │
└──────────────────────────────────────────────────────────────┘

2. 偏好数据:从反馈到标注#

2.1 数据形式#

每个偏好样本是一个三元组四元组

(x, yw, yl)(x,\ y_w,\ y_l)

其中:

  • xx:提示(prompt)
  • ywy_w:被人类标注为”更好”的回答(winner)
  • yly_l:被人类标注为”更差”的回答(loser)

2.2 数据来源#

preference_data_sources = {
# 1. 人类标注
"human_annotation": "标注员对同一 prompt 的多个回答进行排序",
# 2. AI 反馈(RLAIF / Constitutional AI)
"ai_feedback": "用强模型按宪法原则评判弱模型回答",
# 3. 用户隐式反馈
"implicit_feedback": "点赞、采纳、停留时间、复制按钮",
# 4. 合成数据
"synthetic": "用 prompt 模板生成 y_w, 再故意制造 y_l 错误",
}

2.3 数据质量的关键#

维度影响工程经验
标注一致性RM 学到正确偏好多标注员 + Krippendorff α
多样性RM 不偏科跨领域、跨任务、跨长度
边界 caseRM 鲁棒性故意加入对抗样本
失败模式覆盖知道”哪里不好”红队测试数据
数据陷阱

标注员有风格偏好(偏好长回答),导致 RM 学会”越长越好”。解决:在 prompt 中明确告知”长度不是评判标准”。


3. 奖励模型(Reward Model)#

3.1 Bradley-Terry 模型#

假设人类偏好遵循 Bradley-Terry 模型:

P(ywylx)=exp(R(x,yw))exp(R(x,yw))+exp(R(x,yl))=σ(R(x,yw)R(x,yl))P(y_w \succ y_l \mid x) = \frac{\exp(R(x, y_w))}{\exp(R(x, y_w)) + \exp(R(x, y_l))} = \sigma\big(R(x, y_w) - R(x, y_l)\big)

其中 R(x,y)R(x, y) 是真实的”人类偏好分数”。我们用一个神经网络 RθR_\theta 来近似它。

3.2 损失函数#

对数似然:

LRM=E(x,yw,yl)D[logσ(Rθ(x,yw)Rθ(x,yl))]\mathcal{L}_{\text{RM}} = -\mathbb{E}_{(x,y_w,y_l)\sim D}\Big[\log \sigma\big(R_\theta(x,y_w) - R_\theta(x,y_l)\big)\Big]

直觉:拉大 winner 和 loser 的分数差

3.3 实现#

import torch
import torch.nn as nn
from transformers import AutoModelForCausalLM
class RewardModel(nn.Module):
"""
基于 LLM 的奖励模型。
通常是一个 LLM + 一个标量回归头,预测回答的"人类偏好分数"。
"""
def __init__(self, base_model_path: str, cache_dir: str = None):
super().__init__()
# 加载与 SFT 相同架构的 LLM
self.backbone = AutoModelForCausalLM.from_pretrained(
base_model_path, cache_dir=cache_dir, torch_dtype=torch.bfloat16
)
hidden_size = self.backbone.config.hidden_size
# 标量奖励头
self.score_head = nn.Linear(hidden_size, 1, bias=False)
# 初始化为接近 0(让初始分数居中)
nn.init.zeros_(self.score_head.weight)
def forward(self, input_ids: torch.Tensor, attention_mask: torch.Tensor):
"""
输入: 拼接 [prompt; response]
输出: 最后一个 token 的标量分数
"""
outputs = self.backbone(
input_ids=input_ids,
attention_mask=attention_mask,
output_hidden_states=True,
)
# 取每个序列最后一个有效 token 的隐藏状态
last_hidden = outputs.hidden_states[-1] # (B, L, H)
sequence_lengths = attention_mask.sum(dim=1) - 1
batch_idx = torch.arange(last_hidden.size(0), device=last_hidden.device)
last_token_hidden = last_hidden[batch_idx, sequence_lengths]
score = self.score_head(last_token_hidden).squeeze(-1)
return score
class RewardModelLoss(nn.Module):
"""Bradley-Terry 偏好损失"""
def forward(self, score_w: torch.Tensor, score_l: torch.Tensor) -> torch.Tensor:
return -torch.nn.functional.logsigmoid(score_w - score_l).mean()

3.4 训练实践#

def train_reward_model(model, dataset, optimizer, epochs=2, batch_size=4):
for epoch in range(epochs):
for batch in dataset:
# batch 包含 (x, y_w, y_l) 三组 tokenized 输入
score_w = model(batch["input_ids_w"], batch["attention_mask_w"])
score_l = model(batch["input_ids_l"], batch["attention_mask_l"])
loss = -torch.nn.functional.logsigmoid(score_w - score_l).mean()
optimizer.zero_grad()
loss.backward()
optimizer.step()

3.5 评估 RM 的方法#

def evaluate_rm(model, eval_pairs):
"""
评估 RM 的"判别准确率":
在测试集上,正确判定 y_w > y_l 的比例。
"""
correct = 0
for pair in eval_pairs:
score_w = model(pair["x_w"])
score_l = model(pair["x_l"])
if score_w > score_l:
correct += 1
return correct / len(eval_pairs)

4. PPO:经典的策略优化算法#

4.1 为什么不用 SFT 直接拟合 RM?#

直觉:用 RM 给回答打分,然后 SFT 用 rewardp(yx)\text{reward} \cdot p(y|x) 加权拟合。问题

  1. 分布偏移:RM 只在 SFT 数据上学过,对”模型自己生成的分布”外推差
  2. Reward hacking:模型学会 RM 的盲点(比如生成”看起来很好但其实乱码”的回答)
  3. 无约束:可能偏离原始 SFT 模型,丧失能力

4.2 RL 基础#

把 LLM 视为一个自回归策略 πθ(yx)\pi_\theta(y|x)

πθ(yx)=t=1yπθ(ytx,y<t)\pi_\theta(y|x) = \prod_{t=1}^{|y|} \pi_\theta(y_t | x, y_{<t})

目标是最大化期望奖励:

J(θ)=Eyπθ[R(x,y)]J(\theta) = \mathbb{E}_{y\sim\pi_\theta}\big[R(x,y)\big]

4.3 KL 约束:锚定参考策略#

为防止 πθ\pi_\theta 偏离太远,加入 KL 惩罚:

JRLHF(θ)=Eyπθ[R(x,y)βKL(πθ(x)πref(x))]J_{\text{RLHF}}(\theta) = \mathbb{E}_{y\sim\pi_\theta}\Big[R(x,y) - \beta\,\text{KL}\big(\pi_\theta(\cdot|x)\,\|\,\pi_{\text{ref}}(\cdot|x)\big)\Big]

其中 πref\pi_{\text{ref}} 是 SFT 模型(参数冻结),β\beta 控制约束强度。

直觉

KL 项相当于”不许忘本”。模型可以优化 RM,但不能变成另一个完全不同的模型。

4.4 PPO 目标函数#

PPO 是信赖域优化的实用版本:

LPPO(θ)=Et[min(rt(θ)At, clip(rt(θ),1ϵ,1+ϵ)At)]\mathcal{L}_{\text{PPO}}(\theta) = -\mathbb{E}_t\Big[\min\big(r_t(\theta)\,A_t,\ \text{clip}(r_t(\theta), 1-\epsilon, 1+\epsilon)\,A_t\big)\Big]

其中:

  • 重要性比率:rt(θ)=πθ(atst)πθold(atst)r_t(\theta) = \frac{\pi_\theta(a_t|s_t)}{\pi_{\theta_{\text{old}}}(a_t|s_t)}
  • 优势函数:AtA_t(用 GAE 或 critic 估计)
  • ϵ\epsilon 通常为 0.2

clip 机制:限制新旧策略的比率不超出 [1ϵ,1+ϵ][1-\epsilon, 1+\epsilon],避免一次更新步子过大。

4.5 RM + KL 的奖励设计#

PPO 中每个 token 的”奖励”:

rt={R(x,y)β(logπθ(yt)logπref(yt))t=Tβ(logπθ(yt)logπref(yt))t<Tr_t = \begin{cases} R(x, y) - \beta\,\big(\log \pi_\theta(y_t|\cdot) - \log \pi_{\text{ref}}(y_t|\cdot)\big) & t = T \\ -\beta\,\big(\log \pi_\theta(y_t|\cdot) - \log \pi_{\text{ref}}(y_t|\cdot)\big) & t < T \end{cases}

只有最后一个 token获得真实 RM 分数,前面所有 token 的”奖励”只是负的 KL 惩罚——鼓励每个位置的策略不偏离参考。

4.6 PPO for LLM 的完整实现#

import torch
import torch.nn.functional as F
def compute_gae(rewards, values, dones, gamma=0.99, lam=0.95):
"""广义优势估计 GAE"""
advantages = torch.zeros_like(rewards)
last_adv = 0
T = rewards.size(1)
for t in reversed(range(T)):
if t == T - 1:
next_value = 0
else:
next_value = values[:, t + 1]
nonterminal = 1.0 - dones[:, t]
delta = rewards[:, t] + gamma * next_value * nonterminal - values[:, t]
last_adv = delta + gamma * lam * nonterminal * last_adv
advantages[:, t] = last_adv
returns = advantages + values
return advantages, returns
def ppo_loss(
log_probs_new, # 新策略对每个 token 的 log prob: (B, T)
log_probs_old, # 旧策略(rollout 时)的 log prob
advantages, # GAE 优势
clip_ratio=0.2,
):
"""PPO clipped surrogate loss"""
ratio = torch.exp(log_probs_new - log_probs_old)
surr1 = ratio * advantages
surr2 = torch.clamp(ratio, 1 - clip_ratio, 1 + clip_ratio) * advantages
policy_loss = -torch.min(surr1, surr2).mean()
return policy_loss
def rlhf_train_step(
policy_model, # π_θ,待优化
ref_model, # π_ref,冻结
reward_model, # R(x,y)
critic, # 价值网络 V(s)
batch, # prompt 列表
beta=0.1, # KL 系数
clip_ratio=0.2,
):
"""
RLHF 单步训练流程(简化的 PPO):
1. 用当前 policy 生成回答(rollout)
2. 用 RM 评分
3. 计算 KL 惩罚
4. 用 GAE 计算优势
5. PPO 更新 policy 与 critic
"""
prompts = batch["prompts"]
# === 1. Rollout:用当前策略生成回答 ===
with torch.no_grad():
responses, response_mask = policy_model.generate(
prompts, max_new_tokens=256, do_sample=True, temperature=1.0
)
# === 2. 计算旧策略的 log prob(用于重要性采样) ===
with torch.no_grad():
log_probs_old = compute_log_probs(policy_model, responses)
# === 3. 用奖励模型打分 ===
with torch.no_grad():
rewards = reward_model(prompts + responses)
# === 4. 计算 KL 惩罚(per token) ===
with torch.no_grad():
log_probs_ref = compute_log_probs(ref_model, responses)
kl_per_token = log_probs_old - log_probs_ref # = log(π_θ / π_ref)
# 最后一个 token 获得 RM 分数;其余 token 仅 KL 惩罚
T = responses.size(1)
token_rewards = -beta * kl_per_token
token_rewards[:, -1] += rewards
# === 5. GAE 计算优势 ===
with torch.no_grad():
values = critic(responses)
dones = torch.zeros_like(token_rewards)
dones[:, -1] = 1.0 # 序列结束
advantages, returns = compute_gae(token_rewards, values, dones)
advantages = (advantages - advantages.mean()) / (advantages.std() + 1e-8)
# === 6. PPO 更新(通常做 K_mini_epochs 次) ===
for _ in range(4):
log_probs_new = compute_log_probs(policy_model, responses)
policy_loss = ppo_loss(log_probs_new, log_probs_old, advantages, clip_ratio)
value_pred = critic(responses)
value_loss = F.mse_loss(value_pred, returns)
loss = policy_loss + 0.5 * value_loss
loss.backward()
# ... optimizer.step()

4.7 PPO 的工程痛点#

痛点原因缓解
显存爆炸同时持有 policy、ref、RM、criticLoRA + 共享参数
训练不稳定大 reward 方差Reward 归一化、KL warmup
Reward hacking模型找到 RM 漏洞多 RM ensemble
每步 4 模型前向vLLM rollout
崩溃极端 KL 时崩早停 + checkpoint rollback
经典教训

InstructGPT 论文报告:RLHF 训练中,约 10-30% 的训练会因奖励坍缩或 KL 爆炸而中断。需要持续监控。


5. GRPO:DeepSeek 提出的高效替代#

5.1 动机#

PPO 的最大开销:

  • 一个额外的 critic 网络(与 policy 同尺寸)
  • 每个 prompt 一次采样 → GAE 优势估计
  • 4 个模型同时在显存

5.2 GRPO 核心思想#

**GRPO(Group Relative Policy Optimization)**由 DeepSeek 提出:

不需要 critic,对同一 prompt 采样一组回答,用组内相对排名作为优势。

5.3 算法流程#

对每个 prompt x:
1. 用 π_θ 采样 G 个回答 {y_1, y_2, ..., y_G}
2. 用 RM 给每个回答打分 {r_1, r_2, ..., r_G}
3. 组内归一化得到优势:
A_i = (r_i - mean(r)) / std(r)
4. 用优势做 PPO 风格更新

5.4 优势计算#

Ai=rimean(r)std(r),i=1,,GA_i = \frac{r_i - \text{mean}(\mathbf{r})}{\text{std}(\mathbf{r})}, \quad i = 1,\ldots,G

直觉:比平均好的回答获得正优势,比平均差的获得负优势。无需 critic,无需 GAE。

5.5 完整损失#

LGRPO(θ)=E[1Gi=1G(min(riAi,clip(ri,1ϵ,1+ϵ)Ai)βKL(πθπref))]\mathcal{L}_{\text{GRPO}}(\theta) = -\mathbb{E}\Big[\frac{1}{G}\sum_{i=1}^{G}\big(\min(r_i A_i, \text{clip}(r_i, 1-\epsilon, 1+\epsilon) A_i) - \beta\,\text{KL}(\pi_\theta \| \pi_{\text{ref}})\big)\Big]

其中重要性比率:

ri(θ)=πθ(yix)πθold(yix)r_i(\theta) = \frac{\pi_\theta(y_i|x)}{\pi_{\theta_{\text{old}}}(y_i|x)}

5.6 GRPO 实现#

import torch
import torch.nn.functional as F
def grpo_loss(
log_probs_new, # (B, G, T) — B 个 prompt,每个 G 个回答
log_probs_old, # 同上
rewards_group, # (B, G) — 组内每个回答的 RM 分数
ref_log_probs, # (B, G, T)
beta=0.04,
clip_ratio=0.2,
):
"""
GRPO 损失(DeepSeek-R1 风格)。
log_probs_new, log_probs_old, ref_log_probs 形状: (B, G, T)
rewards_group 形状: (B, G)
"""
# === 组内归一化得到优势 ===
mean_r = rewards_group.mean(dim=-1, keepdim=True)
std_r = rewards_group.std(dim=-1, keepdim=True) + 1e-8
advantages = (rewards_group - mean_r) / std_r # (B, G)
# === 重要性比率 ===
# 这里我们用平均 log prob(per sequence)作为比率
ratio = torch.exp(
(log_probs_new - log_probs_old).sum(dim=-1)
) # (B, G)
# === PPO-style clipped surrogate ===
surr1 = ratio * advantages
surr2 = torch.clamp(ratio, 1 - clip_ratio, 1 + clip_ratio) * advantages
policy_loss = -torch.min(surr1, surr2).mean()
# === KL 惩罚 ===
kl = (log_probs_new - ref_log_probs).sum(dim=-1).mean()
kl_loss = beta * kl
total_loss = policy_loss + kl_loss
return total_loss, {"policy_loss": policy_loss.item(), "kl": kl.item()}

5.7 PPO vs GRPO 对比#

维度PPOGRPO
Critic需要不需要
优势估计GAE + Value Net组内排名
显存4 模型2 模型 (policy + ref)
采样数1/GG(按 prompt)
训练稳定较稳定需要足够大的 G
代表工作InstructGPT, ChatGPTDeepSeek-R1

6. DPO:免强化学习的对齐#

6.1 核心洞见#

DPO(Direct Preference Optimization)由 Stanford 在 2023 年提出,关键问题是:

能不能绕过 RM 和 RL,直接用偏好数据训练 LLM?

答案是:可以。RLHF 的目标函数有一个闭式解

6.2 推导:从 RLHF 到 DPO#

RLHF 目标:

maxπEx,yπ[R(x,y)]βKL(π(x)πref(x))\max_\pi \mathbb{E}_{x,y\sim\pi}\Big[R(x,y)\Big] - \beta\,\text{KL}\big(\pi(\cdot|x)\,\|\,\pi_{\text{ref}}(\cdot|x)\big)

其最优解为:

π(yx)=1Z(x)πref(yx)exp ⁣(1βR(x,y))\pi^*(y|x) = \frac{1}{Z(x)}\pi_{\text{ref}}(y|x)\exp\!\Big(\frac{1}{\beta}R(x,y)\Big)

其中 Z(x)=yπref(yx)exp(R(x,y)/β)Z(x) = \sum_y \pi_{\text{ref}}(y|x)\exp(R(x,y)/\beta) 是归一化常数。

反解出 RM:

R(x,y)=βlogπ(yx)πref(yx)+βlogZ(x)R(x,y) = \beta\log\frac{\pi^*(y|x)}{\pi_{\text{ref}}(y|x)} + \beta\log Z(x)

代入 Bradley-Terry 偏好模型(Z(x)Z(x) 抵消):

P(ywylx)=σ(βlogπθ(ywx)πref(ywx)βlogπθ(ylx)πref(ylx))P(y_w \succ y_l | x) = \sigma\Big(\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)}\Big)

这就是 DPO 损失

6.3 DPO 损失#

LDPO(θ)=E(x,yw,yl)[logσ(βΔθ(x,yw,yl))]\mathcal{L}_{\text{DPO}}(\theta) = -\mathbb{E}_{(x,y_w,y_l)}\Big[\log\sigma\big(\beta\,\Delta_\theta(x,y_w,y_l)\big)\Big]

其中:

Δθ=logπθ(ywx)πref(ywx)logπθ(ylx)πref(ylx)\Delta_\theta = \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)}

6.4 关键优势#

RLHF 流程:
偏好数据 → 训练 RM → PPO 优化 policy
(3 个阶段,复杂)
DPO 流程:
偏好数据 → 直接训练 policy
(1 个阶段,简单)
维度RLHF/PPODPO
训练阶段3(RM、critic、policy)1(policy)
显存4 模型2 模型
超参β\beta + clip + GAE + KL只需 β\beta
在线采样需要不需要(offline)
稳定性易崩稳定
性能略好(一般)与 PPO 相当
代表模型GPT-4, Claude 2Llama 3 Instruct, Mistral

6.5 DPO 实现#

import torch
import torch.nn.functional as F
def compute_log_probs(model, input_ids, attention_mask, response_mask):
"""计算回答部分的 log π(y|x) 之和"""
outputs = model(input_ids=input_ids, attention_mask=attention_mask)
logits = outputs.logits[:, :-1, :] # 预测下一个 token
labels = input_ids[:, 1:]
log_probs = F.log_softmax(logits, dim=-1)
# 取出真实 token 的 log prob
token_log_probs = log_probs.gather(2, labels.unsqueeze(-1)).squeeze(-1)
# 只对 response 部分求和(mask 掉 prompt)
response_token_log_probs = token_log_probs * response_mask[:, 1:]
return response_token_log_probs.sum(dim=-1)
def dpo_loss(
policy_chosen_logps, # π_θ(y_w|x) 对数和
policy_rejected_logps,
ref_chosen_logps, # π_ref(y_w|x) 对数和
ref_rejected_logps,
beta=0.1,
):
"""
DPO 损失。
policy_chosen_logps: (B,)
policy_rejected_logps: (B,)
ref_chosen_logps: (B,)
ref_rejected_logps: (B,)
"""
# log π_θ(y|x) - log π_ref(y|x)
policy_logratios = policy_chosen_logps - policy_rejected_logps
ref_logratios = ref_chosen_logps - ref_rejected_logps
# DPO 目标:β * (Δ_θ - Δ_ref)
logits = beta * (policy_logratios - ref_logratios)
# 偏好损失
loss = -F.logsigmoid(logits).mean()
# 额外监控:chosen reward margin
chosen_rewards = beta * (policy_chosen_logps - ref_chosen_logps).detach()
rejected_rewards = beta * (policy_rejected_logps - ref_rejected_logps).detach()
return loss, {
"chosen_rewards": chosen_rewards.mean().item(),
"rejected_rewards": rejected_rewards.mean().item(),
"accuracy": (chosen_rewards > rejected_rewards).float().mean().item(),
}

6.6 DPO 训练循环#

from torch.optim import AdamW
def train_dpo(policy_model, ref_model, dataloader, beta=0.1, lr=1e-6, epochs=1):
optimizer = AdamW(policy_model.parameters(), lr=lr)
ref_model.eval() # 冻结
for epoch in range(epochs):
for batch in dataloader:
# batch: {chosen: input_ids, mask, response_mask, rejected: ...}
# Policy 对 chosen 和 rejected 的 log prob
policy_chosen_logps = compute_log_probs(
policy_model, batch["chosen_input_ids"],
batch["chosen_attention_mask"], batch["chosen_response_mask"]
)
policy_rejected_logps = compute_log_probs(
policy_model, batch["rejected_input_ids"],
batch["rejected_attention_mask"], batch["rejected_response_mask"]
)
# Ref(不计算梯度)
with torch.no_grad():
ref_chosen_logps = compute_log_probs(
ref_model, batch["chosen_input_ids"],
batch["chosen_attention_mask"], batch["chosen_response_mask"]
)
ref_rejected_logps = compute_log_probs(
ref_model, batch["rejected_input_ids"],
batch["rejected_attention_mask"], batch["rejected_response_mask"]
)
loss, metrics = dpo_loss(
policy_chosen_logps, policy_rejected_logps,
ref_chosen_logps, ref_rejected_logps,
beta=beta,
)
optimizer.zero_grad()
loss.backward()
torch.nn.utils.clip_grad_norm_(policy_model.parameters(), 1.0)
optimizer.step()
print(f"loss={loss.item():.4f} "
f"acc={metrics['accuracy']:.2f} "
f"chosen_r={metrics['chosen_rewards']:.2f} "
f"rejected_r={metrics['rejected_rewards']:.2f}")

6.7 DPO 的局限与变体#

DPO 偏差

DPO 容易过拟合到偏好数据,并出现”verbosity bias”——偏好变长但不一定变好。

主要变体:

算法改进点公式
IPO防止过拟合L=(logπθ(yw)πref(yw)logπθ(yl)πref(yl)12β)2\mathcal{L} = (\log\frac{\pi_\theta(y_w)}{\pi_{\text{ref}}(y_w)} - \log\frac{\pi_\theta(y_l)}{\pi_{\text{ref}}(y_l)} - \frac{1}{2\beta})^2
KTO不需要成对偏好(单回答 + 标签)Kahneman-Tversky 前景理论
SimPO移除 reference modelL=logσ(ywywR(yw)ylylR(yl)γ)\mathcal{L} = -\log\sigma(\frac{\|y_w\|}{\|y_w\|}R(y_w) - \frac{\|y_l\|}{\|y_l\|}R(y_l) - \gamma)
ORPOSFT + DPO 联合联合 SFT 与 odds ratio 损失
CPOSFT + DPO 简化加 SFT 正则项

7. 进阶:从 RLHF 到 RLAIF / Constitutional AI#

7.1 RLAIF (RL from AI Feedback)#

动机:人类标注慢、贵、不一致。用强模型替代人类打标。

传统 RLHF:
人类对 (y_A, y_B) 排序 → RM → PPO
RLAIF:
GPT-4 对 (y_A, y_B) 按"宪法原则"排序 → RM → PPO

7.2 Constitutional AI (CAI)#

Anthropic 提出,两阶段

阶段 1:监督式(SL-CAI)

1. 模型生成回答 y
2. 模型基于"宪法原则"(如"不要有害")批评 y
3. 模型根据批评改写 y'
4. 用 (prompt, y') 做监督微调

阶段 2:RL-CAI

1. 模型生成回答 y_A, y_B
2. 模型按宪法原则判断哪个更好
3. 用这些 AI 偏好训练 RM
4. PPO 训练

宪法原则示例:

## 宪法(Constitution)
1. 请选择更**有帮助**的回答。
2. 请选择更**诚实**的回答。
3. 请选择更**无害**的回答,不应协助暴力、欺骗。
4. 请避免**歧视性**内容。
5. 请避免**违反隐私**的回答。

7.3 自我奖励语言模型(Meta,2024)#

迭代过程:
1. 用 CAI 生成偏好数据
2. 训练 RM
3. 用 DPO 训练 LLM
4. 重复:用更强的 LLM 重新打标
→ 模型自己当老师

8. 实战:完整 RLHF 训练流水线#

8.1 三阶段流水线#

┌──────────────────────────────────────────────────────────────┐
│ 完整 RLHF 训练流水线 │
├──────────────────────────────────────────────────────────────┤
│ │
│ Stage 0: Base Model (预训练 LLM) │
│ ↓ │
│ Stage 1: SFT (监督微调) │
│ ↓ 用高质量指令数据训练 π_SFT │
│ Stage 2: Reward Model Training │
│ ↓ 用偏好数据训练 R_θ │
│ Stage 3: RL Fine-tuning (PPO / GRPO / DPO) │
│ ↓ │
│ Final: Aligned Model │
│ │
└──────────────────────────────────────────────────────────────┘

8.2 推荐训练顺序(基于 Llama 2/3 论文经验)#

1. 预训练(基模型) ............................. 1-3 月,~1万 GPU·小时
2. SFT(指令微调) ............................... 数小时
3. RLHF 阶段 A:采样 + RM 训练 .................. 数小时
4. RLHF 阶段 B:PPO/DPO ......................... 数十小时
5. 安全对齐(可选的第二轮 RLHF) ............... 数小时

8.3 关键超参表#

超参推荐值备注
学习率(policy)1e-6 ~ 5e-6比 SFT 小一个数量级
学习率(RM)1e-5 ~ 5e-5RM 可以稍大
β\beta(KL 系数)0.04 ~ 0.2DPO 论文用 0.1
PPO clip ϵ\epsilon0.2标准值
Rollout 采样数 GG4 ~ 16GRPO 用更大
Mini-batch 大小1 ~ 4受显存限制
GAE λ\lambda0.95
折扣 γ\gamma1.0序列级任务

8.4 监控指标#

metrics_to_log = {
# === RM 训练 ===
"rm/loss": "RM Bradley-Terry 损失",
"rm/accuracy": "RM 在测试集上判别准确率",
"rm/score_margin": "winner - loser 平均分数差",
# === PPO/DPO 训练 ===
"policy/kl": "π_θ 与 π_ref 的 KL",
"policy/reward": "RM 给当前生成回答的平均分",
"policy/reward_std": "RM 分数方差",
"policy/clip_fraction": "被 clip 的 token 比例",
"policy/advantages": "优势均值",
# === 任务指标 ===
"eval/helpfulness": "GPT-4 评分(1-10)",
"eval/harmlessness": "安全率",
"eval/win_rate": "相对基模型的胜率",
}

8.5 常见 Failure Mode#

┌────────────────────────┬──────────────────────────────────┐
│ 现象 │ 原因 / 解决 │
├────────────────────────┼──────────────────────────────────┤
│ KL 爆炸 │ β 太小 / LR 太大 → 增大 β、降低 LR │
│ Reward 坍缩到 0 │ RM 过拟合 → 加正则、做 ensemble │
│ 模型输出变成乱码 │ Reward hacking → 多 RM、加规则 │
│ 模型变得太保守(拒绝一切)│ RM 偏负样本 → 重新平衡数据 │
│ 偏好过拟合(DPO) │ 学习率太大 / epoch 多 → 减小 │
│ Verbosity bias(越长越好)│ RM 没控制长度 → 加长度归一化 │
└────────────────────────┴──────────────────────────────────┘

9. 算法全景对比#

9.1 主流对齐方法#

┌─────────────────────────────────────────────────────────────┐
│ 对齐方法谱系 │
├─────────────────────────────────────────────────────────────┤
│ │
│ RL-based: │
│ ├── PPO (2017) ── 经典,4 模型,复杂 │
│ ├── GRPO (2024) ── DeepSeek-R1,无 critic │
│ ├── REINFORCE ── 最简,公式简洁 │
│ └── A2C / A3C ── 通用 RL,LLM 中较少用 │
│ │
│ RL-free (Direct Preference): │
│ ├── DPO (2023) ── 开山之作,1 阶段 │
│ ├── IPO (2023) ── 防过拟合 │
│ ├── KTO (2024) ── 不需成对偏好 │
│ ├── SimPO (2024) ── 无参考模型 │
│ ├── ORPO (2024) ── SFT + DPO 联合 │
│ └── CPO (2024) ── SFT + DPO 正则 │
│ │
│ Self-Play / Iterative: │
│ ├── Constitutional AI ── AI 当标注员 │
│ ├── Self-Rewarding LM ── 自我奖励迭代 │
│ └── SPIN / Iterative DPO── 多轮迭代偏好对齐 │
│ │
└─────────────────────────────────────────────────────────────┘

9.2 决策树#

需要对齐 LLM
├── 你有多少 GPU?多少数据?
│ │
│ ├── 资源受限(< 8 卡 A100)
│ │ └── ✅ DPO / SimPO(最便宜、最稳)
│ │
│ ├── 中等资源(8-32 卡)
│ │ ├── 数据多 + 想追最强性能 → ✅ GRPO
│ │ └── 数据少 + 想稳定 → ✅ DPO
│ │
│ └── 大量资源(> 64 卡)
│ └── ✅ PPO + 大 RM ensemble
├── 你能采集偏好数据吗?
│ │
│ ├── 可以(人工标注)
│ │ └── ✅ PPO / DPO
│ │
│ ├── 不能人工,但有强模型
│ │ └── ✅ RLAIF + PPO / DPO
│ │
│ └── 都没有
│ └── ✅ KTO(只需要"好/坏"标签)
└── 是否需要在线探索?
├── 是 → ✅ PPO / GRPO
└── 否 → ✅ DPO(offline)

9.3 性能 vs 复杂度矩阵#

算法实现复杂度显存性能稳定性推荐场景
PPO★★★★★★★大厂、追 SOTA
GRPO★★★★★★★★DeepSeek 复现
DPO★★★★★★★★★快速迭代、初创
IPO★★★★★★★★DPO 过拟合时
KTO★★★★★★★只有二值标签
SimPO最低★★★★★★★★显存紧张

10. 核心数学公式汇总#

10.1 Bradley-Terry 偏好模型#

P(ywylx)=σ(R(x,yw)R(x,yl))P(y_w \succ y_l | x) = \sigma\big(R(x,y_w) - R(x,y_l)\big)

10.2 RM 损失#

LRM=E[logσ(Rθ(x,yw)Rθ(x,yl))]\mathcal{L}_{\text{RM}} = -\mathbb{E}\Big[\log\sigma\big(R_\theta(x,y_w) - R_\theta(x,y_l)\big)\Big]

10.3 RLHF 目标#

J(πθ)=E[R(x,y)]βKL(πθ(x)πref(x))J(\pi_\theta) = \mathbb{E}\Big[R(x,y)\Big] - \beta\,\text{KL}\big(\pi_\theta(\cdot|x)\,\|\,\pi_{\text{ref}}(\cdot|x)\big)

10.4 PPO Clipped Surrogate#

LCLIP=Et[min(rtAt, clip(rt,1ϵ,1+ϵ)At)]\mathcal{L}^{\text{CLIP}} = -\mathbb{E}_t\Big[\min\big(r_t A_t,\ \text{clip}(r_t, 1-\epsilon, 1+\epsilon)\,A_t\big)\Big]

10.5 GRPO 组内归一化#

Ai=rimean(r)std(r)A_i = \frac{r_i - \text{mean}(\mathbf{r})}{\text{std}(\mathbf{r})}

10.6 DPO 损失#

LDPO=E[logσ(βΔθ)],Δθ=logπθ(yw)πref(yw)logπθ(yl)πref(yl)\mathcal{L}_{\text{DPO}} = -\mathbb{E}\Big[\log\sigma\big(\beta\,\Delta_\theta\big)\Big], \quad \Delta_\theta = \log\frac{\pi_\theta(y_w)}{\pi_{\text{ref}}(y_w)} - \log\frac{\pi_\theta(y_l)}{\pi_{\text{ref}}(y_l)}

10.7 IPO 损失#

LIPO=E[(logπθ(yw)πref(yw)logπθ(yl)πref(yl)12β)2]\mathcal{L}_{\text{IPO}} = \mathbb{E}\Big[\big(\log\frac{\pi_\theta(y_w)}{\pi_{\text{ref}}(y_w)} - \log\frac{\pi_\theta(y_l)}{\pi_{\text{ref}}(y_l)} - \frac{1}{2\beta}\big)^2\Big]

11. 总结#

11.1 对齐范式的演进#

阶段 1: SFT only
→ 学会"按指令回答"
→ 无法处理偏好、价值观
阶段 2: RLHF (InstructGPT, ChatGPT)
→ 引入 RM + PPO
→ 性能强但训练复杂
阶段 3: Direct Preference (DPO)
→ 闭式解,无需 RL
→ 工程简单,性能相当
阶段 4: Self-Improvement (RLAIF, Self-Rewarding)
→ AI 替代人类标注
→ 持续自我改进

11.2 选择建议#

项目初期 / 资源受限:
→ DPO 是最好的起点。简单、稳定、性能强。
追求 SOTA:
→ PPO + 大 RM(如果算力足够)
→ 或 GRPO(DeepSeek 路径)
数据形式特殊:
→ 只有"好/坏"标签 → KTO
→ 没有 reference model → SimPO
长期迭代:
→ Constitutional AI + 自我奖励
→ SPIN / Iterative DPO

11.3 未解决的问题#

  • 超人类反馈:模型比人类专家更强时,谁来评判?
  • 多目标对齐:Helpful + Harmless + Honest 之间的权衡
  • 奖励模型的鲁棒性:对抗样本、分布外泛化
  • 对齐税(Alignment Tax):对齐带来的能力损失如何最小化
  • 可解释对齐:能否理解模型为什么”对齐”了
进阶阅读

推荐按以下顺序阅读论文:

  1. InstructGPT(2022)—— RLHF 经典
  2. DPO(2023)—— 直接偏好优化
  3. Constitutional AI(2022)—— RLAIF 思想
  4. DeepSeek-R1(2024)—— GRPO 与推理 RL
  5. SimPO(2024)—— 简洁的现代变体

参考资料#

  1. Ouyang, L., et al. (2022). “Training language models to follow instructions with human feedback.” NeurIPS.
  2. Christiano, P., et al. (2017). “Deep reinforcement learning from human preferences.” NeurIPS.
  3. Schulman, J., et al. (2017). “Proximal Policy Optimization Algorithms.” arXiv.
  4. Rafailov, R., et al. (2023). “Direct Preference Optimization: Your Language Model is Secretly a Reward Model.” NeurIPS.
  5. Azar, M., et al. (2023). “A General Theoretical Paradigm to Understand Learning from Human Feedback.” AISTATS (IPO).
  6. Ethayarajh, K., et al. (2024). “KTO: Model Alignment as Prospect Theoretic Optimization.” ICML.
  7. Meng, Y., et al. (2024). “SimPO: Simple Preference Optimization with a Reference-Free Reward.” arXiv.
  8. Shao, Z., et al. (2024). “DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models.” arXiv (GRPO).
  9. Bai, Y., et al. (2022). “Constitutional AI: Harmlessness from AI Feedback.” arXiv.
  10. Touvron, H., et al. (2023). “LLaMA 2: Open Foundation and Fine-Tuned Chat Models.” arXiv.
  11. Guo, D., et al. (2025). “DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning.” arXiv.
  12. Lambert, N., et al. (2024). “RewardBench: Evaluating Reward Models for Language Modeling.” arXiv.

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

RLHF 深度解析:从人类反馈到 PPO/GRPO/DPO 的对齐革命
https://aiattnstudio.link/posts/rlhf/
作者
Federico
发布于
2026-07-16
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author

Federico

AI Research Lab

Hello, I'm Federico.

关于实验室 / About
公告

欢迎来到Federico的个人博客

分类
标签
站点统计
57文章
7分类
404标签
1
1. 引言:为什么需要”对齐”?
1.1 从 SFT 到 RLHF 的进化
1.2 SFT 解决不了的问题
1.3 RLHF 的核心思想
2
2. 偏好数据:从反馈到标注
2.1 数据形式
2.2 数据来源
2.3 数据质量的关键
3
3. 奖励模型(Reward Model)
3.1 Bradley-Terry 模型
3.2 损失函数
3.3 实现
3.4 训练实践
3.5 评估 RM 的方法
4
4. PPO:经典的策略优化算法
4.1 为什么不用 SFT 直接拟合 RM?
4.2 RL 基础
4.3 KL 约束:锚定参考策略
4.4 PPO 目标函数
4.5 RM + KL 的奖励设计
4.6 PPO for LLM 的完整实现
4.7 PPO 的工程痛点
5
5. GRPO:DeepSeek 提出的高效替代
5.1 动机
5.2 GRPO 核心思想
5.3 算法流程
5.4 优势计算
5.5 完整损失
5.6 GRPO 实现
5.7 PPO vs GRPO 对比
6
6. DPO:免强化学习的对齐
6.1 核心洞见
6.2 推导:从 RLHF 到 DPO
6.3 DPO 损失
6.4 关键优势
6.5 DPO 实现
6.6 DPO 训练循环
6.7 DPO 的局限与变体
7
7. 进阶:从 RLHF 到 RLAIF / Constitutional AI
7.1 RLAIF (RL from AI Feedback)
7.2 Constitutional AI (CAI)
7.3 自我奖励语言模型(Meta,2024)
8
8. 实战:完整 RLHF 训练流水线
8.1 三阶段流水线
8.2 推荐训练顺序(基于 Llama 2/3 论文经验)
8.3 关键超参表
8.4 监控指标
8.5 常见 Failure Mode
9
9. 算法全景对比
9.1 主流对齐方法
9.2 决策树
9.3 性能 vs 复杂度矩阵
10
10. 核心数学公式汇总
10.1 Bradley-Terry 偏好模型
10.2 RM 损失
10.3 RLHF 目标
10.4 PPO Clipped Surrogate
10.5 GRPO 组内归一化
10.6 DPO 损失
10.7 IPO 损失
11
11. 总结
11.1 对齐范式的演进
11.2 选择建议
11.3 未解决的问题
12
参考资料