# 近端策略优化 (Proximal Policy Optimization, PPO) 最后更新时间:2025年6月19日。 近端策略优化 (Proximal Policy Optimization, PPO) 是一类由 OpenAI 在 2017 年提出的用于强化学习的策略梯度方法。PPO 在简洁性、稳定性和性能之间取得了平衡,使其成为现代强化学习应用中最广泛使用的算法之一,包括大规模语言模型的微调。 传统的策略梯度方法,如 REINFORCE 或 Vanilla Policy Gradient,存在以下问题: - 方差高且样本效率低。 - 由于策略更新幅度过大导致不稳定。 PPO 通过使用一种裁剪的代理目标函数来解决这个问题,该目标函数可以避免过大的更新,而无需二阶导数。 有关 PPO 更详细的技术信息,我们建议阅读 [OpenAI spinning up 教程](https://spinningup.openai.com/en/latest/algorithms/ppo.html) 的导言,以及论文 "[Proximal Policy Optimization Algorithms](https://arxiv.org/abs/1707.06347)"。 ## 核心组件 - **Actor-Critic 架构**:PPO 需要一个 actor 模型(策略)和一个 critic 模型(价值函数)。这与其他不需要 critic 模型的算法,如 GRPO 和 RLOO 不同。 - **广义优势估计 (Generalized Advantage Estimation, GAE)**:PPO 使用 GAE 来计算优势值,这有助于在保持低偏差的同时减少策略梯度估计中的方差。 - **裁剪的代理目标函数 (Clipped Surrogate Objective)**:PPO 的核心是通过裁剪的代理目标函数实现的,该函数限制了策略的更新幅度。 ## 配置 请注意,所有包含 `micro_batch_size` 的配置项用于配置每次前向或后向传播的最大样本或 token 数量,以避免 GPU 显存溢出 (GPU OOMs)。该值不应改变算法或收敛行为。 大多数 critic 的配置项与 actor 类似。请注意,下图中省略了 critic 模型。 ![image](https://github.com/user-attachments/assets/16aebad1-0da6-4eb3-806d-54a74e712c2d) - `data.train_batch_size`: 用于生成一组采样轨迹/rollout 的全局提示(prompts)批量大小。响应/轨迹的数量为 `data.train_batch_size * actor_rollout.ref.rollout.n` - `actor_rollout_ref.actor.ppo_mini_batch_size`: 采样轨迹集被划分为多个 PPO actor 更新的 mini-batch,batch_size 为 `ppo_mini_batch_size`。`ppo_mini_batch_size` 是所有 worker 的全局大小。 - `critic.ppo_mini_batch_size`: 采样轨迹集被划分为多个 PPO critic 更新的 mini-batch,batch_size 为 `ppo_mini_batch_size`。`ppo_mini_batch_size` 是所有 worker 的全局大小。 - `actor_rollout_ref.actor.clip_ratio`: PPO 的裁剪范围。默认为 0.2。 - `actor_rollout_ref.actor.ppo_epochs`: 在一组采样轨迹上进行 PPO actor 更新的 epoch 数量。 - `critic.ppo_epochs`: 在一组采样轨迹上进行 PPO critic 更新的 epoch 数量。默认为 `actor_rollout_ref.actor.ppo_epochs`。 - `algorithm.gemma`: 折扣因子。 - `algorithm.lam`: GAE 估计器中用于权衡偏差和方差的 lambda 项。 - `algorithm.adv_estimator`: 支持 gae, grpo, reinforce_plus_plus, reinforce_plus_plus_baseline, rloo。 ## 高级扩展 ### KL 散度控制 用于防止策略过于偏离参考策略的选项。有两种机制可用:KL 奖励惩罚 (KL reward penalty) 和 KL 损失 (KL loss)。更多技术细节,请参阅 [Training language models to follow instructions with human feedback](https://arxiv.org/abs/2203.02155)。 用于 KL 损失的 KL 散度控制选项: - `actor_rollout_ref.actor.use_kl_loss`: 在 actor 中使用 KL 损失。使用时,不对奖励函数应用 KL。默认为 False。 - `actor_rollout_ref.actor.kl_loss_coef`: KL 损失的系数。默认为 0.001。 - `actor_rollout_ref.actor.kl_loss_type`: 支持 kl(k1), abs, mse(k2), low_var_kl(k3) 和 full。在末尾添加 "+"(例如,'k1+' 和 'k3+')将直接应用 k2 以实现无偏梯度估计,无论 KL 值如何估计(有关更多详细信息,请参阅 https://github.com/volcengine/verl/pull/2953#issuecomment-3162113848)。如何计算 actor 和参考策略之间的 KL 散度。有关详细分析,请参阅这篇博文:http://joschu.net/blog/kl-approx.html 在奖励中使用 KL 惩罚的选项: - `algorithm.use_kl_in_reward`: 是否在奖励中启用 KL 惩罚。默认为 False。 - `algorithm.kl_penalty`: 支持 kl(k1), abs, mse(k2), low_var_kl(k3) 和 full。这定义了计算 actor 和参考策略之间 KL 散度的方式。有关具体选项,请参阅 `core_algos.py` 中的 `kl_penalty`。有关详细分析,请参阅这篇博文:http://joschu.net/blog/kl-approx.html - `algorithm.kl_ctrl.kl_coef`: 奖励内 KL 惩罚的(初始)系数。默认为 0.001。 - `algorithm.kl_ctrl.type`: 'fixed' 表示 FixedKLController,'adaptive' 表示 AdaptiveKLController。 - `algorithm.kl_ctrl.horizon`: 有关详细信息,请参阅 AdaptiveKLController 的源代码。 - `algorithm.kl_ctrl.target_kl`: 有关详细信息,请参阅 AdaptiveKLController 的源代码。 ### 双裁剪 PPO (Dual-clip PPO) 双裁剪 PPO 引入了一种方法,当优势小于零时,对策略比率应用下限,当乘以一个较大的比率时,不会超过指定的下限。 ![image](https://github.com/user-attachments/assets/fc232181-d8b0-4307-8dd2-4dc0a4c1c139) - `actor_rollout_ref.actor.clip_ratio_c`: 双裁剪 PPO 值的下限,默认为 3.0。 ## 参考示例 Qwen2.5 训练日志和命令:[链接](https://github.com/eric-haibin-lin/verl-data/blob/experiments/gsm8k/Qwen2.5-0.5B-bsz256_2-prompt1024-resp512-0.567.log) ```bash bash run_gemma.sh trainer.n_gpus_per_node=1 \ actor_rollout_ref.rollout.tensor_model_parallel_size=1 \ trainer.logger=console \ critic.model.path=Qwen/Qwen2.5-0.5B-Instruct \ actor_rollout_ref.model.path=Qwen/Qwen2.5-0.5B-Instruct \ data.train_batch_size=256 \ actor_rollout_ref.actor.ppo_mini_batch_size=64 \ actor_rollout_ref.actor.ppo_micro_batch_size=2 \ critic.ppo_micro_batch_size=2 ``` verl v0.2 的参考性能: | 模型 | 方法 | 分数 | 链接 | |-------------------------------|------------------|-------|------------------------------------------------------------------------------------------------| | Qwen/Qwen2.5-0.5B-Instruct | 预训练模型 | 36.4 | [Qwen Blog](https://qwenlm.github.io/blog/qwen2.5-llm/) | | Qwen/Qwen2.5-0.5B-Instruct | PPO | 56.7 | [PPO 命令和日志](https://github.com/eric-haibin-lin/verl-data/blob/experiments/gsm8k/Qwen2.5-0.5B-bsz256_2-prompt1024-resp512-0.567.log) |