Skip to content

fix: make post-warmup cosine LR scheduling effective and configurable - #293

Open
yamsam wants to merge 2 commits into
devfrom
feat/cosine-lr-scheduler
Open

fix: make post-warmup cosine LR scheduling effective and configurable#293
yamsam wants to merge 2 commits into
devfrom
feat/cosine-lr-scheduler

Conversation

@yamsam

@yamsam yamsam commented Jul 24, 2026

Copy link
Copy Markdown

Summary

Fix the learning-rate schedule so that cosine decay is applied correctly after warmup.

The previous CosineAnnealingWarmUpRestarts implementation used
MultiplicativeLR(lambda=1.0) after warmup. Despite its name, it therefore kept
the learning rate constant instead of applying cosine annealing.

This PR introduces a real linear-warmup → cosine-decay schedule while preserving
the previous behavior for backward-compatible experiments.

Based on dev.

Changes

Scheduler behavior

  • Add WarmupCosineAnnealingLR: linear warmup followed by
    CosineAnnealingLR.
  • Rename the previous warmup → constant implementation to
    WarmupConstantLR.
  • Keep CosineAnnealingWarmUpRestarts as an alias for the legacy constant
    implementation to preserve existing imports.
  • Add build_lr_scheduler(...) to select cosine or constant.
  • Prevent the legacy final-10-epoch manual LR step-down from overriding the
    cosine schedule. The legacy step-down remains active only in constant mode.

Resume behavior

  • Rebuild and fast-forward the scheduler to the completed training progress
    when resuming from a checkpoint.
  • Avoid resetting a resumed cosine run directly to the peak learning rate.
  • Preserve schedule continuity when resuming with either the same or a new base
    learning rate.
  • Convert completed epochs to optimizer steps when using batch-level scheduler
    updates.

Configuration

The following options are available through TrainConfig and
train_predictor.py:

Option Default Description
lr_schedule_type cosine cosine or legacy constant
learning_rate 1e-4 Peak/base learning rate
warm_up_epoch 5 Warmup duration in epochs
lr_start_factor 0.1 Initial LR as a fraction of the peak LR
lr_eta_min 1e-6 Minimum cosine LR
lr_cosine_t_max 0 Cosine duration in epochs; 0 selects the remaining epochs automatically
lr_scheduler_interval epoch Update the scheduler per epoch or per batch

When lr_scheduler_interval=batch, warmup duration, explicit T_max, and
resume progress are converted from epochs to optimizer steps using the training
DataLoader length.

The legacy final-phase parameters remain unchanged.

Behavior change and compatibility

  • New training runs use actual cosine decay by default.
  • The previous training policy remains available with
    --lr_schedule_type constant.
  • Existing imports of CosineAnnealingWarmUpRestarts continue to work and
    retain the previous warmup → constant scheduler behavior.
  • To reproduce an older run when resuming, explicitly select
    --lr_schedule_type constant.

Verification

  • LR scheduler tests: 15 passed
  • Ruff lint: passed
  • Ruff format check: passed
  • Pre-commit hooks: passed
  • Verified cosine and legacy constant behavior with the mini dataset.
  • Verified checkpoint resume without an LR jump.
  • Verified custom start_factor, eta_min, T_max, and batch-level scheduler
    updates with a mini-dataset training run.

yamsam and others added 2 commits July 24, 2026 16:29
The scheduler named CosineAnnealingWarmUpRestarts actually held the lr
CONSTANT after warmup (post-warmup phase was MultiplicativeLR(lambda=1.0)),
so training collapsed right after warmup: every model peaked in the warmup
epochs and then degraded.

- Add WarmupCosineAnnealingLR: linear warmup then real cosine decay to
  eta_min over the remaining epochs (matches original planTF).
- Rename the legacy behavior to WarmupConstantLR (accurate name), kept for
  backward-compatible reproduction of pre-existing runs.
- Keep CosineAnnealingWarmUpRestarts as an alias bound to the exact legacy
  (constant) behavior so existing imports and resumed checkpoints reproduce.
- Add build_lr_scheduler dispatch and --lr_schedule_type {cosine,constant}
  (default cosine). Training now cosine-decays by default; select "constant"
  to reproduce old runs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Isamu Yamashita <isamu.yamashita@tier4.jp>
@yamsam

yamsam commented Jul 27, 2026

Copy link
Copy Markdown
Author

Comparison results with the legacy implementation

image

@yamsam yamsam changed the title fix: Fix CosineAnnealingWarmUpRestarts fix: make post-warmup cosine LR scheduling effective and configurable Jul 28, 2026
@yamsam
yamsam marked this pull request as ready for review July 29, 2026 06:47
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