Add UP (Unbounded Positive Asymmetric Optimization) to trl.experimental - #2
Open
yashb98 wants to merge 3 commits into
Open
Add UP (Unbounded Positive Asymmetric Optimization) to trl.experimental#2yashb98 wants to merge 3 commits into
trl.experimental#2yashb98 wants to merge 3 commits into
Conversation
Implements UP (https://huggingface.co/papers/2607.06987), a GRPO variant that routes tokens asymmetrically on the sign of the advantage. For positive advantages the importance ratio is replaced by the self-anchored ratio pi/sg(pi), whose forward value is exactly 1 and whose gradient is the unclipped REINFORCE gradient, independent of the old policy, so correct but low-confidence tokens are never truncated by the trust region. Non-positive advantages keep the standard clipped surrogate. Aggregation follows DAPO's global active-token normalization, matching the paper's UP-DAPO instantiation. Only the low-side clip ratio is logged, since the positive branch is unbounded by design. Follows the trl/experimental/gmpo layout: a UPConfig subclassing GRPOConfig (adding no fields, only documenting which inherited ones still bite) and a UPTrainer subclassing GRPOTrainer that overrides _compute_loss. use_liger_kernel raises NotImplementedError: GRPOTrainer.compute_loss routes to the fused Liger loss before _compute_loss is reached, which would silently optimize the GRPO objective instead of UP. Tests assert numerics rather than smoke-testing training. The positive branch reproduces the REINFORCE gradient and is invariant to old_per_token_logps; the non-positive branch is bitwise identical to dapo; delta caps the non-positive branch and gates whether epsilon_high binds at all; importance_sampling_level leaves the positive branch unchanged; and beta > 0 adds and logs the KL term.
yashb98
force-pushed
the
feat/experimental-up
branch
from
July 29, 2026 15:45
f71e4af to
67b6e43
Compare
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 does this PR do?
Adds
trl/experimental/up/, implementing Unbounded Positive Asymmetric Optimization from the UP paper as aGRPOTrainersubclass that overrides_compute_loss. It follows thetrl/experimental/gmpo/layout.Fixes huggingface#6407
I originally wrote this as a core
loss_type="up"value, then noticed recent new methods have been landing intrl/experimental/instead, so I moved it. That branch still exists and the two are numerically identical, so if you would rather have this as a coreloss_typeI can switch it back in a few minutes. Happy either way.Method
UP splits on the sign of the advantage. For positive advantages it replaces the importance ratio with a self-anchored one:
Its forward value is exactly 1 and its gradient is the plain REINFORCE gradient, so positive updates are never clipped and do not depend on
π_old. Non-positive advantages keep the usual clipped surrogate as a safeguard. Aggregation follows DAPO's global active-token normalization, matching the paper's UP-DAPO instantiation.Notes for review
base_trainer.py:"UPTrainer"added to_TELEMETRY_TRAINERS, since the comment there says a new trainer needs an explicit entry. Nothing else outsidetrl/experimental/up/.use_liger_kernel=TrueraisesNotImplementedError.GRPOTrainer.compute_lossroutes to the fused Liger loss before_compute_lossis reached, so without the guard the trainer would silently optimize the GRPO objective instead of UP. Worth flagging thatGMPOTrainerlooks like it has the same hole; I have not opened anything about it since I may be misreading the dispatch.epsilon_highhas no effect with the defaultdelta=None, and more generally wheneverdelta >= 1 + epsilon_high. Positive advantages skip clipping, and for non-positive ones the upper bound is dominated. Only adeltabelow1 + epsilon_highmakes it bind. Table A1 of the paper lists noε_highfor UP-DAPO accordingly. There is a test for this.importance_sampling_level="sequence"changes only the non-positive branch. The positive branch is unaffected, because the global active-token normalization exactly cancels the sequence-level length normalization. Also tested.UPConfigadds no fields. It exists as the autodoc surface for the semantics above and for symmetry with the other experimental configs.is_high_clippedrequires a positive advantage and UP routes those to the unclipped branch.Tests
UP's positive branch has a forward value of exactly 1, so asserting on the loss alone cannot tell a correct implementation from one that detached the wrong tensor. The gradient is what distinguishes them, so the tests check gradients, and then the loss value separately:
old_per_token_logpschangesGRPOTrainer'sdapodeltacaps the non-positive branch, and gates whetherepsilon_highbinds at allimportance_sampling_levelleaves the positive branch unchangedbeta > 0adds and logs the KL termVerification
Rebased on
de63151.tests/experimental/test_up_trainer.py: 8 passed. ruff, ruff format and the doc-builder hook pass on the changed files.I also checked this module against the core
loss_type="up"branch it replaces, on identical seeded inputs: loss, gradient norm and gradient sum are bit-identical across six cases (token and sequence levels, with all-positive, all-negative and mixed advantages). The move did not change the objective.Results, including a negative one
Small-scale runs on Qwen3-0.6B and Qwen3-4B with GSM8K. These do not show a reward win and I am not claiming one.
What reproduced: the clip is one-sided, and entropy separates upward for UP, matching Fig. 3(a).
What did not: with
beta=0, UP's entropy crosses 2.0 nats for good around step 236 and reward collapses without recovering. It is capability loss rather than truncation, since completions mostly finish and still score near zero. At 4B the same pattern starts, entropy passes 2.0 by step 173 and mean reward falls from 0.87 over the first 100 steps to 0.30 over the last 100 while dapo holds 0.71, but that arm is only 500 steps and partially recovers late. So it is a weaker version of the same failure rather than a repeat, and at least not a 0.6B-only artifact.Adding a KL anchor (
beta=0.04) removes the collapse. Entropy stays below 2.0 for 2000 steps and reward holds around 0.35. That fits the paper: its UP-GRPO keeps the KL term (Eq. 15), and its UP-DAPO results are at 14B.The docs carry a one-line version of that next to the config example, pointing at the paper's own UP-GRPO variant rather than at my numbers. I have no 14B run and am not extrapolating to one.
curves: 2000 steps at 0.6B, the KL-anchor overlay, and the 4B run
Prior art
verl#7022 adds the same method to verl. Opened 2026-07-13, still open and unmerged, and the author appears to be the paper's first author. The positive branch is mathematically identical. The negative branches differ only in defaults: verl's dual clip (
clip_ratio_c) is on at 3.0, TRL's equivalent (delta) is off unless you set it.Jackie2049/trl#6andJackie2049/verl#9are fork-internal, not upstream.Before submitting
docs/source/up.md, apaper_index.mdsubsection, and a_toctree.ymlentry.AI writing disclosure
Who can review?
Anyone once CI is green. @qgallouedec or @kashif may be interested, given the GRPO surface.