EasyOptimization

Warmup + Linear Decay LR Schedule

Optimization

Easy

Problem

Most modern training pipelines start with a warmup phase where the learning rate gradually increases from zero, followed by a decay phase where it gradually decreases. This prevents early instability from large updates while still allowing the optimizer to escape sharp minima later.

Given a base learning rate, warmup steps, total steps, and the current step, compute the learning rate at that step.

Schedule

Warmup phase (current_step < warmup_steps): the learning rate increases linearly from 0 to base_lr.

lr = base\_lr \times \frac{current\_step}{warmup\_steps}

Decay phase (current_step >= warmup_steps): the learning rate decreases linearly from base_lr to 0.

lr = base\_lr \times \frac{total\_steps - current\_step}{total\_steps - warmup\_steps}

Theory

At the very beginning of training, everything is random:

If you apply a full-strength learning rate to these unreliable gradients, the results can be catastrophic:


Warmup: Starting Gently

Warmup addresses this by starting with a very small (or zero) learning rate and gradually increasing it over the first several hundred or thousand steps.

The linear warmup formula for step t < W (warmup steps):

\eta(t) = \eta_0 \cdot \frac{t}{W}

During warmup, several things stabilize:


Who Needs Warmup (and How Much)

Different settings need different amounts of warmup:

Transformer models:

Large batch training:

Adam/AdamW:

Fine-tuning pretrained models:

Small models with SGD:


Why Decay After Warmup

After warmup, the learning rate is at its peak value \eta_0. If it stayed there for the rest of training:

Decaying the learning rate over time fixes this:


The Complete Three-Phase Schedule

Phase 1: Warmup (step t < W)

Learning rate ramps up linearly from 0 to \eta_0:

\eta(t) = \eta_0 \cdot \frac{t}{W}

Example with W = 1000, \eta_0 = 0.001:

Phase 2: Linear decay (W \leq t \leq T)

Learning rate decreases linearly from \eta_0 to 0:

\eta(t) = \eta_0 \cdot \frac{T - t}{T - W}

Example with W = 1000, T = 10000, \eta_0 = 0.001:

Phase 3: Post-training (t > T)

Learning rate stays fixed at 0 (or \eta_{\min} if specified).


The Shape

If you plot \eta vs. step, the schedule looks like a triangle (or a ramp up followed by a ramp down):

The peak is always at the warmup boundary t = W. The warmup is typically much shorter than the total training, so the triangle is asymmetric: a short rise followed by a long decline.


Edge Cases

Zero warmup (W = 0):

Warmup equals total steps (W = T):

Step beyond total steps (t > T):


Warmup + Linear Decay vs. Other Schedules


Where This Schedule Shows Up

Examples

Example 1

Input
base_lr = 0.1, warmup_steps = 10, total_steps = 100, current_step = 5
Output
0.05
Explanation
Step 5 is halfway through the linear warmup.

Example 2

Input
base_lr = 0.1, warmup_steps = 10, total_steps = 100, current_step = 55
Output
0.05

Hints

  1. Use the warmup fraction when the current step is below the warmup boundary.
  2. Use the remaining-step fraction during linear decay.

Requirements

Constraints

Starter Code

def warmup_decay_schedule(base_lr: float, warmup_steps: int, total_steps: int, current_step: int) -> float:
    """
    Returns the learning rate for the requested training step.
    """
    # Write code here
    pass

Test Cases

CaseMatches
Warmup phaseExample 1public
Decay phaseExample 2public