Prhub

#6806 [rollout, algo] fix: compute rollout_is_seq_fraction from raw weights

原始 PR 作者 EazyReal 合并时间 2026-06-26 09:40 文件变更 2 提交数 1 评论 1 代码增减 +38 / -3

执行摘要

修复 rollout_is_seq_fraction 无法跳变

修复一个结构性死指标,TIS 场景下每个权重都被 clamp 到 <= rollout_is_threshold,导致 per-sequence 均值不可能超过阈值,从而使 rollout_is_seq_fraction_high 永远为 0。详见 PR body。

建议合并。虽然改动小但修复了一个真实死指标,便于用户监控极端权重比例。

讨论亮点

无实质性 reviewer 讨论;代码审查机器人 gemini-code-assist 自动生成总结但无反馈;Luosuu 审核通过。

实现拆解

  1. 修改 compute_is_metrics 指标计算:在 verl/trainer/ppo/rollout_corr_helper.py 中,将原本使用 seq_mean_weights(clamp 后权重)的 rollout_is_seq_fraction_high 和 rollout_is_seq_fraction_low 改为使用 raw_seq_mean_weights(原始权重),通过 verl_F.masked_mean(raw_rollout_is_weights, response_mask, axis=-1) 得到。
  2. 保留描述性指标:rollout_is_seq_mean、rollout_is_seq_std、rollout_is_seq_max、rollout_is_seq_min 等仍基于 clamp 后权重,因为这些指标描述的是实际应用的权重。
  3. 新增单元测试:在 tests/trainer/ppo/test_rollout_corr.py 中新增 test_seq_fraction_high_uses_raw_weights,构造一组数据覆盖原始均值超阈值而 clamp 后均值不超的情形,断言修复后指标正确。
文件 模块 状态 重要度
verl/trainer/ppo/rollout_corr_helper.py 训练器 modified 6.06
tests/trainer/ppo/test_rollout_corr.py 评分校正 modified 5.83

关键符号

compute_is_metrics

关键源码片段

verl/trainer/ppo/rollout_corr_helper.py core-logic

核心修复文件,修改 `compute_is_metrics` 中的指标计算逻辑,将 `seq_mean_weights` 替换为 `raw_seq_mean_weights`。

# verl/trainer/ppo/rollout_corr_helper.py,compute_is_metrics 函数末尾
# 原代码使用 seq_mean_weights(clamp 后权重的序列均值),
# 导致 rollout_is_seq_fraction_high 永远为 0,因为每个权重都被 clamp 到阈值以下。
# 修改后使用 raw_seq_mean_weights(原始权重的序列均值),
# 使这些指标能真正反映极端权重比例。
# 保留 seq_mean_weights 用于描述性指标(均值 / 标准差 / 最值),
# 因为它们描述的是实际应用的权重。
raw_seq_mean_weights: torch.Tensor = verl_F.masked_mean(raw_rollout_is_weights, response_mask, axis=-1)
metrics["rollout_is_seq_fraction_high"] = (raw_seq_mean_weights > rollout_is_threshold).float().mean().item()
metrics["rollout_is_seq_fraction_low"] = (
    (raw_seq_mean_weights < rollout_is_threshold_lower).float().mean().item()
)
tests/trainer/ppo/test_rollout_corr.py test-coverage

新增单元测试,验证修复后的指标从原始权重计算。

# tests/trainer/ppo/test_rollout_corr.py
# 新增测试函数,验证 rollout_is_seq_fraction_high 基于原始权重计算
# 设计:sequence 0 原始均值 3.5 > 2.0,clamp 后均值 1.5 < 2.0;
# sequence 1 原始和 clamp 后均值均 < 2.0。
# 若使用 clamp 后权重,high fraction 应为 0(原 bug);
# 正确实现应返回 0.5(seq0 超,seq1 不超)。
def test_seq_fraction_high_uses_raw_weights():
    device = "cuda" if torch.cuda.is_available() else "cpu"
    threshold = 2.0
    raw_rollout_is_weights = torch.tensor([[1.0, 6.0], [0.9, 1.1]], device=device)
    rollout_is_weights = raw_rollout_is_weights.clamp(max=threshold)
    response_mask = torch.ones_like(raw_rollout_is_weights)
    log_ratio_for_metrics = torch.log(raw_rollout_is_weights)
    metrics = compute_is_metrics(
        rollout_is_weights=rollout_is_weights,
        raw_rollout_is_weights=raw_rollout_is_weights,
        log_ratio_for_metrics=log_ratio_for_metrics,
        response_mask=response_mask,
        rollout_is="token",
        rollout_is_threshold=threshold,
    )
    assert metrics["rollout_is_seq_fraction_high"] == pytest.approx(0.5)

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

风险极低:变更只影响两个死指标的计算源,不影响实际权重或训练结果;新增测试覆盖该逻辑;描述性指标保持不变。

影响范围仅限于 compute_is_metrics 输出的 rollout_is_seq_fraction_high 和 rollout_is_seq_fraction_low 两个指标,使之变活,对训练流程无影响。

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论