Proposes cyclical learning rates that move between a lower and an upper bound, and a learning-rate range test for choosing the bounds. Presented at WACV 2017.
Learning Rate Schedules: Warmup, Decay & Cycling
How warmup, decay and cyclical schedules change the learning rate over a training run, including the Transformer's warmup with inverse-square-root decay and cosine annealing.
Intuition
The idea in plain words, before the symbols.
The learning rate multiplies every optimizer update. In plain gradient descent it scales the gradient directly; adaptive optimizers such as Adam first rescale the gradient coordinate by coordinate and then multiply by . A schedule changes from one update to the next.
Three shapes are common:
- Warmup: start with a small rate and raise it over the first few hundred or thousand updates. Goyal et al. (2017) introduced a gradual linear warmup to train ResNet-50 on ImageNet with mini-batches of 8,192 images, and the original Transformer warmed up linearly for 4,000 steps before decaying (Vaswani et al., 2017). One proposed explanation for why warmup helps Adam-type optimizers is that their per-coordinate scaling rests on very few gradients in the first updates (Liu et al., 2020).
- Decay: lower the rate later in training so that late updates are smaller. Linear and cosine decay are common; the cosine curve comes from the annealing schedule in SGDR (Loshchilov and Hutter, 2017).
- Cycling: move the rate up and down between two bounds instead of only down. Smith (2017) proposed these cyclical learning rates, with a short range test for choosing the bounds.
The code computes warmup followed by cosine decay. The demo also offers linear decay, inverse-square-root decay and a constant rate for comparison.
Study prompts for this section: Intuition
Each button copies a prompt about this section to your clipboard, for an AI assistant you already use. Nothing is sent by this site.
Mathematics
Definitions, assumptions and the derivation.
Indexing. Here a schedule is a list of exactly rates, one for each optimizer update . Assume integers and , with . This counting is the convention of this page, not a universal scheduler API convention: libraries differ over whether a boundary value is used at an update or is the scheduler's state before or after one. The warmup skips the rate zero, so its first rate is positive when ; gives the all-zero schedule. Only updates that are applied count: an attempted update that is skipped, for example because its gradient overflowed, does not advance here. Training libraries differ on this as well.
For a decay coordinate , define
Choose or . When , there is no warmup, and spans all updates:
When , the first updates form a linear warmup that skips zero, followed by decay:
Update reaches ; it is both the last warmup update and the start of decay. When , update uses and is already below the peak, so the peak is not repeated. When , the post-warmup segment instead remains constant at . The final update, , uses and reaches . So is where decay ends, not necessarily the smallest rate in the run: an early warmup rate can be smaller.
Inverse-square-root decay is the decay half of the original Transformer schedule (Vaswani et al., 2017, §5.3). With step number , model width and warmup steps, that schedule was
which rises linearly for steps, peaks at , and then falls as . The demo's inverse-square-root option drops the warmup and starts the decay at its peak at update :
For every schedule, the demo reports the mean over all updates,
not the mean of the fewer points used to draw the chart. The cosine decay above is one half-cycle of the SGDR annealing curve, without restarts.
Same budget, different timing
The mean, or equivalently the sum , is a schedule's total budget. Two schedules can spend the same budget at different times. Take , , and , so the decay coordinate is for :
They differ only at , where the cosine is higher by , and at , where it is lower by the same , so both sums are and both means . Now move a parameter from with , where the direction is fixed in advance. After six updates . With throughout, both schedules end at , by different paths: after three updates the cosine run is at and the linear one at . With the endpoints separate, for linear and for cosine, because the endpoint weights each rate by the direction it meets. In general the two endpoints differ by , so they agree whenever , whatever the other directions are.
In training the directions are not fixed in advance: they come from gradients that depend on where earlier steps went, so changing the schedule also changes them. The calculation holds them fixed to isolate timing; it does not say which schedule trains better.
Study prompts for this section: Mathematics
Each button copies a prompt about this section to your clipboard, for an AI assistant you already use. Nothing is sent by this site.
Code
The same calculation as runnable code, in the notation of the derivation.
import math
def warmup_cosine(T, Tw, eta_max, eta_min):
if not isinstance(T, int) or isinstance(T, bool) or T < 2:
raise ValueError("T must be an integer with T >= 2")
if not isinstance(Tw, int) or isinstance(Tw, bool) or not 0 <= Tw < T:
raise ValueError("Tw must be an integer with 0 <= Tw < T")
if not all(math.isfinite(v) for v in (eta_max, eta_min)):
raise ValueError("learning-rate bounds must be finite")
if not 0 <= eta_min <= eta_max:
raise ValueError("require 0 <= eta_min <= eta_max")
lr = [0.0] * T
for t in range(T):
if Tw > 0 and t < Tw:
lr[t] = eta_max * (t + 1) / Tw
else:
u = t / (T - 1) if Tw == 0 else (t - Tw + 1) / (T - Tw)
lr[t] = eta_min + 0.5 * (eta_max - eta_min) * (1 + math.cos(math.pi * u))
return lr
T, Tw = 10_000, 500
lr = warmup_cosine(T=T, Tw=Tw, eta_max=3e-4, eta_min=3e-5)
print("lr[0], lr[Tw-1], lr[Tw], lr[-1]:", lr[0], lr[Tw - 1], lr[Tw], lr[-1])
print("avg lr over all applied updates:", sum(lr) / len(lr))
The second block works the six-update comparison above in exact arithmetic, writing each number as with fractions and , using only Python's standard library.
from fractions import Fraction as F
# Exact numbers a + b*sqrt(2), stored as the pair (a, b).
def num(a, b=0):
return (F(a), F(b))
def add(x, y):
return (x[0] + y[0], x[1] + y[1])
def times(k, x):
return (k * x[0], k * x[1])
def show(x):
a, b = x
return str(a) if b == 0 else (f"{b}*sqrt(2)" if a == 0 else f"{a} + {b}*sqrt(2)")
def final_theta(rates, directions):
"""theta_6 = -(sum of eta_t * q_t), starting from theta_0 = 0."""
total = num(0)
for rate, q in zip(rates, directions):
total = add(total, times(q, rate))
return times(-1, total)
# T = 6, two warmup updates, eta_max = 1, eta_min = 0. The cosine rates at t = 2 and t = 4
# are (2 + sqrt(2))/4 and (2 - sqrt(2))/4.
linear = [num(F(1, 2)), num(1), num(F(3, 4)), num(F(1, 2)), num(F(1, 4)), num(0)]
cosine = [num(F(1, 2)), num(1), num(F(1, 2), F(1, 4)), num(F(1, 2)), num(F(1, 2), F(-1, 4)), num(0)]
ones = [1] * 6
assert final_theta(linear, ones) == final_theta(cosine, ones) == num(-3) # equal budgets, equal endpoints
signed = [0, 0, 1, 0, -1, 0]
assert final_theta(linear, signed) == num(F(-1, 2))
assert final_theta(cosine, signed) == num(0, F(-1, 2)) # -sqrt(2)/2
# The endpoints still agree whenever q_2 = q_4, however the other directions vary.
q = [7, -3, 2, 9, 2, -5]
assert final_theta(linear, q) == final_theta(cosine, q)
print("constant direction, final theta:", show(final_theta(linear, ones)), show(final_theta(cosine, ones)))
print("signed direction, final theta:", show(final_theta(linear, signed)), show(final_theta(cosine, signed)))
Study prompts for this section: Code
Each button copies a prompt about this section to your clipboard, for an AI assistant you already use. Nothing is sent by this site.
Demo
Change an input, predict the result, and see which quantities respond.
Explore Learning Rate Schedules: Warmup, Decay & Cycling
Observation guide
Optional and ungraded. Opening a guide saves nothing.
Choose what to inspect in Learning Rate Schedules: Warmup, Decay & Cycling, then open its guide.
Predict how the first rate compares with the mean over the whole run, then reveal the curve. Change the warmup length and the decay shape and watch the first rate, the mean over all updates, the final rate, and where warmup ends and decay begins. The chart draws a subset of the points; the numbers use all of them.
The practice after the demo works the six-update comparison from the mathematics by hand: equal budgets, different timing.
Study prompts for this section: Demo
Each button copies a prompt about this section to your clipboard, for an AI assistant you already use. Nothing is sent by this site.
Practice
Two six-update schedules with the same total budget. Work out the rates, then change the directions and see when the timing matters.
Concept: Learning Rate Schedules: Warmup, Decay & Cycling
What is the smallest example of Learning Rate Schedules you can work through by hand, and what does it show?
DetailsOptimization
Reference id
concept:optimization/learning-rate-schedulesAfter the first pass
Go deeper
Optional material for a second reading. Sources are always shown; the other panels open from their headings or from these links, and closing one keeps what you wrote or revealed.What to look for in each sectionChoose a section and what you expect to see in it, then read short advice.
Section by section
Choose what to look for in each section
How warmup, decay and cyclical schedules change the learning rate over a training run, including the Transformer's warmup with inverse-square-root decay and cosine annealing.

Start with the picture, metaphor, or geometric mechanism.
Choose what you expect to see in this section of Learning Rate Schedules: Warmup, Decay & Cycling.
Questions to ask of the pictureChoose a part of the picture and what you expect, then read short advice.
Looking at the picture
Questions to ask of the picture
How warmup, decay and cyclical schedules change the learning rate over a training run, including the Transformer's warmup with inverse-square-root decay and cosine annealing.
Which part of the picture should you look at first?
Pick the part of the picture you expect to explain Learning Rate Schedules: Warmup, Decay & Cycling.
Sources
References for this page
A reference shows where an idea comes from; it does not vouch for every step on this page.Introduces cosine annealing from a maximum to a minimum rate within each restart cycle (ICLR 2017). It does not define this page's linear warmup or its enumeration of exactly T applied updates.
Trains the Transformer with Adam and a learning rate that rises linearly for 4,000 warmup steps and then decays in proportion to the inverse square root of the step number (NIPS 2017).
Introduces a gradual warmup that raises the learning rate linearly over the first five epochs, which lets ResNet-50 train with mini-batches of 8,192 images without losing accuracy (technical report).
Argues that Adam's adaptive learning rate has large variance in the first updates, when few squared gradients have been averaged, and that warmup reduces it (ICLR 2020).
Textbook treatment of decreasing the learning rate during training, including linear decay to a final rate after a set number of iterations.
What each claim rests on1 claim, each with its sources, where it appears on this page, and its caveats.
Claims and sources
How warmup, decay and cyclical schedules change the learning rate over a training run, including the Transformer's warmup with inverse-square-root decay and cosine annealing.
The checks were made by this site, not by an independent reviewer.
Smith supports LR range tests and CLR between boundary values. SGDR supports cosine annealing between maximum and minimum endpoints within a restart cycle. The update indexing, the shared peak and the exact...
This check does not cover warmup or inverse-square-root schedules (sourced separately on this page to Goyal et al. and Vaswani et al.), a universal scheduler-library indexing convention, convergence guarante...
Smith supports the learning rate as a key hyperparameter, cyclical learning rates between two bounds, and a range test for choosing the bounds. Loshchilov and Hutter support warm restarts and half-cosine annealing from eta_max to eta_min within a cycle. Neither paper defines the linear warmup, the inverse-square-root schedule, the update indexing used on this page, convergence behavior, or whether one schedule is better; warmup and inverse-square-root decay are sourced separately.
Explain it without the pageWrite your own explanation before asking for feedback. Your draft and any hints stay while this page is open.
Practice · Learning Rate Schedules: Warmup, Decay & Cycling
Try the idea in your own words
How warmup, decay and cyclical schedules change the learning rate over a training run, including the Transformer's warmup with inverse-square-root decay and cosine annealing.
Concept · Selected for practice
Learning Rate Schedules: Warmup, Decay & Cycling
What it rests on: Sources: Cyclical Learning Rates for Training Neural Networks; SGDR: Stochastic Gradient Descent with Warm Restarts; Attention Is All You Need
Context and links
Optimization
Explain the mechanism
For Learning Rate Schedules: Warmup, Decay & Cycling: What is the smallest example of Learning Rate Schedules you can work through by hand, and what does it show? Explain your answer, including what changes, why, and which assumption matters.
A rough first thought is enough. Your draft stays when you change tasks.
Your draft stays on this page and is cleared when you leave or reload.
A little help · Explain
Open one hint at a time. These are suggestions, not your answer or a grade.
0 of 3 hints shown for this question.
Clearing your answer keeps this help record. Outside help is your own report; this page cannot check it.
Where am I stuck? (optional)
Take your draft to a feedback conversation
No AI feedback runs here. You can copy a prompt to use elsewhere; nothing is sent automatically. Review the text before sharing, and leave out private information.
Write an attempt before copying a feedback prompt.
A draft, or an AI reply to it, is not a test of what you have learned. To check that, try a different case later without help.
Ask about this pagePick one item on this page and copy a prompt about it into an AI assistant you already use. Notes you write here stay in this browser.
assert final_theta(linear, ones) == final_theta(cosine, ones) == num(-3) # equal budgets, equal endpointsYour question
Choose what your question is about
Pick the idea, equation, source, code, claim, misconception or demo state you want to ask about. The prompt you copy includes it, so the answer can stay on that item.Open the draft below to save one note and next action in this browser.
Learning Rate Schedules: Warmup, Decay & Cycling
What is the smallest example of Learning Rate Schedules you can work through by hand, and what does it show?
Fixed prompts generated from this item. They are not comments from people or independent reviews.
The 6 cited sources must support this exact item, not just the surrounding topic.
Connect the definition to one equation, piece of code or demo before widening the discussion.
Change one input, then check that the same relationship holds in the mathematics, the code and the demo.
You can state the mechanism in your own words
Local action draftNo local draft saved yetOpen when you are ready to write one next action
This draft stays in this browser and is attached to this item only.
- What the 6 cited sources say about this exact item
- The definition, its prerequisites, and a contrasting concept
- The equation or code that makes the concept concrete
- One demo state that shows what stays the same as the inputs change
- You can state the mechanism in your own words
- You can name the prerequisite that would clear up the confusion
- You can predict how the result changes when one input changes
Reference id
concept/concept-notebook/optimization/learning-rate-schedules
concept:optimization/learning-rate-schedules