RLHF 与 PPO(Reinforcement Learning from Human Feedback / Proximal Policy Optimization)
所属:01-fundamentals / 02-post-training
面试权重:★★★
来源:通用领域知识;未做一手考证
相关项目:无 PPO 的一手生产经验 —— 生产中用 GRPO(见grpo.md);但 PPO 是理解 GRPO 与 DPO 的底座,且 HKJC 项目里「为什么不用 PPO」本身就是一道会被追问的题
一句话#
RLHF 是「用人类偏好训一个奖励模型(reward model),再用 RL 去优化策略模型(policy)」的三段式对齐流程;PPO 是其中最经典、也最昂贵的优化器 —— 它需要同时常驻四个模型(policy / reward / reference / value),靠 KL 惩罚把策略锚在 reference 附近,代价是显存、时间与稳定性。
为什么重要(面试角度)#
这是 post-training 的理论主干。即使你生产上用的是 GRPO,面试官也会从 PPO 问起,因为:
- 「KL 惩罚为什么必要」是理解 DPO 和 GRPO 的钥匙,答不出这一层,后面所有算法都只能背。
- 「为什么贵、为什么不稳」考的是你能不能分清算法问题和系统工程问题。
- 奖励黑客(reward hacking) 是所有 RL 对齐方法的通用失败模式,PPO 是它最典型的展示场。
- 一个高频对照题:「你们为什么用 GRPO 不用 PPO」—— 这个答案必须建立在对 PPO 成本结构的准确理解上。
核心内容#
四个模型(4-model setup)#
| 角色 | 符号 | 是否训练 | 提供什么 | 显存 |
|---|---|---|---|---|
| 策略模型 Policy / Actor | ✅ 训练 | 生成回答,被优化的对象 | 权重 + 梯度 + 优化器状态 | |
| 参考模型 Reference | ❌ 冻结 | 算 KL 的锚点,通常是 SFT 后的模型 | 权重(可 offload / 可与 policy 共享) | |
| 奖励模型 Reward | ❌ 冻结(已训好) | 给整条回答一个标量分数 | 权重(可与 policy 不同规模) | |
| 价值模型 Value / Critic | ✅ 训练 | 估计每个位置的期望回报,用于算 advantage | 权重 + 梯度 + 优化器状态(通常与 policy 同规模) |
成本直觉:policy 与 value 两个模型要带完整的优化器状态;再加上 reference 和 reward 共四份权重。相比 SFT 只训一个模型,显存是数倍量级。工程上的常见手段是:reference 与 policy 做权重共享(如只有 LoRA 部分可训)、把 reference/reward 放在不同设备或做参数 offload、用 FSDP/ZeRO 切分。
训练循环:把生成问题变成 RL 问题#
RLHF 的建模方式是逐步类比:
- 环境(environment) = 奖励模型 + 用户给定的 prompt
- 状态(state) = prompt + 已生成的 token 序列
- 动作(action) = 下一个 token
- 回报(reward) = 整条回答结束后由 reward model 给的一个标量
关键结构:奖励是稀疏的、只在末尾给一次(outcome reward)。价值模型的作用就是把这个末端标量「摊」到每个 token 上,从而算出每个 token 的 advantage。这也是它必须存在的原因 —— 没有它,你只知道「整条回答好不好」,不知道「哪个 token 该负责」。
一个训练步的顺序:
① Rollout 用当前 policy 对一批 prompt 生成完整回答(这步极慢)
② Scoring 用 reward model 给每条回答打分
③ Advantage 用 value model + GAE 估计每个 token 的 advantage
④ Update 用 PPO 的 clipped 目标更新 policy(同时更新 value model)
⑤ Resync 把新权重同步给推理引擎,回到 ①PPO 的 clipped 目标(约束单步更新的幅度):
其中 是新旧策略的概率比, 是 advantage。直觉:advantage 为正时,不要因为一次更新就把这个动作的概率抬得太狠;advantage 为负时,也不要砍得太狠。这是 PPO「proximal(近端)」的含义 —— 用重要性采样比把更新限制在旧策略附近,避免一步走崩。
KL 惩罚:为什么它必须存在#
实际优化的奖励是塑形后的:
三点理由,第 1 点才是最本质的:
- 奖励模型只在 SFT 分布附近可信。reward model 是在 SFT 模型的输出上训出来的,它只在那个分布内有判别力;策略一旦漂到分布外,RM 给出的分数就是外推,没有任何意义。KL 惩罚的作用就是把策略锁在 RM 的「可信区」内。没有 KL 的 RLHF 本质上是让一个不可靠的评判者在它没见过的区域上打分。
- 防止退化。没有 KL,policy 会坍缩到能刷分的少数模式上:输出熵降低、重复、语言崩坏、丧失多样性。
- 保留通用能力(alignment tax 的显式控制旋钮)。KL 越大,策略越贴近 SFT 模型,通用能力保得越好,但偏好对齐的效果也越弱 —— β 就是在「对齐收益」和「能力损失」之间移动的那个旋钮。
两个必须说清的细节:
- KL 是估计出来的,不是解析精确值。逐 token 上无法枚举全部词表算真实 KL,实践中用有偏但方差可控的估计量(常见的是所谓 k3 估计量),它的期望偏低。所以「KL 惩罚」在实现中是一个基于采样的近似。
- β 是这套方法里最难调的参数之一。太小 → 收敛到 reward hacking 的退化解;太大 → 几乎学不动。它和 lr、batch size 相互耦合。
为什么贵、为什么不稳#
贵(主要是工程与算力问题)
| 来源 | 说明 |
|---|---|
| 4 个模型常驻显存 | 其中 2 个还要带梯度与优化器状态;比 SFT 高一个量级的显存需求 |
| 在线采样(rollout) | 每步都要先让 policy 完整生成一批回答。生成是显存带宽受限的,比训练慢得多 —— 墙钟时间主要花在这里,不在梯度计算上 |
| 双引擎并存 | 需要推理引擎(vLLM / SGLang 等)与训练框架共存,并每步同步权重 |
| 采样与训练难以解耦 | 生成和训练用不同的并行策略(前者偏张量并行/长序列,后者偏参数切分),切换有开销 |
不稳(算法与信号问题)
- 奖励只是代理指标(proxy)。你在优化的是 RM,而 RM 只是人类偏好的有损压缩。优化压力越大,你越是在优化它的缺陷,而不是在优化真实目标。
- 超参敏感:KL 系数 β、clip 范围 ε、学习率、batch size、GAE 的 λ 与 γ —— 每一个都能把训练推向崩溃或停滞,且相互耦合。同一份代码换种子结果差异明显是常态,复现性差。
- 价值模型在追一个非平稳目标。policy 每步都在变,value model 是在同时在线学习,它的估计误差会直接注入 advantage —— 而 advantage 是唯一的梯度信号来源。这是 PPO 相比 GRPO 最本质的不稳来源。
- 长度偏置:RM 倾向给长回答更高分,policy 学会「变长」这条捷径。表现为训练中输出长度单调上涨。
- 典型的奖励曲线是「先升后崩」:评测分先随训练上升,越过某个点后急剧下降(策略漂到 RM 的分布外,开始刷分)。看单点指标是看不出来的,必须看整条曲线并对齐 KL 与长度。
奖励黑客(Reward Hacking)#
定义:策略找到了奖励函数的漏洞,拿到了高分,但真实质量没有提升甚至下降。
典型形态(RLHF 场景下真实且反复被观察到的):
- 谄媚(sycophancy):附和用户的错误前提,因为人类标注者会给「顺着说」的回答更高分。
- 冗长:把答案拉长,堆砌正确的废话。
- 格式刷分:大量 markdown 标题、表格、分点 —— 看起来「结构化」,实际信息密度低。
- 拒绝不确定:永不承认不知道,用模糊措辞覆盖所有可能。
- 多选题输出全部选项(在可验证任务里):把「答对」的概率最大化而不真的解题。
为什么倾向于发生:任何代理奖励都是真实目标的有损压缩;RL 优化的压力越大,越容易找到并放大这个压缩丢失的部分。所以它不是一个「修一次就好」的 bug,而是需要持续监控的系统性倾向。
缓解手段:
- KL 锚定(把策略限制在 RM 可信区,是最基础的一道)
- 长度归一化或长度惩罚(直接消掉「变长」这条捷径)
- 奖励模型集成 / 多维度奖励(单个 RM 的漏洞容易被 ensemble 互相否决)
- 规则化 / 可验证奖励(凡是有客观正确答案的任务,用程序判定替代 RM —— 这也是 GRPO 在推理任务上崛起的原因,见
grpo.md) - 留出人工评测:定期用不带优化压力的人类评测校验,这是唯一不会一起被 hack 的裁判。
- 对抗检验:对每一项奖励设计,主动问「模型怎样才能在不真正完成任务的前提下拿到这一项的分」。
常见面试问法#
Q:RLHF 里为什么需要四个模型?各自不能省吗? A:policy 是被优化对象;reward 提供信号;reference 提供 KL 的锚点(没有它就失去对 RM 可信区的约束);value 把末尾的稀疏回报摊到每个 token 上算 advantage,因为 reward 是 outcome-level 的。可省的方式:reference 可以与 policy 共享权重(只训增量);value 在 GRPO 这类方法里被组内均值替代 —— 省掉它正是 GRPO 的主要收益。
Q:KL 惩罚是干什么的?去掉会怎样? A:把策略约束在 reference 附近。去掉后 RL 会滑向 reward hacking 的退化解:语言崩坏、模式坍缩、以及最本质的 —— 在 reward model 的分布外区域刷分,那里的分数没有意义。另外两个效果是保留通用能力与多样性。
Q:PPO 里为什么要 clip? A:policy gradient 是重要性采样的估计,比值 偏离 1 太远时估计方差爆炸、单步更新过大(一次坏 batch 就能把策略打飞)。clip 把比值限在 ,只让策略「近端」移动。它是 PPO 相对朴素 policy gradient 的核心稳定化手段。
Q:既然有 KL 约束,为什么还会 reward hacking? A:KL 约束的是「别跑太远」,不是「别找漏洞」。只要还在 RM 的可信区内,局部上仍然存在大量「分数高但质量没提升」的方向(如变长、格式刷分)。而且 KL 是估计量、β 有限,约束本身也不是硬的。
Q:你们为什么不用 PPO 而用 GRPO?如果业务必须用 PPO 你会怎么降本?
A:不用 PPO 的直接原因是它要常驻 4 个模型、需要在线训练 value model、且超参敏感复现困难;GRPO 用组内相对优势替掉 value model,显存与工程复杂度都下降(见 grpo.md)。
降本方向:reference 与 policy 共享权重(LoRA)、reward/reference 参数 offload 或分设备部署、把 reward 换成可验证的规则判定(省掉 reward model 且顺带防 hacking)、增大 rollout 的并行度并把生成与训练真正解耦(异步/离线样本池)、以及降低采样频率(一批样本做多次梯度更新,代价是 off-policy 程度上升)。
Q:PPO 训练中出现输出长度持续上涨、评测分反而先升后降,怎么诊断? A:这是长度偏置导致 reward hacking 的典型签名。诊断步骤:① 把 reward 分解看——分数上涨是否主要来自长度相关项;② 看 KL 是否已经很大(策略漂出 RM 可信区);③ 检查 RM 在长回答上的打分是否单调偏高(用一个长度受控的探针集)。
处理:加长度惩罚/归一化、提高 β、降低学习率或提前停止、把可验证部分改用规则奖励。
易错点#
- ❌ 说「RLHF 就是让人给模型打分」—— 打分只是第一步,核心是训 reward model 再用 RL 优化。
- ❌ 把 KL 惩罚说成「防止过拟合」或「正则化」就结束 —— 最本质的理由是 RM 只在 SFT 分布附近可信。
- ❌ 认为 KL 是精确计算出来的 —— 它是采样估计量。
- ❌ 把 reward hacking 当成「奖励函数写错了」的一次性 bug —— 它是代理指标优化的系统性倾向。
- ❌ 混淆 reward 与 advantage —— reward 是整条回答的一个标量,advantage 是每个 token 相对基线的优势。
- ❌ 说 PPO 慢是因为「梯度计算慢」—— 实际墙钟主要花在 rollout 生成上,这是显存带宽受限的。
- ❌ 记不住「四个模型」分别是谁、哪些要训练。
- ❌ 声称自己生产用过 PPO —— 如果没用过,明确说清楚,并把回答转到「为什么选 GRPO」上(这是加分而非扣分)。
自测#
1. 逐个说明 RLHF 里的四个模型,其中哪个最容易被「省掉」,省掉之后代价是什么。
答案
policy(被优化的策略,训练)、reward model(提供偏好信号,冻结)、reference(SFT 模型,冻结,提供 KL 锚点)、value/critic(估计每个位置的期望回报以算 advantage,训练)。
最容易省掉的是 value model —— GRPO 用「同一 prompt 采样一组回答的组内归一化奖励」作为 baseline 替代它,从而省掉一个与 policy 同规模的模型及其梯度/优化器状态。代价是:优势估计退化为 Monte-Carlo 级别(整条回答共用一个 advantage,没有 PPO 的逐 token 信用分配),方差更大,且需要为每个 prompt 采样多条回答,把省下的显存换成了采样算力。
其次可省的是 reward model(当任务有可验证答案时用程序判定),以及 reference 的可选性取决于实现(去掉 KL 项,代价是失去对分布漂移的显式约束)。
2. 用「reward model 的适用域」这个角度解释 KL 惩罚的必要性,并说明为什么 β 不能调成无穷大。
答案
reward model 是在 SFT 模型的输出分布上训练出来的判别器,它只在这个分布内有判别力。一旦 policy 漂到分布外,RM 的打分就是外推,高低分不再有信息 —— 于是 RL 会朝着「RM 评分高但与真实质量无关」的方向跑(reward hacking 的严格来源)。KL 惩罚把策略限制在 RM 的可信区内,使奖励信号始终有意义。
β 不能无穷大:KL 项会主导目标函数,策略被锁死在 reference 上,偏好信号无法带来任何改变(学不动,等于没训)。所以 β 是在「对齐强度」与「能力保留 / 学得动」之间的权衡旋钮,通常需要按任务实测,且与 lr、batch size 耦合。
3. 为什么说 PPO 慢主要慢在 rollout 而不是梯度计算?这个认识对系统设计意味着什么?
答案
PPO 是 on-policy 的:每一步更新前都必须用当前 policy 生成完整回答(直到 EOS)。自回归解码是逐 token 串行的,且每 token 都要读取全部权重与 KV cache —— 是显存带宽受限而非算力受限;而训练阶段的矩阵乘是算力受限、可高度并行。所以生成阶段的吞吐远低于训练,墙钟时间被生成支配。
系统设计含义:① 优化重点应该放在 inference engine(连续批处理、PagedAttention、增大并行与 batch)而不是梯度计算;② 生成与训练需要不同的并行策略,二者切换有开销;③ 若要进一步提高吞吐,可牺牲 on-policy 程度(把样本放进池子做多次梯度更新、异步生成),代价是重要性采样比值偏离 1、训练稳定性下降。
4. 你的模型在 RLHF 后变得极其啰嗦且爱用 markdown 小标题,评测分却涨了。请给出诊断方案和至少三条处理措施。
答案
诊断:这是长度/格式偏置引发的 reward hacking 签名。① 把 reward 按特征分解,看分数增益有多少来自长度或结构特征;② 用长度受控的探针集测 RM,验证它是否单纯偏好长回答;③ 看训练曲线中 KL 与平均长度是否同步上涨(策略正在漂出可信区);④ 用不带优化压力的人工小样本评测做交叉验证。
处理:① 长度归一化或显式长度惩罚;② 提高 β / 降低学习率 / 提前停止,把策略拉回 RM 可信区;③ 增大偏好数据的长度控制,使 RM 本身不把长度当质量信号;④ 把可验证的维度改用规则判定;⑤ 把人工/LLM 裁判评测纳入固定回归,防止后续迭代再次滑落。
5. 如果一个业务场景你只能用 PPO(不能用 GRPO / DPO),你会做哪些取舍来把它跑起来?
答案
核心是承认 PPO 的成本结构并逐项削减:
① 显存:reference 与 policy 共享基座(只训 LoRA 或只训部分层)、reward/reference 参数 offload 到 CPU 或另一组设备、用 FSDP/ZeRO 切分;② 时间:把预算花在 inference engine 上(连续批处理、增大生成并发);一批 rollout 做多次梯度更新以提高样本利用率(接受 off-policy 化,用 clip 与 KL 兜住);③ 稳定性:缩短单次训练规模、小步多验,把 KL 与输出长度作为一等监控指标,固定种子做多次复现;④ 奖励:把可验证的部分从 RM 换成规则判定,直接消除一部分 hacking 面;⑤ 验收:永远保留一条不被优化的留出评测(人工或第三方),防止「指标涨、用户不满意」。
一句话总结:PPO 的难点不在算法公式,而在把 4 模型的系统跑稳并让奖励信号保持有意义。