Skip to content

loss: add --use-adaptive-entropy (Skywork-OR1) - #3220

Open
behroozazarkhalili wants to merge 2 commits into
radixark:mainfrom
behroozazarkhalili:feat/adaptive-entropy
Open

behroozazarkhalili wants to merge 2 commits into
radixark:mainfrom
behroozazarkhalili:feat/adaptive-entropy

Conversation

@behroozazarkhalili

Copy link
Copy Markdown
Contributor

What

Adds --use-adaptive-entropy, the Skywork-OR1 adaptive entropy bonus, to the policy loss. With it on, the entropy bonus applies only while the previous step's entropy is at or below --entropy-target, and the coefficient moves by --entropy-coef-delta per optimizer step (up at or below the target, down above it) within [--entropy-coef-min, --entropy-coef-max], starting from --entropy-coef.

  • loss_hub/entropy_control.py holds the rule: entropy_coef_to_apply(args) (gated by the previous step's entropy, so every micro-batch of a step applies the same bonus) and update_adaptive_entropy(args, loss_dict), called once per optimizer step in both the FSDP actor and the Megatron train_one_step (last pipeline stage) on the reduced entropy_loss, which aggregate_train_losses makes identical on every loss rank.
  • Entropy is computed whenever the mode is on so the controller keeps its signal, but carries a gradient only when the bonus is non-zero.
  • Runtime state lives on args.adaptive_entropy_coef / args.adaptive_entropy_last; --entropy-coef itself is never rewritten. The coefficient that will apply next is reported as the entropy_coef train metric.
  • Off by default; the fixed --entropy-coef path is unchanged.

Test

  • tests/fast/backends/training_utils/loss_hub/test_entropy_control.py: gate on/off, up/down moves, clamps, no-op when off or when the metric is missing, entropy_coef reporting.
  • tests/fast/backends/training_utils/loss/test_adaptive_entropy.py: through policy_loss_function with the shared fixtures: gated-off step equals the zero-coefficient loss while still reporting entropy; gated-on step equals the static-coefficient loss; entropy requires grad only when the bonus applies.

Verification

On a CPU SLURM node: the 16 new tests pass; tests/fast/backends/training_utils, tests/fast/backends/test_fsdp_train.py, tests/fast/backends/megatron_utils and tests/fast/utils/test_arguments.py pass (756 passed, 11 skipped); removing the gate in entropy_coef_to_apply makes 4 of the new tests fail; ruff, black -l 119, isort --profile black clean. Not run on GPU.

Scope

Loss-side only. No change to rollout, checkpoints, or the fixed-coefficient path. Megatron pickles args into checkpoints but does not compare or restore these fields, so a resumed run restarts the controller from --entropy-coef.

cc @fzyzcjy @yueming-yuan

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

A fixed --entropy-coef either does nothing useful or keeps pushing entropy
up after the policy has recovered. Skywork-OR1's adaptive scheme applies the
bonus only while entropy is at or below a target and moves the coefficient
by a fixed delta per optimizer step, up at or below the target and down
above it, within a clamp. entropy_control.py holds the rule: the loss reads
the coefficient gated by the previous step's entropy, so every micro-batch
of a step applies the same bonus, and both trainers update it once per step
from the reduced entropy_loss, which aggregate_train_losses makes identical
on every loss rank. Entropy is computed whenever the mode is on so the
controller keeps its signal, but it carries a gradient only when the bonus
is non-zero. The runtime state lives on args.adaptive_entropy_coef so the
user's --entropy-coef is never rewritten, and the coefficient that will
apply next is reported as the entropy_coef train metric. Off by default.
…zer step

Preserve the adaptive entropy state when a non-finite grad norm skips the
optimizer step or --disable-optimizer prevents an update. Also leave it
unchanged when no optimizer is present.

Previously, NaN entropy decremented the coefficient and became
adaptive_entropy_last. Since NaN > target is false, this left the entropy
bonus gate open for the next step.

Guard the Megatron update with not disable_optimizer and valid_step so it
now matches the adaptive KL controller. Cover skipped and applied steps
through the existing fast train_one_step fixture.
@behroozazarkhalili

Copy link
Copy Markdown
Contributor Author

@fzyzcjy @yueming-yuan friendly ping. This is rebased onto current main and merges cleanly, with the CPU checks green. The controller moved to loss/hub/entropy_control.py after #3248, and the shared torch-native trainer calls it. Rebasing also turned up a bug in this PR, fixed in a second commit: Megatron updated the entropy coefficient on skipped steps too (non-finite grad norm, --disable-optimizer). A NaN entropy then lowered the coefficient and left the gate open. It now moves only on an applied optimizer step, the same rule the adaptive KL controller in #3222 uses. Eight cases on the real train_one_step cover it; without the fix the seven skipped-step cases fail. The GPU stages still need a run-ci-* label.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant