← All Posts
Deep Learning · OptimizersChapter 01 / 11

SGD: Learning from Noisy Gradients

Derive the mini-batch update, see where sampling noise comes from, and explore learning-rate stability.

A neural network may have billions of parameters, but one SGD update has a simple contract: estimate the direction in which training loss increases, then move a short distance the other way. The complications come from which examples supplied that direction and how far the step travels.

The distinction to keep in mind

Backpropagation computes derivatives. SGD uses those derivatives to change parameters. Changing the optimizer does not change the chain rule used to compute a gradient.

1. From a training loss to an update

Let $w\in\mathbb R^d$ collect the parameters, and let $\ell_i(w)$ be the loss on training example $i$. With $N$ examples, the average training objective is

$$L(w)=\frac1N\sum_{i=1}^N\ell_i(w).$$

Why is the first-order change in loss $\Delta L\approx\nabla L(w)^\top\Delta w$? Build it in three short steps:

Now choose $\Delta w=-\eta\nabla L(w)$ with learning rate $\eta>0$. Plugging this in gives $\Delta L\approx\nabla L(w)^\top(-\eta\nabla L(w))=-\eta\|\nabla L(w)\|^2\le 0$. That is why the update rule has a minus sign. It is a local approximation: a large step can leave the region where the local slope is accurate.

Computing the full gradient requires all $N$ examples. SGD replaces it with a sampled estimate. At step $t$, using a batch $\mathcal B_t$ of size $B$:

$$\begin{aligned}g_t&=\frac1B\sum_{i\in\mathcal B_t}\nabla\ell_i(w_{t-1}),\\w_t&=w_{t-1}-\eta_t g_t.\end{aligned}$$

One example gives classical stochastic gradient descent; a subset gives mini-batch SGD; using the entire dataset gives full-batch gradient descent. In deep learning, “SGD” usually includes the mini-batch case. The loss reduction matters: summing instead of averaging a batch multiplies the gradient by $B$ and changes the effective step scale.

2. Why the gradient is perpendicular to the tangent

A contour line connects points that have the same loss $L(w)=c$. At any point $w$ on a contour, compare two vectors:

Because moving along the contour tangent does not change the loss ($\Delta L\approx 0$), plugging $\Delta w=t$ into the first-order change formula $\Delta L\approx\nabla L(w)^\top\Delta w$ makes the dot product of these two vectors zero:

$$\nabla L(w)^\top t=\|\nabla L(w)\|\,\|t\|\cos\theta=0\implies\cos\theta=0\implies\theta=90^\circ.$$

Therefore, the gradient $\nabla L(w)$—and the SGD step $-\eta\nabla L(w)$—are always perpendicular ($90^\circ$) to the contour tangent $t$.

At any point w on a constant-loss contour L(w) = constant, the gradient vector nabla L(w) and the contour tangent vector t satisfy nabla L(w)^T t = 0, so they meet at a 90-degree angle.
Scroll the figure horizontally on small screens.
Because $\Delta L\approx\nabla L(w)^\top t=0$ along a constant-loss contour, both $\nabla L(w)$ and the SGD step $-\eta\nabla L(w)$ are perpendicular ($90^\circ$) to the contour tangent $t$.

3. Where the randomness enters

Different training examples pull the parameters in slightly different directions. Any single random mini-batch $g_t$ is noisy, but because every example has an equal $1/N$ chance of being picked, the batch gradient equals the true full-dataset gradient on average:

$$\mathbb E[g_t]=\nabla L(w).$$

How much does averaging $B$ examples reduce the noise? Suppose one random example’s gradient has variance $\sigma^2$ (so its typical noise size, or standard deviation, is $\sigma$). For a batch average $g_t=\frac1B(g^{(1)}+\cdots+g^{(B)})$ of $B$ independent examples, two basic variance rules apply:

Because noise shrinks with $\sqrt{B}$, $4\times$ larger batch size cuts the gradient noise in half ($\sqrt{4}=2$), and using the full dataset ($B=N$ without replacement) removes sampling noise completely.

4. Why a large learning rate can explode

Consider one curved direction with loss $L(w)=\tfrac12\lambda w^2$, where $\lambda>0$ measures curvature. Its gradient is $\lambda w$, so a full-gradient step gives

$$w_t=(1-\eta\lambda)w_{t-1}.$$

The distance to zero shrinks only when $|1-\eta\lambda|<1$, or $0<\eta<2/\lambda$. If $\eta\lambda$ lies between 1 and 2, the sign flips each step but the oscillations shrink. Above 2 they grow. At exactly 2, the iterate alternates without getting closer.

In multiple dimensions, a quadratic has several curvature directions. Because each gradient step leaves the current contour perpendicular to its tangent, elongated contours direct most of the step across the steepest wall while the sharpest curvature limits the stable learning rate. That same small rate may make progress frustratingly slow in a flatter direction. This is the narrow-valley problem that motivates momentum and preconditioning. This bound is exact for a positive-definite quadratic with full gradients, not a universal safe learning rate for a neural network.

5. Lab: noise and curvature are different problems

To let you test batch noise and valley steepness separately, the lab below runs SGD on a simple 2D bowl with minimum at $w^*=(0,0)$:

SGD trajectory explorer

Start at $(3,2)$. Each click evaluates a fresh batch gradient and applies one update.

6. A training loop without hidden scaling

# Plain mini-batch SGD; loss is averaged over the batch.
optimizer = torch.optim.SGD(model.parameters(), lr=0.03)
for inputs, targets in loader:
    optimizer.zero_grad(set_to_none=True)
    predictions = model(inputs)
    loss = criterion(predictions, targets)  # reduction="mean"
    loss.backward()
    optimizer.step()

The optimizer reads gradients already computed by backpropagation. Clear them deliberately: PyTorch accumulates gradients into buffers. For $K$ equal-sized microbatches representing one larger batch, divide each mean loss by $K$, accumulate backward passes, and call step() once. Unequal microbatch sizes require weighting by their example counts to reproduce the same average. Batch-dependent layers can still make microbatch training differ from a single large forward pass.

Plain SGD needs no persistent per-parameter momentum or second-moment buffer. It still needs parameters, gradients, and the model’s other training memory. A learning-rate schedule changes $\eta_t$ over training; a smaller late rate reduces stochastic wandering but also slows movement. Monitor validation performance separately from training loss. Low training loss alone does not establish useful generalization.

7. Questions worth answering

Why doesn’t the negative gradient always point straight toward the minimum?

Because $-\nabla L(w)$ is perpendicular to the contour tangent at $w$. On an elongated contour, the tangent is tilted relative to the ray to the minimum, so the normal points across the steeper axis rather than toward the minimizer.

Does a rising loss after one step prove the implementation is broken?

No. A noisy gradient can increase full loss, and the evaluated batch may also change. Inspect a consistent evaluation set and the trend. With full gradients on a smooth quadratic and a rate inside its stability interval, persistent growth is a different warning.

If batch size doubles, should the learning rate double?

There is no universal requirement. Averaging keeps the expected gradient scale unchanged. Batch-size learning-rate rules concern training dynamics, noise, and the number of updates per epoch; they are not needed to correct an averaged gradient’s units.

What should you check before replacing SGD?

Loss reduction, gradient clearing, data scaling, learning rate, and a reproducible small run. An adaptive optimizer can change scaling; it cannot repair a wrong gradient or target.

Sources and further reading

Bottou, Stochastic Gradient Descent Tricks develops the stochastic approximation viewpoint. PyTorch’s SGD documentation specifies its implementation options. The worked vectors, contour-tangent orthogonality diagram, quadratic dataset, stability calculation, and interactive experiment above are constructed for these notes.