Visual walkthrough — Adam and AdamW optimizers
Everything here is the visual companion to the parent note. The maths there is correct — here we watch it happen.
Step 1 — The problem: one learning rate cannot fit every slope
WHAT. Imagine a landscape where "height" is the loss (how wrong the model is) and "position" is a parameter (a single knob in the network). Plain gradient descent reads the slope (the steepness under your feet, pointing uphill) and steps downhill:
Here is the gradient — the slope, positive when the ground rises as grows. We subtract it so we move away from uphill, i.e. downhill. (Greek "eta") is the learning rate, the length of one stride.
WHY it fails. Different knobs sit on wildly different slopes. One global stride that is safe on a steep cliff is painfully slow on a gentle plain.
PICTURE. Two valleys side by side. The same stride overshoots the steep one (bounces across) and crawls in the flat one.

The fix Adam proposes: give each direction its own stride, decided by two running summaries of the gradient. We build those summaries next.
Step 2 — The tool we need: an Exponential Moving Average
WHAT. Each minibatch hands us a fresh, noisy slope . We want a smooth summary that trusts recent data but does not forget instantly. That tool is the exponential moving average (EMA):
WHY this tool and not a plain average? A plain average over all past gradients weights the ancient first step as much as the latest — but early gradients are stale, the landscape has moved on. The EMA is a leaky bucket: each step it keeps fraction of the old contents and pours in fraction of the new. Old values fade geometrically (), so recent slopes dominate automatically. See Exponential Moving Average.
PICTURE. The leaky bucket: old water partly drains, a splash of the new gradient is added, the level (=) is a smoothed trace of the noisy input.

We will use this same EMA machine twice — once on the gradient, once on its square.
Step 3 — First moment: smooth the direction (momentum)
WHAT. Feed the raw gradient into the EMA. Call the result , the first moment:
With the bucket keeps of its old content, so is a heavily smoothed version of the slope — essentially an estimate of the average gradient .
WHY. Noisy minibatch gradients zig-zag. Averaging cancels the random wobble and keeps only the consistent pull — the true downhill direction. This is exactly the idea behind Momentum and Nesterov Acceleration: build velocity along persistent directions.
PICTURE. A jittery cloud of raw arrows ; the smooth arrow threads through their average, wobble removed.

Step 4 — Second moment: smooth the magnitude
WHAT. Run the same EMA on the squared gradient (squaring is elementwise — each coordinate separately). Call it , the second moment:
Squaring throws away the sign and keeps only how big the slope is. So estimates — the typical magnitude/variance of the gradient in that direction. makes this an even slower, longer-memory average than .
WHY. A direction with large is steep or noisy — we want small steps there. A direction with tiny is flat and reliable — we can stride there. is the per-direction "danger meter." This is the RMSProp idea.
PICTURE. Two coordinates: one with big bouncing squared-gradients (high , red danger meter full), one with small steady ones (low , meter low).

Step 5 — The zero-start bias, and why we must correct it
WHAT. Both buckets start empty: . So on step 1 the bucket is mostly still empty water — the summary reads too small. Unrolling the recursion for a roughly constant gradient with mean :
The factor is the fraction of the bucket that has actually filled by step . At it is only — we read 10% of the truth. We repair this by dividing it back out: The hat () means "bias-corrected." Now : honest.
WHY. Without this, early is tiny, so explodes and the first steps are dangerously huge — exactly when training is most fragile. See Bias-Variance in Gradient Estimation.
PICTURE. The correction factor rising from small toward ; the raw curve crawls up, the corrected snaps to the true value from step one.

As , , the factor , and the correction quietly switches itself off — it only matters early.
Step 6 — The update: a signal-to-noise ratio
WHAT. Combine everything. Move against the smoothed direction , but divide by the smoothed magnitude :
We take (not ) because has units of gradient-squared; its square root has the same units as , so the ratio is a clean dimensionless number. keeps the denominator from ever being .
WHY. Read as signal ÷ noise:
- Consistent direction: , ratio → a full, confident stride of size .
- Noisy direction: , ratio → a timid step. Adam slows down where it is unsure.
And it is scale-invariant: multiply every gradient by and both and scale by — the ratio is unchanged. This is what SGD could never do.
PICTURE. A dial: numerator = how aligned the recent gradients are, denominator = how large/noisy they are; the needle lands near for a clean signal, near for pure noise.

Step 7 — Edge cases: watch every corner
WHAT. Three degenerate situations, and what the formula does in each.
- First step (). , , so the ratio . The step magnitude is exactly , no matter how big or small is — a normalized "compass" step.
- Steady constant gradient (). , , ratio : again magnitude . Adam erases gradient scale in steady state.
- Vanishing gradient (). Then and the guard takes over: step , capped — the update does not blow up, it fades.
WHY show all three. A reader must never meet a case you skipped. Whether the gradient is huge, tiny, positive, negative, or zero, the step size stays near (or safely shrinks), because the denominator tracks the numerator.
PICTURE. Three mini-panels — first step, steady state, near-zero gradient — each showing the resulting step length hugging (except the guarded fade at zero).

Step 8 — AdamW: pull weight decay out of the divide
WHAT. Weight decay shrinks weights toward zero to fight overfitting. The old trick added into the gradient — but then it gets divided by like everything else, so heavily-gradiented weights decay less. Backwards. AdamW keeps decay outside the adaptive fraction:
WHY. Now every weight multiplies by the same factor each step — clean, gradient-independent regularization.
PICTURE. Left: Adam+L2, decay arrows scaled unevenly by (small-gradient weight decays far more). Right: AdamW, all decay arrows the same length.

The one-picture summary
Two EMAs — one of the gradient (, direction) and one of its square (, magnitude) — are bias-corrected, then the update takes the ratio , a scale-free signal-to-noise stride, and AdamW subtracts a separate uniform decay. That is the whole optimizer in one flow.

Recall Feynman retelling — the whole walkthrough in plain words
You are hiking downhill in fog. You cannot trust one footstep, so you keep two notebooks. Notebook one (==) writes down a smoothed "which way have I been heading" — that cancels the random zig-zag. Notebook two (==) writes down "how steep and slippery has each direction been" by averaging the squared slopes. Because both notebooks started blank, their early entries read too low, so you scale them up by a fading factor ( — the bias correction) that only matters in the first pages. To actually step, you take direction ÷ steepness: on a consistent gentle slope that ratio is about so you stride a full ; on a noisy steep one it is near so you inch forward. This makes your step size roughly everywhere, ignoring how big the raw slope is. Finally, AdamW adds one honest rule: shrink every weight by the same small amount each step, kept outside the ratio so heavy-gradient weights are not spared.
Recall Quick self-test
Steady-state Adam step on a constant gradient ? ::: — magnitude , scale erased. Why square root over and not itself? ::: to match units with so the ratio is dimensionless and scale-invariant. Where does AdamW put weight decay? ::: outside the divide, as a uniform subtraction.
Related: Stochastic Gradient Descent · Learning Rate Schedules · 3.2.05 Adam and AdamW optimizers (Hinglish)