Textbook › Part III Deep Learning: what assumption you add
CHAPTER 3

Carrying the Error Down — Backpropagation

FREE14 min

Chapter 1 showed that the direction to move a weight is set by p−yp - y, the gap between prediction and truth. That was with one layer. Stack layers and only the top one knows the gap: the weights below never touch the output, so they have no way of knowing how wrong they were.

How does the gap get down there? Chapter 0-2 already answered it. Multiply along a chain, add across a branch — the chain rule, and nothing else. This chapter writes that rule in the shape of layers, checks it against numerical differentiation, and then measures the case where it fails to arrive (vanishing gradients). No new principle appears.

1. The forward pass

Write layers l=1,…,Ll = 1, \dots, L as

z(l)=W(l)a(l−1)+b(l),a(l)=φ(z(l))z^{(l)} = W^{(l)} a^{(l-1)} + b^{(l)}, \qquad a^{(l)} = \varphi\big(z^{(l)}\big)
(1)

with a(0)=xa^{(0)} = x the input and a(L)a^{(L)} the output. φ\varphi is applied componentwise (Chapter 0-2, case (b)).

The loss ℓ\ell is a function of the output alone, and there are LL sets of weights. What we need is the gradient with respect to every W(l)W^{(l)}.

2. The chain rule in the shape of layers

Define one key quantity: how much the loss moves when that layer's input z(l)z^{(l)} moves.

δ(l)  =  ∂ℓ∂z(l)  ∈  Rnl\delta^{(l)} \;=\; \frac{\partial \ell}{\partial z^{(l)}} \;\in\; \mathbb{R}^{n_l}

At the output layer, the form from Chapter 1 carries over directly (for cross-entropy with softmax):

δ(L)  =  p−y\delta^{(L)} \;=\; p - y
(2)

Now descend. The only route by which z(l)z^{(l)} reaches the loss is through a(l)=φ(z(l))a^{(l)} = \varphi(z^{(l)}) into z(l+1)z^{(l+1)}, so applying equation (7) of Chapter 0-2 (Jf∘g=JfJgJ_{f\circ g} = J_f J_g):

δ(l)  =  (W(l+1)⊤δ(l+1))∘φ′(z(l))\delta^{(l)} \;=\; \Big( W^{(l+1)\top} \delta^{(l+1)} \Big) \circ \varphi'\big(z^{(l)}\big)
(3)

That single line is all of backpropagation. Read it in two halves.

  • Multiplying by W(l+1)⊤W^{(l+1)\top} redistributes the layer above's error in proportion to the weights. Routes that mattered going forward get more of the error coming back.
  • The ∘ φ′(z(l))\circ\, \varphi'(z^{(l)}) multiplies by how responsive the activation was at that point. Where the slope is flat (saturated), almost nothing gets through.
The Hadamard product $\circ$ in equation (3) is not a notational convenience. The Jacobian of a componentwise activation is diagonal (Chapter 0-2, case (b)), and multiplying by a diagonal matrix is the same as multiplying elementwise. No $(128,128)$ matrix is built; one $(128,)$ vector does it — a factor of 128 in memory.

Once δ\delta is in hand, the weight gradients are one product:

∂ℓ∂W(l)  =  δ(l)(a(l−1))⊤,∂ℓ∂b(l)  =  δ(l)\frac{\partial \ell}{\partial W^{(l)}} \;=\; \delta^{(l)} \big(a^{(l-1)}\big)^{\top}, \qquad \frac{\partial \ell}{\partial b^{(l)}} \;=\; \delta^{(l)}
(4)

Here a(l−1)a^{(l-1)} is the value from the forward pass, which is why those intermediates cannot be thrown away (section 5).

FIG 1The same figure as Chapter 0-2. The product on the "chain" side is the vertical flow of equation (3), layer to layer; the sum on the "branch" side is what happens when one value feeds several routes. Drop a route and the total parts company with the measurement — exactly what a forgotten branch does in a multi-layer implementation

3. Checking that it is actually right

The derivation is short, and a wrong sign or a missing transpose leaves its shape intact. Implementations that run but are wrong are easy to write, so check it mechanically, with the central difference from Chapter 0-2 equation (2).

Measured: a small network of 4 inputs, hidden layers of 6 and 5, 3 outputs, loss 12∥out−y∥2\tfrac{1}{2}\lVert \text{out} - y \rVert^2, comparing equation (4) against the central difference (h=10−6h = 10^{-6}) for every one of the 83 parameters.

activation parameters checked largest difference
sigmoid 83 4.2×10−114.2\times10^{-11}
tanh 83 2.5×10−102.5\times10^{-10}
ReLU 83 1.1×10−111.1\times10^{-11}

They agree. The size of the difference is the central difference's own error (order h2h^2), not backpropagation's.

This check is the kind you run once, right after writing the code. It cannot be used for training: each parameter costs two forward passes, so a hundred million parameters cost two hundred million (Chapter 0-2). It is a tool for verifying, not a method for learning.

4. Why "backward"

As Chapter 0-2 showed, matrix products can be taken in any order, and the order changes the cost. The loss is one output; the parameters number in the millions. In that shape, multiplying from the left — descending from the output side — is the cheap one.

For the same three stages (J1∈R1×10J_1 \in \mathbb{R}^{1\times10}, J2∈R10×128J_2 \in \mathbb{R}^{10\times128}, J3∈R128×784J_3 \in \mathbb{R}^{128\times784}), left-to-right costs 101,632101{,}632 multiplications against 1,011,3601{,}011{,}360 — 9.95 times. Going left, what you hold is always a row vector (that is δ\delta), and no large matrix is ever formed.

The name "backpropagation" describes the order of computation, nothing more. The differentiation rule is the same chain rule either way; the only choice made is which end to multiply from. For a problem with one input and millions of outputs, forward would be the cheaper direction (forward-mode automatic differentiation).

5. The price — keeping every intermediate

Equation (4) contains a(l−1)a^{(l-1)}. Descending needs values computed on the way up. So during the forward pass, nothing can be discarded.

Batch 32, width 1024, 24 layers: 32×1024×24×4 bytes=3.00 MB32 \times 1024 \times 24 \times 4\ \text{bytes} = 3.00\ \text{MB}. Raise the batch to 256 and it is 24.00 MB (eight times). In a real model this accumulates across every kind of layer, so training memory is usually set by stored activations rather than by model size. That is why memory runs out the moment you raise the batch size.

6. Sometimes it does not arrive — vanishing gradients

Repeat equation (3) LL times and the δ\delta reaching layer 1 is a product of (weight) × (activation slope) over every layer. If the per-layer factor sits below 1, depth shrinks it exponentially — the same 0.42n0.42^n shape seen in the Chapter 0-2 figure.

Measured at width 128 and 20 layers, with weights initialised as N(0, g2/nin)\mathcal{N}(0,\, g^2/n_{\text{in}}), calling gg the gain:

activation gain gg layer 1's ∥δ∥\lVert\delta\rVert ÷ last layer's
sigmoid 1 1.4×10−121.4\times10^{-12}
tanh 1 0.933
tanh 2 87.787.7
ReLU 1 1.8×10−31.8\times10^{-3}
ReLU 2\sqrt{2} 1.37
FIG 2Per-layer ‖δ‖ relative to the last layer, on a log scale. Bars on the 1 line mean the magnitude is preserved. Switch activation and move the gain: the same activation both vanishes and explodes. Add layers and a tiny per-layer difference compounds into orders of magnitude

(The figure uses width 64 and draws its own weights, so its numbers do not match the table exactly. Measured: ReLU at g=1g=1 reads 1.8×10−31.8\times10^{-3} in the table and 0.0018 in the figure; sigmoid at g=1g=1, 1.4×10−121.4\times10^{-12} against 1.0×10−121.0\times10^{-12}; tanh at g=1g=1 is further apart, 0.933 against 0.442. What matches is the pattern, not any single measured value.)

A common misreading: "gradients vanish because of the activation function"

Half right. Look at rows two and three above. Same tanh, same 20 layers, gain moved from 1 to 2 — and 0.9330.933 becomes 87.787.7. Not vanishing but exploding. Lower the gain instead and it vanishes.

tanh gain ratio (layer 1 ÷ last)
0.5 2.1×10−62.1\times10^{-6}
1.0 0.933
1.5 9.31
2.0 87.7
3.0 1.6×1031.6\times10^{3}

ReLU behaves the same way: at g=1g=1 it shrinks to 1.8×10−31.8\times10^{-3}, and at g=2g=\sqrt{2} it returns to 1.37. So "ReLU does not vanish" is wrong too. What governs this is not the activation but the per-layer product of (weight size) × (activation slope). The 2\sqrt{2} is exactly the factor that compensates for ReLU zeroing out half its inputs.

That said, the activation does have properties of its own. The derivative of sigmoid peaks at 0.250.25, so try to recover that with gain:

sigmoid gain ratio
1 1.4×10−121.4\times10^{-12}
2 5.1×10−85.1\times10^{-8}
4 2.2×10−42.2\times10^{-4}
8 7.2×10−27.2\times10^{-2}

It improves, but even at eight it does not reach 1. Raising the gain also saturates it — inputs grow and push φ′\varphi' into its flat region — so what you win you give back. That squeeze is why sigmoid is hard to stack deeply.

The conclusion is neither "change the activation" nor "fix the initialisation" but look at the product. When a deep model will not train, read the sequence of per-layer $\lVert\delta\rVert$ — which is exactly what the figure above plots. Swapping the activation alone often fails because it leaves the other half, the weight scale, untouched.

Exercises

The answers are folded away. Work them first.

Exercise 1. About equation (3). (a) What are the dimensions of W(l+1)⊤W^{(l+1)\top}, writing nln_l for layer ll's width? (b) Why is there a transpose? (c) Why is ∘ φ′\circ\,\varphi' a Hadamard product rather than a matrix product?

Show the answer

(a) nl×nl+1n_l \times n_{l+1}. Going forward W(l+1)W^{(l+1)} is nl+1×nln_{l+1} \times n_l (outputs × inputs), so transposing swaps them. Multiplying δ(l+1)∈Rnl+1\delta^{(l+1)} \in \mathbb{R}^{n_{l+1}} gives Rnl\mathbb{R}^{n_l} — the shapes agree.

(b) Because the Jacobian is being multiplied from the left. The Jacobian of z(l+1)=W(l+1)a(l)z^{(l+1)} = W^{(l+1)}a^{(l)} is W(l+1)W^{(l+1)} itself (Chapter 0-2, case (a)), and the chain rule gives ∂ℓ/∂a(l)=(∂ℓ/∂z(l+1)) W(l+1)\partial\ell/\partial a^{(l)} = (\partial \ell/\partial z^{(l+1)})\, W^{(l+1)}. Rewrite that as a column vector and the transpose appears. It is not a new rule, just a row vector written vertically.

(c) Because a componentwise activation has a diagonal Jacobian. ai=φ(zi)a_i = \varphi(z_i) does not involve zjz_j for j≠ij \neq i, so the off-diagonal entries are zero, and multiplying by a diagonal matrix equals multiplying elementwise. No (nl,nl)(n_l, n_l) matrix is needed — one (nl,)(n_l,) vector does it.

Exercise 2. In a 20-layer network, δ\delta shrinks by a factor of 0.8 per layer on average. (a) How large is layer 1's δ\delta relative to the last layer's? (b) What about 40 layers? (c) If the per-layer factor improved to 0.95, what is the 20-layer ratio?

Show the answer

(a) 0.819≈1.4×10−20.8^{19} \approx 1.4\times10^{-2} (19 hops between layers) — roughly one hundredth.

(b) 0.839≈1.7×10−40.8^{39} \approx 1.7\times10^{-4}. Doubling the depth squares the ratio. Depth rides in the exponent, so a tiny per-layer difference becomes orders of magnitude when deep.

(c) 0.9519≈0.3770.95^{19} \approx 0.377. Going from 0.8 to 0.95 per layer — a small change — turns 1.4×10−21.4\times10^{-2} into 0.3770.377, about 26 times better. Initialisation and normalisation earn their keep by pulling the per-layer factor toward 1.

Exercise 3. You are checking a backward pass you wrote. (a) How? (b) How close is close enough? (c) Why can this not be used for training itself?

Show the answer

(a) Compare against central differences (Chapter 0-2, equation (2)). Move one parameter by ±h\pm h, measure the loss twice, and compare (L+−L−)/2h(L_+ - L_-)/2h against the backward pass. Do it for every parameter — one agreeing parameter will not catch a wrong transpose (the text checks all 83).

(b) Around 10−910^{-9} with h=10−6h = 10^{-6}. The measurements in the text came in at 10−1110^{-11} to 10−1010^{-10}. Shrinking hh too far makes cancellation worse, not better, so nothing below about 10−810^{-8}. With a kinked function like ReLU, parameters whose perturbation straddles the kink will disagree — that is not an implementation error.

(c) The counts do not compare. Each parameter costs two forward passes, so nn parameters cost 2n2n. Backpropagation produces every gradient in a small multiple of one forward pass. At a hundred million parameters that is two hundred million passes against a handful.

What this chapter does not say

  • How automatic differentiation is implemented — representing the graph, registering a backward rule per operation — is not covered. Equations (3) and (4) are specific to fully connected layers; convolution and attention take other forms, derived the same way from the chain rule.
  • Remedies for vanishing and exploding gradients (residual connections, normalisation layers, gradient clipping, initialisation schemes) appear by name only; they are Chapter 5 onward. The measurements here stop at what happens, not how to fix it.
  • The numbers are single measurements on synthetic data with one fixed initialisation. Change the depth, width or activation and they change. What does not change is the shape: the per-layer factor acts through an exponent.
  • The memory estimate counts activations only — not gradients, optimiser state (twice the weights for Adam) or temporary buffers.
  • Every number was computed and checked (central-difference agreement across all 83 parameters for three activations, the per-layer ∥δ∥\lVert\delta\rVert at 20 layers, the gain sweeps for tanh and sigmoid, and the memory estimate).

Going deeper

Comments

Sign in to comment