资讯动态

verl 中 PPO 训练指南:从算法原理到配置实战

发布时间:2026/9/13 20:17:56 来源:尧图企业网站定制
verl 中 PPO 训练指南从算法原理到配置实战【免费下载链接】verlverl/HybridFlow: A Flexible and Efficient RL Post-Training Framework项目地址: https://gitcode.com/GitHub_Trending/ve/verl本篇技术指南围绕开源 RL 后训练框架 verlHybridFlow中 PPOProximal Policy Optimization训练器的完整实现展开先梳理 PPO 的算法内核Actor-Critic 架构、GAE 优势估计、Clipped Surrogate Objective再逐项解析train_batch_size、ppo_mini_batch_size、clip_ratio、algorithm.gamma/lam/adv_estimator等关键配置的语义深入 KL 散度控制与 Dual-clip PPO 两种高级扩展最后以 Qwen2.5-0.5B GSM8K 训练为例给出可直接复制的命令行与仓库内参考脚本。读者读完可以独立配置并运行 verl 的 PPO 训练并理解每一步在源码中的落点。PPO 算法核心为何选择 clipped surrogate objectivePPOProximal Policy Optimization是 OpenAI 于 2017 年提出的一族策略梯度policy gradient方法在简单性、稳定性和性能之间取得了良好平衡也是当前大规模语言模型LLM后训练中最常用的强化学习算法之一。传统策略梯度方法如 REINFORCE / Vanilla Policy Gradient存在两个突出问题高方差、样本效率低单条轨迹的回报估计波动大需要大量样本才能稳定收敛更新步长不可控策略更新过大容易导致训练崩溃或性能骤降。PPO 用截断的替代目标Clipped Surrogate Objective解决上述问题——它无需计算二阶导数区别于 TRPO 的自然梯度方法只通过把重要性采样比率importance sampling ratio限制在[1-ε, 1ε]区间内即可约束单次更新幅度兼顾了实现简单与训练稳定。在 verl 中这一目标的实现位于 core_algos.py 的compute_policy_loss_vanilla注册名为vanilla。核心代码如下节选自 core_algos.pynegative_approx_kl log_prob - old_log_prob # 新旧策略对数概率差 negative_approx_kl torch.clamp(negative_approx_kl, min-20.0, max20.0) # 数值稳定 ratio torch.exp(negative_approx_kl) # 重要性采样比率 r(θ) pg_losses1 -advantages * ratio pg_losses2 -advantages * torch.clamp(ratio, 1 - cliprange_low, 1 cliprange_high) clip_pg_losses1 torch.maximum(pg_losses1, pg_losses2) # max(-r·A, -clip(r)·A) pg_losses torch.where(advantages 0, clip_pg_losses2, clip_pg_losses1)即对每个 token 取max(-r·A, -clip(r)·A)对应论文中的min(r·A, clip(r)·A)最大化形式取负后变为最小化。此外verl 还实现了clip_ratio_low与clip_ratio_high的非对称截断能力允许上下界不同所有策略损失通过agg_loss按loss_agg_mode聚合默认token-meanagg_loss同时支持token-sum、seq-mean-token-sum、seq-mean-token-mean等模式并保证损失在 FSDP/Megatron 不同并行策略下数值一致见 core_algos.py。说明本节以 PPO 的 vanilla 策略损失为主线。verl 的POLICY_LOSS_REGISTRY还注册了 gspo、sapo、gpg、clip_cov、kl_cov、dro、cispo、bypass_mode 等扩展损失均可通过actor_rollout_ref.actor.policy_loss.loss_mode切换。关键组件Actor-Critic、GAE 与配置总览PPO 的三个关键组件对应 verl 的三类核心配置域Actor-Critic 架构PPO 同时需要actor策略模型与critic价值函数模型。这是它与 GRPO、RLOO 等无需 critic 的算法最本质的区别——critic 用于估计 token 级价值进而计算优势。在 verl 中critic 由critic配置域管理其模型与 actor 可以不同例如 actor 用 Qwen2.5-0.5B-Instructcritic 可复用同一模型权重或另设路径。配置上 critic 的默认strategy独立于 actor如fsdp参考实现见 critic.yaml。GAEGeneralized Advantage EstimationPPO 使用 GAE 计算优势值A_t δ_t (γλ)δ_{t1} ...在降低方差与保持低偏差之间取得平衡其中γgamma是折扣因子、λlam是偏差-方差权衡系数。verl 的实现位于compute_gae_advantage_returncore_algos.py它从序列末尾反向递推 TD-error并利用response_mask跳过 observation token 的 value/TD-error 计算测试用例见 test_core_algos_on_cpu.py 中的test_multi_turn_compute_gae_advantage_return。Clipped Surrogate Objective上文已述对应clip_ratio等配置。一个重要的配置约定所有包含micro_batch_size的配置仅用于控制每次前向/反向的最大样本数或 token 数以避免 GPU OOM其取值不应改变算法的收敛行为。换言之这些参数只影响吞吐与显存占用不影响最终训练效果。critic 的多数配置与 actor 类似下文图中省略了 critic原文档示意图此处以文字表述PPO 训练数据流为data.train_batch_size个 prompt → 采样得到若干 response 轨迹 → 计算奖励/价值/优势 → 拆分 mini-batch 更新 actor 与 critic。PPO 训练核心配置速查表以下为 verl PPO 训练中最核心的配置项及其语义默认值以仓库当前 actor.yaml、critic.yaml、ppo_trainer.yaml 为准配置项含义默认值data.train_batch_size用于生成一批采样轨迹的全局 prompt 批量大小实际响应/轨迹数为train_batch_size * actor_rollout_ref.rollout.n由 data 配置指定actor_rollout_ref.actor.ppo_mini_batch_size将一批轨迹按此大小拆分为多个 mini-batch 用于 actor 的 PPO 更新为跨所有 worker 的全局值256critic.ppo_mini_batch_size将一批轨迹按此大小拆分用于 critic 的 PPO 更新同样为全局值继承 actor${oc.select:actor_rollout_ref.actor.ppo_mini_batch_size,256}actor_rollout_ref.actor.ppo_micro_batch_size已废弃见ppo_micro_batch_size_per_gpu与ppo_max_token_len_per_gpu每次前向/反向的最大样本数防 OOMnullactor_rollout_ref.actor.clip_ratioPPO 截断范围 ε0.2actor_rollout_ref.actor.clip_ratio_low/clip_ratio_high非对称截断的下/上界0.2 / 0.2actor_rollout_ref.actor.ppo_epochs对同一批采样轨迹进行 PPO 更新的轮数actor1critic.ppo_epochs对同一批轨迹进行 critic 更新的轮数继承 actor${oc.select:actor_rollout_ref.actor.ppo_epochs,1}critic.cliprange_value价值函数value head更新的截断范围0.5algorithm.gamma折扣因子 γ1.0algorithm.lamGAE 中偏差-方差权衡系数 λ1.0algorithm.adv_estimator优势估计器支持gae、grpo、reinforce_plus_plus、reinforce_plus_plus_baseline、rloo等gaecritic 的价值函数损失同样带截断vpredclipped clip(vpreds, values - cliprange_value, values cliprange_value)并取max((vpred-returns)², (vpredclipped-returns)²)的 0.5 倍见 core_algos.py。优势估计器从 GAE 到多种无 critic 变体algorithm.adv_estimator决定优势advantage如何计算。verl 通过AdvantageEstimator枚举 register_adv_est装饰器实现注册表机制core_algos.pyget_adv_estimator_fn按名称取函数且用户可以用字符串名注册自定义估计器不可重复注册同名函数见 test_core_algos_on_cpu.py 的TestRegisterAdvEst。当前枚举支持gae、grpo、reinforce_plus_plus、reinforce_plus_plus_baseline、remax、rloo、opo、grpo_passk、gpg、rloo_vectorized、grpo_vectorized、optimal_token_baseline、tir_optimal_token_baseline、gdpo。文档明确列出的五种如下gae默认估计器依赖 critic 提供 token 级价值见compute_gae_advantage_returncore_algos.py。计算delta reward_t γ·nextvalues - values_t递推lastgaelam delta γλ·lastgaelam最终advantages masked_whiten(advantages, response_mask)对优势做白化归一化returns advantages values。grpoGRPO 风格仅使用结果奖励outcome reward无需 critic。按 prompt 分组组内scores (r_i - mean_group) / (std_group ε)可通过algorithm.norm_adv_by_std_in_grpo关闭按标准差归一化即 Dr.GRPO 的变体见compute_grpo_outcome_advantagecore_algos.py。reinforce_plus_plusREINFORCE无 critic、无分组使用折扣回报并做masked_whiten见compute_reinforce_plus_plus_outcome_advantagecore_algos.py。reinforce_plus_plus_baselineREINFORCE 的组均值 baseline 版本组内减去均值后再白化见compute_reinforce_plus_plus_baseline_outcome_advantagecore_algos.py。rlooRLOOLeave-One-Out组内计算 leave-one-out baselinescores_i r_i·n/(n-1) - mean_group·n/(n-1)n1 时生效见compute_rloo_outcome_advantagecore_algos.py。从源码结构看grpo/rloo等基于分组index数组的估计器均要求actor_rollout_ref.rollout.n 1每组多个响应而gae无此约束。GRPO/RLOO 的向量化实现grpo_vectorized、rloo_vectorized与原始实现保持数值一致测试通过torch.allclose(rtol1e-5, atol1e-6)校验见 test_core_algos_on_cpu.py 的向量化等价性测试。注意当adv_estimator ! gae如 grpo/rloo时通常不需要 criticverl 的critic.enable默认会根据优势估计器类型自动开关 critic worker。KL 散度控制KL loss 与 in-reward KL penalty为了防止策略偏离参考策略reference policy过远verl 提供两种 KL 控制机制KL 惩罚进入奖励与KL 直接作为 loss。二者原理参考 InstructGPTTraining language models to follow instructions with human feedback一文。机制一KL 作为 actor 的 lossuse_kl_loss通过以下三个配置开启并使用 KL loss典型用于 GRPO 等无 critic 场景actor_rollout_ref.actor.use_kl_loss在 actor 中使用 KL loss。启用后不再在奖励函数中施加 KL。默认False。actor_rollout_ref.actor.kl_loss_coefKL loss 的系数。默认0.001。actor_rollout_ref.actor.kl_loss_typeKL 散度的计算方式支持kl(k1)、abs、mse(k2)、low_var_kl(k3)、full。末尾追加如k1、k3表示使用straight-through技巧前向保持原估计器的值反向使用k2的无偏梯度。默认low_var_kl。机制二KL 惩罚进入奖励use_kl_in_rewardalgorithm.use_kl_in_reward是否启用 in-reward KL 惩罚。默认False。algorithm.kl_penaltyKL 散度的估计方式支持kl(k1)、abs、mse(k2)、low_var_kl(k3)、full与kl_loss_type取值一一对应具体实现见 core_algos.py 的kl_penalty/kl_penalty_forward。k1 logprob - ref_logprobk2 0.5·(logprob-ref_logprob)²k3 clamp(exp(clamp(ref_logprob-logprob,-20,20)) - (ref_logprob-logprob) - 1, -10, 10)。末尾加同样启用 k2 梯度 straight-through。algorithm.kl_ctrl.kl_coefin-reward KL 惩罚的初始系数。默认0.001。algorithm.kl_ctrl.typefixed对应FixedKLControlleradaptive对应AdaptiveKLController。algorithm.kl_ctrl.horizon与algorithm.kl_ctrl.target_klAdaptiveKLController使用——每次按proportional_error clip(current_kl/target - 1, -0.2, 0.2)与mult 1 proportional_error·n_steps/horizon更新系数见 core_algos.py即观测到的 KL 超过目标时按 horizon 逐步调大系数反之调小。get_kl_controllercore_algos.py是二者的工厂函数adaptive 模式要求horizon 0。奖励与 KL 的结合点在compute_rewardscore_algos.pytoken_level_rewards token_level_scores - kl·kl_ratio其中kl old_log_prob - ref_log_prob。因此启用 in-reward KL 惩罚时需要同时配置参考模型actor_rollout_ref.ref配置文件见 ppo_trainer.yaml 中对 ref 的说明。straight-through 行为有专门测试覆盖test_kl_penalty_straight_through_value_matches_base验证k3的前向值与k3一致test_kl_penalty_k3_plus_uses_k2_gradient验证k3的梯度与k2完全一致见 test_core_algos_on_cpu.py。Dual-clip PPO对抗优势下界的二次截断Dual-clip PPO 在标准 PPO 基础上增加一个下界约束当优势A 0不利样本时如果策略比率r(θ)被放大得过大其损失项-r·A不得超过-clip_ratio_c·A所规定的下界从而避免对负优势样本的过度惩罚导致的不稳定。verl 的实现位于compute_policy_loss_vanillacore_algos.pypg_losses3 -advantages * clip_ratio_c # 下界项 clip_pg_losses2 torch.min(pg_losses3, clip_pg_losses1) # 对 A0 的额外截断 pg_losses torch.where(advantages 0, clip_pg_losses2, clip_pg_losses1)配置项actor_rollout_ref.actor.clip_ratio_cDual-clip PPO 的比率下界默认3.0。源码要求其值必须 1.0否则抛出断言错误见 core_algos.py。同时verl 会额外计算并上报actor/pg_clipfrac_lower指标用于观测负优势样本被下界截断的比例。DPPOBinary-TV / Binary-KL等变体还利用clip_ratio_c作为截断重要性采样TIS的阈值默认 20.0见同文件中的compute_policy_loss_dppo_tv/compute_policy_loss_dppo_kl。实战示例Qwen2.5-0.5B GSM8K PPO 训练最小可运行命令原文档给出的 PPO 覆盖式命令行在examples/ppo_trainer下以脚本方式运行bash run_gemma.sh \ trainer.n_gpus_per_node1 \ actor_rollout_ref.rollout.tensor_model_parallel_size1 \ trainer.loggerconsole \ critic.model.pathQwen/Qwen2.5-0.5B-Instruct \ actor_rollout_ref.model.pathQwen/Qwen2.5-0.5B-Instruct \ data.train_batch_size256 \ actor_rollout_ref.actor.ppo_mini_batch_size64 \ actor_rollout_ref.actor.ppo_micro_batch_size2 \ critic.ppo_micro_batch_size2解读各覆盖参数单卡单 TP 部署n_gpus_per_node1、tensor_model_parallel_size1控制台日志trainer.loggerconsoleactor 与 critic 均使用 Qwen2.5-0.5B-Instruct全局批次 256、actor/critic mini-batch 64即每个 PPO epoch 内拆分为 4 个 mini-batch 更新ppo_micro_batch_size2控制单次前向的样本上限以避免显存溢出当前版本已将其废弃推荐使用actor_rollout_ref.actor.use_dynamic_bszTrue配合ppo_max_token_len_per_gpu见 actor.yaml。仓库内参考脚本仓库当前提供了更完整的 PPO 参考脚本 run_qwen3_8b_fsdp.shFSDP 训练GPU/NPU 通用自动探测设备其关键配置片段DATA( algorithm.adv_estimatorgae data.train_batch_size${TRAIN_BATCH_SIZE} # 默认 1024 data.max_prompt_length1024 data.max_response_length2048 ) ACTOR( actor_rollout_ref.actor.optim.lr1e-6 actor_rollout_ref.actor.ppo_mini_batch_size256 actor_rollout_ref.actor.use_dynamic_bszTrue actor_rollout_ref.actor.ppo_max_token_len_per_gpu24576 actor_rollout_ref.actor.entropy_coeff0 ) ROLLOUT( actor_rollout_ref.rollout.namevllm # 或 sglang actor_rollout_ref.rollout.n1 actor_rollout_ref.rollout.tensor_model_parallel_size2 actor_rollout_ref.rollout.gpu_memory_utilization0.6 ) CRITIC( critic.model.path${CRITIC_MODEL_PATH} critic.optim.lr1e-5 critic.use_dynamic_bszTrue )运行方式仓库根目录bash examples/ppo_trainer/run_qwen3_8b_fsdp.sh该脚本会以uv run --frozen --all-packages --extra vllm --extra fsdp python3 -m verl.trainer.main_ppo启动GPU vllm/sglang 后端时入口为 main_ppo.py。Megatron 后端可参考 run_qwen3_8b_megatron.sh。训练前需按 prepare_data.rst 准备 GSM8K / MATH 的 parquet 数据并通过GSM8K_TRAIN_FILE等环境变量指定路径。参考性能文档给出的 verl v0.2 参考性能GSM8K模型方法ScoreQwen/Qwen2.5-0.5B-Instruct预训练模型未训练36.4Qwen/Qwen2.5-0.5B-InstructPPObsz256、2 epochs、prompt1024、resp51256.7该结果对应的训练配置为data.train_batch_size256、prompt 长度上限 1024、response 长度上限 512。注意该数值属于历史版本verl v0.2参考数据实际复现请以当前仓库版本与硬件环境为准训练过程中可通过trainer.logger配置console/wandb等观察actor/pg_clipfrac、actor/ppo_kl、critic/vf_clipfrac等指标判断收敛与截断情况。小结verl 的 PPO 实现将算法核心GAE、clipped surrogate objective、KL 控制、dual-clip集中在 core_algos.py 一个文件中由不同并行策略FSDP / Megatron的训练器复用并通过注册表机制与 YAML 配置解耦从而在保持算法稳定性的同时具备高度可扩展性。理解本文涉及的配置项——尤其是ppo_mini_batch_size算法语义与ppo_max_token_len_per_gpu仅影响显存的区别、adv_estimator的选择有/无 critic、以及 KL 控制的两种机制——即可根据业务需求灵活搭建 PPO 训练。需要了解 GRPO、RLOO、REINFORCE 等算法的更多细节时可继续阅读 grpo.md、rloo.md 等对应文档或直接查看 ppo_trainer.yaml 与 actor.yaml 的完整字段注释。【免费下载链接】verlverl/HybridFlow: A Flexible and Efficient RL Post-Training Framework项目地址: https://gitcode.com/GitHub_Trending/ve/verl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价