Fix BEMACallback parameter alignment when some parameters are frozen - #7043
Fix BEMACallback parameter alignment when some parameters are frozen#7043yurekami wants to merge 1 commit into
Conversation
BEMACallback caches only the trainable parameters of the trained model (skipping requires_grad=False) but writes the BEMA weights by zipping that list against running_model.parameters(), which includes every parameter. With any frozen parameter the two sequences are positionally misaligned: zip(strict=True) raises on a length mismatch, and would otherwise write each BEMA tensor into the wrong parameter of the running model. Cache the matching running-model parameters by name at on_train_begin and zip against that list instead. Adds test_frozen_parameters, which freezes the embedding matrix and checks every trainable parameter of the running model against the BEMA formula while the frozen one is left untouched. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011vZKTbRaDh8FuXSbVpQomD
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.
Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 71dc9f0. Configure here.
| ) | ||
| torch.testing.assert_close( | ||
| running_params["model.embed_tokens.weight"], self.model.model.embed_tokens.weight, check_dtype=False | ||
| ) |
There was a problem hiding this comment.
Test compares tensors across devices
Medium Severity
The new frozen-parameter test builds the expected BEMA weights from thetat on the training device and compares them to running_model tensors, which live on the callback device (default cpu). On GPU that subtraction and assert_close fail with a device mismatch, so the regression test does not run in this project's GPU CI.
Reviewed by Cursor Bugbot for commit 71dc9f0. Configure here.


What does this PR do?
BEMACallbackcaches only the trainable parameters of the trained model inon_train_begin(it skipsrequires_grad=False), but_bema_updatewrites the BEMA weights by zipping that list againstself.running_model.parameters(), which yields every parameter. As soon as any parameter is frozen the two sequences are positionally misaligned:zip(..., strict=True)raises on the length mismatch, and withoutstricteach BEMA tensor would be written into the wrong parameter of the running model.Repro: freeze the embedding matrix (
model.model.embed_tokens.weight.requires_grad_(False)) and train withBEMACallback(update_freq=1):This PR caches the matching running-model parameters by name in
on_train_begin(self.running_params) and zips against that list, so frozen parameters are skipped consistently on both sides.Test:
TestBEMACallback::test_frozen_parametersfreezes the embedding matrix, trains for 9 steps, and checks every trainable parameter of the running model againstema + alpha * (theta_t - theta_0)matched by name, while the frozen embedding is left equal to the trained model's. Fails onmainwith the error above, passes here.check_dtype=Falsebecauserunning_modelis built from the config and may carry a different dtype than the trained model (pre-existing, unrelated to this fix).Fixes # (none filed; found while reading
trl/trainer/callbacks.py)Before submitting
Who can review?
Anyone in the community is free to review the PR once the tests have passed.
🤖 Generated with Claude Code
https://claude.ai/code/session_011vZKTbRaDh8FuXSbVpQomD
Note
Medium Risk
Changes training callback weight-update logic; incorrect alignment could corrupt saved BEMA checkpoints, though the fix is narrow and covered by a regression test.
Overview
Fixes
BEMACallbackwhen some weights are frozen (requires_grad=False). Trainable tensors were tracked in a filtered list, but BEMA updates were applied by zipping against every parameter inrunning_model, which misaligned or crashed (strict=Truelength mismatch / wrong tensor shapes).on_train_beginnow buildsrunning_paramsby parameter name for each trainable weight, and_update_bema_weightswrites only into those tensors. Frozen weights in the running copy are no longer touched by the BEMA loop.Adds
test_frozen_parameters: freezesembed_tokens, trains withupdate_freq=1, checks trainable running weights matchema + alpha * (θₜ - θ₀)and the frozen embedding stays equal to the training model.Reviewed by Cursor Bugbot for commit 71dc9f0. Bugbot is set up for automated code reviews on this repo. Configure here.