Repository navigation
[training_utils, trainer, tests] feat: raw log-prob mismatch metrics for rollout vs actor - #8025
Conversation
…for rollout vs actor Signed-off-by: cr-gao <gaochenrui@sjtu.edu.cn>
SamitHuang
left a comment
There was a problem hiding this comment.
Useful gate for exact 0-diff train-rollout work: rollout_probs_diff_* really can hide 1-ULP log-prob differences, and summing mismatch_count in the V1 aggregator is the right aggregation for a zero-element check.
One correctness nits on the inline comment: keep the mismatch count on the same .float() path as rollout_logprobs_diff, otherwise mixed bf16/fp32 batches can disagree between the count and the abs-diff metrics.
Also:
test_all_masked_returns_invalidonly checksmismatch_count == 0; please also assert the new*_diff_max/*_diff_meanstaynanon the early-return path.- The checklist says no docs page lists these keys, but
docs/ascend_tutorial/zh/dev_guide/model_dev/parameter_and_metrics.mdalready documentstraining/rollout_probs_diff_*— worth adding the three new keys there (or correcting the checklist).
| rollout_logprobs_diff = calculate_log_prob_diff( | ||
| actor_old_log_probs.float(), rollout_old_log_probs.float(), response_mask_bool | ||
| ) | ||
| logprobs_mismatch = torch.masked_select(actor_old_log_probs != rollout_old_log_probs, response_mask_bool) |
There was a problem hiding this comment.
!= compares the native dtypes, while rollout_logprobs_diff above casts both sides with .float() first. If old_log_probs / rollout_log_probs ever differ in dtype (bf16 vs fp32 is common), the mismatch count and the abs-diff metrics can disagree. Prefer deriving the count from the already-casted tensor, e.g. int((rollout_logprobs_diff != 0).sum().item()), so both metrics share one comparison path.
What does this PR do?
Adds three raw log-prob metrics next to the existing
training/rollout_probs_diff_*:training/rollout_logprobs_mismatch_count: valid response tokens whoserollout_log_probs != old_log_probstraining/rollout_logprobs_diff_max/_mean: |Δ| of the raw log-probsrollout_probs_diff_*comparesexp(log_prob)and cannot see a 1-ULP log-prob difference (float32-0.10000000149vs-0.10000000894give the same prob). Exact 0-diff train-rollout work (#7688, verl-project/verl-omni#637) needs a gate that only passes at zero elements, so the count is exposed directly. In the V1 trainer the count is aggregated by sum, not mean.Emitted from
calculate_debug_metrics, so every existing caller (v1 trainer, legacy trainer, separation trainer) gets it underrollout.calculate_log_probs=Truewith no config change.Checklist Before Starting
[training_utils, trainer, tests] feat: ...Test
pytest tests/utils/debug/test_metrics.py tests/trainer/ppo/v1/test_metrics_aggregator_on_cpu.py -q # 23 passedNew cases: 1-ULP float32 pair where
rollout_probs_diff_max == 0butmismatch_count == 1; all-masked batch returnsvalid=0, mismatch_count=0; aggregator sums the count across iterations.API and Usage Example
No API change. Three new keys in the metrics dict when
actor_rollout_ref.rollout.calculate_log_probs=True.Design & Code Changes
verl/utils/debug/metrics.py: compute the raw comparison alongside the prob-based one; default keys on an all-masked batch.verl/trainer/ppo/v1/utils.py:rollout_logprobs_mismatch_countuses thesumaggregation rule.Checklist Before Submitting
pre-commit run --files <changed files>: ruff, ruff format, mypy, license, docstring, structure checks pass.AI assistance was used for this change. I reviewed every line and ran the tests.