Gradient descent looks simple on paper: compute a gradient and move in the opposite direction. But on a loss surface that is steep in one direction and flat in another, that rule can produce an unhelpful zigzag. Momentum and adaptive learning rates address different parts of this problem; Adam combines them.
Start with a loss that is difficult to navigate
Consider the convex quadratic
Its minimum is at . The gradient is eighteen times more sensitive to than to at equal coordinates. A single learning rate must be small enough not to overshoot in the steep direction, even when we would prefer much larger steps in the shallow direction.
Ordinary gradient descent updates parameters by
For this quadratic, the update is . Its magnitude shrinks only when , so stable convergence in that coordinate requires . That is already a concrete reason why the same learning rate may behave differently across directions.
Momentum remembers the direction of travel
Momentum replaces the raw gradient with a moving average (here, using the unnormalized convention):
Consistent gradients accumulate, while rapidly alternating gradients can partially cancel. In a narrow valley, that can damp oscillations and accelerate progress along the valley. The learning rate and momentum coefficient still require tuning; momentum is not guaranteed to improve every trajectory.
RMSprop adapts to gradient magnitude
RMSprop tracks a moving average of squared gradients, independently for each coordinate:
The square and square root are elementwise. Coordinates with persistently large gradients receive smaller effective steps. This is not the same as momentum: RMSprop remembers scale, while momentum remembers direction.
Adam combines both ideas
Adam maintains first and second moment estimates:
Because both accumulators start at zero, their early estimates are biased toward zero. Adam corrects this initialization effect:
In the demonstration below, and . RMSprop and momentum use their own fixed decay factors. This isolates the qualitative differences between the update rules.
Optimizer trajectories on the same loss
All methods start at (2.5, 1.1). The objective is f(x,y) = ½(x² + 18y²). Learning rates are deliberately shared to expose different step-size behavior, not to optimize each method.
A large shared learning rate may cause some methods to diverge. Momentum uses β=0.9; RMSprop uses β=0.9; Adam uses β₁=0.9, β₂=0.999 and bias correction. This is a deterministic full-gradient illustration, not a noisy minibatch benchmark.
Implementing Adam without an optimizer library
The important implementation detail is that counts parameter updates, not epochs. Bias correction must use the same update index as the moment estimates.
import numpy as np
m = np.zeros_like(theta)v = np.zeros_like(theta)beta1, beta2 = 0.9, 0.999lr, eps = 0.01, 1e-8
for t in range(1, num_steps + 1): grad = gradient(theta) m = beta1 * m + (1 - beta1) * grad v = beta2 * v + (1 - beta2) * grad**2 m_hat = m / (1 - beta1**t) v_hat = v / (1 - beta2**t) theta -= lr * m_hat / (np.sqrt(v_hat) + eps)What the picture does not establish
A single deterministic quadratic cannot establish which optimizer is best for a neural network. Neural-network losses are nonconvex, minibatch gradients are noisy, and generalization matters beyond training loss. Adaptive optimizers can converge quickly while still behaving differently from SGD with momentum on held-out data. Weight decay also matters: AdamW decouples weight decay from Adam’s gradient update.
The useful mental model is narrower: momentum smooths directions; RMSprop rescales coordinates; Adam combines those mechanisms and corrects their initialization bias.
Further reading
- Kingma and Ba, Adam: A Method for Stochastic Optimization.
- Loshchilov and Hutter, Decoupled Weight Decay Regularization.