Skip to content

Training Deep Networks

The training loop: SGD, mini-batches, epochs

The rhythm every model is trained by

Real training never touches the whole dataset at once. It loops over shuffled mini-batches for many epochs, spending a little gradient noise to buy a lot of speed.

You already know how to take one gradient step: measure the loss, backprop to get the gradient, nudge every parameter downhill. The training loop is the boring, powerful machine that wraps that step and runs it thousands of times - but with a twist. Instead of computing the gradient over all your data every time (accurate but slow), it estimates it from a small random batch (noisy but fast). That single trade - a little noise for a lot of speed - is why modern models train at all.

The loop is an outer wrapper

Everything you learned earlier was one step. Training just wraps that step in two loops: an outer loop over epochs (full passes over the data) and an inner loop over mini-batches. Inside the innermost line sits the exact gradient step from gradient descent (Lesson 11), fed by the gradients from backprop (Lesson 22). Nothing new happens per step - there is just a lot of steps.

The loop that wraps gradient descent

Here is the entire idea in code. Read it top to bottom: shuffle, slice into batches, and for each batch do one forward pass, one loss, one backward pass, one update. Then repeat for the next epoch. Every deep-learning framework is an elaboration of these lines.

for epoch in range(num_epochs):        # outer loop: full passes over the data
    shuffle(dataset)                    # fresh random order each epoch
    for batch in batches(dataset, B):  # inner loop: one mini-batch of size B
        preds = model(batch.x)         # forward pass   (Lesson 20)
        loss  = loss_fn(preds, batch.y) # how wrong, on THIS batch
        grads = loss.backward()        # backprop       (Lesson 22)
        for p in model.params:
            p -= lr * grads[p]         # gradient step  (Lesson 11)
The canonical training loop

Batch, stochastic, or mini-batch?

The only real design choice is how many examples go into each gradient estimate - the batch size . That one number defines three classic variants, sitting on a spectrum from slow-and-exact to fast-and-noisy.

VariantBatch size Gradient per stepCharacter
Batch (BGD)exact, whole datasetsmooth but slow & memory-heavy
Stochastic (SGD)one example, very noisyfast, jittery, cheap per step
Mini-batchsmall sample, mild noisethe practical default

In practice mini-batch wins almost everywhere: batches of 32-512 give a decent gradient estimate, keep the GPU busy with parallel matrix work, and let you take hundreds of update steps in the time full-batch takes one. Confusingly, people still say "SGD" for the mini-batch case - the "stochastic" just means "gradient from a random sample," whatever the size.

Epoch, batch size, iteration - the vocabulary

With training examples and batch size , one epoch (one full pass over the data) takes exactly

where is the number of epochs and an iteration (or step) is one weight update from one batch. Example: examples, , so iterations per epoch. Smaller means more, noisier steps per epoch; larger means fewer, steadier ones.

A live training dashboard

Time to watch the loop breathe. Below, a tiny classifier is trained by mini-batch SGD on a two-blob dataset. Press Run to watch the loss descend in real time; the faint amber line is the raw per-batch loss (that jitter is the mini-batch noise), and the bold teal line is the per-epoch average trend. Shrink the batch size to make the amber line thrash; then crank the learning rate toward the top and watch the whole thing explode. Use Step epoch to advance one epoch at a time and see the decision boundary on the right snap into place.

Mini-batch training run · step · break it
epoch14 / 14loss0.024accuracy97%converged ✓
per-batch loss (noisy)epoch average (trend)class 1class 0

The loss curve. Descends and settles when the rate is sane; ricochets upward when it is too high.

Feature space. The dashed line is the decision boundary; a red ring marks a misclassified point.

Noise is a feature, not just a bug

Those amber jitters look like a defect, but the wobble is doing useful work: a noisy gradient lets the optimizer rattle out of shallow bad spots that a perfectly smooth full-batch descent would slide straight into. You are trading a little accuracy per step for many more steps per second - and a bit of healthy randomness on the side. It is faster, cheaper, and often finds better solutions.

The learning rate is the knob that bites

Drag the rate slider to the top of its range. The loss stops descending, leaps upward, and the boundary flails - every update overshoots the minimum instead of stepping toward it, so the error grows geometrically. Too small and it crawls; too large and it diverges. Finding the largest rate that still descends smoothly is the single most important tuning move in all of deep learning.

Reading the loss curve

The loss curve is your instrument panel. A healthy run drops fast, then flattens into a noisy plateau - that flattening is your cue that a fixed rate has done its job. The next move is to decay the learning rate over time on a schedule: big steps early to cover ground, tiny steps late to settle precisely. The giant pretraining run of Lesson 50 does exactly this over billions of steps, and the next lesson makes momentum, Adam, and schedules precise. A curve that rises means the rate is too high; a curve that plateaus early and high means it is too low or the model is too small. Same loop, same reading, whether you train a toy classifier or a trillion-token language model.

Check yourself

A dataset of 1024 examples is trained with batch size 32. How many weight updates happen in one epoch?

In the dashboard, a loss curve that spikes upward and diverges instead of settling down usually means:

Recall: why does mini-batch gradient descent almost always beat pure full-batch training in practice?

Try to state it, then check.

Lock it in

  • The training loop is one gradient step wrapped in two loops: an outer loop over epochs (full passes) and an inner loop over mini-batches - each innermost line is one forward pass, loss, backward pass, and update.
  • Batch size sets the spectrum: (exact but slow), (SGD, noisy), (mini-batch, the practical default at 32-512).
  • Vocabulary: iterations per epoch , and total updates .
  • Gradient noise is a feature: it keeps the GPU busy with parallel work and helps the optimizer rattle out of shallow bad spots, trading a little per-step accuracy for many more steps per second.
  • The learning rate is the knob that bites: too small crawls, too large diverges, and a decaying schedule (big steps early, tiny steps late) settles precisely.

Primary source

Andrew Ng derives mini-batch gradient descent, batch-size intuition, and learning-rate tuning step by step in the Deep Learning Specialization. For the hands-on, code-first version - building and reading training loops in a live notebook - work through fast.ai's Practical Deep Learning.

Ask your teacher

Want to see how batch size interacts with the learning rate (the "linear scaling rule"), or why gradient noise behaves like implicit regularization? Ask and I will build the follow-up. The big idea to carry forward: this outer loop is the same loop wrapped around the gradient step from Lesson 11 and the backprop from Lesson 22 - the very loop that pretrains an LLM (Lesson 50), just run on trillions of tokens instead of two blobs.