PPO(Proximal Policy Optimization)是 RLHF(Reinforcement Learning from Human Feedback)流程中最常用的强化学习算法:ChatGPT、Claude 早期的对齐训练都用它,把一个已经会说话的模型,调整成”说话方式更符合人类偏好”的模型。这篇文章按照”为什么需要它 → 怎么推导出来 → 怎么套进 LLM 训练”的顺序拆解 PPO,重点放在它在 LLM RLHF 场景下的具体形态,而不是经典 Atari/MuJoCo 场景。
1. RLHF 全貌与 MDP 形式化
典型的 RLHF 流程分三步:SFT——用人工标注的高质量问答对,对预训练模型做监督微调,得到一个”听得懂指令”的基础策略;训练 Reward Model(RM)——让标注员对同一个 prompt 的多个模型输出排序,训练出一个输入 prompt 与回应 、输出一个标量分数的评分模型 ,代表”人类会有多喜欢这个回应”;PPO 阶段——把 SFT 模型当成初始策略,用 RM 给的分数当作强化学习的奖励信号,持续优化这个策略。PPO 只处理第三步,但它能不能训好,很大程度取决于前两步的质量——如果 RM 学得不准,PPO 会忠实地把策略优化到 RM 的盲点上(这就是后面会谈到的 reward hacking)。
要把语言生成套进强化学习的框架里,首先要把生成过程翻译成 MDP(马尔可夫决策过程)的语言:状态(state) 是 prompt 加上目前为止已生成的词元,即 ;动作(action) 是下一个要生成的词元,动作空间就是整个词表(通常有数万到十几万个词元);策略(policy) 就是 LLM 本身, 是模型在目前上下文下、对下一个词元的概率分布;一个回合(episode)是一次完整的生成,从 prompt 开始直到 EOS 或截断为止。奖励(reward)是跟经典强化学习差异最大的地方:RM 通常只在生成结束后对整个序列打一次分,中间任何一个词元都不会从”环境”得到即时奖励,因此原始的 reward 是序列级、稀疏的,只落在最后一个词元上。这个结构——“每个词元是一步决策,但奖励只出现在最后”——决定了后面 GAE 与 KL 惩罚需要如何设计。
2. 从策略梯度到裁剪目标
强化学习最直接的做法是策略梯度:直接对期望回报 取梯度。REINFORCE 给出的估计式是:
直觉很简单:如果采样到的一条轨迹的回报 为正,就提高这个被采样到的动作的概率;为负就降低。问题在于 来自蒙特卡洛采样,方差很高,序列一长(LLM 生成常常上百个词元)、动作空间一大(词表数万个词元),方差会被进一步放大。标准的解法是引入一个 baseline(通常是状态价值函数 ),把原始回报换成优势函数(advantage)——衡量”这个动作比这个状态下的平均水平好多少”,均值为零,方差明显降低:
策略梯度还有一个更棘手的问题:更新幅度很难控制。学习率稍微大一点,单次梯度更新就可能让策略输出的分布产生剧烈变化——对 LLM 来说,这可能表现为模型几步之内就开始输出乱码,或者崩塌成一种能骗过 RM、但语言质量很差的退化模式。这种偏移一旦发生就很难恢复,因为下一批采样已经是从被破坏的策略生成的。TRPO(Trust Region Policy Optimization)的做法是显式约束新旧策略之间的 KL 散度,把每次更新限制在一个”信任域”内——但这需要求解一个带约束的二阶优化问题,实现复杂且开销大。PPO 的出发点是:能不能用更简单的一阶方法达到类似的效果?
PPO 的答案是用概率比来衡量新旧策略的差异:。如果直接优化 ,当 很大时,优化过程会激进地把 往上推,导致策略一步就跨出信任域。PPO 的裁剪目标把这个比值压进一个固定区间:
通常取 0.1 到 0.2 之间。当 (这个动作比平均水平好)时,一旦 超过 ,裁剪后的项就不再增长,梯度也就不再有诱因继续把 往上推; 时对称成立——一旦 低于 ,目标函数也不会因为 继续降低而变得更好。取 而不是直接用裁剪后的值,是为了保证这个目标永远是真实目标的悲观下界——不管 的正负号是什么,实际被优化的永远是较保守的那个估计,避免模型根据单一样本的优势估计做出过度自信、不可逆的更新。这就是”proximal(近端)“名称的由来:用便宜的一阶方法,达到跟 TRPO”每次更新幅度有界”类似的效果。
3. GAE 与完整损失函数
裁剪目标里的 需要一个价值函数 来估计。PPO 通常搭配 GAE(Generalized Advantage Estimation)来计算优势:
是单步 TD 误差, 控制”往前看多远”: 时 GAE 退化成只用单步 TD 误差(低方差、高偏差); 时退化成蒙特卡洛优势估计(高方差、无偏),常用取值在 0.9 到 0.97 之间权衡。在 LLM RLHF 场景下,因为原始奖励只落在序列的最后一个词元, 需要学会”预测从目前生成位置到结束,最终会拿到的 RM 分数”——这正是为什么需要额外训练一个 Critic(价值模型),通常从 SFT 模型或 RM 初始化,把输出维度改成每个词元位置输出一个标量。
实务上 PPO 的总损失是三项的组合:
是前面推导的裁剪策略目标,用来训练 Actor; 是 Critic 的回归损失(其中 ); 是策略的熵,加上熵奖励是为了鼓励策略保留一定的随机性,避免过早坍缩成确定性输出。、 分别控制价值损失与熵奖励的权重。
4. LLM RLHF 中的 PPO:四个模型与 KL 惩罚
经典强化学习场景(例如 MuJoCo)里,PPO 只需要 Actor 和 Critic 两个网络。LLM RLHF 的 PPO 阶段要同时在显存里保留四个模型,这是相比经典 PPO 最大的工程挑战:
| 模型 | 是否训练 | 角色 |
|---|---|---|
| Policy / Actor | 训练 | 目前正在优化的 LLM,从 SFT 模型初始化,负责生成回应 |
| Reference Model | 冻结 | SFT 模型的只读副本,只用来计算 KL 惩罚,避免 Policy 偏离太远 |
| Reward Model | 冻结 | 单独训练好的评分模型,只在序列结尾给出一个标量分数 |
| Critic / Value Model | 训练 | 预测每个词元位置的价值 ,为 GAE 提供优势估计 |
四个模型的参数量往往相近(Critic 与 Reward Model 有时共享主干、只差输出头),这代表 PPO 阶段的显存和算力开销大致是纯推理的好几倍——这也是后续 GRPO 等变体想要砍掉 Critic 的直接动机。
只靠 RM 给的分数当奖励,很容易让策略往 RM 的盲点方向优化,而不是真的变好。RLHF 的标准做法是把 Policy 与 Reference Model 之间的 KL 散度当作惩罚项,加进奖励里:
这个 KL 惩罚是逐词元计算的,每一步都会加进奖励里,而 RM 的分数只出现在最后一个词元——GAE 会透过时序差分的信用分配,自动把末尾的 RM 分数往前传播到较早的词元,而每一步自身的 KL 偏移也会立刻计入奖励,两者不冲突。 的取值非常敏感:太小起不到约束作用,容易 reward hacking;太大策略几乎不敢偏离 SFT 模型,学不到 RM 想教的偏好。InstructGPT 等工作用自适应 KL 控制:持续监控实际 KL 值与目标 KL 之间的偏差,用一个简单的比例控制器动态调整 ,而不是固定成一个常数。
5. 实务上的坑与 PPO 之外的变体
工程实务上常见的坑:Reward hacking——策略找到 RM 评分函数的漏洞,而不是真的提升质量,常见表现是回应异常冗长(RM 偏好长回应)或堆砌 RM 恰好喜欢的措辞;缓解方式包括 KL 惩罚、RM 集成,以及定期用新数据重新训练 RM。PPO epoch 数太多是个问题——对同一批 rollout 数据重复太多次梯度更新,会让策略对这批数据过拟合,KL 也会很快失控;LLM RLHF 通常只做 1–2 个 epoch,比经典强化学习场景保守得多。Value Model 训练不稳定——Critic 要从头学会预测最终的 RM 分数本来就不容易,训练初期噪声很大的价值估计会污染优势估计,因此有些实践会先单独热身 Critic。奖励归一化——RM 的分数尺度在不同批次之间可能漂移,常用滑动平均/标准差归一化(whitening)来处理。采样参数——rollout 阶段用的 temperature/top-p 直接决定探索到的动作分布,进而影响优势估计的方差,是一个容易被忽略、但影响很大的超参数。
PPO 的主要代价是”重”:需要单独训练 RM、维护 Critic、同时跑四个模型。这两年的变体各自砍掉了一部分复杂度:**DPO(Direct Preference Optimization)**完全跳过显式的 RM 和 PPO 的采样-更新循环,直接从人类偏好对 构造一个对比损失函数,用监督学习的方式优化策略——代价是假设了 Bradley-Terry 偏好模型,并且失去了在线探索的灵活性。**GRPO(Group Relative Policy Optimization,DeepSeekMath 提出)**保留了 PPO 的裁剪目标和在线 rollout,但去掉了 Critic——对同一个 prompt 采样一组输出,用这组输出的奖励均值和方差对每个输出的优势做归一化,直接省掉一个跟 Policy 同等规模的模型,是目前 LLM 推理能力训练中很受欢迎的简化方向。两者都是用”PPO 的通用性”换”更少的模型、更简单的流程”——PPO 依然是最成熟、最通用的基线,但如果偏好数据足够规整,或者可以接受用组内相对奖励做近似,更轻量的变体往往有更好的性价比。
归根结底,PPO 在 LLM RLHF 里做的事情,是在”用 RM 的分数改进模型”这件事上,套上”任何一次更新都不能偏离参考模型太远”的约束:裁剪代理目标限制单次更新的幅度,GAE 把稀疏的序列级奖励合理地分配到每个词元上,KL 惩罚在奖励层面再加一道防线。理解这三块各自解决什么问题,比背下最终目标函数的公式更重要。