Full-batch gradient descent updates the parameters only after computing the gradient of the average loss over the entire dataset. Every single step therefore has to look at all training examples before it can move the parameters at all. When is large, this makes each step expensive and learning slow.

The trade-off SGD makes

Pure stochastic gradient descent replaces the exact full-dataset gradient with the gradient of one training example, drawn at random. The cost per step collapses from to , but the step no longer follows the true gradient: it follows a noisy, randomly chosen estimate of it. The rest of this note makes that estimate precise. It is unbiased, meaning that on average it equals the true gradient, and its very noise turns out to help on the nonconvex landscapes of deep learning.

The objective being minimised

Using the notation of the neural networks vocabulary, the training set is

and the objective is the empirical risk, the average of the per-example losses,

where is the loss contributed by the single pair .

A concrete per-example loss

For mean squared error, the loss of one example is

where is the network’s output on input .

By linearity of differentiation, the gradient that full-batch descent would use is the average of the per-example gradients,

This is the exact quantity that SGD will replace by a single random term of the sum.

How a step chooses its example

A single SGD step uses one training example, identified by its index. Let denote the index used at step . In pure SGD a step, an iteration, and a parameter update are the same event: one example in, one update out.

The index is supplied by shuffling epochs. An epoch is one full pass through the dataset. At the start of epoch a fresh random permutation of is drawn, and the epoch visits the examples in that order, . Each step then carries two numbers: its global index , and its position inside the current epoch . The two are related by

The permutation is drawn once per epoch; the steps that follow consume its indices in order, and after the -th step the epoch closes and a new permutation is drawn.

Two epochs over a four-example dataset

Take , with examples indexed , and suppose the first two permutations drawn are and . The global step counter then unrolls as follows.

step epoch position example
1113
2121
3134
4142
5212
6224
7231
8243

Two facts are visible at once:

  • within an epoch every index appears exactly once, so one epoch uses every example exactly once, in a random order;
  • is just the dictionary between a global step and its (epoch, position) pair: step , for instance, is the step of epoch , so .

What happens between epochs is just as telling. The same four examples reappear in epoch 2, but under a new permutation, so an example is revisited across epochs, in a different order each time, and never twice within a single epoch. Training for several epochs is exactly this: the dataset reused again and again, reshuffled each time.

Shuffling is far from a cosmetic detail.

Datasets are seldom stored in random order: examples tend to arrive grouped by class, by source, or by the time they were collected. Read in that fixed order, the consecutive single-example gradients stop pointing in scattered directions and start pointing the same way, because neighbouring examples resemble one another. The update then becomes a coherent drift that fits one region of the data and is partly undone when the next block arrives, and the trajectory ends up tracing the storage order of the dataset rather than descending its average loss. A fresh permutation each epoch removes this, and the benefit runs deeper than the order merely looking random. Decorrelating successive steps lets their fluctuations cancel over a short window instead of compounding in one direction, so the path follows the average loss rather than chasing whatever block is currently being read.

Reshuffling also severs a silent coupling: under a fixed order a given example is always visited at the same point of every epoch, and therefore always meets the same learning rate, the same schedule phase, the same neighbours. Reshuffling makes that treatment uniform across the dataset, so no example is systematically privileged or penalised over training.

A counterintuitive payoff: shuffling can beat independent sampling

Reshuffling without replacement is not merely a convenient stand-in for the independent draws assumed in the analysis below. In many settings it converges faster. Forcing every example to appear exactly once per epoch makes the gradient accumulated over a whole epoch lower in variance than independent sampling, which may draw some examples twice and miss others across the same span; in the extreme, summed over a full epoch the per-example gradients always add up to the exact full-dataset gradient, with no sampling variance left at all. The clean independent model is the easier one to analyse, yet the messier scheme that real training uses is frequently the better optimiser. This gap is the subject of the random reshuffling literature.

The update, and why its gradient is random

Once is fixed, the step feeds example through the network, computes its per-example gradient by backpropagation, and steps downhill along it:

Written coordinate by coordinate over the weights and biases collected in , the same rule reads

These are not two rules but one: the compact -update written out per coordinate.

The decisive feature of this update is that its gradient is not a fixed vector. Because the index is drawn at random, is a random vector, and every property of SGD that follows is a statement about how that random vector relates to the true gradient.

The per-example gradient is unbiased

The link between the noisy single-example gradient and the true gradient is exact, and it is the central theoretical justification for SGD. It is cleanest to state under the idealised model of uniform sampling with replacement, in which every step draws

independently of the other steps.

Warning

This model is an idealisation, and one feature of it deserves to be named, because it is the first thing that looks wrong about it: since the draws are independent, the same example can be picked at two different steps while another is skipped in between, which real training deliberately avoids. It is adopted here for a single reason, that independence makes the expectation below transparent, and the box that follows shows the conclusion is unchanged under the no-repeat sampling that actual training uses.

Collect the step’s gradient into the random vector

Its expectation is taken over the random index , componentwise across the coordinates of . By the definition of expectation for a discrete random variable, and then by uniformity,

The right-hand side is exactly the full-dataset gradient written down earlier, so

The unbiasedness result

The single-example gradient is an unbiased estimator of the full-dataset gradient: averaged over the random index, it equals the true gradient exactly. This is what makes SGD a principled method rather than a cheap heuristic. In expectation the noisy SGD trajectory does what full-batch descent does, even though no individual step matches its full-batch counterpart.

Unbiased is not the same as accurate

The equality holds only in expectation. For any single realised draw of , the one-example gradient can point well away from the true gradient; the agreement is recovered only as an average over many steps. Reading as at each step is the most common early misconception about SGD.

Drawing the example: the practical regimes

The proof above assumed uniform sampling with replacement ( drawn i.i.d., ). That model was chosen for one reason: independent draws make every step’s distribution identical and free of history, so the expectation of a single step is the whole argument. It is a convenience, not a requirement, and the regime used in practice inherits the same conclusion.

Without replacement (random reshuffling). Real training shuffles once per epoch, so within an epoch the examples are drawn without replacement. This does not weaken the result. Each position of a uniformly random permutation is itself marginally uniform: of the equally likely orderings, the that fix example at position give , so the per-step expectation still holds at every step. Reshuffling only couples the steps inside an epoch, and that coupling is benign: a complete epoch touches every example exactly once, so the per-step gradients averaged over one epoch reproduce the true gradient exactly, not merely in expectation. This is also the regime motivated earlier, where a fresh permutation breaks the correlations of a fixed traversal order. The two benefits are independent: one keeps the estimate unbiased, the other avoids a deterministic ordering.

Non-uniform sampling. The draw need not be uniform. If example is taken with probability , then the reweighted gradient is again unbiased for , since

This is what importance sampling exploits: drawing higher-gradient examples more often and reweighting accordingly reduces the variance of the estimate without disturbing its mean.

Why the noise helps

Because one example need not represent the whole dataset, the gradient can swing substantially from step to step, and the SGD path is far less smooth than the full-batch one. Informally one writes

but this is only a heuristic: the discrepancy at a single step can be large, and the approximation becomes exact only in expectation.

That roughness is not purely a defect.

Noise as a feature, not a bug

The sampling noise nudges the trajectory off any single deterministic path. On the nonconvex landscapes classified by the Hessian, this helps the iterates escape poor local minima and slip off saddle points, where a full-batch optimiser stalls because its gradient vanishes. The same noise that makes any one step inaccurate makes the whole trajectory explore more broadly. Beyond its lower cost per step, this is a key reason SGD often generalises better than full-batch descent on deep networks.

"SGD" in everyday usage

In practice the term SGD is used loosely to include mini-batch SGD, which averages the gradient over a small batch of examples per step. Strictly, pure SGD is the case of exactly one example per update, the version analysed here.