Neural network formulas: a cheat sheet · The next level

SGD, Momentum and RMSProp: how weights go down the loss surface

The three steps Adam is built from. We take apart stochastic gradient descent, heavy-ball momentum and dividing the step by the root-mean-square gradient: why the step is limited by ηL < 2, where mini-batch noise comes from, how momentum speeds up descent along a ravine and why every weight needs its own step scale.

Javharbek Abdulatipov · 35 min read
$$\theta_t=\theta_{t-1}-\eta\,g_t$$

Why we need it

Training a neural network means searching for the minimum of a loss function $L(\theta)$ over millions or billions of weights $\theta$. There is no closed-form formula for the minimum: the loss depends on the weights in too complicated a way. All we can do is walk towards the minimum step by step, and the only guide at every step is the gradient $\nabla L$, the vector pointing in the direction of the fastest growth of the loss. We step the opposite way.

This page is about three steps of one method:

  • SGD (stochastic gradient descent) — a step against the gradient computed on a small random batch of examples, a mini-batch;
  • Momentum (the heavy-ball method) — a step against the accumulated sum of past gradients: inertia damps zigzags and speeds up descent along gentle directions;
  • RMSProp — a step divided by the root-mean-square size of recent gradients: every weight gets its own step scale.

Combine the second and third steps, add bias correction, and you get Adam. And SGD with momentum still trains many convolutional networks for images, often generalizing better on them than adaptive methods.

The essentials in a minute

$\theta_t=\theta_{t-1}-\eta g_t$. The step is stable only if $\eta L<2$, where $L$ is the largest curvature of the loss. An elongated valley (a large condition number $\kappa$) makes SGD crawl; momentum $u_t=\beta u_{t-1}+g_t$ with well-chosen $\eta$ and $\beta$ cuts the journey from about $\kappa$ to about $\sqrt\kappa$ steps; RMSProp divides the step by $\sqrt{v_t}$ and evens out the scales of different weights.

Intuition: a step downhill

Imagine walking down a hill in thick fog. All you can see is the slope under your feet: which way and how steeply it goes down. A sensible strategy is to step in the direction of the steepest descent, look around and repeat. The length of the step is set by the learning rate $\eta$.

Short steps are safe but slow. A step that is too long jumps over the bottom of the pit onto the opposite slope — and if it lands higher there, the next step throws it even further. See how this looks on the simplest loss $f(\theta)=L\theta^2/2$: its gradient is $f'(\theta)=L\theta$ and its curvature (second derivative) is $L$.

Figure 1. Gradient descent on a parabola. Top: the steps along the curve (you can drag the starting point $\theta_0$); bottom: the distance to the minimum $|\theta_t|$ on a log scale. With $L=2$ and $\eta=0.3$ every step multiplies $\theta$ by $1-\eta L=0.4$, and from $\theta_0=2$ it takes 6 steps to reach $|\theta|<0.01$. Increase $\eta$: at $0.5$ the minimum is reached in one step, at $0.6$ the point jumps over the minimum, and for $\eta>1$ descent diverges.
What to notice

One number decides everything: $\eta L$. For $\eta L<1$ descent is monotone, for $1<\eta L<2$ the point jumps over the minimum but still approaches it, for $\eta L>2$ it flies off. The step $\eta=1/L$ hits the minimum at once — but only while the curvature is the same in every direction.

The formula, bone by bone

$$\theta_t=\theta_{t-1}-\eta\,g_t,\qquad g_t=\frac1B\sum_{i\in B_t}\nabla_\theta\,\ell(x_i,y_i;\,\theta_{t-1})$$
$\theta_{t-1}$
the current weights, the vector of all model parameters;
$g_t$
the stochastic gradient: the mean of the loss gradients $\ell$ over a mini-batch $B_t$ of $B$ random examples;
$\eta$
the learning rate, a positive number, usually between $10^{-4}$ and $10^{-1}$;
$-\eta\,g_t$
the step: against the gradient, of length $\eta\|g_t\|$ — the steeper the slope, the longer the step.

Why it works. Expand the loss in a Taylor series around the current point: $L(\theta-\eta g)\approx L(\theta)-\eta\,\|g\|^2$. While the step is small the loss drops by about $\eta\|g\|^2$, and this is the fastest decrease among all steps of the same length: the dot product $\langle\nabla L,\,d\rangle$ for a fixed length $\|d\|$ is smallest when $d$ points against the gradient.

A worked example

$f(\theta)=\theta^2$, $\theta_0=3$, $\eta=0.1$. The gradient is $g_1=2\cdot3=6$, the step is $-0.1\cdot6=-0.6$, the new value is $\theta_1=2.4$, and the loss drops from $9$ to $5.76$. Every further step again multiplies $\theta$ by $1-2\eta=0.8$.

How large can the step be: the descent lemma

Let the gradient of $f$ be Lipschitz with constant $L$: $\|\nabla f(a)-\nabla f(b)\|\le L\|a-b\|$ (for a twice-differentiable $f$ this means the eigenvalues of the Hessian are at most $L$ in absolute value). Then $f$ lies below the parabola touching it at the current point, and for the step $\theta-\eta g$ with $g=\nabla f(\theta)$:

$$f(\theta-\eta g)\le f(\theta)-\eta\Bigl(1-\frac{L\eta}{2}\Bigr)\|g\|^2$$

The factor $1-L\eta/2$ is positive for $\eta<2/L$ — exactly the stability boundary from Figure 1. The guaranteed decrease is largest at $\eta=1/L$: then $f$ drops by at least $\|g\|^2/(2L)$.

For a quadratic $f=\tfrac12\theta^\top H\theta$ the step is a linear map $\theta_t=(I-\eta H)\,\theta_{t-1}$. In the eigenbasis of $H$ every coordinate is multiplied by $1-\eta\lambda_i$, and descent converges if and only if $|1-\eta\lambda_i|<1$ for all $i$, that is $0<\eta<2/\lambda_{\max}$ (for a positive definite $H$).

The condition number: why descent can be slow

If the curvatures differ between directions, the step has to adapt to the steepest one: $\eta<2/\lambda_{\max}$. Then along the gentlest direction a coordinate shrinks per step by only the fraction $\eta\lambda_{\min}<2/\kappa$, where $\kappa=\lambda_{\max}/\lambda_{\min}$ is the condition number. Even with the best constant step $\eta=2/(\lambda_{\max}+\lambda_{\min})$ the error shrinks per step only by the factor $(\kappa-1)/(\kappa+1)$:

$$\|\theta_t-\theta^*\|\le\Bigl(\frac{\kappa-1}{\kappa+1}\Bigr)^{t}\,\|\theta_0-\theta^*\|$$

At $\kappa=100$ the factor is $0.980$, and reducing the error a thousandfold takes about 345 steps. A rough rule: SGD spends on the order of $\kappa$ steps per digit of accuracy.

MethodStepStateHyperparameters
SGD$\theta_t=\theta_{t-1}-\eta g_t$none$\eta$
Momentum$u_t=\beta u_{t-1}+g_t$,
$\theta_t=\theta_{t-1}-\eta u_t$
$u$: one number per weight$\eta$, $\beta\approx0.9$
RMSProp$v_t=\beta v_{t-1}+(1-\beta)g_t^2$,
$\theta_t=\theta_{t-1}-\eta\,\dfrac{g_t}{\sqrt{v_t}+\epsilon}$
$v$: one number per weight$\eta$, $\beta=0.9$–$0.99$, $\epsilon$

Stochasticity: mini-batches and noise

The full gradient is the mean over all $N$ examples of the training set. With millions of examples one such step would cost a pass over all the data. SGD takes a random mini-batch of $B$ examples. Its gradient is an unbiased estimate of the full one: it equals $\nabla L$ on average, but every time it deviates by random noise.

$$\mathbb E\,[g_t]=\nabla L(\theta),\qquad \operatorname{Cov}[g_t]=\frac{\Sigma}{B}\cdot\frac{N-B}{N-1}$$
$\Sigma$
the covariance of per-example gradients at the current point (normalized by $N$);
$\frac{N-B}{N-1}$
the correction for sampling without replacement: at $B=N$ the noise vanishes.

The noise variance falls as $1/B$ while the cost of a step grows as $B$. So within one epoch (one pass over the data) small batches make many imprecise steps and large batches few precise ones. The figure shows linear regression $y\approx wx+b$ on 200 points with the loss $L=\frac1{2N}\sum(wx_i+b-y_i)^2$: a quadratic “bowl” over the plane of the weights $(w,\,b)$.

Figure 2. Left: the SGD path over the loss contours; the orange points show where the next step would land for 40 different random batches, the arrow is the full-gradient step. Right: the excess loss over the minimum $L-L^*$ by epoch. After 8 epochs with $\eta=0.05$, starting from $5.84$: batch 1 reaches $1.4\cdot10^{-3}$, batch 10 reaches $0.044$, batch 50 reaches $1.06$, and the full gradient (only 8 steps) reaches $2.0$. Press “Play” and compare the clouds: for $B=1$ it stays wide even at the minimum.
Noise is not only a nuisance

At the minimum the full gradient is zero, but the stochastic one is not. With a constant $\eta$, SGD does not stop but jitters in a cloud whose size grows like $\sqrt\eta$; that is why the rate is lowered towards the end of training. On the other hand, the same noise helps escape saddle points and narrow minima; there is evidence that it biases training towards flatter minima that generalize better.

The linear scaling rule for the batch size

If the batch grows $k$ times, the noise variance drops $k$ times, but there are $k$ times fewer steps per epoch. Goyal et al. (2017) proposed to raise $\eta$ $k$ times as well: that is how ResNet-50 was trained on ImageNet with a batch of 8192 in one hour without losing accuracy. The rule holds up to some “critical” batch size and requires warmup — a gradual increase of $\eta$ over the first epochs.

Momentum: the inertia of a heavy ball

Gradient descent is a massless point: at every moment it moves exactly where the slope points. Boris Polyak (1964) proposed to give it mass. A heavy ball rolls, builds up speed and does not react to every bump. In the formula the velocity is the vector $u$:

$$u_t=\beta\,u_{t-1}+g_t,\qquad \theta_t=\theta_{t-1}-\eta\,u_t$$
$u_t$
the accumulated direction (the momentum buffer), $u_0=0$;
$\beta$
the momentum coefficient, $0\le\beta<1$, usually $0.9$; at $\beta=0$ this is plain SGD.

Unroll the recursion: $u_t=g_t+\beta g_{t-1}+\beta^2 g_{t-2}+\dots$ — a weighted sum of all past gradients with exponentially decaying weights. If gradients keep pointing the same way from step to step, they add up and the step grows to $\eta/(1-\beta)$, ten times larger at $\beta=0.9$. If the sign flips (a zigzag across a ravine), the terms cancel each other.

Figure 3. Left: the weight with which a gradient $k$ steps old enters $u_t$; the bright bars are the most recent gradients that together carry at least half of the total weight. Right: the response of $u_t$ to a constant gradient $g=1$: it grows towards $1/(1-\beta)=10$ and reaches $90\%$ of the limit by step 22. At $\beta=0.9$ half of the weight falls on the last 7 gradients, at $\beta=0.99$ on the last 69, with a memory window of 100 steps.
Two ways to write the same momentum

PyTorch writes $u_t=\beta u_{t-1}+g_t$, as here. The exponential moving average (EMA) $m_t=\beta m_{t-1}+(1-\beta)g_t$ is also common: it differs by the constant factor $1-\beta$, which moves into $\eta$. The EMA is exactly what sits in the numerator of Adam. Switch the form in the figure: the EMA starts at $0.1$ instead of 1 and only gradually reaches the true value — this underestimate in the first steps is the reason for bias correction in Adam.

Why momentum accelerates: theory on a quadratic

Take one direction with curvature $L$ and write $h=\eta L$. Substitute $g_t=L\theta_{t-1}$ and eliminate $u$ (from the second formula $\eta u_{t-1}=\theta_{t-2}-\theta_{t-1}$). We get a second-order linear recurrence:

$$\theta_t=(1+\beta-h)\,\theta_{t-1}-\beta\,\theta_{t-2}$$

Its behaviour is set by the roots of the characteristic equation $\lambda^2-(1+\beta-h)\lambda+\beta=0$. The convergence rate is the largest root modulus $\rho$: the error decays roughly like $\rho^t$.

Figure 4. Left: a map of the rate $\rho$ over $\eta L$ (log scale) and $\beta$: blue means fast convergence, red means divergence, the solid line is the boundary $\rho=1$, the dashed lines mark critical damping. Drag the blue point. Right: $\theta_t$ for SGD with the same $\eta$ and with momentum. At $\eta L=0.04$ SGD needs 170 steps to reach $|\theta|<10^{-3}$ ($\rho=0.96$), momentum with $\beta=0.9$ needs 130 steps with oscillations, Nesterov with the same $\beta$ needs 87, and critical damping $\beta=(1-\sqrt{0.04})^2=0.64$ gives 41 steps ($\rho=0.8$).
Derivation: the stability region and the optimal momentum

The roots are complex when $(1+\beta-h)^2<4\beta$, i.e. for $(1-\sqrt\beta)^2<h<(1+\sqrt\beta)^2$. The product of the roots is $\beta$, so $|\lambda_1|=|\lambda_2|=\sqrt\beta$: $\theta_t$ oscillates and decays by the factor $\sqrt\beta$ per step regardless of $h$. Outside this band the roots are real. Together the two cases give the exact stability region (the Schur–Cohn conditions for a quadratic):

$$0<\eta L<2(1+\beta)$$

— momentum almost doubles the admissible step (for SGD it is $\eta L<2$).

Let the curvatures fill the interval $[\mu,\,L]$, $\kappa=L/\mu$. Choose $\eta$ and $\beta$ so that both ends land on the edges of the complex band: $(1-\sqrt\beta)^2=\eta\mu$ and $(1+\sqrt\beta)^2=\eta L$. Then all directions decay equally fast:

$$\eta=\frac{4}{(\sqrt L+\sqrt\mu)^2},\qquad \beta=\Bigl(\frac{\sqrt\kappa-1}{\sqrt\kappa+1}\Bigr)^2,\qquad \rho=\sqrt\beta=\frac{\sqrt\kappa-1}{\sqrt\kappa+1}$$

Compare with the best SGD, $\rho=(\kappa-1)/(\kappa+1)$. At $\kappa=100$ this is $0.818$ versus $0.980$: about 35 steps instead of 345 to reduce the error a thousandfold. The number of steps grows like $\sqrt\kappa$ rather than $\kappa$ — that is the heavy ball’s acceleration.

Nesterov: the gradient where momentum is taking you

Yurii Nesterov (1983) proposed to compute the gradient not at the current point but where momentum will carry the ball anyway. In PyTorch’s form (nesterov=True) this is a correction to the step:

$$u_t=\beta u_{t-1}+g_t,\qquad \theta_t=\theta_{t-1}-\eta\,(g_t+\beta u_t)$$

The characteristic equation becomes $\lambda^2-(1+\beta)(1-h)\lambda+\beta(1-h)=0$. Along gentle directions oscillations decay faster ($\rho=\sqrt{\beta(1-h)}$ instead of $\sqrt\beta$), but the stability region is narrower: $\eta L<2(1+\beta)/(1+2\beta)$, only $1.36$ at $\beta=0.9$. Switch Figure 4 to “Nesterov” to see both features.

RMSProp: a step of its own for every weight

SGD and Momentum use one rate $\eta$ for all weights. But the gradients of different weights can differ by orders of magnitude: embeddings of rare words get rare large kicks, the biases of the last layer get constant small ones. A shared $\eta$ is too large for some and too small for others. RMSProp (Geoffrey Hinton, Coursera lectures, 2012) divides the step of each weight by its typical gradient size:

$$v_t=\beta\,v_{t-1}+(1-\beta)\,g_t^2,\qquad\theta_t=\theta_{t-1}-\eta\,\frac{g_t}{\sqrt{v_t}+\epsilon}$$
$g_t^2$
an element-wise square: every weight has its own $v$;
$v_t$
the exponential moving average of the squared gradient, an estimate of $\mathbb E[g^2]$ over the last $\sim1/(1-\beta)$ steps, $v_0=0$;
$\sqrt{v_t}$
the root mean square (RMS) of the gradient — hence the name;
$\epsilon$
a small constant ($10^{-8}$) against division by zero.

Dividing by $\sqrt{v_t}$ makes the step dimensionless: multiply all gradients of a weight by 1000 and $\sqrt v$ grows 1000 times too, so the step does not change. A typical step becomes of order $\eta$ — the rate now sets the step length directly in the units of the weights.

Figure 5. The gradient of one weight whose scale changes: at step 100 it grows 10 times, at step 200 it drops 100 times. Top: $|g_t|$ and $\sqrt{v_t}$; bottom: the step length. The SGD step jumps by two orders of magnitude together with the gradient, the RMSProp step stays of order $\eta=0.01$. But adaptation lags: after the rise the step briefly spikes (at $\beta=0.9$ up to $0.030$ against the bound $0.032$), and after the drop it sags — the old large $v$ needs about $\ln10^4/\ln(1/0.9)\approx87$ steps to be forgotten.
A built-in step bound

From $v_t\ge(1-\beta)g_t^2$ it follows that $|g_t|/\sqrt{v_t}\le1/\sqrt{1-\beta}$. The RMSProp step never exceeds $\eta/\sqrt{1-\beta}$: $3.16\,\eta$ at $\beta=0.9$ and $10\,\eta$ at $\beta=0.99$. This is a protection against exploding gradients that SGD does not have.

Where RMSProp comes from: AdaGrad and Rprop

The predecessor is AdaGrad (Duchi, Hazan, Singer, 2011): $v_t=v_{t-1}+g_t^2$, a sum instead of an average. It is good for convex problems with sparse features, but in neural networks $v$ only grows, and the step $\eta/\sqrt{v_t}$ inevitably decays to zero. RMSProp replaced the sum with an exponential average that has finite memory.

Another root is Rprop (Riedmiller and Braun, 1993), which uses only the sign of the gradient. RMSProp can be read as its mini-batch version: at $\beta=0$ we get $v_t=g_t^2$ and the step $\eta\operatorname{sign}(g_t)$.

Importantly, RMSProp scales the coordinate axes but does not rotate them. This is diagonal preconditioning. If a ravine runs diagonally between weights, dividing by $\sqrt v$ helps little — you can see it in Figure 6 with a 45° rotation.

Trajectories in 2D and 3D

Let us compare the three methods on one problem — an elongated quadratic valley $f=\tfrac12(a^2+\kappa b^2)$, where $a$ and $b$ are the coordinates along and across the ravine: the curvature across is $\kappa$ times larger than along. The start is at $a=-3.4$, $b=0.9$, where $f=46.3$.

Figure 6. A ravine with $\kappa=100$: the view from above and the surface in 3D (you can rotate it). With $\eta=0.018$ SGD jumps across the ravine ($\eta\lambda_{\max}=1.8$) and crawls slowly along it: after 100 steps $f$ only drops to $0.15$. Momentum with $\beta=0.9$ reaches $2.2\cdot10^{-4}$, RMSProp with $\eta=0.1$ reaches $0.026$: it quickly gets down to the floor but then jitters with a step of order $\eta$. Rotate the ravine by 45°: SGD and Momentum do not notice, but RMSProp loses its advantage — $0.30$ instead of $0.026$.

The second classic is the Rosenbrock function $f=(1-x)^2+100(y-x^2)^2$: a narrow curved “banana” with its minimum at $(1,\,1)$. Here the curvature changes from point to point, and no constant step is ideal.

Figure 7. 3000 steps from the point $(-1.5,\,2)$, which you can drag. SGD with $\eta=0.001$ only gets to $f=0.049$. Momentum with the same $\eta$ and $\beta=0.9$ gets through the banana: $f<10^{-3}$ at step 666 and $3\cdot10^{-12}$ by the end. RMSProp with $\eta=0.01$ gets stuck around $f\approx0.02$: its step barely shrinks near the floor. The $t$ slider shows where all three are at any moment.
The map is not the territory

Two-dimensional pictures are useful but deceptive: a real network has millions of dimensions, most critical points there are saddles rather than local minima, and the loss surface itself depends on the mini-batch. Use the pictures for intuition about mechanisms (zigzag, inertia, scale), not for choosing an optimizer.

In code: from scratch and in PyTorch

All three methods fit into two small classes. Note that the state ($u$ or $v$) is an array of the same size as the weights, so Momentum and RMSProp double the memory for parameters and Adam triples it.

pythonimport numpy as np

class SGD:
    """SGD with momentum and the Nesterov variant, as in torch.optim.SGD."""
    def __init__(self, lr=0.01, momentum=0.0, nesterov=False):
        self.lr, self.beta, self.nesterov, self.u = lr, momentum, nesterov, None

    def step(self, theta, g):
        if self.beta == 0:
            return theta - self.lr * g
        self.u = g.copy() if self.u is None else self.beta * self.u + g
        d = g + self.beta * self.u if self.nesterov else self.u
        return theta - self.lr * d

class RMSProp:
    """RMSProp: every weight gets its own step scale."""
    def __init__(self, lr=0.01, beta=0.99, eps=1e-8):
        self.lr, self.beta, self.eps, self.v = lr, beta, eps, None

    def step(self, theta, g):
        if self.v is None:
            self.v = np.zeros_like(theta)
        self.v = self.beta * self.v + (1 - self.beta) * g * g
        return theta - self.lr * g / (np.sqrt(self.v) + self.eps)

# An elongated valley f = (a² + 100·b²)/2, as in Figure 6
H = np.diag([1.0, 100.0])
f = lambda th: 0.5 * th @ H @ th
grad = lambda th: H @ th

for name, opt in [("SGD", SGD(lr=0.018)),
                  ("Momentum", SGD(lr=0.018, momentum=0.9)),
                  ("Nesterov", SGD(lr=0.018, momentum=0.9, nesterov=True)),
                  ("RMSProp", RMSProp(lr=0.1, beta=0.9))]:
    th = np.array([-3.4, 0.9])
    for t in range(100):
        th = opt.step(th, grad(th))
    print(f"{name:9s} f = {f(th):.2e}")
# SGD       f = 1.53e-01
# Momentum  f = 2.23e-04
# Nesterov  f = 3.14e+57   ← diverges: ηλ_max = 1.8 > 2(1+β)/(1+2β) ≈ 1.36
# RMSProp   f = 2.60e-02

The numbers in the comments match Figure 6, and torch.optim.SGD and torch.optim.RMSprop give the same values on the same problem. Nesterov with the same $\eta$ diverges — exactly as the stability condition from the momentum section predicts.

pythonimport torch
import torch.nn.functional as F

model = torch.nn.Linear(10, 1)

# SGD with momentum and weight decay, the classic for convolutional networks
opt = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9,
                      nesterov=True, weight_decay=1e-4)
# RMSProp: PyTorch calls the smoothing factor alpha (default 0.99)
# opt = torch.optim.RMSprop(model.parameters(), lr=1e-3, alpha=0.99, eps=1e-8)

for x, y in loader:                  # mini-batches from a DataLoader
    opt.zero_grad()                  # gradients accumulate, so reset them
    loss = F.mse_loss(model(x), y)
    loss.backward()                  # g_t lands in param.grad
    opt.step()                       # θ ← θ − η·(…)
Two forms of momentum in libraries

PyTorch stores the sum of raw gradients and multiplies it by the current $\eta$: $\theta\leftarrow\theta-\eta_t u_t$. Keras and the classic paper by Sutskever et al. (2013) store a velocity already multiplied by the rate: $v_t=\beta v_{t-1}-\eta_t g_t$, $\theta\leftarrow\theta+v_t$. With a constant $\eta$ the forms are equivalent, with a schedule they are not: in PyTorch a new $\eta$ immediately applies to the whole accumulated buffer.

Hyperparameters and practice

ParameterTypical valuesHow to choose
$\eta$ (SGD with momentum)$0.01$–$0.1$the largest value at which the loss still falls steadily; ResNet: $0.1$ at batch 256
$\beta$ (momentum)$0.9$, sometimes $0.95$–$0.99$a larger $\beta$ means longer memory and stronger acceleration, but a higher risk of oscillation
$\beta$ of RMSProp (alpha)$0.9$–$0.99$averaging window $1/(1-\beta)$: 10 to 100 steps
$\eta$ (RMSProp)$10^{-4}$–$10^{-3}$a step of order $\eta$ in the units of the weights
$B$ (batch)32–512when $B$ grows $k$ times, raise $\eta$ $k$ times, with warmup
weight decay$10^{-4}$–$5\cdot10^{-4}$shrinks the weights; for SGD it coincides with $L_2$ regularization
  • Learning-rate schedule. Step decay (multiply by $0.1$ at epochs 30 and 60 out of 90 — the ResNet classic), cosine or one-cycle. A constant $\eta$ leaves a noise cloud around the minimum.
  • Warmup. Over the first hundreds to thousands of steps $\eta$ grows linearly from a small value — especially important with a large batch.
  • Gradient clipping by norm protects against rare huge gradients in RNNs and transformers.
  • Learning-rate search (the LR range test, Leslie Smith): a short run with an exponentially growing $\eta$; pick a value well below the point where the loss starts to rise.
  • Normalization of inputs, batch normalization and sensible initialization lower the condition number and allow a larger $\eta$.

Common mistakes

  1. A forgotten zero_grad(). In PyTorch gradients accumulate in .grad; without resetting, $g_t$ becomes the sum of all past gradients — not momentum, but a bug.
  2. A learning rate that is too large: the loss grows or turns into NaN. By Figure 1 you need $\eta<2/\lambda_{\max}$; first of all reduce $\eta$ 3–10 times.
  3. Carrying $\eta$ over between optimizers. With momentum $\beta=0.9$ the steady-state step is 10 times larger than SGD’s with the same $\eta$. For RMSProp and Adam $\eta$ is in different units altogether: $10^{-3}$ is normal for them and usually too small for SGD.
  4. Changing the batch without changing the rate. The batch grew 8 times and $\eta$ stayed — the network learns more slowly per epoch; the batch shrank — the noise may destabilize training.
  5. $\epsilon=10^{-8}$ in low precision. In float16 this number rounds to zero, and when $v\approx0$ the RMSProp step explodes; with mixed precision $v$ is kept in float32 or $\epsilon$ is made larger.
  6. A constant rate until the end of training. Without lowering $\eta$, SGD jitters around the minimum and the last epochs achieve almost nothing.
  • Adam: the numerator is EMA momentum, the denominator is $\sqrt{v}$ from RMSProp, plus bias correction.
  • MSE: its gradient $\frac2n\sum_i(\hat y_i-y_i)\,x_i$ is, up to a factor of 2, the $g_t$ of the linear regression in Figure 2 (the loss there is half the MSE).
  • BCE and cross-entropy: the gradient with respect to the logits, $\hat y-y$, is the simplest descent signal.
  • The sigmoid: saturation produces tiny gradients — SGD almost stands still on them, while RMSProp stretches the step.
  • Huber: caps the gradient of outliers — a relative of gradient clipping.

Summary

1) SGD: $\theta_t=\theta_{t-1}-\eta g_t$, where $g_t$ is an unbiased mini-batch estimate of the gradient; the noise variance falls as $1/B$. 2) Stability: $\eta<2/\lambda_{\max}$; the speed is set by the condition number $\kappa$ — on the order of $\kappa$ steps per digit of accuracy. 3) Momentum $u_t=\beta u_{t-1}+g_t$ is an exponential memory of gradients with window $1/(1-\beta)$; on quadratics it cuts the journey to the order of $\sqrt\kappa$ steps and extends stability to $\eta L<2(1+\beta)$. 4) RMSProp divides the step by $\sqrt{v_t}$: the step is dimensionless, of order $\eta$, but the adaptation is only diagonal. 5) EMA momentum + RMSProp + bias correction = Adam.

Check yourself

1. $f(\theta)=5\theta^2$. For which constant $\eta$ does gradient descent converge?
2. What is the memory window of momentum at $\beta=0.95$?
3. The batch grew from 32 to 128 (there is far more data than $B$). What happens to the variance of the stochastic gradient?
4. All gradients of one weight are multiplied by 100. How does the RMSProp step change once $v$ settles (ignoring $\epsilon$)?
5. Why does momentum speed up descent along an elongated ravine?