An optimizer is three decisions: a direction, a step size over time, and a way of living with noise. This section studies the second decision, the schedule t \mapsto \eta_t.
Two facts force it to exist:
Constant \eta: SGD parks on a noise floor\propto \eta. The rate must come down.
The target rate is often unstable at initialization. The rate must first come up.
Theory ranks few shapes (the proofs that exist live in the math appendix), so we proceed empirically: one CNN, one dataset, every schedule.
A testbed
LeNet-style CNN on Fashion-MNIST, modernized: ReLU, max-pooling, BatchNorm after every hidden layer, Xavier init pinned in both frameworks (without the norm layers, survivable \eta is a seed-dependent coin flip).
A scheduler is any callable epoch -> learning rate.
The training loop consults it at the start of every epoch and writes the rate into the optimizer; nothing else changes.
Stateless by design: a pure function of t can be plotted, resumed, and branched from a saved checkpoint.
Baseline: constant \eta = 0.3
train loss 0.059, train acc 0.979, test acc 0.904
Both failure modes on one plot: loss noisy to the end (riding the noise floor), and test accuracy stalls while train accuracy climbs — overfitting.
Square-root decay
\eta_t = \eta_0 (t+1)^{-1/2} — the convex-optimal rate from 9.3. A scheduler is a callable:
class SquareRootScheduler:def__init__(self, lr=0.1):self.lr = lrdef__call__(self, epoch):returnself.lr *pow(epoch +1.0, -0.5)scheduler = SquareRootScheduler(lr=0.3)d2l.plot(d2l.arange(num_epochs), [scheduler(t) for t inrange(num_epochs)], xlabel='epoch', ylabel='learning rate')
Square-root decay: training
train loss 0.088, train acc 0.970, test acc 0.905
The loss is smoother, but test accuracy remains below the constant baseline. The rate is too small at both ends: gives up the high early rate within ~3 epochs, yet ends with the largest tail \eta of any decay here. Shape matters.
One parameter, no milestones, no kinks (Loshchilov & Hutter, 2016).
train loss 0.080, train acc 0.975, test acc 0.909
The stay-high, decay-hard shapes (multiplicative, piecewise, cosine) beat the baseline and are too close to call from single runs. Cosine won on convenience, not measured superiority.
Warmup: the other end of the schedule
At initialization the loss surface is sharp; the target rate can kill the run in step one.
Standard fix since Goyal et al. (2017): linear ramp from \approx 0 over the first epochs.
Mechanism (Kalra & Barkeshli, 2024): early training at a growing rate reduces sharpness, raising the stability ceiling before the full rate arrives.
Adam has a second reason: an estimated preconditioner should not be trusted cold.
Warmup and initial stability
Even a BatchNorm network has a stability limit. A cold start at \eta = 7.5 (25× the baseline) remains at chance accuracy after one epoch:
train loss 2.315, train acc 0.097, test acc 0.100
A five-epoch ramp to the same rate permits training to reach 80–90% accuracy:
train loss 0.207, train acc 0.921, test acc 0.891
Warmup + cosine
The default recipe of the late 2010s, and still strong:
train loss 0.047, train acc 0.987, test acc 0.910
Dependence of cosine decay on the horizon
The horizon T is baked in from step one.
Mid-run checkpoints: rate never came down → not finished models.
Want 2× the budget after the fact? Retrain.
Scaling-law study at 5 budgets? 5 full runs.
Warmup–stable–decay (MiniCPM; Hu et al., 2024): warm up, hold the peak constant for most of the run, decay in the last 10–20%. Every plateau checkpoint is horizon-free; the decay is a harvest step.
Loss reduction during WSD decay
train loss 0.027, train acc 0.994, test acc 0.914
Plateau loss remains above cosine’s, then decreases rapidly when the decay begins. Same final range as cosine at the same budget.
A geometric interpretation of WSD
Wen et al. (2024) model the loss surface as a winding valley with steep walls, gently sloping floor.
High constant rate: the iterate bounces between walls while drifting fast along the floor. Measured loss is inflated; progress is real.
Decay reduces the transverse oscillation, so the measured loss approaches that of the valley floor already reached.
This extends the noisy-quadratic interpretation of §9.3 to a curved valley.
Branching off the plateau
Train warmup + stable only (no horizon committed), keep going as long as you like, then clone and decay whenever you want a finished model:
The branch reaches the accuracy range of the full cosine run even though the horizon is chosen afterward. One plateau run can therefore supply branched decays for several budgets (Hägele et al., 2024).
Plain SGD carries no state, so cloning parameters sufficed. With momentum or Adam, branch the optimizer state too.
Current schedule choices
Linear decay to zero matched or beat cosine and WSD in careful LLM sweeps (Bergsma et al., 2025), with the final rate accounting for much of the difference.
Schedule-free (Defazio et al., 2024): constant rate; gradients at an interpolation of iterate and average, evaluate the average. This implements variance reduction without a predetermined horizon.
Not settled: GLM-4.5 ablated WSD vs. cosine and shipped cosine (Zeng et al., 2025). Differences at matched tuning are small.
Schedules are inexpensive to evaluate and materially affect training. Plateau checkpoints allow the decay horizon to be selected after pretraining.