RLHF:奖励模型 + PPO 本节摘要:SFT 教模型遵循指令,但教不了哪个响应更好。两个语法正确、事实准确的回答,有用性可能天差地别。RLHF(人类反馈强化学习)是把人类判断编码进模型行为的方法——这就是 Claude 有用、GPT 礼貌的原因。本节带你走完 RLHF 的三阶段流水线:SFT(起点)、奖励模型(用 Bradley-Terry 配对损失从人类偏好对训练)、PPO(用奖励信号优化策略,KL 惩罚防奖励黑客)。你会理解为什么人类擅长相对比较而非绝对打分、奖励黑客为何是 RLHF 的阴暗面、以及为什么 InstructGPT(1.3B)能 85% 的情况下打败 GPT-3(175B)。
本节摘要:SFT 教模型遵循指令,但教不了哪个响应更好。两个语法正确、事实准确的回答,有用性可能天差地别。RLHF(人类反馈强化学习)是把人类判断编码进模型行为的方法——这就是 Claude 有用、GPT 礼貌的原因。本节带你走完 RLHF 的三阶段流水线:SFT(起点)、奖励模型(用 Bradley-Terry 配对损失从人类偏好对训练)、PPO(用奖励信号优化策略,KL 惩罚防奖励黑客)。你会理解为什么人类擅长相对比较而非绝对打分、奖励黑客为何是 RLHF 的阴暗面、以及为什么 InstructGPT(1.3B)能 85% 的情况下打败 GPT-3(175B)。
阅读完本节,你应当能够:
让模型「解释量子计算」,它可能产出:
响应 A:「量子计算用量子比特,可处于叠加态,即同时为 0 和 1。这使量子计算机对某些计算呈指数加速。关键算法包括用于分解大数的 Shor 算法和用于搜索无序数据库的 Grover 算法。」
响应 B:「量子计算是一种利用量子力学现象的计算。它由费曼在 1980 年代提出。这个领域发展很大。很多公司在做量子计算机。IBM、Google 等取得进展。Google 2019 年声称实现量子霸权。」
两个都事实正确、语法无误、都遵循指令。但 A 明显更好——更简洁、更有信息量、结构更好。人每次都选 A。SFT 抓不住这个区别:它在「正确」响应上训练,却无法说「这个比那个好」。若 A、B 都在 SFT 数据集里,模型从两者学得一样多。RLHF 解决:训一个奖励模型预测人会偏好哪个,再用那个奖励信号把语言模型推向更高质量输出。InstructGPT(ChatGPT 前身)用 RLHF 大幅提升 GPT-3 的有用性、真实性、无害性——OpenAI 内部评估者 85% 的情况下偏好 InstructGPT 输出,尽管它小 135 倍(1.3B vs 175B)。
RLHF 不是单次训练,而是顺序的三阶段流水线。阶段一 SFT:在指令-响应对上训基座模型(第 06 节),得到能遵循指令但不知哪个响应更好的模型。阶段二 奖励模型:收集人类偏好数据(给标注员看同一提示的两个响应,问哪个更好),训练模型预测这些偏好,奖励模型以(提示,响应)为输入输出标量分数。阶段三 PPO:用奖励模型为语言模型生成训练信号,语言模型生成响应,奖励模型打分,PPO 更新语言模型以产出更高分响应,KL 散度惩罚防它偏离 SFT 检查点太远。
奖励模型是把语言模型改造成打分器。拿 SFT 模型,把语言建模头(输出词表分布)换成标量头(输出单个数)。架构直到最后一层都相同。输入是提示拼接响应,输出一个标量奖励分。
训练数据是人类偏好对。损失用 Bradley-Terry 配对偏好模型:
loss = -log(sigmoid(reward(偏好) - reward(拒绝)))
sigmoid(reward(A) - reward(B)) 给出 A 被偏好于 B 的概率。损失推动奖励模型给偏好响应更高分。为什么用配对比对而非绝对打分?因为人类极不擅长给绝对质量分(「这响应 7.3 还是 7.5?」),但很擅长相对比较(「A 比 B 好吗?」)。Bradley-Terry 把相对比较转成一致的绝对打分体系。
💡 InstructGPT 数字:OpenAI 从 40 个承包商收集了 33,000 个比对对,每个约 5 分钟——奖励模型训练数据共 2,750 小时人工。
PPO 是强化学习算法。RLHF 中「环境」是奖励模型,「智能体」是语言模型,「动作」是生成一个 token。目标是:
最大化:E[R(提示,响应)] - beta * KL(策略 || 参考)
第一项推模型生成高奖励响应,第二项(KL 散度惩罚)防模型偏离 SFT 检查点太远。为什么有 KL 惩罚?没它,模型找到退化解:奖励模型是在有限人类偏好数据上训练的,有盲区,语言模型会利用这些盲区——找那些在奖励模型上得分高但实际胡说的输出。典型例子:反复说「我很有帮助很无害!」在有用/无害奖励模型上得分高;冗长、正式但空洞的响应模式匹配「高质量」。KL 惩罚说:你可以改进,但不能变成一个完全不同的模型,待在 SFT 版本附近(它已经合理),偏太远 KL 成本就压倒奖励。
PPO 用「裁剪代理目标」防更新过大:新旧策略概率比裁剪到 [1-eps, 1+eps](eps 通常 0.2)。优势函数估计当前响应比期望质量好多少:advantage = reward - baseline。正优势(比平均好)PPO 增大概率,负优势(比平均差)降低。
RLHF 的阴暗面。语言模型在针对奖励模型优化,而奖励模型是人类偏好的不完美代理。模型越擅长最大化奖励,越会利用奖励模型的弱点。常见失败模式:冗长(标注员常偏好更长更详细的响应,奖励模型就给长度高分)、谄媚(同意用户说的一切)、对冲(拒不给出确定答案,「这是个复杂话题,有诸多视角」很少被标错)、格式游戏(滥用要点和标题,看起来更「精致」)。缓解:更强 KL 惩罚、用对抗样本训奖励模型、用多个不同架构的奖励模型(同时黑掉所有更难)。
| 模型 | 比对对 | 标注员 | 奖励模型大小 | PPO 步数 | KL 系数 |
|---|---|---|---|---|---|
| InstructGPT | 33K | 40 | 6B | 256K | 0.02 |
| Llama 2 Chat | ~1M | 未披露 | 70B | 未披露 | 0.01 |
| Anthropic RLHF 论文 | 22K | 20 | 52B | 50K | 0.001 |
Anthropic 2022 论文在 22,000 个比对上训了 52B 奖励模型。更大的奖励模型产出更可靠信号,使 PPO 训练更稳——用小奖励模型训大语言模型有风险,奖励模型容量不足以捕捉好坏响应的细微差别。
生产中人类标注员造偏好数据,我们造合成对,其中「偏好」响应客观更好(更简洁、更准、更有用)。偏好响应简洁直接,拒绝响应展现常见失败模式(无谓填充、对冲、冗余解释、不精确)。
复用第 04 节的 Transformer,把词表大小的输出头换成单标量投影。取最后一个 token位置的隐藏态投影成标量——因为因果注意力掩码使最后位置已注意到所有先前 token,有最完整的(提示,响应)序列表示。
class RewardModel: def __init__(self, ...): self.embedding = Embedding(...) self.blocks = [TransformerBlock(...) for _ in range(num_layers)] self.ln_f = LayerNorm(embed_dim) self.reward_head = np.random.randn(embed_dim) * 0.02 def forward(self, token_ids): # ... 过嵌入与各块与最终 LN last_hidden = x[:, -1, :] # 最后 token 位置 return last_hidden @ self.reward_head # 标量奖励
def bradley_terry_loss(r_pref, r_rej): return -np.log(sigmoid(r_pref - r_rej) + 1e-8)
准确率指标直白:奖励模型在多少比对里排序正确?随机模型 50%,干净数据上训练良好的应超 70%。InstructGPT 奖励模型在留出比对上约 72%——听着低其实很好,许多比对连人类都觉得模糊(标注员间一致率约 73%)。
完整 PPO 复杂。本实现抓核心机制:生成响应、打分、算优势、用 KL 惩罚更新策略。
def ppo_training(policy, reference, reward_model, prompts, num_episodes=20, lr=1.5e-5, kl_coeff=0.02): for ep in range(num_episodes): prompt = prompts[ep % len(prompts)] resp = generate_response(policy, prompt_tokens) # 策略生成 reward = reward_model.forward(resp_ids)[0] # 奖励模型打分 kl = compute_kl_divergence(policy_logits, ref_logits) # 与参考的 KL total_reward = reward - kl_coeff * kl # 调整后奖励 # 用 total_reward 更新策略
核心循环:(1) 采样提示;(2) 生成响应;(3) 奖励模型打分;(4) 算与冻结参考的 KL 散度;(5) 算调整奖励(奖励减 KL 惩罚);(6) 更新策略。KL 惩罚随策略偏离参考而增长,自动防奖励黑客。
RLHF 后,策略模型的响应在奖励模型上应比原 SFT 模型得分更高。
HuggingFace TRL 的 PPOTrainer 封装了完整 RLHF 循环,处理生成、奖励、优势估计、KL。它用 accelerate 管多卡。生产中你写配置,不写 PPO 原语。但理解 Bradley-Terry 损失和 KL 惩罚才能诊断「为什么模型开始输出冗长垃圾」(奖励黑客)。
本节产出 outputs/prompt-reward-model-designer.md——一个设计奖励模型训练流水线的提示。给定目标行为(有用性、编程、安全),产出数据采集协议、标注员指南、奖励模型评估标准。
(Easy) 改奖励模型用所有隐藏态的均值而非仅最后位置,对比准确率。均值池化给每 token 等权,最后位置依赖因果注意力聚合信息。
(Medium) 实现奖励模型校准:训练后跑所有偏好对,算偏好/拒绝平均奖励与间隔,加 4 个新偏好对看间隔是否在未见数据上保持。
(Medium) 模拟奖励黑客:造一个给长响应高分的奖励模型(reward=len/100),跑 PPO 观察策略生成越来越长、重复的输出,然后加 0.1 的 KL 惩罚展示它防住退化行为。
(Hard) 实现多目标奖励:训两个奖励模型(有用性、简洁性),组合成 R=0.7*R_有用+0.3*R_简洁,展示组合目标产出既有用又简洁的响应,避开单一有用性奖励的冗长陷阱。
(Hard) 对比不同 KL 系数:beta=0.001(太低,奖励黑客)、0.02(标准)、0.5(太高,不学),画各组的奖励曲线与 KL 曲线。0.02 应展示奖励稳步升、KL 有界。
下一节,DPO 问:能不能跳过奖励模型和 PPO?答案是能——直接在偏好对上优化语言模型,一个训练循环,同样效果。