部署校正
作者: Yingru Li
最后更新时间:10/30/2025。
本文档提供了对 verl 中部署校正实现的全貌概述。
命名说明:这个功能称为“部署校正”,以反映完整的功能性:重要性采样(IS)权重、拒绝采样(RS)和否决机制。内部变量 rollout_is_weights 保留其名称,因为它专门指 IS 权重组件。
BibTeX 引用
@misc{liu-li-2025,
title = {When Speed Kills Stability: Demystifying RL Collapse from the Training-Inference Mismatch},
url = {https://yingru.notion.site/When-Speed-Kills-Stability-Demystifying-RL-Collapse-from-the-Training-Inference-Mismatch-271211a558b7808d8b12d403fd15edda},
author = {Jiacai Liu and Yingru Li and Yuqian Fu and Jiawei Wang and Qian Liu and Yu Shen},
year = {2025},
month = sep,
}
概述
部署校正提供了一个统一的框架来处理 RL 训练中的一般离线策略问题。任何数据收集分布与训练分布不同的场景都可以从这些方法中受益。
常见离线策略场景:
策略不匹配(实现差异)
不同的精度:FP8 vs FP16 vs BF16 vs FP32
不同的后端:vLLM vs SGLang vs FSDP vs Megatron
即使权重相同,不同的实现
时滞(模型陈旧)
部署时使用较旧的检查点,而训练已进展
异步部署工作进程,具有陈旧参数
分布式/异步 RL 系统中的常见问题
回放缓冲区
在早期迭代的历史轨迹上训练
来自不同策略版本的经验回放
数据增强或重采样策略
离线策略算法
专家演示的行为克隆
DAPO(来自辅助策略的数据)
使用来自不同策略轨迹的任何算法
数据质量过滤
对收集数据进行重新加权或过滤
参考学习中修改的分布
具有分布转移的课程学习
这些离线策略差距可能导致训练不稳定和策略崩溃。部署校正使用重要性采样(IS)权重和拒绝采样(RS)来校正数据收集和训练之间的任何分布转移。
重要说明:常见实现错误
许多 LLM-RL 实现错误地应用 PPO,忽略实际部署策略 π_rollout 并假设训练参考策略 π_old 是行为策略。这在 π_rollout ≠ π_old 时在数学上是错误的(这在 LLM-RL 中由于部署和训练之间的精度/后端差异而典型)。
这不是 PPO 的错 - PPO 本身在数学上是正确的。问题在于错误假设 π_old = π_rollout 在天真的实现中。
这份文档中引入的部署校正框架,正是为了解决这种关键实现错误。这种错误导致 RL 训练崩溃,被博客文章 “When Speed Kills Stability: Demystifying RL Collapse from the Training-Inference Mismatch” 识别并激发其开发。
数学上正确的方法:
解耦模式:三个策略(π_rollout, π_old, π_θ),IS 从 π_rollout 到 π_old 校正
旁路模式:两个策略(π_rollout = π_old, π_θ),使用实际部署策略作为 PPO 锚点
旁路 + 策略梯度模式:两个策略(π_rollout, π_θ),IS/RS 校正和无 PPO 裁剪
详见数学公式部分。
关键设计原则:IS 权重和拒绝采样的分离
实现干净地分离了两个正交机制:
IS 权重(
rollout_is_weights):用于梯度校正的连续重新加权策略比率:解耦模式下的 π_old/π_rollout 或旁路模式下的 π_θ/π_rollout
安全绑定:截断到 [exp(-20), exp(20)] ≈ [2e-9, 5e8] 以防止溢出
令牌级别:绑定每令牌比率
序列级别:绑定比率乘积(广播到所有令牌)
截断:通过
.clamp(max=rollout_is_threshold)上限截断(TIS:截断重要性采样)在填充处置零:乘以 response_mask 以在填充位置置零
用于加权策略梯度(方差降低)
拒绝采样(
modified_response_mask):二进制过滤用于异常排除创建二进制掩码:1 = 保留,0 = 拒绝
拒绝 IS 比率在 [lower_threshold, upper_threshold] 之外的令牌/序列
否决机制:独立拒绝包含灾难性令牌的序列
修改 response_mask 以从训练中排除被拒绝样本
用于损失聚合(被拒绝样本不贡献梯度或分母)
这种分离确保:
✅ IS 权重提供连续重新加权(降低方差)
✅ 拒绝采样提供硬过滤(移除极端异常值)
✅ 两个机制可以独立启用或一起使用
✅ 正确损失归一化(被拒绝样本从所有计算中排除)
✅ 安全绑定防止所有情况下的数值溢出
快速开始:使用验证预设
新增:我们现在提供了类型化配置与验证预设,用于常见场景。这些预设已在各种模型和训练场景中经过数万 GPU 小时验证。
Python API
from verl.trainer.config.algorithm import RolloutCorrectionConfig
# 解耦模式与令牌级别 IS
config = RolloutCorrectionConfig.decoupled_token_is()
# 解耦模式与序列级别 IS
config = RolloutCorrectionConfig.decoupled_seq_is()
# 解耦模式与序列 IS + 拒绝采样
config = RolloutCorrectionConfig.decoupled_seq_is_rs()
# 解耦模式与几何 RS + 否决(最大异常敏感度)
config = RolloutCorrectionConfig.decoupled_geo_rs()
# 性能模式:PPO 与旁路
config = RolloutCorrectionConfig.ppo_is_bypass()
# 高级:纯策略梯度与 IS
config = RolloutCorrectionConfig.pg_is()
# 高级:纯策略梯度与拒绝采样(旁路 + 纯 + 几何 RS)
config = RolloutCorrectionConfig.pg_rs()
# 指标仅模式(无校正)
config = RolloutCorrectionConfig.disabled()
YAML 配置(高级)
对于高级定制或 YAML 基础配置:
algorithm:
rollout_correction:
rollout_is: token # IS 权重:"token", "sequence", 或 null
rollout_is_threshold: 2.0 # IS 权重上阈值
rollout_is_batch_normalize: false # 批量归一化 IS 权重到 mean=1.0
rollout_rs: null # 拒绝采样:"token", "sequence", "geometric", 或 null
rollout_rs_threshold: null # RS 上阈值(如果启用 rollout_rs 则必需)
rollout_rs_threshold_lower: null # RS 下阈值(如果为 null 则自动取倒数)
rollout_token_veto_threshold: null # 每令牌否决阈值(null = 禁用)
bypass_mode: false # 跳过 old_log_prob 计算
use_policy_gradient: false # 使用策略梯度损失(vs PPO 损失)
# 必需:启用 log prob 计算
actor_rollout_ref:
rollout:
calculate_log_probs: true
文件
核心实现
verl/trainer/ppo/rollout_corr_helper.py- 包含compute_rollout_correction_and_rejection_mask()和compute_offpolicy_metrics()verl/trainer/ppo/core_algos.py- 部署校正与 PPO 和纯 IS 模式的集成(compute_policy_loss_with_rollout_correction())verl/trainer/ppo/ray_trainer.py- 旁路模式实现(跳过old_log_prob计算)verl/workers/actor/dp_actor.py- 模式选择逻辑和指标收集
配置文件
verl/trainer/config/algorithm.py-AlgoConfig中的部署校正参数verl/workers/config/actor.py-ActorConfig中的部署校正参数verl/trainer/config/actor/actor.yaml- 部署校正配置节verl/trainer/config/ppo_trainer.yaml- 带有部署校正的算法配置
文档
docs/examples/config.rst- 配置参数描述
示例脚本
recipe/dapo/run_dapo_qwen2.5_32b_rollout_corr.sh- 带有部署校正的 DAPO 示例examples/rollout_correction/run_with_rollout_corr.sh- 基本示例
测试
tests/trainer/ppo/test_rollout_corr.py- IS/RS 机制的单元测试tests/trainer/ppo/test_rollout_corr_integration.py- 集成测试
配置参数
所有参数位于 algorithm.rollout_correction 下:
rollout_is (str 或 null)
重要性采样权重聚合级别:
null= 不计算 IS 权重(指标仅模式)"token":每令牌 IS 权重解耦模式:ρ_t = π_old(t)/π_rollout(t)
旁路/纯 IS 模式:ρ_t = π_θ(t)/π_rollout(t)
每令牌独立截断
典型阈值:1.5 - 5.0
"sequence":每序列权重 ρ_seq = ∏_t ρ_t跨序列乘法聚合
典型阈值:2.0 - 10.0
所有 IS 权重安全绑定到 [exp(-20), exp(20)] ≈ [2e-9, 5e8]
rollout_is_threshold (float)
IS 权重截断的上阈值。默认:2.0
通过
.clamp(max=rollout_is_threshold)截断 IS 权重(TIS:截断重要性采样)用于方差降低的应用到 IS 权重
与拒绝采样分离(由
rollout_rs参数控制)
rollout_rs (str 或 null)
拒绝采样聚合级别:
null= 无拒绝采样"token":拒绝异常比率的个别令牌"sequence":拒绝异常比率的整个序列"geometric":几何平均聚合用于拒绝典型阈值:1.0002 - 1.001
rollout_rs_threshold (float 或 null)
拒绝采样的上阈值。默认:null
必需 当
rollout_rs启用时(必须明确设置)比率 > 阈值的令牌/序列被屏蔽
rollout_rs_threshold_lower (float 或 null)
拒绝采样的下阈值。默认:null
如果
null,使用上阈值的倒数(1/upper)比率 < 阈值的令牌/序列被屏蔽
rollout_token_veto_threshold (float 或 null)
灾难异常下的每令牌否决。默认:null
检查未绑定每令牌比率,在安全绑定之前
如果任何令牌比率 < 阈值,整个序列被拒绝
独立于
rollout_is和rollout_rs设置典型值:启用时为
1e-4到1e-6示例:
1e-4捕获 10,000x 不太可能的令牌
rollout_is_batch_normalize (bool)
对 IS 权重应用批量归一化。默认:False
True:归一化 IS 权重以在每个批次中具有 mean=1.0令牌级别 IS:归一化所有令牌权重
序列级别 IS:归一化序列平均值(每序列一个权重)
False:使用原始(截断)IS 权重通过确保每批次平均权重为 1.0 降低方差
应用于截断后以保留截断语义
仅影响 IS 权重值,不影响拒绝采样
理解框架:组件和组合
部署校正框架建立在正交组件上,可以灵活组合。理解这些组件有助于为你的场景选择正确的配置。
关键组件
操作模式(节:操作模式)
解耦:三个策略(π_rollout, π_old, π_θ),分离 π_old 计算
旁路:两个策略(π_rollout = π_old, π_θ),跳过 π_old 计算
损失函数
PPO:带裁剪的标准 RL 训练
纯 IS:策略梯度仅(无裁剪)
IS/RS 聚合级别
令牌:每令牌 IS 权重/拒绝
序列:序列级别 IS 权重/拒绝
几何:几何平均(仅用于拒绝)
安全机制
否决:拒绝包含灾难令牌的序列
详见数学公式。
预设配置指南
本节提供了对验证预设的详细指导,每个预设是针对常见场景优化的组件特定组合。
理解预设
可用预设方法
预设方法 |
模式 |
IS 级别 |
RS 级别 |
属性 |
|---|---|---|---|---|
|
解耦 |
token |
- |
每令牌 IS 权重 |
|
解耦 |
sequence |
- |
序列级别 IS 权重 |
|
解耦 |
sequence |
sequence |
序列 IS + 序列 RS |
|
解耦 |
- |
geometric + veto |
几何 RS + 否决,无 IS 权重 |
|
旁路 |
- |
- |
旁路模式,跳过 old_log_prob |
|
旁路 |
- |
geometric + veto |
策略梯度与 RS(无 IS 权重) |
|
旁路 |
sequence |
- |
策略梯度与 IS |
|
- |
- |
- |
指标仅,无校正 |
注意: 所有预设都使用 PPO 损失,除了 pg_is() 和 pg_rs(),它们使用策略梯度(两者都需要 use_policy_gradient=True)。
其他支持组合(需要手动配置)
预设方法之外的其他支持组合:
令牌 IS + 令牌 RS:在配置中手动组合
纯令牌 RS:令牌级别 RS 仅,无 IS 权重
纯序列 RS:序列级别 RS 仅,无 IS 权重
详见下面的详细配置示例。
关键属性:
任何聚合级别(token/sequence/geometric)在解耦或旁路模式下均有效
所有组合由实现完全支持
拒绝采样独立于 IS 加权
纯 RS(
pg_rs)使用旁路 + 几何 RS 与use_policy_gradient=True(无 IS 权重)
1. 解耦模式与令牌级别重要性采样(decoupled_token_is)
配置:
config = RolloutCorrectionConfig.decoupled_token_is(threshold=2.0)
组件:
操作模式:解耦(3 个策略)
损失:带裁剪的 PPO
IS 聚合:令牌级别
RS:无(可单独添加)
等价 YAML:
algorithm:
rollout_correction:
rollout_is: token
rollout_is_threshold: 2.0
rollout_rs: null
bypass_mode: false # 解耦模式
属性:
每令牌独立截断
低于序列级别方差(比率乘积单独绑定)
典型阈值:1.5 - 5.0
2. 解耦模式与序列级别重要性采样(decoupled_seq_is)
配置:
config = RolloutCorrectionConfig.decoupled_seq_is(threshold=2.0)
组件:
操作模式:解耦(3 个策略)
损失:带裁剪的 PPO
IS 聚合:序列级别
RS:无(可单独添加)
等价 YAML:
algorithm:
rollout_correction:
rollout_is: sequence
rollout_is_threshold: 2.0
rollout_rs: null
bypass_mode: false # 解耦模式
属性:
跨序列乘法聚合
对异常值比序列级别更敏感
典型阈值:2.0 - 10.0(高于令牌级别)
3. 解耦模式与序列级别 IS + 拒绝采样(decoupled_seq_is_rs)
配置:
config = RolloutCorrectionConfig.decoupled_seq_is_rs(is_threshold=2.0, rs_threshold=2.0)
组件:
操作模式:解耦(3 个策略)
损失:带裁剪的 PPO
IS 聚合:序列级别
RS:序列级别拒绝
等价 YAML:
algorithm:
rollout_correction:
rollout_is: sequence
rollout_is_threshold: 2.0
rollout_rs: sequence
rollout_rs_threshold: 2.0
rollout_rs_threshold_lower: 0.5 # 阈值倒数
bypass_mode: false # 解耦模式
属性:
双机制:IS 重新加权 + 拒绝过滤
降低有效样本大小(拒绝异常值)
用于严重的离线策略差距
4. 解耦模式与几何拒绝采样(decoupled_geo_rs)
配置:
config = RolloutCorrectionConfig.decoupled_geo_rs(rs_threshold=1.001, veto_threshold=1e-4)
组件:
操作模式:解耦(3 个策略)
损失:带裁剪的 PPO
IS 聚合:无(纯拒绝)
RS:几何级别拒绝
否决:启用
等价 YAML:
algorithm:
rollout_correction:
rollout_is: null
rollout_rs: geometric
rollout_rs_threshold: 1.001
rollout_rs_threshold_lower: 0.999
rollout_token_veto_threshold: 1e-4
bypass_mode: false # 解耦模式
属性:
无 IS 权重(纯拒绝)
几何平均聚合(比算术乘积更敏感)
典型阈值:1.0001 - 1.001(比序列/令牌级别更紧)
基于平均每令牌比率偏差拒绝序列
为什么紧阈值? 几何平均非常敏感。对每个比率 1.01 的 100 个令牌:
乘积:1.01^100 ≈ 2.7
几何平均:1.01
阈值 1.001 拒绝平均每令牌偏差 > 0.1% 的序列。
5. PPO 与旁路模式(ppo_is_bypass)
配置:
config = RolloutCorrectionConfig.ppo_is_bypass(threshold=2.0)
组件:
操作模式:旁路(2 个策略:π_rollout = π_old, π_θ)
损失:带裁剪的 PPO
IS 聚合:不需要(π_old = π_rollout)
RS:无
等价 YAML:
algorithm:
rollout_correction:
rollout_is: token # 指标占位符
rollout_is_threshold: 2.0
rollout_rs: null
bypass_mode: true # 旁路模式
use_policy_gradient: false
属性:
跳过
actor.compute_log_prob()前向传递PPO 针对 π_rollout 裁剪(行为策略)
设置 π_old = π_rollout(两策略设置)
不分离近端策略和行为策略
配置要求:
设置
actor_rollout_ref.rollout.calculate_log_probs: true
6. 策略梯度与 IS(pg_is)
配置:
config = RolloutCorrectionConfig.pg_is(threshold=2.0)
组件:
操作模式:旁路(2 个策略:π_rollout, π_θ)
损失:纯 IS(策略梯度仅,无 PPO 裁剪)
IS 聚合:序列级别
RS:无
等价 YAML:
algorithm:
rollout_correction:
rollout_is: sequence
rollout_is_threshold: 2.0
rollout_rs: null
bypass_mode: true # 必需
use_policy_gradient: true # 使用策略梯度损失(无 PPO 裁剪)
属性:
策略梯度损失(无 PPO 裁剪)
单前向传递(跳过 old_log_prob 计算)
IS 权重即时计算在损失函数中
7. 策略梯度与拒绝采样(pg_rs)
配置:
config = RolloutCorrectionConfig.pg_rs(
rs_threshold=1.001,
veto_threshold=1e-4
)
组件:
操作模式:旁路(2 个策略:π_rollout, π_θ)
损失:纯策略梯度(无 PPO 裁剪,
use_policy_gradient=True通过)IS 聚合:无
RS:几何级别拒绝
否决:启用
等价 YAML:
algorithm:
rollout_correction:
rollout_is: null
rollout_rs: geometric
rollout_rs_threshold: 1.001
rollout_rs_threshold_lower: 0.999
rollout_token_veto_threshold: 1e-4
bypass_mode: true
use_policy_gradient: true
属性:
纯几何 RS(无 IS 权重,仅拒绝)
跳过
actor.compute_log_prob()前向传递(旁路模式)否决机制启用
典型阈值:1.0001 - 1.001(比序列/令牌级别更紧)
附加有用配置(未作为预设公开)
这些配置完全支持但还没有便利预设方法。
1. 令牌 IS + 令牌 RS(token_is_rs)
令牌级别 IS 权重与令牌级别 RS 遮罩。
Python:
config = RolloutCorrectionConfig(
rollout_is="token",
rollout_is_threshold=2.0,
rollout_rs="token",
rollout_rs_threshold=2.0,
)
属性: 每令牌 IS 权重 + 每令牌 RS 遮罩。
2. 纯令牌 RS(token_rs)
令牌级别 RS 仅,无 IS 权重。
Python:
config = RolloutCorrectionConfig(
rollout_is=None,
rollout_rs="token",
rollout_rs_threshold=2.0,
)
属性: 令牌级别 RS 遮罩,无 IS 重新加权。
3. 纯序列 RS(seq_rs)
序列级别 RS 仅,无 IS 权重。
Python:
config = RolloutCorrectionConfig(
rollout_is=None,
rollout_rs="sequence",
rollout_rs_threshold=2.0,
)
属性: 序列级别 RS 遮罩,无 IS 重新加权。
总结:IS 权重的处理方式
IS 权重(rollout_is_weights)经过固定处理管道:
阶段 1:安全绑定(防止溢出)
令牌级别:
exp(clamp(log_ratio, -20, 20))每令牌 → 绑定每个令牌到 [2e-9, 5e8]序列级别:
exp(clamp(sum(log_ratio), -20, 20))→ 绑定乘积到 [2e-9, 5e8],广播到所有令牌
阶段 2:截断(降低方差)
.clamp(max=rollout_is_threshold)→ 在上阈值处截断权重(TIS:截断重要性采样)无下限截断(保留小权重下的无偏性质)
阶段 3:填充零化(正确聚合)
weights * response_mask→ 在填充位置置零
阶段 4:可选批量归一化
如果
rollout_is_batch_normalize=True:归一化权重到每批次 mean=1.0在截断后应用以保留截断语义
拒绝采样(分离机制)
拒绝采样通过 compute_rollout_rejection_mask() 修改 response_mask(NOT 权重):
独立计算安全绑定比率
创建二进制遮罩:在 [lower_threshold, upper_threshold] 之外的令牌/序列 → 0(拒绝)
否决:检查未绑定每令牌比率(在安全绑定前),拒绝包含灾难令牌的整个序列
修改遮罩用于损失聚合(被拒绝样本从训练中排除)
操作模式
框架提供两种操作模式用于计算 π_old,可以与不同损失函数组合。
操作模式和配置
配置 |
|
|
操作模式 |
损失函数 |
描述 |
|---|---|---|---|---|---|
解耦 |
|
|
解耦 |
PPO |
单独计算 |
旁路 |
|
|
旁路 |
PPO |
设置 |
旁路 + PG |
|
|
旁路 |
策略梯度 |
具有策略梯度损失的旁路模式(无 PPO 裁剪) |
操作模式细节
解耦模式(三个策略)
策略设置:
π_rollout:行为策略(数据收集)
π_old:近端策略(在训练时期开始通过
actor.compute_log_prob()计算)π_θ:当前策略(正被更新)
配置: bypass_mode = false
属性:
✅ 实现批次大小不变性
✅ 单独校正漂移 1(rollout→old)和漂移 2(old→current)
✅ 高效陈旧数据利用
❌ 需要额外前向传递(
actor.compute_log_prob())
旁路模式(两个策略)
策略设置:
π_rollout:行为策略(数据收集)
π_old = π_rollout:近端策略等于行为策略
π_θ:当前策略(正被更新)
配置: bypass_mode = true
属性:
✅ 跳过
actor.compute_log_prob()调用(更快)✅ 处理使用策略梯度的离线策略校正(IS/RS 时)
✅ 使用两个策略而不是三个(π_rollout = π_old)
⚠️ 不分离近端策略和行为策略(与解耦模式不同)
IS/RS 聚合级别(相对于操作模式正交)
聚合级别可以独立于操作模式选择。任何聚合级别在解耦或旁路模式下有效。
|
|
行为 |
|---|---|---|
|
|
禁用:无计算,无指标,无拒绝 |
|
|
拒绝仅:计算指标,NO 权重校正,YES 拒绝采样 |
|
|
IS 权重仅:权重校正启用,NO 拒绝采样 |
|
|
全校正:权重校正和拒绝采样均启用 |
关键洞察
✅ 任何 IS/RS 聚合级别(token/sequence/geometric)可在任一解耦或旁路模式下使用
✅ 你可以单独使用拒绝采样而无 IS 权重校正(
rollout_is=null, rollout_rs="token")✅ 你可以单独使用 IS 权重而无异常值拒绝(
rollout_is="token", rollout_rs=null)✅ 你可以一起使用两者(
rollout_is="token", rollout_rs="token")✅ 你可以仅监控指标而不应用校正,通过设置两者为 null 但仍提供 rollout_log_probs
否决拒绝(如果通过 rollout_token_veto_threshold 启用)独立于 IS 和 RS 设置应用。
理论: 详见rollout_corr_math.md §3.3 以获取聚合级别详情。
示例工作流
推荐:旁路 + 策略梯度模式
此工作流使用旁路模式和纯策略梯度损失以提高效率。
首先使用指标仅来理解离线策略差距:
algorithm: rollout_correction: rollout_is: null rollout_rs: null bypass_mode: true # 旁路模式(推荐) use_policy_gradient: true # 纯策略梯度(推荐)
监控
rollout_corr/kl,rollout_corr/log_ppl_abs_diff,rollout_corr/chi2_token来评估离线策略差距。如果看到高异常分数,则启用拒绝采样:
algorithm: rollout_correction: rollout_is: null rollout_rs: sequence # 或 "geometric" 以获得更高敏感度 rollout_rs_threshold: 2.0 bypass_mode: true # 旁路模式 use_policy_gradient: true # 纯策略梯度
这将异常值从训练中排除而不修改梯度。
一旦舒适指标,则启用全 IS 校正:
algorithm: rollout_correction: rollout_is: sequence # 推荐:无偏,适合大多数情况 rollout_is_threshold: 2.0 rollout_rs: sequence # 或 "geometric" 以进行更激进过滤 rollout_rs_threshold: 2.0 bypass_mode: true # 旁路模式 use_policy_gradient: true # 纯策略梯度
旁路 + 策略梯度模式的优势:
✅ 跳过昂贵的
actor.compute_log_prob()前向传递(更快)✅ 在损失函数中即时计算 IS 权重(π_θ / π_rollout)
✅ 比 PPO 简单(无裁剪,纯策略梯度带 IS/RS)
✅ 对所有 IS/RS 组合有效
使用
基本设置
algorithm:
rollout_correction:
rollout_is: token # 在令牌级别启用 IS 权重
rollout_is_threshold: 2.0 # IS 权重阈值
rollout_rs: null # 无拒绝采样
rollout_token_veto_threshold: null # 无否决
actor_rollout_ref:
rollout:
calculate_log_probs: true # 必需!
指标
所有指标以 rollout_corr/ 为前缀记录。例如,rollout_is_mean 显示为 rollout_corr/rollout_is_mean。
这些涵盖:
诊断指标:KL 发散,困惑度差异(测量离线策略差距)
校正统计:IS 权重,拒绝率,否决统计(测量应用校正)
核心 IS 权重指标
rollout_is_mean:跨所有有效令牌的平均重要性采样权重值接近 1.0 表示最小离线策略差距
rollout_is_std:IS 权重的标准差更高值表示 IS 权重更大的方差
rollout_is_min:观察到的最小 IS 权重显示最欠权重令牌/序列
对于 sequence/geometric:从未绑定对数空间比率计算(真最小)
对于 token:从安全绑定权重计算
rollout_is_max:观察到的最大 IS 权重显示最过权重令牌/序列
对于 sequence/geometric:从未绑定对数空间比率计算(真最大,在安全绑定前)
对于 token:从安全绑定权重计算(在阈值裁剪前)
与
rollout_is_threshold比较以查看裁剪影响
有效样本大小
rollout_is_eff_sample_size:IS 加权后的有效样本大小公式:
1 / mean(weights²),权重归一化范围:0.0 到 1.0(作为原始批次的比率)
较低值表示权重集中在较少样本上
否决机制指标
rollout_is_veto_fraction:被否决机制拒绝的序列分数重要:序列通过
response_mask=0拒绝,NOT 通过修改 IS 权重IS 权重不受否决影响:已安全绑定和截断
否决检查未绑定每令牌比率(在安全绑定前的真比率)
解耦模式:π_old(t)/π_rollout(t)
旁路/纯 IS 模式:π_θ(t)/π_rollout(t)
检测灾难令牌(真比率 < veto_threshold,如 < 1e-4)
rollout_is_catastrophic_token_fraction:低于否决阈值的令牌分数在应用序列级别否决之前识别问题令牌
检查未绑定每令牌比率(真比率,不安全绑定)
每个灾难令牌导致其整个序列拒绝
阈值超出指标
rollout_is_ratio_fraction_high:超过上阈值的权重分数显示高位的裁剪/遮罩发生频率
对于 sequence/geometric:从未绑定对数空间比率计算(真超出)
对于 token:从安全绑定权重计算(在阈值裁剪前)
rollout_is_ratio_fraction_low:低于下阈值(1/upper_threshold)的权重分数诊断指标显示低于倒数阈值的权重有多少
对于 sequence/geometric:从未绑定对数空间比率计算(真超出)
对于 token:从安全绑定权重计算(在裁剪前)
序列级别指标(序列聚合)
rollout_is_seq_mean:序列级别平均 IS 权重对于序列级别聚合应匹配
rollout_is_mean
rollout_is_seq_std:序列级别 IS 权重的标准差rollout_is_seq_min:最小序列级别 IS 权重rollout_is_seq_max:最大序列级别 IS 权重rollout_is_seq_max_deviation:序列级别最大绝对偏差从 1.0显示最坏序列离线策略差距
rollout_is_seq_fraction_high:超过上阈值的序列分数rollout_is_seq_fraction_low:低于下阈值的序列分数
拒绝采样指标(rollout_rs 启用时)
rollout_rs_masked_fraction:拒绝采样遮罩的令牌分数重要:拒绝采样修改
response_mask(将拒绝令牌置 0)独立于 IS 权重:IS 权重仍被截断;拒绝是独立的过滤步骤
仅在
rollout_rs启用时(token/sequence/geometric)出现
rollout_rs_seq_masked_fraction:具有至少一个拒绝令牌的序列分数显示拒绝采样的序列级别影响
令牌级别 RS:如果任何令牌在 [lower, upper] 之外则序列拒绝
序列级别 RS:基于序列级别比率接受/拒绝整个序列
几何 RS:基于几何平均接受/拒绝整个序列
离线策略诊断指标(训练 vs 部署策略)
术语说明: 这些指标使用 “training” 来指训练参考策略,使用 “rollout” 来指 π_rollout(用于数据收集的行为策略)。
解耦模式:”training” = π_old(在训练时期开始计算)
旁路/纯 IS 模式:”training” = π_θ(正被训练的当前策略)
在旁路/纯 IS 模式下,指标直接测量 π_θ 和 π_rollout 之间的漂移。
training_ppl:训练参考策略的困惑度(解耦模式中的 π_old,旁路/纯 IS 模式中的 π_θ)公式:
exp(-mean(log_probs))较低值表示更高模型信心
rollout_ppl:部署策略 π_rollout 的困惑度(例如 vLLM BF16)ppl_ratio:训练 PPL 与部署 PPL 的比率公式:
exp(mean(log(training_ppl / rollout_ppl)))含义:> 1.0 意味着训练比部署更没信心
training_log_ppl:训练策略的对数困惑度用于识别趋势(线性刻度)
rollout_log_ppl:部署策略的对数困惑度log_ppl_diff:对数困惑度的平均差异公式:
mean(log_ppl_rollout - log_ppl_training)符号指示哪种策略更自信
log_ppl_abs_diff:平均绝对对数困惑度差异不考虑方向的离线策略差距大小
log_ppl_diff_max:跨序列的最大对数困惑度差异识别最坏序列
log_ppl_diff_min:最小对数困惑度差异kl:KL 发散 KL(π_rollout || π_training)公式:
mean(log_prob_rollout - log_prob_training)注意:可以为负(deploy 是更没信心)
k3_kl:K3 KL 估计器公式:
mean(exp(log_ratio) - log_ratio - 1)小 KL 值更稳定
始终非负
chi2_token:令牌级别的卡方发散公式:
mean(ratio²) - 1,比率 = π_training/π_rollout测量 IS 权重分布的二阶矩
始终非负
chi2_seq:序列级别的卡方发散公式:
mean((∏_t ratio_t)²) - 1IS 权重的序列级别二阶矩
比令牌级别对卡方更敏感
示例:代码中访问指标
# 指标从 compute_rollout_correction_and_rejection_mask 返回
from verl.trainer.ppo.rollout_corr_helper import compute_rollout_correction_and_rejection_mask
# 返回 3 值(权重,modified_response_mask,指标)
weights_proto, modified_response_mask, metrics = compute_rollout_correction_and_rejection_mask(
old_log_prob=training_log_probs, # 从训练策略
rollout_log_prob=rollout_log_probs, # 从部署策略
response_mask=response_mask,
rollout_is="token", # 在令牌级别启用 IS 权重
rollout_is_threshold=2.0,
rollout_rs="token", # 在令牌级别启用拒绝采样
rollout_rs_threshold=2.0,
rollout_rs_threshold_lower=0.5,
rollout_token_veto_threshold=1e-4, # 为灾难异常启用否决
)
# 提取 IS 权重(处理过,在填充处置零)
is_weights = weights_proto.batch["rollout_is_weights"]
# IS 权重处理(令牌级别 IS 启用时):
# 1. 安全绑定:exp(clamp(log_ratio, -20, 20)) 每令牌
# 2. 截断:.clamp(max=2.0) 以限制极端权重
# 3. 置零填充:在填充位置置零
# 注意:IS 权重始终截断(TIS:截断重要性采样)
# modified_response_mask 应用拒绝(由于 rollout_rs="token"):
# 1. RS 拒绝:在 [0.5, 2.0] 之外的令牌通过 response_mask 置零
# 2. 否决拒绝:具有灾难令牌的序列通过置零
# 注意:否决检查未绑定每令牌比率(在安全绑定前)
# 注意:RS 和 IS 是分离机制 - 两者均可独立启用
# 所有指标具有 'rollout_corr/' 前缀
print(f"Mean IS weight: {metrics['rollout_corr/rollout_is_mean']:.3f}")
print(f"Effective sample size: {metrics['rollout_corr/rollout_is_eff_sample_size']:.3f}")
print(f"Veto fraction: {metrics['rollout_corr/rollout_is_veto_fraction']:.3f}")
print(f"RS masked fraction: {metrics['rollout_corr/rollout_rs_masked_fraction']:.3f}")
print(f"KL divergence: {metrics['rollout_corr/kl']:.3f}")
# 检查有效令牌的 IS 权重(非填充)
valid_weights = is_weights[response_mask.bool()]