feat: ESS-guided learning-rate scaling for off-policy/async RL (default off)#57
Open
ZhentingWang wants to merge 1 commit into
Open
feat: ESS-guided learning-rate scaling for off-policy/async RL (default off)#57ZhentingWang wants to merge 1 commit into
ZhentingWang wants to merge 1 commit into
Conversation
…lt off) VCPO-style (arXiv:2602.17616) ESS-guided LR scaling: shrink the effective LR by sqrt(ESS/B) when off-policy importance weights are heavy-tailed. Native, opt-in (--use-ess-lr, default off -> bit-exact legacy); megatron actor only, critic never scaled. New module ess_lr.py + one call in loss.py; applied around optimizer.step in model.py; metrics via extra_metrics; fast unit tests.
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.
What
Adds ESS-guided LR scaling (VCPO-style, arXiv:2602.17616) as a native, opt-in training feature. In fully-async / off-policy RL a few stale trajectories can dominate the update (heavy-tailed importance weights), collapsing the effective sample size (ESS). When that happens we shrink the effective LR by
sqrt(ESS / B)for that update. Gated behind--use-ess-lr(default off → bit-exact legacy).Algorithm
Per trajectory
i, sequence-level (length-normalized = geometric-mean IS):rho → 1⇒ on-policy, weights even, no shrink.rho → 0⇒ a few stale trajectories dominate ⇒ shrink LR. The per-token quantitytrain_logp − rollout_logpis exactly the existingtrain_inference_mismatchsignal, so ESS-LR is a complement to TIS that adds an adaptive decay at the LR level.How it's wired
backends/training_utils/ess_lr.py, new):ess_lr_compute()runs once per rollout fromcompute_advantages_and_returns()(over the full batch, before the rollout's optimizer-step loop) and stashes{scale, rho}in module state. On any missing input (e.g.--use-rollout-logprobs, the critic path, a non-last PP stage) it resets to a no-opscale=1for that rollout rather than carrying a stale value; errors propagate rather than silently disabling.backends/megatron_utils/model.py): the scale is broadcast across the PP group (it is only computed on the last PP stage) and temporarily applied to the param-group LRs aroundoptimizer.step(), then restored before the scheduler advances. Policy/actor only (loss_type == "policy_loss"); the critic is never scaled.utils/arguments.py):--use-ess-lr,--ess-lr-floor.train/lr_scale,train/rho_essvia the standardextra_metricschannel.Distributed correctness
m_i. CP mask-chunking mirrors the existing advantage-whitening path.Σw / Σw² / Bare all-reduced over the intra-DP group so ESS is global; skipped whendp_size == 1(local sums are already global, and avoids aNone-group → WORLD fallback).use_ess_lr and loss_type == policy_loss), so no rank divergence.Default-off / bit-exactness
When
--use-ess-lris unset,ess_lr_compute()returns immediately and the optimizer block is skipped entirely (no broadcast, no LR mutation) — the legacy path is byte-for-byte unchanged.Scope / limitations
miles_validate_args(--use-ess-lrassertstrain_backend == "megatron"); the FSDP step does not consume the scale.Tests
tests/fast/backends/training_utils/test_ess_lr.py(fast, no distributed): pure ESS math (equal-weights → 1, skew →sqrt(rho), floor clamp, cap ≤ 1), enabled-path state update (mock parallel state,w=[1,5] → rho=0.692), missing-input reset, and the default-off no-op.