Repository navigation
Pool PPO micro-batch statistics by token and sample counts - #7041
Closed
behroozazarkhalili wants to merge 5 commits into
Closed
behroozazarkhalili wants to merge 5 commits into
behroozazarkhalili wants to merge 5 commits into
Conversation
PPOTrainer averaged one scalar per micro-batch slot, so a short final micro-batch carried the same weight as a full one and unwritten slots contributed zeros. The seven per-update means now store weighted numerators with active token counts (masked losses and clip fractions) or micro-batch sizes (approx KL, entropy, ratio) and reduce as total numerator over total count. val/ratio_var keeps its variance over slot means on a separate buffer. The regression test runs one CPU update with micro-batches of 4 and 2 samples, records the live tensors entering each statistic, and pools them independently. It fails on the previous reduction. Fixes #7012
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
The statistic buffers are sized (num_ppo_epochs, num_mini_batches, gradient_accumulation_steps) but the micro-batch loop writes only the slots it visits, so with gradient_accumulation_steps=3 and num_mini_batches=2 two of six slots stay at their zero initialisation. val/ratio_var took the variance over the whole buffer and those zeros inflated it: with learning_rate=0 every ratio is exactly 1 and the logged variance was 0.2667 instead of 0. The count buffer marks the written slots, so the variance is now taken over those. The regression test trains with learning_rate=0 under that split and asserts val/ratio_var is 0; it fails on the previous commit.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c054088. Configure here.
Collaborator
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Fixes #7012.
What
PPOTrainerreduced its per-update statistics with an unweighted mean over micro-batch slots. Each slot holds amasked_mean(or plain mean) of its own micro-batch, so with a short final micro-batch the reported number was a mean of means, not the token or sample mean it is documented as. Unwritten slots, whenstats_shapeis larger than the loop writes, also contributed zeros.The seven means now store weighted numerators and reduce as total numerator over total count:
loss/policy_avg,policy/clipfrac_avgweight by the active response-token count of the micro-batch.loss/value_avg,val/clipfrac_avgweight by the active value-token count (padding_mask_p1).policy/approxkl_avg,policy/entropy_avg,val/ratioare per-token statistics: each slot now stores amasked_meanover the response tokens times the response-token count, and the reduction divides by the gathered response-token count. Before, the plain.mean()in those three slots included pad positions, and the first version of this PR only reweighted that mean by micro-batch size (corrected in 42c71bf).val/ratio_varkeeps its variance over slot means, on its own buffer, because the issue leaves that population undefined, but now only over the slots the loop wrote: the response-token count buffer marks them, and the unwritten zeros used to inflate it (withlearning_rate=0under a 3-over-2 split every ratio is 1 and the logged variance was 0.2667 instead of 0).Test
test_uneven_micro_batch_stats_are_pooledruns one CPU update withper_device_train_batch_size=4, gradient_accumulation_steps=3, num_mini_batches=2, which splits each minibatch into micro-batches of 4 and 2 samples. It spies on the module-levelmasked_meanandselective_log_softmaxto record the live tensors entering each statistic, pools them independently, and compares with the logged metrics.Verification
On a compute node (job 58032838):
tests/experimental/test_ppo_trainer.pygives 57 passed, 2 skipped;ppo_trainer.py: the test fails at the first pooled comparison;loss/policy_avgby the sample count instead of the token count: fails;test_ratio_var_ignores_unwritten_statstrains withlearning_rate=0,gradient_accumulation_steps=3andnum_mini_batches=2and assertsval/ratio_varis 0; on the previous commit it reads 0.2667.Limits
gather_for_metricspath as before.Note
Medium Risk
Changes how PPO training metrics are reduced across micro-batches, which affects monitoring and any logic keyed on those logs; training loss/backprop paths are unchanged but reported KL/entropy/ratio values will differ when batching is uneven.
Overview
PPO logged averages no longer take an unweighted mean over micro-batch slots (which skewed uneven 4 vs 2 splits and let empty slots pull metrics toward zero). Each step now accumulates weighted numerators—policy-side stats (
loss/policy_avg, clip fractions, approx KL, entropy,val/ratio) scale by active response-token count; value-side stats usepadding_mask_p1counts—and divides by the gathered totals aftergather_for_metrics.Per-micro-batch computation also aligns with masking: approximate KL and entropy use
masked_meanon the response mask instead of raw.mean(), and ratio logging uses masked means.val/ratio_varis still variance across per-slot mean ratios, but only slots withpadding_count > 0, so unwritten buffer zeros no longer inflate variance (e.g. LR=0 case).Tests add
test_uneven_micro_batch_stats_are_pooled(monkeypatchedmasked_mean/selective_log_softmaxvs logged metrics) andtest_ratio_var_ignores_unwritten_stats.Reviewed by Cursor Bugbot for commit 42c71bf. Bugbot is set up for automated code reviews on this repo. Configure here.