Skip to content

pl_model: RDT-style weight EMA, validated in place of raw weights - #701

Draft
RyanPCo wants to merge 1 commit into
ryanco/ephemeral-stagefrom
ryanco/weight-ema
Draft

RyanPCo wants to merge 1 commit into
ryanco/ephemeral-stagefrom
ryanco/weight-ema

Conversation

@RyanPCo

@RyanPCo RyanPCo commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Opt-in EMA of the trainable weights, using RDT's schedule: decay 1 - (1 + n)^-0.75, capped at 0.9999.

  • egomimic/pl_utils/ema.py: WeightEMA, an fp32 shadow copy updated with one fused _foreach_lerp_ per optimizer step.
  • ModelWrapper: updates the EMA once per optimizer step and validates on the EMA weights, restoring the raw weights afterwards; the raw backup is kept on CPU during validation. Checkpoints store the EMA under ema, and state_dict keeps the raw weights even when a checkpoint is saved mid-validation. A checkpoint without an EMA starts one from its current weights.
  • load_checkpoint_weights passes the EMA through, so mode=eval evaluates the EMA weights.

Enable with +model.ema.enabled=true (optional: +model.ema.power, +model.ema.max_decay).

Tested: unit tests only (tests/unit/test_ema.py, CPU).
Not yet tested on GPU:

  • trainer=debug run: checkpoint has an ema key, and Train/ema_decay is logged
  • resume continues num_updates
  • mode=eval matches the EMA val metrics
  • peak memory at validation on the 1B config

🤖 Generated with Claude Code

https://claude.ai/code/session_01Jk3skP294hqzoTA37vu4xK

RyanPCo commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@aidang3019
aidang3019 changed the base branch from ryanco/replay-fractional-stride to graphite-base/701 September 30, 2026 01:06
@RyanPCo
RyanPCo changed the base branch from graphite-base/701 to ryanco/ephemeral-stage October 12, 2026 20:27
@RyanPCo
RyanPCo force-pushed the ryanco/ephemeral-stage branch from 6e5d9e1 to 8c92207 Compare October 12, 2026 21:50
@RyanPCo
RyanPCo force-pushed the ryanco/ephemeral-stage branch from 2f0c6a8 to 3e255fd Compare October 19, 2026 19:57
Opt-in via model.ema (enabled, power, max_decay). Decay follows RDT's
1 - (1 + n)^-0.75 capped at 0.9999. When on, validation and mode=eval run
on the EMA weights; checkpoints carry them under an 'ema' key and keep raw
weights in state_dict even when saved mid-validation. The raw-weight backup
during validation lives on CPU.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Jk3skP294hqzoTA37vu4xK
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