Visual walkthrough — Learning rate warmup
Step 0 — The picture we are trying to draw
Before any formula, let us agree on the canvas. We are drawing a graph.
- The horizontal axis is = the training step number. One step = one weight update from one batch. So is the very first update, the second, and so on. It only ever counts up.
- The vertical axis is (the Greek letter "eta"). This is the learning rate: how big a step the optimizer takes. Look back at the update rule — a bigger means a bigger jump for the weights .
Our whole job on this page is to decide: for each step , what value should have? That is a function , and a function is just a curve on this canvas.

Step 1 — Two dots pin down the ramp
WHAT. We place exactly two points on the empty canvas:
- Point — "at step , be small."
- Point — "at step , be at the peak."
WHY. The parent note gave two hard requirements: start small, end at peak. Each requirement is one dot. Two dots is exactly enough to define one straight line — no more, no less. We choose a straight line because it is the simplest continuous path connecting them; nothing in the problem demands a fancier curve.
PICTURE. Two red dots floating on the axes, nothing between them yet. This is the skeleton every warmup curve hangs on.

Step 2 — Connect the dots: the line equation, term by term
WHAT. We draw the straight line through and and write its equation.
WHY a line and not a curve? A line has constant slope — the LR grows by the same tiny amount every step. That predictable, gentle rise is exactly the "warm the engine slowly" behaviour we want. No sudden jumps.
How to build a line from two dots. Start at the left dot's height, then add "how far up we still need to go" times "how far along we are":
Read each piece:
- — the base camp. At the last two factors vanish and . ✓
- — the gap we must climb. Not the peak itself — the difference.
- — the progress fraction. At it is ; at it is . It slides from to as we march through warmup, handing us that fraction of the gap.
Check the right end: at , the fraction is , so . ✓ Both dots satisfied.

Step 3 — The common special case: start at zero
WHAT. Set (the default in most recipes) and watch the formula collapse.
WHY. Starting from literally means the very first update does nothing — the safest possible beginning when the gradients are wild. It also makes the algebra clean, which is why libraries default to it.
Substitute :
Now the height is simply "peak times progress fraction." At a quarter of the way, , you get a quarter of peak.
PICTURE. The same ramp, but now the line launches from the origin — the red segment leaves the corner of the axes.

Step 4 — What happens after ? We must not stop here.
WHAT. The ramp only covers . Past that, the line would keep rising forever — nonsense. We need a second piece of the curve.
WHY. A permanently high LR never lets the model settle into a fine minimum (see the parent's mistake list). So after we reach the peak we want to come back down gently toward . We need a decay that:
- starts at exactly where warmup ended (no jump),
- ends near at the final step ,
- has a flat slope at both ends — flat at the top so the handoff from warmup is smooth, flat at the bottom so training finishes calmly.
PICTURE. The ramp reaches the peak, then a big question mark hovers over the region : which downhill curve fits all three demands?

Step 5 — Why a cosine, and how to bend it into place
WHAT. We answer the Step-4 question with a half-cosine curve. See Cosine annealing for the full treatment.
WHY cosine and not a straight line down? A straight downhill line has the same steepness everywhere, including at the very top and very bottom — that violates our "flat at both ends" wish. The cosine function is special: it is perfectly flat (zero slope) at its peaks and troughs. That is exactly the shape we need.
Building it, factor by factor. Take the raw cosine on the interval where its argument runs from to . There falls from down to . We reshape it in three moves:
- — a fresh progress fraction for the decay phase. It is right when warmup ends () and at the final step (). Same trick as Step 2, new interval.
- — stretches that progress into the angle range , exactly the stretch of cosine that falls from to .
- — lifts the cosine up so it runs from (at the top) down to (at the bottom) instead of to . No more negative learning rates.
- — the half and the peak together rescale that range into .
Check the joins:
- At : , , so . Matches the top of the ramp — no jump. ✓
- At : , , so . Ends at zero. ✓

Step 6 — Degenerate cases: don't let the curve break
WHAT. We poke the formula at its extreme inputs to be sure nothing explodes.
WHY. A schedule that divides by zero or goes negative can silently NaN a whole training run. We check the corners.
- (no warmup). The ramp would divide by zero. In practice "" means skip the ramp entirely: jump straight to the peak at and start cosine immediately. The curve is just the decay half.
- (all warmup, no decay). You ramp the entire run and never come down — the parent's "forgot to decay" mistake. The cosine piece never runs.
- (training past the planned end). The progress , turns back upward and would rise again — undesired. Real code clamps to (or holds the final value) for .
- . The gap , so the ramp is a flat horizontal line — effectively no warmup, just a constant then decay.

The one-picture summary
Here is the whole life of the learning rate on one axis: the red curve rises linearly from to across the first steps (Steps 1–3), then cosine-decays smoothly to by step (Steps 4–5), with flat slopes stitching the two pieces together. Everything in the Adam optimizer / RAdam / large-batch story is about why this red shape beats a flat line.

Recall Feynman: the whole walkthrough in plain words
I want to decide how big a step my network should take at every moment of training. I draw an empty graph: time going right, step-size going up. I put down two dots — "tiny at the start" and "big at step " — and connect them with a straight line, because a straight line grows the step-size by the same small amount each moment. That is warmup. But if I keep climbing forever the network never settles, so after the peak I want to come back down smoothly. A straight line down is too abrupt at the ends, so I use a cosine, because a cosine is naturally flat where it turns around — flat at the top (smooth handoff) and flat at the bottom (calm finish). I shift and shrink that cosine so it slides from the peak down to zero. Finally I check the weird cases — no warmup, all warmup, running past the end — and clamp the curve so it never divides by zero or bounces back up. The result is one red curve: rise gently, cruise the peak briefly, glide down to zero.