Purpose

This note covers the optimizers that show up in real training loops and the small amount of theory that explains their behavior: gradient descent and conditioning, stochastic gradients, momentum and Nesterov, Adam and decoupled weight decay, and schedules. Throughout, claims are tagged as theorems (proved for restricted function classes, usually convex quadratics) or heuristics (empirical, justified by what trains well). The gradients being descended are derived in Matrix Calculus for Machine Learning; convex background is in Convexity, Lagrangians, and KKT.

Gradient descent and conditioning

Gradient descent iterates . On a strongly convex quadratic with eigenvalues , the error contracts linearly, and with the optimal fixed step the rate is governed by the condition number :

This is a theorem (standard; see Nesterov’s Introductory Lectures or B&V §9.3). Its content: a well-conditioned problem ( near 1) converges in a few steps, and an ill-conditioned one crawls, because the step size is hostage to the steepest direction while progress is needed along the flattest. Deep Learning ch. 8 treats ill-conditioning as the first of the fundamental difficulties in neural net training. The other headline difficulty is saddle points: for high-dimensional nonconvex problems, critical points are overwhelmingly saddles rather than bad local minima (Dauphin et al. 2014, an empirical-plus-random-matrix argument, not a theorem about neural nets).

Stochastic gradients

SGD replaces with an unbiased minibatch estimate. The classical convergence guarantee (Robbins and Monro, 1951) requires the step sizes to satisfy

enough total step to get anywhere, but decaying fast enough that gradient noise stops moving you (DL ch. 8.3.1). In practice nobody anneals to zero; constant-then-decay schedules are heuristics tuned by validation loss.

Batch size trades gradient variance against per-step cost. Variance of the minibatch gradient falls as , so returns diminish: doubling the batch halves the variance but doubles the compute, a sublinear win in wall-clock terms once parallel hardware saturates (DL ch. 8.1.3). The claim that small-batch noise acts as a regularizer and large batches can generalize worse is empirical, not settled theory.

Momentum and Nesterov

Classical momentum (Polyak) accumulates a velocity:

Along directions where gradients agree step after step, velocity builds toward a terminal speed , a amplification, 10x at ; along oscillating directions, contributions cancel. That is exactly the medicine for ill-conditioning. On quadratics this is a theorem: momentum improves the iteration count from to with the optimal (Sutskever et al. 2013, citing Polyak 1964).

Nesterov’s variant evaluates the gradient at the look-ahead point:

The correction matters most when velocity is about to overshoot: the look-ahead gradient sees the far wall one step early. Sutskever et al. showed the two differ only in where the gradient is taken, that NAG is more tolerant of large , and that momentum plus careful initialization lets plain first-order methods train deep networks previously thought to need second-order machinery. The mize notes give the standard reparameterization that implements NAG as a small correction term on classical momentum, which is how frameworks implement nesterov=True.

Adam and weight decay

Adam keeps exponential moving averages of the gradient and its square, corrects their initialization bias, and scales each coordinate’s step by its own noise level:

Defaults from the paper: , , , . The per-coordinate scaling makes updates invariant to diagonal rescaling of the gradient and bounds the effective step near , which is why Adam tolerates sloppy learning-rate choices that would blow up SGD. The bias correction exists because drags early averages toward zero; dividing by undoes it, and it matters precisely when is close to 1.

Weight decay in Adam has a subtlety worth knowing. Adding to the loss (L2 regularization) feeds through the adaptive machinery, so parameters with large historical gradients get less decay, coupling regularization strength to gradient history. Loshchilov and Hutter decouple it, applying directly in the update, outside the scaling. That is AdamW. Their evidence is empirical, restoring Adam’s generalization to SGD-with-momentum levels on image classification, and AdamW is now the default in most transformer training. In PyTorch these are literally torch.optim.Adam(weight_decay=...) (coupled L2) versus torch.optim.AdamW (decoupled); the two optimize different effective objectives.

Learning-rate schedules (step decay, cosine, warmup) are heuristics layered on top. Warmup interacts specifically with Adam: early in training is estimated from few samples, so the first steps can be badly scaled, and ramping up over the first few thousand steps is the standard mitigation.

What is proved vs. what is practiced

On strongly convex quadratics with condition number :

MethodIterations to convergeStatus
Gradient descent, optimal step, factor per steptheorem
Heavy-ball momentum, optimal theorem (Polyak 1964)
SGD, Robbins-Monro stepsconverges in probabilitytheorem
Adam / AdamW, constant trains well with defaultsheuristic

The theorems live on quadratics; their transfer to deep nets is empirical. But the vs. gap is real and large, the measured comparison below shows six orders of magnitude at , and it is the reason momentum in some form is in every practical optimizer.

A measured comparison

The claims about conditioning and momentum are checkable on the quadratic where the theory is exact. , so :

import numpy as np
 
H = np.diag([1.0, 100.0])
def grad(th): return H @ th
 
def run(update, steps=200):
    th, state = np.array([1.0, 1.0]), None
    hist = []
    for t in range(steps):
        th, state = update(th, state, t)
        hist.append(np.sqrt(th @ H @ th))
    return hist
 
a = 2 / (1 + 100)                       # optimal GD step for this spectrum
gd   = run(lambda th, s, t: (th - a * grad(th), None))
 
mu = (np.sqrt(100) - 1) / (np.sqrt(100) + 1)   # optimal momentum
am = (2 / (1 + np.sqrt(1/100)))**2 / 100       # matching step size
def mom(th, v, t):
    v = mu * (v if v is not None else 0) - am * grad(th)
    return th + v, v
heavy = run(mom)
 
print(f"GD after 200 steps:       {gd[-1]:.3e}")     # 1.840e-01
print(f"momentum after 200 steps: {heavy[-1]:.3e}")  # 5.583e-08

Measured on this machine (NumPy 2.x, the script above verbatim): plain GD with its optimal step ends at error norm after 200 iterations. The initial norm is , so the contraction factor is , matching the theory’s to three digits. Heavy-ball momentum with the optimal reaches , better by more than six orders of magnitude. The versus gap is not an asymptotic nicety; at it is the difference between converged and not.

Sources