Home / Deep Learning

Optimizers in Neural Networks

By Updated

Visualize how different optimization algorithms navigate the "Loss Landscape" to find the global minimum. Run multiple in parallel to observe realistic relative speeds!

0.1x

Optimization State

Target Minimum is at (0, 0)

Overview

Visualize how different optimization algorithms navigate the "Loss Landscape" to find the global minimum.

In this guide
  1. What each one adds
  2. Why plain SGD zig-zags
  3. Momentum, precisely
  4. What Adam really stores
  5. Which optimiser to reach for
  6. From one global step size to per-param steps
  7. What Adam really computes
  8. Try this above
  9. What often goes wrong
  10. In one line
  11. Choosing one, and the schedule that goes with it
  12. Memory, and the newer options
  13. Four optimisers on one badly-scaled bowl
  14. Questions people ask
  15. Recap in one screen

Optimizers in Neural Networks: A Practical Guide

Every optimiser here computes the same gradient. They differ entirely in how much they remember about the gradients that came before.

What each one adds

  • SGD — θ ← θ − ηg. No memory at all. Each step depends just on the current gradient.
  • Momentum — v ← βv + g, then θ ← θ − ηv with β around 0.9. Builds up velocity in consistent ways and cancels out oscillation.
  • RMSprop — divides each param's step by a running root-mean-square of its recent gradients. So each param gets a step size suited to its own scale.
  • Adam — momentum and RMSprop together, plus a correction for the fact that both averages start at zero.

The progression from SGD to Adam is a progression in memory: SGD remembers nothing, momentum remembers an exponential average of past gradients, RMSprop remembers an exponential average of past squared gradients. And Adam remembers both. Each addition solves a set failure mode — oscillation in ravines, slow progress on plateaus. And uneven param scales — at the cost of two extra state vectors per param. Adam with its default hyperparameters (lr=0.001, beta1=0.9, beta2=0.999) is the standard starting point for nearly all deep learning tasks. AdamW (Adam with decoupled weight decay) is the variant used in transformer training. For convex problems or when the dataset is very large, plain SGD with momentum and a well-tuned learning rate schedule can match or beat Adam. It is why it stays standard for training large pic classifiers. This page runs all four optimisers on the same loss surface, plots their trajectories. And shows the per-step state (velocity, squared-gradient average) that explains each path.

Why plain SGD zig-zags

Picture a long narrow valley where the gradient across the valley is 10 and along it is 0.1. With η = 0.01, SGD steps 0.1 across and 0.001 along — a hundred to one. It bounces off the steep walls while creeping toward the actual min.

Momentum fixes this by accumulation: the across-valley parts alternate sign and cancel, while the along-valley parts all point the same way and add up. RMSprop fixes it differently, by normalising both ways to roughly equal step sizes.

Momentum, precisely

Plain SGD steps in the way of the current gradient and forgets all before it. Momentum keeps a running average of past gradients and steps along that instead:

v ← βv + (1 − β)∇L    w ← w − ηv

With the usual β = 0.9 the velocity is an average over roughly the last ten gradients. Consistent ways accumulate and speed up. Ways that flip sign each step cancel out. That is just the fix for a narrow valley. There the gradient across the valley alternates while the gradient along it stays constant — the oscillation cancels and the useful way survives.

What Adam really stores

Adam keeps two running averages per param: the mean of the gradients (momentum, as above) and the mean of their squares. It divides the step by the square root of that second average:

w ← w − η · m̂. / (√v̂ + ε)

The effect is a per-param learning rate. A param that has always seen large gradients gets a less effective step. One that has seen small or infrequent gradients gets a more one. That is what makes Adam so effective on sparse data. There rare features would otherwise learn thousands of times more slowly than common ones.

The cost is memory: two extra vals per param. So optimiser state is three times the size of the net. On a large net that is a real constraint. And it is why plain SGD with momentum is still used where memory is tight.

Which optimiser to reach for

  • AdamW — the default for almost all now. And the correct choice whenever weight decay is used, since plain Adam’s L2 term gets rescaled by the adaptive step and stops behaving like decay.
  • SGD with momentum — still the best final accuracy on large vision nets, given a good learning-rate schedule. It needs more tuning and generalises slightly better.
  • Adam — fine when there is no weight decay. Otherwise prefer AdamW.
  • Adagrad / RMSprop — largely superseded by Adam, which mixes their ideas with momentum.

A real note: the optimiser is not a substitute for the learning rate. Adam’s default of 0.001 is a reasonable starting point rather than a universal answer. And a badly chosen rate will defeat any optimiser on this list.

From one global step size to per-param steps

Plain gradient descent applies one learning rate to each param. That is a poor fit for a real network. There some params sit on steep slopes and others on nearly flat ones.

Optimisers are the successive fixes for that, and they build on each other:

OptimiserIdea added
SGDStep against the gradient
SGD + momentumAccumulate a velocity across steps
NesterovLook ahead before stepping
AdaGradDivide by accumulated squared gradients — per-parameter rates
RMSPropSame, but with a decaying average so it does not stall
AdamRMSProp plus momentum, with bias correction
AdamWAdam with weight decay applied correctly

Momentum is the first and biggest win. Averaging recent gradients builds speed in consistent ways and cancels oscillation across a narrow valley.

AdaGrad added per-param scaling, but its accumulator just grows. So the effective learning rate decays to zero and training stalls. RMSProp replaced the running sum with an exponential moving average, which fixed it.

Adam mixes the two: a moving average of gradients (momentum) and of squared gradients (scaling), each bias-corrected for the first few steps when the averages start at zero.

What Adam really computes

m ← β₁m + (1−β₁)g    v ← β₂v + (1−β₂)g²

w ← w − η · m̂. / (√v̂ + ε)

m is the smoothed gradient, v the smoothed squared gradient. Dividing by √v means a param with always large gradients takes less steps and one with tiny gradients takes more ones — the per-param adaptation.

The defaults are unusually reliable: β₁ = 0.9, β₂ = 0.999, ε = 1e-8. Those are almost never worth changing. β₂ = 0.999 corresponds to a memory of roughly a thousand steps. It is why Adam is stable but slow to react to a genuine change in the loss landscape.

AdamW is the version to use. Plain Adam applies weight decay by adding it to the gradient. It then gets divided by √v — so params with small gradients are penalised more. It was never the intent. AdamW applies the decay right to the weights, decoupled from the adaptive scaling. The gap is measurable. And it is why each transformer recipe names AdamW.

Try this above

  1. Select All (Check) and run. Watch SGD (red) oscillate while Adam (green) takes a far more direct route.
  2. Raise Learning Rate gradually. There is a value where SGD diverges outright but the adaptive ways still converge.
  3. Now drop the learning rate very low and run again. SGD's path turns clean — it was never the algorithm's fault, it was the step size.
  4. Use Sim Speed to slow it right down and watch Momentum overshoot the min and come back.

What often goes wrong

Carrying a learning rate between optimisers. A good SGD learning rate is often 0.01–0.1. Adam's usual default is 0.001. Swapping optimiser while keeping η is one of the most common reasons a switch to Adam appears to make things worse.Assuming Adam always wins. It often converges fastest. But well-tuned SGD with momentum often generalises better on vision tasks. And a good deal of published work still uses it for just that reason. Fast to a worse min is not a win.

In one line

Same downhill way, other memory — and memory is what stops you bouncing off the walls.

Choosing one, and the schedule that goes with it

SituationOptimiserStarting learning rate
Transformers, language modelsAdamW1e-4 to 3e-4, with warm-up
Vision, from scratchSGD + momentum 0.9, or AdamW0.1 (SGD) / 1e-3 (AdamW)
Fine-tuning a pretrained modelAdamW1e-5 to 1e-4
Tabular data, small networksAdamW1e-3
Sparse features, embeddingsAdam or Adagrad1e-3

The honest summary of a long-running debate: AdamW converges faster and needs less tuning. Well-tuned SGD with momentum sometimes generalises slightly better on vision tasks. If you have limited time, use AdamW.

The schedule matters as much as the optimiser. Two parts are standard:

Warm-up — ramp the learning rate from near zero over the first few hundred or few thousand steps. Adam's variance estimate is unreliable early on. And a large first step can damage the initialisation. Key for transformers.

Cosine decay — smoothly reduce the rate to near zero over training. Reliably beats a constant rate, and beats step decay in most comparisons.

import torch

opt = torch.optim.AdamW(model.parameters(), lr=3e-4, weight_decay=0.01)
sched = torch.optim.lr_scheduler.OneCycleLR(
    opt, max_lr=3e-4, total_steps=epochs * len(loader), pct_start=0.1)

for batch in loader:
    loss = criterion(model(batch.x), batch.y)
    opt.zero_grad()
    loss.backward()
    torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
    opt.step()
    sched.step()          # per batch for OneCycle, not per epoch

Memory, and the newer options

Adam stores two extra vals per param. So its optimiser state is twice the net size. For a 7-billion-param net in 32-bit that is 56GB of optimiser state alone. It is why large-net training uses 8-bit optimisers, sharding across devices (ZeRO). Or memory-fast variants such as Adafactor and Lion.

Lion keeps just momentum and uses the sign of the update, halving the state. Sophia and other second-order-flavoured ways use curvature estimates. These matter at scale. For ordinary work AdamW stays the right default.

Four optimisers on one badly-scaled bowl

A surface 1000x steeper in one way than the other -- the normal case in a real network. Plain SGD cannot solve it. And watching why explains each optimiser invented since.

example_01.pyNumPy
Output

Building on the same setup, the next block shows the left cases.

example_02.pyNumPy
Output

The next block covers the left steps.

example_03.pyNumPy
Output

The next block continues with the left demonstrations.

example_04.pyNumPy
Output

Building on the same setup, the next block shows the left cases.

example_05.pyNumPy
Output

Questions people ask

Should I ever use plain SGD? With momentum, yes — it is still strong on vision with a good schedule. Without momentum, in effect never.

Do I need to tune β₁ and β₂? Almost never. β₂ = 0.95 is sometimes used for very large nets where the default is too slow to adapt.

Why does my loss spike after a while with Adam? Often the learning rate is too high for the later, sharper part of the landscape. A decaying schedule fixes it.

What weight decay should I use? 0.01 to 0.1 with AdamW is typical. Note that it applies to weights. And biases and normalisation params are often excluded.

Is Adam bad for generalisation? The old claim is overstated. AdamW closed most of the gap. And with a proper schedule the gap is small.

Can I change optimiser mid-training? You can. And the state is lost, so expect a temporary disruption. Sometimes done deliberately: Adam early, SGD late.

Recap in one screen

  • Momentum accumulates a velocity. Adaptive ways give each param its own effective step size.
  • Adam mixes both with bias correction. AdamW fixes how weight decay interacts with the scaling.
  • Defaults (β₁ = 0.9, β₂ = 0.999) are reliable and rarely need changing.
  • Warm-up plus cosine decay is the modern schedule. And matters as much as the optimiser choice.
  • Adam's state doubles memory use. It is why large-scale training uses sharded or 8-bit variants.

Recall check

0 of 3

Say the answer out loud before you reveal it — recalling it is what makes it stick, and rereading it is not.

  1. Without scrolling back — what is the one-line takeaway from this module?

  2. What does this module say about “What each one adds”?

  3. What does this module say about “Why plain SGD zig-zags”?

Cheat sheet

Optimizers in Neural Networks

Run several optimizers in parallel on one loss surface and see how momentum and adaptive learning rates change the route.

DEEP LEARNING · vizlearn.in/deep_learning/optimizers_in_neural_networks.html

Further reading

About the author

Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.