PPO
1. PPO
Proximal Policy Optimization Algorithms
两阶段循环
为什么可以“多轮”
通常情况下,如果对同一批数据进行多轮优化,策略会因为更新过头而崩溃。但 PPO 引入了 Clipped Objective(裁剪目标函数):
- 安全护栏:在每一轮优化中,PPO 会计算新策略和采样时的旧策略的概率比。如果这个比值超出了设定的范围(比如 ),梯度就会被“截断”。
- 效果:这确保了即使在这一批数据上反复“薅羊毛”优化,新策略也不会跑得离旧策略太远,从而保证了训练的稳定性。
1.1. 采样阶段 (Sampling Phase)
- 动作:让当前的策略 在环境中运行一段时间。
- 产出:收集一批轨迹数据(包括状态 、动作 、奖励 等)。
- 性质:这些数据是“新鲜”的,反映了当前策略的行为模式。
在这个阶段,神经网络的参数是固定不动的(即 )。Actor (策略网络):在环境中根据概率分布选择动作。数据收集:把 存入一个临时的 Buffer。目标:收集足够数量的轨迹(比如 2048 个时间步)。
1.1.1. 计算“标签” (Preprocessing)
在开始训练前,利用收集到的数据计算两个关键值:
- (Advantage):优势函数,用来衡量这个动作比平均水平好多少。
- (Returns):这一步动作带来的累积奖励。
注意到
- :新旧策略概率比(用于 Actor)。
- :优势估计(用于 Actor,决定更新方向)。
- :回报目标值(用于 Critic,提升估值精度)。
如果只用即时奖励 作为目标,Critic 就会变得非常“短视”。即时奖励 :只代表当前这一步的好坏。回报目标 :代表从当前时刻起,在轨迹剩余部分上累计(折现)后的总回报。目标是让 Critic 具备“向前看”的能力,因此用 去拟合这个 。
(Returns):作为 Critic 网络的监督信号(标签)。
- 计算逻辑:通过 (优势)与采样时旧的 相加得到:。
- 物理意义:它代表了在当前策略下,从状态 开始预期能获得的折现总奖励。Critic 的优化目标就是让预测值 尽可能接近这个 。
这意味着:
- 先用 GAE 算出了优势估计 。
- 通过 ,便可反向推导出这一步动作对应的“目标回报” 。
- 价值损失 (Value Loss) 就变成了:。
1.1.2. 小结
- Actor:利用 (相对好坏)来决定 的更新方向。
- Critic:利用 (绝对得分)来修正自己对世界的认知。
1.2. 优化阶段 (Optimization Phase)
多轮优化 (Several Epochs):
- 动作:将刚才采样的这一批数据反复输入神经网络进行多次梯度更新。
- 关键点:在传统的 On-policy 算法(如普通的策略梯度)中,这批数据更新一次就必须扔掉。但 PPO 允许在同一批数据上跑 3 轮、5 轮甚至 10 轮(Epochs)。
要把 Buffer 里的数据,分成更小的 Mini-batches,重复训练 个 Epochs(比如 )。在每一个 Epoch 里的微观操作:计算概率比 :用当前正在更新的 计算动作概率,除以采样时的 计算的概率。应用裁剪 :如果 偏离 1 太远(比如超过 20%),就强行截断。梯度更新:通过反向传播更新参数 。
为什么 允许“多轮更新”。PPO 能够从 On-policy 转向近乎 Off-policy 的理论支柱,PPO 本质上是利用了重要性采样技术。
- 理论背景:优化目标是新策略 ,但训练数据来自旧策略 的采样分布。
- 补偿机制:通过概率比率 ,对数据分布偏差做重要性采样修正。
- 约束:重要性采样要求两个分布不能差太远,否则方差会爆炸。这正是 存在的根本原因——它在数学上维护了重要性采样的有效区间。
1.2.1. 优势估计
通常采用 GAE (Generalized Advantage Estimation)。
简单来说,优势函数 的目标是回答:“在状态 下采取动作 ,比平均情况(即 Baseline)好多少?”
1.2.1.1. 计算时序差分残差(Temporal Difference Error)
首先计算每一个时间步的即时偏差 。它衡量了“实际观测到的奖励 + 下一步的估值”与“当前估值”之间的差距:
- :当前步获得的奖励。
- :神经网络(Critic)对下一步状态的估值。
- :神经网络(Critic)对当前状态的估值。
1.2.1.2. 累加衰减
[0, T)
优势估计 不是只看当前这一步,而是要把未来的 都考虑进来,但要进行指数衰减。公式如下:
这里有两个关键的超参数:
- (Gamma):折扣因子(通常 0.99),决定了对远期奖励的重视程度。
- (Lambda):GAE 因子(通常 0.95),用于在偏差(Bias)和方差(Variance)之间做权衡。
实现时,逆序(t)计算
-
如果 :。这叫 1-step TD。它很稳定(方差小),但如果 函数估值不准,它就会错得离谱(偏差大)。
-
如果 : 变成了从当前步到截断点 的所有奖励累加。这很真实(无偏差),但环境随机性太强,导致数值跳变剧烈(方差大)。
这就是 用于在偏差(Bias)和方差(Variance)之间做权衡的物理意义。PPO 选取 它在“相信神经网络的估值”和“相信实际观测到的奖励”之间取了一个折中。
1.2.1.3. 标准化 (Advantage Normalization)
在算出 个时间步的所有 后,工程上通常会进行一次标准化处理:
- 稳定梯度:在一个 Batch 中,优势值的数值跨度可能很大。标准化后,它们的均值为 0,标准差为 1。
- 逻辑闭环:这确保了在一个 Batch 里,大约有一半的动作会被认为是“好于平均”(正值,增加概率),另一半是“差于平均”(负值,减小概率)。这对于 Adam 优化器的稳定收敛极其重要。
1.2.1.4. 总结计算流程
- 运行 步采样,收集所有的 概率比例和 状态价值。
- 从后往前计算(这样可以用 算出 ):
- 对整个 Batch 进行标准化。
- 将算好的 输入 进行优化。
1.2.2. 损失函数
优势估计 和概率比率 都准备好了,进入 PPO 执行阶段构建 Loss 函数并进行参数更新
Adam 优化器并不是只优化策略,它其实是在同时优化三个目标。
总损失函数 通常长这样:
这三个部分分工明确:
- (策略损失):利用 和 进行裁剪优化。直观上,它会在优势为正时提高动作概率,同时用 clip 限制单次更新幅度,避免策略变化过快。
- (价值损失):通常是均方误差 。它负责让 Critic 的状态价值预测更贴近目标回报(更准确)。
- (熵奖励):鼓励策略保持一定的随机性,避免分布过早塌缩到少数动作上,从而保留探索空间。
MSE 均方误差
1.2.2.1. 执行 Adam 更新
Adam 优化器, 梯度下降 (Gradient Descent)
有了总损失后,流程如下:
- 计算梯度:对总损失关于参数 求导(即之前提到的 )。
- 反向传播:将梯度传回神经网络。
- 参数更新:Adam 优化器根据动量和自适应学习率微调 。
进入 个 Epoch 的循环
针对同一批采样数据(那 个样本),反复进行 次上述的“计算 Loss -> 更新参数”过程。
- 在第 1 遍时:,概率比退化为恒等映射,更新等价于未做分布修正的常规梯度步。
- 在第 遍时:由于参数已经改了好几次,新旧策略的偏差 可能会很大。这时候 Clipping(裁剪) 就会大显身手,强行把那些偏移过大的梯度归零,防止模型跑飞。
注:虽然 PPO 的理论目标是最大化奖励,但在代码实现中,通常会对总目标函数取负值,将其转化为最小化损失,从而用 Adam 等优化器做梯度更新。
1.2.2.2. 更新旧策略
当 次迭代结束,这一批数据的价值就被“榨干”了。
此时,把当前的最新参数 赋值给 。然后清空缓存的数据,回到环境里,开启下一轮 的数据采集。
1.3. Hyperparameters 参考
| 参数 | 常用值 | 作用 |
|---|---|---|
| 裁剪阈值,限制单次更新步长 | ||
| 长期奖励折扣因子 | ||
| GAE 平衡因子 | ||
| 价值损失权重(MSE 权重) | ||
| 熵系数(鼓励探索,防止过早收敛) | ||
| 每个 Batch 的重复训练次数(Epochs) |
2. RLHF 中的 PPO
在很多 LLM 对齐/偏好优化的工程实现里,会看到 “PPO + reference model(参考模型)”。这很容易让人误以为 reference model 是 PPO 论文(Schulman 2017)的一部分;但严格来说,它是 RLHF 场景下额外加入的约束/正则,用来防止策略为了刷 reward 而跑飞(reward hacking、语言退化、分布崩坏等)。
2.1. RLHF 训练 flow
SFT → RM → PPO
可以把最常见的 RLHF 流程理解成三段:
- SFT:用高质量指令数据把模型先教会“基本说话方式”,得到 ;它常常也会作为后面的 (冻结参考模型)。
- Reward Model(RM):用偏好数据训练一个打分器 (或 ),用于刻画“在相同输入下,哪些输出更受偏好”。
- PPO-RLHF:从 初始化可训练策略 ,用 PPO 提高 ,同时用 KL-to-reference 把 拴在 附近。
而 PPO-RLHF 的实现,通常就是把“文本生成”当成一条轨迹上的序列决策,然后复用前边提到的 PPO 两阶段循环:
- 自回归 MDP(最常见的设定):第 步的“动作”是下一个 token ;状态可以抽象成 。
- Rollout:用 采样一批 completions(得到 token 轨迹与 logprob)。
- Reward / shaping:把 RM 分数与 KL shaping 组合成每步可用的标量回报信号(工程上常见是把 KL 摊到 token;RM 可能是序列末一次性给分,也可能有更细的 shaping,取决于实现)。
- reward shaping 在这里可以直观理解为:不只给“最后好不好”的稀疏信号,而是额外构造/改写一组更密、更及时的逐步回报,让 PPO 在生成过程中更容易学、也更可控;其中 per-token 的 KL 项就是很典型的 shaping。
- RM shaping 则更具体:指把 reward model 的偏好信号从“只在结尾给一次分”,扩展成更稠密的过程性反馈(例如分段打分、对关键子结构/步骤给增量奖励、或把可验证规则与 RM 组合成逐步项)。不同系统差异很大;设计不当也可能让模型去“刷 RM shaping”而不是真正提升偏好质量,因此通常仍会配合 KL-to-reference 与谨慎的系数/裁剪。
- Optimization:在同一批数据上算优势(GAE)、跑 + value loss + entropy,重复 个 epoch;最后更新 ,进入下一轮 rollout。
一句话总结:RM 给方向, + KL 给长期护栏,PPO(尤其 clipping)给短期稳定更新。
2.2. 两个“旧策略”不要混
PPO 里几乎总会涉及旧策略,但它通常指的是:
- (PPO 的 old policy):上一轮采样用的策略快照,用于重要性采样比率
它是 每一轮都会更新 的。
而 RLHF 工程里常说的 reference model 一般是:
- (RLHF 的 reference policy/model):冻结的锚点模型(常见做法是 SFT 后的模型),用于给当前策略加一个 “别偏太远” 的约束;它通常在一段训练期间 保持不变 或更新频率很低。
2.3. KL-to-reference:把“别跑飞”写进目标
以 PPO-RLHF 常见写法为例,会把 reward 加上一个 KL 惩罚(或等价的 reward shaping):
这里的符号可以按“一条 RLHF 训练样本”来理解:
- :prompt / 输入上下文(用户问题、题目、对话历史等)
- :response / 输出序列(模型在 条件下生成的整段回答 token 序列)
- :在输入 下输出 的奖励(来自 reward model、规则打分等)
- :在同一个输入 条件下,当前策略相对 reference policy 的分布偏离程度
于是 PPO 实际最大化的是 “奖励 - 偏离 reference 的代价”。直觉上:
- 如果只追 :模型会倾向于钻 reward 的空子,偏离语言先验越来越大。
- 加上 KL:reference model 提供了一个长期锚点,PPO 的 clipped update 提供了一个短期的“每步别迈太大”,两者一起让训练更稳。
备注:不同实现里 KL 可能以多种形式进入(显式 KL penalty、或把 per-token logprob 差写进 reward),但核心都是 “把策略拴在 附近”。
一个常见的工程视角是把 KL “摊平”到 token 级别。设输出序列 ,则
在自回归语言模型里,这里的 时间步 通常就是“生成第 个 token 的那一步”(也就是 token index):
- :第 步采样得到的那个 token
- :到第 步之前已经生成的前缀(第 1 步时为空前缀)
因此 就是这条输出序列的长度(token 数)。这和传统 RL 里“环境每走一步”的时间轴可以不同:在 LLM 文本生成里,“一步”往往等价于“再生成一个 token”。
如果只关心当前采样到的这条序列(on-policy 轨迹)上的惩罚,那么很多实现会定义一个 token 级别的“KL 代价”:
这里的 (logprob)就是:策略模型在时间步 给出的“下一个 token”的条件概率分布 中,取到实际 token 的概率再取对数(通常取自然对数)。
然后把它加进每一步的 reward(reward shaping)。这样累加起来就是序列级别的 logprob 差惩罚:
直觉上:如果某个 token 在当前策略下的概率比 reference 更大(),那它会产生负的 shaping reward(惩罚),从而抑制策略在该方向上“越走越远”。
2.4. 推荐阅读
- Ouyang et al., 2022. Training language models to follow instructions with human feedback (InstructGPT).(SFT → RM → PPO,以及 KL/reference 的由来)
- Stiennon et al., 2020. Learning to summarize with human feedback.(更早期、端到端的 RLHF 案例)
- Ziegler et al., 2019. Fine-Tuning Language Models from Human Preferences.(偏好优化 + KL 正则的直观版本)
扩展(对比视角,理解“reference 并非 PPO 专属”):
- Rafailov et al., 2023. Direct Preference Optimization (DPO).(绕开 RM 与 PPO,但同样体现 anchor/reference 的思想)
3. GRPO:从 PPO / RLHF 再往前走一小步
前文将 PPO 概括为“稳定的策略更新框架”,将 RLHF 概括为“RM + KL-to-reference + PPO”的常见落地形态。进一步地,在 数学推理 / 可验证奖励 这类场景里,训练目标仍然可以用 PPO 的 clipped objective,但 优势(advantage)与 baseline 的估计往往会变得更棘手。
GRPO(Group Relative Policy Optimization) 是在 DeepSeekMath 里提出的、PPO 的一个变体:动机之一是让 RL 在 LLM 场景里更省资源,同时处理 “reward 往往只在序列末出现、但 value 需要 token 级别监督” 这类不匹配。
后续再展开学习
- 仍然很 PPO:整体还是围绕 clipped ratio 的策略更新思路在转(可以把它理解成“骨架仍在 PPO”)。
- 关键变化:去掉 value模型 / critic:GRPO 不再额外训练一个与 policy 同量级的 value function 来给每个 token 做 baseline。
- 用 group 做相对基线:对同一个问题 ,先从旧策略采样一组输出 ,再用 组内相对比较 来构造优势(论文强调这与 reward model 常见的“同题对比训练”更一致)。
- KL 处理方式也可能不同:论文里也讨论了与 PPO 场景下 KL penalty 不同的正则化思路(读 4.1 小节时对照实现会更清晰)。