RL 算法性能调优指南覆盖 PPO / GRPO / DAPO / VERL聚焦超参数 算法特性调优零废话一、训练流程与瓶颈定位1.1 典型 RL 训练循环以 PPO 为例环境交互 → 采样 trajectory → 计算 advantage → 策略更新 → 网络同步 ↑ ↓ 采样慢 更新震荡 / 崩溃每个环节都可能成为瓶颈环节常见问题症状环境交互CPU 单线程GPU 空闲等数据GPU 利用率 30%Advantage 估计GAE 参数不当variance 大Reward 曲线剧烈抖动策略更新LR 过大epoch 过多Loss 爆炸或 NaN价值网络估计偏差大导致策略误导Critic Loss 持续偏高梯度更新梯度爆炸/消失Loss → NaN 或 Critic Loss → ∞1.2 瓶颈快速定位三问Loss 是 NaN→ 梯度爆炸检查clip_range、max_grad_norm、reward scalingReward 不涨→ 策略没更新检查entropy_coef是否探索不足或 LRGPU 闲置→ 环境交互太慢检查num_envs并行环境数二、核心超参数详解2.1 学习率Learning Rate值域效果3e-4~1e-3默认安全区适合大多数任务1e-3~3e-3初期快速收敛但易震荡中后期需lr_decay 1e-4稳定但收敛慢适合复杂任务微调调度策略关键但常被忽略# 余弦退火 — 最通用的选择lrconfig.lr*(1cos(π*step/total_steps))/2# 线性预热 余弦衰减 — 防止初期梯度过大ifstepwarmup_steps:lrconfig.lr*step/warmup_stepselse:progress(step-warmup_steps)/(total_steps-warmup_steps)lrconfig.lr*(1-progress)2.2 PPO-Clip 范围clip_range/epsilon作用限制策略更新步长防止一次更新过大导致性能崩溃。旧策略概率比 r(θ) π_θ(a|s) / π_θ_old(a|s) PPO 目标L^CLIP(θ) E[ min(r(θ)·A, clip(r(θ), 1-ε, 1ε)·A) ] clip 效果当 |A| 大时允许更大的策略变化clip_range策略稳定性样本效率适用场景0.1~0.2保守低震荡较低训练后期、脆弱环境0.2~0.3激进可能震荡高简单任务、离线微调自适应 clipDAPO 核心改进之一动态调整 clip 范围见第五节。2.3 GAEGeneralized Advantage EstimationA_t δ_t (γλ)·δ_{t1} (γλ)²·δ_{t2} ... δ_t r_t γ·V(s_{t1}) - V(s_t)参数作用推荐值λGAE 参数balance variance 与 bias0.9~0.95γ折扣因子未来 reward 重要性0.99标准0.995长视野λ越接近 1bias 小variance 大TD(∞)适合长序列决策λ越接近 0variance 小bias 大TD(0)适合稀疏奖励2.4 Epochs 与 Batch Size参数值效果ppo_epochs4~10多次对同一批数据更新提高样本效率但易过拟合batch_size256~512越大梯度越稳定但显存压力增大num_mini_batch4~8分成更多 mini-batch减少过拟合常见错误ppo_epochs1数据只过一遍样本利用率极低。2.5 熵系数Entropy Coefficient策略熵 H(π) -Σ π(a|s) log π(a|s) 熵大 → 探索多策略更随机 熵小 → exploitation策略更确定entropy_coef效果0禁用策略可能早熟陷入局部最优0.01~0.1标准推荐值随训练衰减前期多探索后期稳定 exploitation自动调节SAC α动态维持目标熵但需要调参稳定早停信号如果 entropy 在前几个 episode 就急剧下降 → 策略已早熟加大entropy_coef。三、价值网络调优3.1 Value Function 估计偏差价值网络估计不准是 RL 训练失败最常见的原因之一真实 V(s) vs 估计 V_θ(s) 偏差Bias高估/低估 reward 方差Variance估计波动大 两者都会导致策略学偏3.2 常用解法① Value Function 损失加权# 过度信任价值网络会中毒加权重限制梯度value_lossF.mse_loss(v_pred,v_target)value_lossmin(value_loss,# 标准 lossF.mse_loss(v_pred.detach(),v_target))# 限制梯度不反向传播② 双 Q 网络Double Q# 用在线网络选择动作用目标网络评估减小高估偏差next_actiononline_network(next_state).argmax(1)next_qtarget_network(next_state,next_action)③ Value ClippingPPO# 限制 value 变化幅度防止 value 估计剧烈波动v_clippedv_oldclamp(v_pred-v_old,-ε,ε)value_lossmax(loss(v_pred,v_target),loss(v_clipped,v_target))3.3 Reward ScalingPendulum 类环境原始 reward 范围很大-1600 ~ 0直接用会数值不稳定# 方法1除以 running reward 标准差rewardreward/running_reward_std# 方法2clamp 到固定范围rewardreward.clamp(-10,10)# 方法3简单除以常数Pendulum 常用 /10.0rewardreward/10.0警告测试集不用 running stats只用训练集的统计值。四、探索策略调优4.1 连续动作空间的探索方法原理优缺点随机扰动DDPG在确定性策略输出上加噪声简单但噪声相关性差熵正则化SAC最大化 π 的熵数学优雅KL 版本有理论保证Normalizing Flow变换简单分布为复杂分布表达力强计算开销增加4.2 离散动作空间的探索方法适用场景UCBUpper Confidence BoundBandit 类任务平衡探索/利用epsilon-greedy简单任务ε 从 1.0 线性/指数衰减到 0.01Gumbel-Softmax可微采样连续近似离散用于策略梯度entropy_coefPPO 中加熵项鼓励探索4.3 经验回放Replay Buffer调优# 经验回放不是越大越好buffer_size100_000# 太大 早期经验被稀释buffer_size10_000# 太小 样本多样性不足# 优先回放PER高 TD Error 的样本更重要priorityabs(TD_error)ε五、DAPO — 自适应 Clip 的 PPO 改进DAPODecoupled Clip and Dynamic Sampling Policy Optimization是 2024-2025 年提出的 PPO 改进核心解决clip 导致的数据效率损失。5.1 PPO-Clip 的根本问题PPO: L^CLIP min(r·A, clip(r, 1-ε, 1ε)·A) 当 A 0优势动作clip 阻止概率比 r 超过 1ε 当 A 0劣势动作clip 阻止概率比 r 低于 1-ε → 问题即使 clip 后被 clip 的样本对梯度贡献变成 0 这些样本被完全浪费5.2 DAPO 的三处核心改进① Token-Level Clip替代 Episode-Level ClipPPO 对整个 episode 的策略变化做 clipDAPO 对每个 token 的策略变化做 clip粒度更细利用率更高。② Dynamic Sampling动态采样# 过滤掉没有信息的样本优势≈0的样本# 这些样本 clip 后梯度贡献为0没必要参与更新maskabs(advantage)threshold losspolicy_loss[mask].mean()③ Decoupled Clip解耦 Clip# PPOclip 和 importance sampling 耦合# DAPO分开处理clip 只作用在 ratio 上不影响 advantage 的计算ratiopi_new/pi_old clipped_ratioclamp(ratio,1-ε,1ε)policy_lossclipped_ratio*advantage效果在 ChatGLM、Shoot 等任务上DAPO 相比 PPO 样本效率提升 1.5-3x。六、GRPO — 免 Critic 的策略优化GRPOGroup Relative Policy Optimization是 DeepSeek 系列提出的新范式核心思想不要 Critic用样本组内的相对比较来估计优势。6.1 GRPO vs PPO 的核心区别PPO: 需要 Value Network V(s) → Critic 估计状态价值 两大网络Actor Critic→ 调参翻倍 GRPO: 同一状态生成多个候选动作组内相对排序 → 无需 Critic6.2 GRPO 算法流程1. 对每个状态 s采样 G 个动作 {a_1, ..., a_G} 2. 对每个 (s, a_i) 估计 Q(s, a_i)用 reward 或奖励模型 3. 组内归一化优势 A_i (Q_i - mean(Q)) / std(Q) 4. 用 PPO-style clip 策略更新 L min(ratio · A_i, clip(ratio, 1-ε, 1ε) · A_i) 5. KL 正则化可选 L β · D_KL(π || π_old)6.3 GRPO 的优势方面PPOGRPO网络数2Actor Critic1只有 ActorCritic 调参需要调 LR、GAE、value loss weight不需要样本效率中等高无 value 估计偏差适用场景通用reward 噪声小大模型 RLHF、reward 估计不稳定场景6.4 GRPO 的注意事项组大小 GG 越大相对排序越可靠但计算成本越高。推荐G8~G16Reward 噪声如果 reward 本身噪声大人类反馈需要 reward model 平滑KL 约束没有 Critic 时加 KL 项防止策略崩溃成 delta 分布七、VERL — 大规模训练工程优化VERLRich Evolution via Large-scale Reinforcement Learning不是算法而是训练工程框架核心解决大模型 RL 训练的系统瓶颈。7.1 大模型 RL 的三个工程挑战1. GPU 内存墙Actor Critic Optimizer States → 显存 OOM 2. 通信瓶颈多 GPU 采样/更新同步GPU 利用率低 3. 离线数据效率已有离线轨迹数据RL 微调效率低7.2 VERL 的核心策略① 梯度累积 虚拟批次实际 batch 32 虚拟 batch 256通过梯度累积多次前向累积梯度 → 用小显存跑大 batch 训练② Actor-Critic 分离部署GPU 0-7: Actor 网络推理显存占用低 GPU 8-15: Critic 网络训练高显存 All-to-All 通信Advantage 计算 → 减少 Critic 推理的显存占用③ 离线数据复用# 对离线轨迹做 advantage 重估计# 用新 Critic 对旧轨迹重新计算 A(s,a)# 不需要重新采样直接复用已有轨迹offline_advantagesnew_critic.estimate(old_trajectories)7.3 配套调参建议配合 VERL 框架参数框架默认值大模型调优建议gradient_accumulation_steps14~8micro_batch_size14~8adam_epsilon1e-81e-6大模型防震荡max_grad_norm1.00.5~2.0八、调试 Checklist按优先级 第一优先级几乎必做Reward scaling除以 std 或 clampmax_grad_norm 0.5~10.0学习率3e-4~1e-4检查 Critic Loss 是否为 NaN 第二优先级效果显著clip_range 0.1~0.2过大不稳定过小不学习GAEλ 0.9~0.95entropy_coef 0防止早熟ppo_epochs 4~10太小样本浪费太大过拟合确认num_envs并行环境数与 GPU 利用率匹配 第三优先级锦上添花LR 预热warmup 500~1000 步余弦退火衰减Double Q 减小高估Priority Experience ReplayAdvantage 标准化减 mean 除 std❌ 常见错误清单错误现象解法LR 过大Loss 爆炸 → NaN降低 10xclip_range 过大策略崩溃降到 0.1~0.2entropy_coef 0策略早熟reward 卡住增加到 0.01~0.1value_loss_weight 过大Critic 压制 Actor 更新降到 0.5~1.0buffer 太小样本多样性不足至少 50000单环境采样GPU 95% 时间在等数据并行num_envs 8九、主流算法对照表算法Critic适用场景调参难度样本效率PPO需要通用首选★★中SAC需要双Q连续控制★★高TD3需要双Q延迟更新连续控制★★★高DQN需要目标网络离散动作★中GRPO不需要大模型 RLHF离线场景★高DAPO需要PPO 升级离线在线★★更高调参的第一原则先让系统稳定运行再追求性能。Loss 不崩溃、Reward 不变差比追求高 Reward 更优先。瓶颈定位永远先于调参。十、VERL 系统参数调优分布式 RL 训练示例脚本examples/grpo_trainer/run_qwen3-32b_npu.shset-x project_nameGRPO-Qwen3exp_nameGRPO-Qwen3-32b-npugen_tp4RAY_DATA_HOME${RAY_DATA_HOME:-${HOME}/verl}MODEL_PATH${MODEL_PATH:-${RAY_DATA_HOME}/models/Qwen3-32B}TRAIN_FILE${TRAIN_FILE:-${RAY_DATA_HOME}/data/gsm8k/train.parquet}TEST_FILE${TEST_FILE:-${RAY_DATA_HOME}/data/gsm8k/test.parquet}python3-m verl.trainer.main_ppo \ algorithm.adv_estimatorgrpo \ data.train_files${TRAIN_FILE}\ data.val_files${TEST_FILE}\ data.train_batch_size1024\ data.max_prompt_length2048\ data.max_response_length2048\ data.filter_overlong_promptsTrue\ data.truncationerror\ data.shuffleFalse\ actor_rollout_ref.model.path${MODEL_PATH}\ actor_rollout_ref.actor.optim.lr1e-6\ actor_rollout_ref.model.use_remove_paddingTrue\ actor_rollout_ref.actor.ulysses_sequence_parallel_size4\actor_rollout_ref.actor.fsdp_config.mixed_precision.param_dtypebf16 \actor_rollout_ref.actor.fsdp_config.mixed_precision.reduce_dtypebf16 \actor_rollout_ref.actor.fsdp_config.mixed_precision.buffer_dtypefp32 \ actor_rollout_ref.actor.ppo_mini_batch_size64\ actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu8\ actor_rollout_ref.actor.use_kl_lossTrue\ actor_rollout_ref.actor.entropy_coeff0\ actor_rollout_ref.actor.kl_loss_coef0.001\ actor_rollout_ref.actor.kl_loss_typelow_var_kl \ actor_rollout_ref.model.enable_gradient_checkpointingTrue\ actor_rollout_ref.actor.fsdp_config.param_offloadTrue\ actor_rollout_ref.actor.fsdp_config.optimizer_offloadFalse\ actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu8\ actor_rollout_ref.rollout.tensor_model_parallel_size${gen_tp}\ actor_rollout_ref.rollout.namevllm \ actor_rollout_ref.rollout.gpu_memory_utilization0.7\ actor_rollout_ref.rollout.n4\ actor_rollout_ref.ref.log_prob_micro_batch_size_per_gpu8\ actor_rollout_ref.ref.fsdp_config.param_offloadTrue\ actor_rollout_ref.actor.use_torch_compileFalse\ actor_rollout_ref.ref.use_torch_compileFalse\ actor_rollout_ref.rollout.enable_chunked_prefillTrue\ actor_rollout_ref.rollout.max_num_batched_tokens32768\ actor_rollout_ref.rollout.checkpoint_engine.update_weights_bucket_megabytes4096\ algorithm.use_kl_in_rewardFalse\ trainer.critic_warmup0\ trainer.logger[console,tensorboard]\ trainer.project_name${project_name}\ trainer.experiment_name${exp_name}\ trainer.n_gpus_per_node8\ trainer.nnodes4\ trainer.resume_from_pathcheckpoints/\ trainer.save_freq500\ trainer.test_freq50\ trainer.total_epochs50$10.1 基础路径与项目配置参数示例值作用project_nameGRPO-Qwen3TensorBoard/WandB 项目名exp_nameGRPO-Qwen3-32b-npu当前实验命名区分不同跑法MODEL_PATHmodels/Qwen3-32B模型权重路径TRAIN_FILE/TEST_FILEgsm8k/train.parquet训练/测试数据resume_from_pathcheckpoints/中断后恢复训练的检查点路径10.2 数据与 Token 长度参数值作用data.train_batch_size1024一次梯度更新用的样本数data.max_prompt_length2048prompt token 上限data.max_response_length2048response token 上限data.filter_overlong_promptsTrue过滤超长 prompt避免 vLLM 崩溃data.truncationerror截断方式error抛异常比静默截断安全data.shuffleFalse训练数据是否打乱max_response_length调参逻辑过短模型无法完整生成回答 → reward 评估不准确 过长vLLM 显存压力增大throughput 下降 推荐GSM8K → 512~1024代码任务 → 2048~409610.3 分布式并行策略参数值含义gen_tp4Tensor Parallelism切分 Q/K/V/O 线性层trainer.n_gpus_per_node8每节点 GPU 数trainer.nnodes4节点总数actor_rollout_ref.actor.ulysses_sequence_parallel_size4Ulysses 序列并行SP对长序列有效actor_rollout_ref.rollout.tensor_model_parallel_size${gen_tp}vLLM 推理时的 TPTP vs FSDP vs Ulysses 怎么选模型能装进单卡 → 不用 TP只用 FSDP更简单 模型装不下 序列很长 → TP Ulysses 序列不长 模型装不下 → FSDP 为主10.4 FSDP 显存 Offload 策略最关键的调参之一参数值显存节省速度影响param_offloadTrue参数 offload 到 CPU★★★★★ 最大慢 2-3xoptimizer_offloadFalseOptimizer states 留 GPU节省保持速度buffer_dtypefp32缓冲区用 fp32更稳略高显存# 32B 模型8卡每卡约 40GB 显存param_offloadTrue,optimizer_offloadFalse# 能跑但慢param_offloadTrue,optimizer_offloadTrue# 显存最省但极慢param_offloadFalse,optimizer_offloadFalse# 显存不够会 OOM经验法则先param_offloadTrue如果 OOM 再开optimizer_offloadTrue。10.5 精度与梯度配置参数值作用param_dtypebf16参数用 bf16省显存足够精度reduce_dtypebf16梯度聚合用 bf16bf16 聚合比 fp32 快buffer_dtypefp32缓冲区用 fp32计算安全不易 NaNenable_gradient_checkpointingTrue前向不存中间激活用时重算省显存 30-50%10.6 PPO Mini-Batch / Micro-Batch 配置参数值含义ppo_mini_batch_size64一次 PPO 更新用的样本数ppo_micro_batch_size_per_gpu8每个 GPU 前向次数gradient accumulationrollout.log_prob_micro_batch_size_per_gpu8rollout log prob 计算的 micro batchref.log_prob_micro_batch_size_per_gpu8reference model log prob 的 micro batch显存不够时的调参顺序1. 先减小 ppo_micro_batch_size8 → 4 → 2 2. 再减小 rollout.log_prob_micro_batch_size 3. 最后开 param_offload10.7 vLLM Rollout 引擎配置参数值作用rollout.namevllm用 vLLM 而非 HF 推理快 5-10xrollout.gpu_memory_utilization0.7vLLM 用 70% 显存30% 留溢出rollout.n4每个 prompt 生成 4 个 candidateGRPO 用rollout.enable_chunked_prefillTrue分块 prefill省显存rollout.max_num_batched_tokens32768一次 batch 的最大 token 数gpu_memory_utilization调参0.7保守不易 OOM但 throughput 低 0.8 ~ 0.85常见推荐值 0.9吞吐最高但多节点训练时易因通信触发 OOMn4的意义GRPO 核心GRPO 需要同个 prompt 生成 G 个动作 → 组内相对排序 n 就是 G推荐 4~16 n 越大排序越可靠但 rollout 成本线性增长10.8 Actor / Reference / Critic 协同配置参数值作用use_kl_lossTrueActor 与 Ref 用 KL 约束防止策略偏离 Ref 太远kl_loss_coef0.001KL 项权重太大学不动太小策略偏离kl_loss_typelow_var_kl低方差 KL 估计比标准 KL 数值更稳定entropy_coeff0不加熵正则GRPO 依赖组内相对排序不需要额外熵项use_kl_in_rewardFalseKL 不进 reward 函数KL 只做梯度约束不做 reward 惩罚10.9 KL 损失调参实战经验kl_loss_coef 太小的表现 → 策略快速偏离 Reference Model → reward 可能很高但输出格式崩溃 → 典型模型开始输出乱码 / 重复 token kl_loss_coef 太小的表现 → 策略几乎不更新reward 不涨 → 相当于原始 SFT 模型 参考范围 小模型7B0.001 ~ 0.01 大模型32B0.0005 ~ 0.001 开源模型Qwen/Llama0.001 ~ 0.00510.10 其他 Trainer 配置参数值作用critic_warmup0Critic 不预热GRPO 不需要 Critic设为 0save_freq500每 500 步保存检查点test_freq50每 50 步跑一次评估total_epochs50总训练轮数logger[console,tensorboard]同时打印和记录WandB 换成wandb10.11 完整调参 ChecklistVERL 分布式场景能跑起来第一步gpu_memory_utilization从 0.7 开始param_offloadTrue先开ppo_micro_batch_size从小往大试4 → 8 → 16filter_overlong_promptsTrue防止 vLLM 崩溃性能调优第二步param_offloadFalse提升速度如果显存够gpu_memory_utilization提到 0.8enable_chunked_prefillTrue开启max_num_batched_tokens配合 batch_size 调收敛调优第三步kl_loss_coef从 0.001 开始根据输出质量调n4GRPO 组大小reward 噪声大时加大actor.optim.lr大模型用更小的 LR1e-6 ~ 5e-6 for 32Bentropy_coeff0对 GRPO 是对的不要改成非 0VERL 调参的本质不是调算法是调显存 / 速度 / 稳定性的三角tradeoff。永远先让它稳定跑起来再追性能。**