Skip to content

Restore the LoRA adapter when resuming from a checkpoint - #166

Merged
alexkroman merged 1 commit into
mainfrom
fix-resume-lora
Oct 20, 2026
Merged

alexkroman merged 1 commit into
mainfrom
fix-resume-lora

Conversation

@alexkroman

Copy link
Copy Markdown
Owner

Summary

Resuming training silently threw away the LoRA adapter.

  • The bug: HF Trainer's _load_from_checkpoint loads model.safetensors and, when that file exists, never reaches its PEFT branch. Our model.safetensors holds only the projector; LoRA is saved separately as adapter_model.safetensors. A resumed run therefore kept the trained projector but restarted LoRA from its initialization, under optimizer moments that belonged to the trained adapter.
  • How it showed up: resuming granite-qwen-verbatim-aug-2 at step 52,000 after a pod reboot, loss jumped from 0.28 to 1.7 and grad norm from 0.4 to 1.9. I stopped the run before its next Hub push, so the good step-52,000 model on the Hub was not overwritten.
  • The fix:
    • New ASRModel.load_lora_checkpoint loads the adapter file into the PEFT-wrapped decoder. It raises if a saved tensor matches no LoRA parameter.
    • ASRTrainer._load_from_checkpoint calls it after the stock load.

Test plan

  • tests/test_resume_checkpoint.py: save a "trained" LoRA model, scramble its weights, resume through ASRTrainer, and check that both the projector and the adapter are restored exactly. A second test reproduces the stock Trainer skipping the adapter, so it fails if transformers changes this. Also covers the edge cases (no adapter file; tensor that matches no parameter).
  • ta dev check, ta dev test

🤖 Generated with Claude Code

HF Trainer's _load_from_checkpoint loads model.safetensors and, when that
file exists, never reaches its PEFT branch. Our model.safetensors holds
only the projector (LoRA is saved separately as adapter_model.safetensors),
so a resumed run kept the trained projector but restarted LoRA from its
initialization under the trained optimizer state. Seen resuming
granite-qwen-verbatim-aug-2 at step 52,000: loss 0.28 -> 1.7, grad norm
0.4 -> 1.9; the run was stopped before its next Hub push.

ASRTrainer._load_from_checkpoint now also calls the new
ASRModel.load_lora_checkpoint, which loads adapter_model.safetensors into
the PEFT-wrapped decoder and raises if a saved tensor matches no LoRA
parameter. A test reproduces the stock Trainer's behaviour so it fails if
transformers changes it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@alexkroman
alexkroman merged commit 39bb971 into main Oct 20, 2026
4 checks passed
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.

2 participants