AI coursesMain page
Back to the library

Backpropagation: every gradient in one backward pass

The chain rule in matrix form, its cost in operations and memory, and what it says about initialization.

On this page
  1. Why we need an algorithm
  2. A chain of functions
  3. The general rule: computational graphs
  4. Backpropagation in matrix form
  5. Batches, cost and memory
  6. Starting the backward pass: the loss
  7. Automatic differentiation
  8. What the backward pass says about training deep networks
  9. Summary
  10. Notes
  11. Problems
  12. References

Gradient descent needs the derivative of the loss with respect to every parameter (article 5). Article 5 computed these derivatives by hand for a network with one hidden unit, and article 7 introduced deep networks whose parameters number in the hundreds of thousands. This article derives the algorithm that computes all of these derivatives at once, backpropagation, in full. We first run it on a chain of scalar functions with actual numbers, then state the general rule for any computation, then derive the matrix form for a deep network and work through an example. We then count its cost in operations and memory, show how the backward pass starts from the loss, place it within automatic differentiation, and finally use the backward equations to explain why the scale of the initial weights decides whether a deep network trains at all.

1. Why we need an algorithm

The simplest way to estimate a derivative is to nudge a parameter and measure the change in the loss. The central difference

∂ℓ∂ϕ≈ℓ(ϕ+ϵ)−ℓ(ϕ−ϵ)2ϵ(8.1)\frac{\partial \ell}{\partial \phi} \approx \frac{\ell(\phi + \epsilon) - \ell(\phi - \epsilon)}{2\epsilon} \tag{8.1}

needs two evaluations of the loss for each parameter, each a full forward pass through the network. For the (784,256,256,10)(784, 256, 256, 10) classifier of article 7, with 269,322 parameters, one gradient would cost 538,644 forward passes. Gradient descent takes thousands of steps, so this is hopeless.

Two observations point to a better method. First, a weight multiplies an activation, so its effect on the loss is proportional to that activation: if the activation is zero, changing the weight does nothing, and if it is large, a small change in the weight has a large effect. Second, a parameter in an early layer affects the loss only through all the layers after it. Every early parameter shares the same downstream path, so the derivatives along that path can be computed once and reused. Backpropagation exploits both: it computes the derivatives with respect to the intermediate values, starting at the loss and working backwards, and then reads off each parameter's derivative from the intermediate value it feeds and the activation it multiplies.

2. A chain of functions

We start with a model that is a chain of scalar operations, the smallest case that has all of backpropagation's steps. We defer the network version until section 4. With one input xx, the model computes:

f0=β0+ω0x,h1=sin⁡(f0),f1=β1+ω1h1,h2=exp⁡(f1),f2=β2+ω2h2,h3=cos⁡(f2),f3=β3+ω3h3,ℓ=(f3−y)2(8.2)\begin{aligned} f_0 &= \beta_0 + \omega_0 x, & h_1 &= \sin(f_0), \\ f_1 &= \beta_1 + \omega_1 h_1, & h_2 &= \exp(f_1), \\ f_2 &= \beta_2 + \omega_2 h_2, & h_3 &= \cos(f_2), \\ f_3 &= \beta_3 + \omega_3 h_3, & \ell &= (f_3 - y)^2 \end{aligned} \tag{8.2}

It has the structure of a deep network with one unit per layer. Each fkf_k is an affine function with a bias βk\beta_k and a weight ωk\omega_k ("omega"), and each hk+1h_{k+1} applies a nonlinear function to it. We use three different nonlinear functions instead of ReLU so that every step of the derivation looks different. The last line is the squared error for one training example (x,y)(x, y). The model has eight parameters.

We take x=0.6x = 0.6, y=0.4y = 0.4 and the parameter values β0=0.1\beta_0 = 0.1, ω0=1.2\omega_0 = 1.2, β1=−0.3\beta_1 = -0.3, ω1=0.8\omega_1 = 0.8, β2=0.2\beta_2 = 0.2, ω2=0.5\omega_2 = 0.5, β3=0.1\beta_3 = 0.1, ω3=1.5\omega_3 = 1.5.

The forward pass evaluates equation 8.2 from top to bottom and stores every intermediate value: f0=0.1+1.2×0.6=0.82f_0 = 0.1 + 1.2 \times 0.6 = 0.82, h1=sin⁡0.82=0.7311h_1 = \sin 0.82 = 0.7311, f1=−0.3+0.8×0.7311=0.2849f_1 = -0.3 + 0.8 \times 0.7311 = 0.2849, h2=e0.2849=1.3297h_2 = e^{0.2849} = 1.3297, f2=0.8648f_2 = 0.8648, h3=cos⁡0.8648=0.6488h_3 = \cos 0.8648 = 0.6488, f3=1.0732f_3 = 1.0732 and finally ℓ=(1.0732−0.4)2=0.4531\ell = (1.0732 - 0.4)^2 = 0.4531.

The backward pass computes the derivative of the loss with respect to each intermediate value, in the opposite order. We start at the end:

∂ℓ∂f3=2(f3−y)=1.3463\frac{\partial \ell}{\partial f_3} = 2(f_3 - y) = 1.3463

The value h3h_3 affects the loss only through f3=β3+ω3h3f_3 = \beta_3 + \omega_3 h_3, which grows by ω3\omega_3 for every unit of h3h_3. By the chain rule:

∂ℓ∂h3=∂f3∂h3 ∂ℓ∂f3=ω3×1.3463=2.0195\frac{\partial \ell}{\partial h_3} = \frac{\partial f_3}{\partial h_3}\,\frac{\partial \ell}{\partial f_3} = \omega_3 \times 1.3463 = 2.0195

Next, f2f_2 affects the loss only through h3=cos⁡f2h_3 = \cos f_2, whose derivative is −sin⁡f2-\sin f_2:

∂ℓ∂f2=∂h3∂f2 ∂ℓ∂h3=−sin⁡(0.8648)×2.0195=−1.5368\frac{\partial \ell}{\partial f_2} = \frac{\partial h_3}{\partial f_2}\,\frac{\partial \ell}{\partial h_3} = -\sin(0.8648) \times 2.0195 = -1.5368

The pattern repeats down the chain. Each step multiplies the derivative computed in the previous step by one local derivative, the derivative of a single operation with respect to its input:

∂ℓ∂hk=ωk∂ℓ∂fk,∂ℓ∂fk−1=ak′(fk−1) ∂ℓ∂hk(8.3)\frac{\partial \ell}{\partial h_k} = \omega_k \frac{\partial \ell}{\partial f_k}, \qquad \frac{\partial \ell}{\partial f_{k-1}} = a_k'(f_{k-1})\,\frac{\partial \ell}{\partial h_k} \tag{8.3}

where aka_k is the nonlinear function of step kk (sin, exp or cos here). In words: to move back past an affine step, multiply by its weight; to move back past a nonlinear step, multiply by the slope of the function at the value it received in the forward pass. The second rule is why the forward pass stored the fkf_k. Continuing gives ∂ℓ/∂h2=−0.7684\partial\ell/\partial h_2 = -0.7684, ∂ℓ/∂f1=e0.2849×(−0.7684)=−1.0217\partial\ell/\partial f_1 = e^{0.2849} \times (-0.7684) = -1.0217, ∂ℓ/∂h1=−0.8174\partial\ell/\partial h_1 = -0.8174 and ∂ℓ/∂f0=cos⁡(0.82)×(−0.8174)=−0.5576\partial\ell/\partial f_0 = \cos(0.82) \times (-0.8174) = -0.5576. Figure 8.1 shows all the values.

A row of nine boxes labelled x, f0, h1, f1, h2, f2, h3, f3 and loss, joined by arrows pointing right. Above each arrow is the operation it performs. Below each box are two numbers: the forward value in dark blue and the derivative of the loss in orange, with orange arrows pointing left.

Figure 8.1 Forward and backward passes through a chain. The model of equation 8.2 with x=0.6x = 0.6 and y=0.4y = 0.4. The forward pass (dark arrows) applies each operation, shown above its arrow, and stores the result (dark numbers). The backward pass (orange arrows) starts from ∂ℓ/∂ℓ=1\partial\ell/\partial\ell = 1 and multiplies by one local derivative per step (equation 8.3), giving the derivative of the loss with respect to every intermediate value (orange numbers).

The parameter derivatives now come almost for free. The bias βk\beta_k enters only through fkf_k, with local derivative 1, and the weight ωk\omega_k enters through fkf_k multiplied by hkh_k (with h0=xh_0 = x):

∂ℓ∂βk=∂ℓ∂fk,∂ℓ∂ωk=hk∂ℓ∂fk(8.4)\frac{\partial \ell}{\partial \beta_k} = \frac{\partial \ell}{\partial f_k}, \qquad \frac{\partial \ell}{\partial \omega_k} = h_k \frac{\partial \ell}{\partial f_k} \tag{8.4}

These are the two observations of section 1 in equation form. The weight's derivative is the derivative at the point where it acts, scaled by the activation it multiplies. For our values:

kk ∂ℓ/∂βk\partial\ell/\partial\beta_k ∂ℓ/∂ωk\partial\ell/\partial\omega_k
0 −0.5576-0.5576 0.6×(−0.5576)=−0.33460.6 \times (-0.5576) = -0.3346
1 −1.0217-1.0217 0.7311×(−1.0217)=−0.74700.7311 \times (-1.0217) = -0.7470
2 −1.5368-1.5368 1.3297×(−1.5368)=−2.04341.3297 \times (-1.5368) = -2.0434
3 1.34631.3463 0.6488×1.3463=0.87350.6488 \times 1.3463 = 0.8735

Each of the eight values agrees with the central difference of equation 8.1, with ϵ=10−6\epsilon = 10^{-6}, to at least six decimal places. The backward pass needed about a dozen multiplications, roughly the work of one forward pass. The central differences needed sixteen forward passes.

3. The general rule: computational graphs

The chain had a single path from each value to the loss. Real networks branch: a hidden unit feeds every unit of the next layer, and a value can be used several times. The general rule handles this.

Any computation can be drawn as a computational graph: each node is a value, and an arrow from node uu to node vv means that vv is computed directly from uu (among other inputs). If uu is used by several nodes v1,…,vmv_1, \ldots, v_m, a small change in uu changes all of them, and the effects on the loss add up. The multivariable chain rule gives:

∂ℓ∂u=∑j=1m∂vj∂u ∂ℓ∂vj(8.5)\frac{\partial \ell}{\partial u} = \sum_{j=1}^{m} \frac{\partial v_j}{\partial u}\,\frac{\partial \ell}{\partial v_j} \tag{8.5}

We can break this down into two parts. The derivatives ∂ℓ/∂vj\partial\ell/\partial v_j belong to nodes later in the graph and are already known if we process nodes from the loss backwards. The factors ∂vj/∂u\partial v_j / \partial u are local: each depends only on the single operation that computes vjv_j, evaluated at the stored forward values. In words: the derivative of the loss with respect to a value is the sum, over everything that uses the value, of that user's derivative times the local derivative.

A tiny example shows the summation. Let u=3u = 3 feed two operations, v1=2u=6v_1 = 2u = 6 and v2=u2=9v_2 = u^2 = 9, and let ℓ=v1+v2=15\ell = v_1 + v_2 = 15. Then ∂ℓ/∂v1=∂ℓ/∂v2=1\partial\ell/\partial v_1 = \partial\ell/\partial v_2 = 1, and equation 8.5 gives ∂ℓ/∂u=2×1+2u×1=8\partial\ell/\partial u = 2 \times 1 + 2u \times 1 = 8. Writing the loss directly as ℓ=2u+u2\ell = 2u + u^2 gives the same derivative, 2+2u=82 + 2u = 8. Forgetting one of the paths, a common bug in hand-written gradients, would give 2 or 6.

The algorithm is then: run the forward pass, storing every node's value; set ∂ℓ/∂ℓ=1\partial\ell/\partial\ell = 1; visit the nodes in reverse order of computation, and for each node apply equation 8.5. Every arrow of the graph is used once in each direction, so the backward pass costs a small constant multiple of the forward pass, however many parameters there are. That is the whole of backpropagation. The rest of this article specializes it to deep networks and examines its consequences.

4. Backpropagation in matrix form

We now apply the general rule to the deep network of article 7 (equation 7.4). It is convenient to name the pre-activations. With h0=x\mathbf{h}_0 = \mathbf{x}, the forward pass computes, for k=0,…,Kk = 0, \ldots, K:

fk=βk+Ωkhk,hk+1=a(fk)  (k<K)(8.6)\mathbf{f}_k = \boldsymbol{\beta}_k + \boldsymbol{\Omega}_k \mathbf{h}_k, \qquad \mathbf{h}_{k+1} = a(\mathbf{f}_k) \ \ (k < K) \tag{8.6}

and the output is fK\mathbf{f}_K. We define the error signal of layer kk as the derivative of the loss with respect to that layer's pre-activations, δk=∂ℓ/∂fk\boldsymbol{\delta}_k = \partial\ell/\partial\mathbf{f}_k, a vector with Dk+1D_{k+1} elements.

Parameters. Element dd of fk\mathbf{f}_k is fk,d=βk,d+∑jΩk,djhk,jf_{k,d} = \beta_{k,d} + \sum_j \Omega_{k,dj} h_{k,j}. The weight Ωk,dj\Omega_{k,dj} appears only in this element, multiplied by hk,jh_{k,j}, so ∂ℓ/∂Ωk,dj=δk,d hk,j\partial\ell/\partial\Omega_{k,dj} = \delta_{k,d}\,h_{k,j}, exactly as in equation 8.4. Collecting all dd and jj:

∂ℓ∂βk=δk,∂ℓ∂Ωk=δkhk⊤(8.7)\frac{\partial \ell}{\partial \boldsymbol{\beta}_k} = \boldsymbol{\delta}_k, \qquad \frac{\partial \ell}{\partial \boldsymbol{\Omega}_k} = \boldsymbol{\delta}_k \mathbf{h}_k^\top \tag{8.7}

The weight gradient is an outer product: a column vector with Dk+1D_{k+1} elements times a row vector with DkD_k elements, which gives a Dk+1×DkD_{k+1} \times D_k matrix, the same shape as Ωk\boldsymbol{\Omega}_k. In words: the gradient for the weight from unit jj to unit dd is unit dd's error signal times unit jj's activation.

Moving back past a weight matrix. Unit jj of hk\mathbf{h}_k is used by every element of fk\mathbf{f}_k, with local derivative ∂fk,d/∂hk,j=Ωk,dj\partial f_{k,d}/\partial h_{k,j} = \Omega_{k,dj}. Equation 8.5 sums over these uses: ∂ℓ/∂hk,j=∑dΩk,dj δk,d\partial\ell/\partial h_{k,j} = \sum_d \Omega_{k,dj}\,\delta_{k,d}. The sum runs down column jj of Ωk\boldsymbol{\Omega}_k, so in matrix form it is a product with the transpose:

∂ℓ∂hk=Ωk⊤δk(8.8)\frac{\partial \ell}{\partial \mathbf{h}_k} = \boldsymbol{\Omega}_k^\top \boldsymbol{\delta}_k \tag{8.8}

The shapes check: (Dk×Dk+1)(D_k \times D_{k+1}) times Dk+1D_{k+1} elements gives DkD_k elements, one per unit of hk\mathbf{h}_k. The forward pass multiplies by Ωk\boldsymbol{\Omega}_k; the backward pass multiplies by Ωk⊤\boldsymbol{\Omega}_k^\top and sends each error signal back along the same connections.

Moving back past the activation. Element jj of hk\mathbf{h}_k depends only on element jj of fk−1\mathbf{f}_{k-1}, so the local derivative is the slope of the activation function there:

δk−1=a′(fk−1)⊙∂ℓ∂hk(8.9)\boldsymbol{\delta}_{k-1} = a'(\mathbf{f}_{k-1}) \odot \frac{\partial \ell}{\partial \mathbf{h}_k} \tag{8.9}

where ⊙\odot multiplies two vectors element by element. For ReLU, the slope is 1 where the pre-activation is positive and 0 where it is negative, so equation 8.9 zeroes the error signal of every inactive unit. (At exactly zero the derivative is undefined; libraries use 0.)

Together, equations 8.7–8.9 are the backward pass for a deep network:

  1. Run the forward pass (equation 8.6), storing every hk\mathbf{h}_k and fk\mathbf{f}_k (for ReLU, the signs of fk\mathbf{f}_k are enough).
  2. Compute δK=∂ℓ/∂fK\boldsymbol{\delta}_K = \partial\ell/\partial\mathbf{f}_K from the loss (section 6).
  3. For k=K,K−1,…,0k = K, K-1, \ldots, 0: compute the parameter gradients of layer kk with equation 8.7; if k>0k > 0, compute δk−1\boldsymbol{\delta}_{k-1} with equations 8.8 and 8.9.

We work through a network with sizes (2,2,2,1)(2, 2, 2, 1), which has 15 parameters, ReLU activations and squared error. The input is x=(1,2)⊤\mathbf{x} = (1, 2)^\top, the target is y=1y = 1, and the parameters are:

Ω0=[1−10.51], β0=[0−1],Ω1=[12−1−1], β1=[0.50],Ω2=[0.5−1], β2=0.5\boldsymbol{\Omega}_0 = \begin{bmatrix} 1 & -1 \\ 0.5 & 1 \end{bmatrix},\ \boldsymbol{\beta}_0 = \begin{bmatrix} 0 \\ -1 \end{bmatrix},\quad \boldsymbol{\Omega}_1 = \begin{bmatrix} 1 & 2 \\ -1 & -1 \end{bmatrix},\ \boldsymbol{\beta}_1 = \begin{bmatrix} 0.5 \\ 0 \end{bmatrix},\quad \boldsymbol{\Omega}_2 = \begin{bmatrix} 0.5 & -1 \end{bmatrix},\ \boldsymbol{\beta}_2 = 0.5

The forward pass gives f0=(1−2, −1+0.5+2)=(−1,1.5)\mathbf{f}_0 = (1 - 2,\ -1 + 0.5 + 2) = (-1, 1.5), so h1=(0,1.5)\mathbf{h}_1 = (0, 1.5): the first unit of layer 1 is inactive. Then f1=(0.5+3, −1.5)=(3.5,−1.5)\mathbf{f}_1 = (0.5 + 3,\ -1.5) = (3.5, -1.5) and h2=(3.5,0)\mathbf{h}_2 = (3.5, 0): the second unit of layer 2 is inactive. The output is f2=0.5+0.5×3.5=2.25f_2 = 0.5 + 0.5 \times 3.5 = 2.25 and the loss is (2.25−1)2=1.5625(2.25 - 1)^2 = 1.5625.

The backward pass starts with δ2=2(2.25−1)=2.5\delta_2 = 2(2.25 - 1) = 2.5. Equation 8.7 gives ∂ℓ/∂Ω2=2.5×(3.5,0)=(8.75,0)\partial\ell/\partial\boldsymbol{\Omega}_2 = 2.5 \times (3.5, 0) = (8.75, 0). Equation 8.8 gives ∂ℓ/∂h2=Ω2⊤×2.5=(1.25,−2.5)\partial\ell/\partial\mathbf{h}_2 = \boldsymbol{\Omega}_2^\top \times 2.5 = (1.25, -2.5), and equation 8.9 zeroes the inactive second element: δ1=(1.25,0)\boldsymbol{\delta}_1 = (1.25, 0). One layer further back:

∂ℓ∂Ω1=[1.250][01.5]=[01.87500],∂ℓ∂h1=Ω1⊤[1.250]=[1.252.5]\frac{\partial \ell}{\partial \boldsymbol{\Omega}_1} = \begin{bmatrix} 1.25 \\ 0 \end{bmatrix} \begin{bmatrix} 0 & 1.5 \end{bmatrix} = \begin{bmatrix} 0 & 1.875 \\ 0 & 0 \end{bmatrix}, \qquad \frac{\partial \ell}{\partial \mathbf{h}_1} = \boldsymbol{\Omega}_1^\top \begin{bmatrix} 1.25 \\ 0 \end{bmatrix} = \begin{bmatrix} 1.25 \\ 2.5 \end{bmatrix}

and zeroing the inactive first unit gives δ0=(0,2.5)\boldsymbol{\delta}_0 = (0, 2.5), so ∂ℓ/∂Ω0=δ0x⊤\partial\ell/\partial\boldsymbol{\Omega}_0 = \boldsymbol{\delta}_0\mathbf{x}^\top has rows (0,0)(0, 0) and (2.5,5)(2.5, 5). All 15 derivatives agree with central differences. Figure 8.2 shows the values on the network.

A network diagram with two inputs, two hidden layers of two units and one output, followed by the loss. Each unit shows its pre-activation, activation and error signal. One unit in each hidden layer is gray and marked inactive, and the connections into and out of it are dashed.

Figure 8.2 Backpropagation through a small ReLU network. Sizes (2,2,2,1)(2, 2, 2, 1), input x=(1,2)\mathbf{x} = (1, 2), target y=1y = 1, parameters as in section 4. Each unit shows its pre-activation ff and activation hh from the forward pass (dark) and its error signal δ=∂ℓ/∂f\delta = \partial\ell/\partial f from the backward pass (orange). The gray units are inactive (f<0f < 0): they pass nothing forward, their error signal is zero, and every weight into or out of them gets a zero gradient for this example (dashed lines).

The example shows two properties that hold in general. First, an inactive ReLU unit blocks the gradient for this example in both directions: its incoming weights get δ=0\delta = 0 and its outgoing weights multiply h=0h = 0. A unit that is inactive for every training example never changes, which is called a dead ReLU. Second, each example's weight gradient δkhk⊤\boldsymbol{\delta}_k\mathbf{h}_k^\top has rank one. The gradient over a batch, a sum of such outer products, usually has higher rank, but at most the batch size.

5. Batches, cost and memory

Training uses a batch of BB examples and the mean loss L=1B∑iℓiL = \frac{1}{B}\sum_i \ell_i (article 5). Each example has its own forward and backward pass, and the gradient of LL is the mean of the per-example gradients. With the activations of the batch as columns, Hk∈RDk×B\mathbf{H}_k \in \mathbb{R}^{D_k \times B} as in article 7, and the error signals as columns of Δk∈RDk+1×B\boldsymbol{\Delta}_k \in \mathbb{R}^{D_{k+1} \times B}, the sum over examples of the outer products in equation 8.7 is one matrix product:

∂L∂Ωk=1B ΔkHk⊤,∂L∂βk=1B Δk1(8.10)\frac{\partial L}{\partial \boldsymbol{\Omega}_k} = \frac{1}{B}\,\boldsymbol{\Delta}_k \mathbf{H}_k^\top, \qquad \frac{\partial L}{\partial \boldsymbol{\beta}_k} = \frac{1}{B}\,\boldsymbol{\Delta}_k \mathbf{1} \tag{8.10}

The shapes are (Dk+1×B)(B×Dk)=Dk+1×Dk(D_{k+1} \times B)(B \times D_k) = D_{k+1} \times D_k: the product sums over the batch dimension. Equation 8.8 becomes Ωk⊤Δk\boldsymbol{\Omega}_k^\top\boldsymbol{\Delta}_k, one product for the whole batch.

Operations. Per layer, the forward pass does one matrix product, ΩkHk\boldsymbol{\Omega}_k\mathbf{H}_k, with Dk+1DkBD_{k+1} D_k B multiply-adds. The backward pass does two of the same size: ΔkHk⊤\boldsymbol{\Delta}_k\mathbf{H}_k^\top for the weight gradient and Ωk⊤Δk\boldsymbol{\Omega}_k^\top\boldsymbol{\Delta}_k to continue backwards. The first layer can skip the second product, because nothing needs ∂ℓ/∂x\partial\ell/\partial\mathbf{x}. So the backward pass costs about twice the forward pass, and a training step about three times. For the (784,256,256,10)(784, 256, 256, 10) classifier, the forward pass needs 268,800 multiply-adds per example and the backward pass 336,896; the ratio is only 1.25 because the large first layer skips its second product.

Memory. Equation 8.10 needs Hk\mathbf{H}_k, and equation 8.9 needs the signs of fk−1\mathbf{f}_{k-1}, both from the forward pass. Training must therefore keep every layer's activations for the whole batch until the backward pass reaches that layer, which costs memory proportional to B∑kDkB \sum_k D_k. At prediction time there is no backward pass, and each layer's activations can be discarded once the next layer is computed. This is why training needs much more memory than prediction, and why the batch size is often limited by memory. Gradient checkpointing [7] trades computation for memory: it stores the activations of only some layers and recomputes the others during the backward pass, which for a chain of KK layers reduces activation memory to about K\sqrt{K} layers' worth at the cost of roughly one extra forward pass.

6. Starting the backward pass: the loss

The backward pass starts from δK=∂ℓ/∂fK\boldsymbol{\delta}_K = \partial\ell/\partial\mathbf{f}_K, which depends on the loss.

Squared error. For ℓ=∑k(fK,k−yk)2\ell = \sum_k (f_{K,k} - y_k)^2, the derivative is δK=2(fK−y)\boldsymbol{\delta}_K = 2(\mathbf{f}_K - \mathbf{y}): the error itself, doubled. If the loss is a mean over II examples, each example's signal is divided by II.

Softmax and cross-entropy. For classification, the network outputs scores z=fK\mathbf{z} = \mathbf{f}_K, softmax turns them into probabilities pk=ezk/∑jezjp_k = e^{z_k}/\sum_j e^{z_j}, and the loss is ℓ=−log⁡pc\ell = -\log p_c for the correct class cc (article 4). Substituting the softmax and using log⁡(ezc)=zc\log(e^{z_c}) = z_c:

ℓ=−zc+log⁡∑jezj\ell = -z_c + \log \sum_{j} e^{z_j}

where jj runs over all classes. The first term depends only on zcz_c, with derivative −1-1 for k=ck = c and 0 otherwise. The derivative of the second term with respect to zkz_k is ezk/∑jezj=pke^{z_k}/\sum_j e^{z_j} = p_k. Together:

∂ℓ∂zk=pk−1[k=c](8.11)\frac{\partial \ell}{\partial z_k} = p_k - \mathbb{1}[k = c] \tag{8.11}

where 1[k=c]\mathbb{1}[k = c] is 1 for the correct class and 0 otherwise. In words: the error signal is the predicted probability minus the target probability. For the scores of article 4, z=(2.0,0.5,−1.0)\mathbf{z} = (2.0, 0.5, -1.0) with probabilities (0.786,0.175,0.039)(0.786, 0.175, 0.039), and the photograph showing a cat, the error signal is (−0.214,0.175,0.039)(-0.214, 0.175, 0.039). Gradient descent moves against it: it raises the cat score and lowers the other two, each in proportion to how wrong its probability is. The elements always sum to zero, because the probabilities sum to 1.

Equation 8.11 is simpler and better behaved than the two steps taken separately. Computing pcp_c first and then −log⁡pc-\log p_c fails when pcp_c underflows to zero in floating point, and the derivative of −log⁡p-\log p alone, −1/p-1/p, is huge exactly where the softmax's own derivative is tiny. Libraries therefore provide a fused "cross-entropy from scores" that computes log⁡∑jezj\log\sum_j e^{z_j} as m+log⁡∑jezj−mm + \log\sum_j e^{z_j - m} with m=max⁡jzjm = \max_j z_j, so no exponential overflows, and uses equation 8.11 for the backward pass.

7. Automatic differentiation

Nothing in sections 3–6 is specific to neural networks. Any program built from operations whose local derivatives are known (additions, products, matrix products, exponentials, ReLU and so on) defines a computational graph, and the backward pass of section 3 computes the derivative of its output with respect to all of its inputs. This is reverse-mode automatic differentiation, and backpropagation is its special case for neural networks. Libraries such as PyTorch and JAX record the operations as the forward pass runs (or trace the program in advance) and provide, for each primitive operation, a rule that maps the derivative with respect to its output to the derivatives with respect to its inputs. Users write only the forward computation.

It helps to see why the reverse direction is the right one. For a chain of layers, the chain rule writes the gradient as a product of Jacobian matrices, ∂ℓ/∂x⊤=∂ℓ/∂fK⊤ JK⋯J1\partial\ell/\partial\mathbf{x}^\top = \partial\ell/\partial\mathbf{f}_K^\top\,\mathbf{J}_K \cdots \mathbf{J}_1, where Jk\mathbf{J}_k is the matrix of derivatives of layer kk's outputs with respect to its inputs. The leftmost factor is a row vector, because the loss is a single number. Multiplying from the left keeps every intermediate result a vector, and each step costs a vector-matrix product. Multiplying from the right instead carries full matrices through the chain. Forward-mode automatic differentiation does the latter one column at a time: it pushes the derivative with respect to one input forward alongside the values, which needs one pass per input or parameter. For a scalar loss and many parameters, reverse mode costs a small constant multiple of one forward pass, independent of the number of parameters [5]; forward mode costs a multiple of the number of parameters. Forward mode wins in the opposite situation, few inputs and many outputs.

Hand-written or custom gradients should be checked against central differences (equation 8.1). The central difference has error proportional to ϵ2\epsilon^2, against ϵ\epsilon for the one-sided version. In 64-bit arithmetic, ϵ\epsilon around 10−610^{-6} and a relative error below about 10−610^{-6} between the two gradients are typical; 32-bit arithmetic is too imprecise for a reliable check. Points within ϵ\epsilon of a ReLU kink can disagree for a legitimate reason, because the two evaluations land on different linear pieces.

8. What the backward pass says about training deep networks

Unrolling equations 8.8 and 8.9 from the output to the first layer shows the structure of the error signal:

δ0=a′(f0)⊙Ω1⊤(a′(f1)⊙Ω2⊤(⋯(a′(fK−1)⊙ΩK⊤δK)⋯))(8.12)\boldsymbol{\delta}_0 = a'(\mathbf{f}_0) \odot \boldsymbol{\Omega}_1^\top \Big( a'(\mathbf{f}_1) \odot \boldsymbol{\Omega}_2^\top \big( \cdots \big( a'(\mathbf{f}_{K-1}) \odot \boldsymbol{\Omega}_K^\top \boldsymbol{\delta}_K \big) \cdots \big) \Big) \tag{8.12}

The signal that reaches an early layer has been multiplied by one weight matrix and one activation slope per layer. Products of many factors tend to grow or shrink exponentially with their length, and the same is true of the forward pass, which multiplies by one weight matrix and one activation per layer. The size of the weights decides which happens. This is the reason behind the initialization rule that article 5 stated without proof, and we can now derive it.

Forward. Suppose the weights of layer kk are drawn independently with mean 0 and variance σ2\sigma^2, the biases are 0, and the pre-activations of the previous layer are symmetric around zero. Element dd of fk\mathbf{f}_k is a sum of DkD_k independent terms Ωk,djhk,j\Omega_{k,dj}h_{k,j}, each with mean 0 and variance σ2 E[hk,j2]\sigma^2\,\mathbb{E}[h_{k,j}^2]. A ReLU of a symmetric variable keeps exactly half of its squared mass, so E[hk,j2]=12Var(fk−1,j)\mathbb{E}[h_{k,j}^2] = \frac{1}{2}\mathrm{Var}(f_{k-1,j}). Hence:

Var(fk)=Dk σ22 Var(fk−1)(8.13)\mathrm{Var}(f_k) = \frac{D_k\,\sigma^2}{2}\,\mathrm{Var}(f_{k-1}) \tag{8.13}

Backward. Element jj of equation 8.8 is a sum of Dk+1D_{k+1} terms Ωk,djδk,d\Omega_{k,dj}\delta_{k,d}, and equation 8.9 keeps about half of the results. Treating the weights, error signals and activation pattern as independent (an approximation, but a good one at initialization), the same argument gives:

Var(δk−1)=Dk+1 σ22 Var(δk)(8.14)\mathrm{Var}(\delta_{k-1}) = \frac{D_{k+1}\,\sigma^2}{2}\,\mathrm{Var}(\delta_k) \tag{8.14}

In words: each layer multiplies the variance of the forward signal by Dkσ2/2D_k\sigma^2/2 and the variance of the backward signal by Dk+1σ2/2D_{k+1}\sigma^2/2. If these factors are smaller than 1, both signals vanish exponentially with depth; if they are larger, both explode. They equal 1 when σ2=2/Dk\sigma^2 = 2/D_k (forward) or σ2=2/Dk+1\sigma^2 = 2/D_{k+1} (backward), which is He initialization [6]. When all hidden layers have the same width DD, both conditions say σ2=2/D\sigma^2 = 2/D.

Figure 8.3 checks this with a simulation: 50 ReLU layers of width 100, no biases, a batch of 256 random inputs, weights with variance c/Dc/D for c=1,2,3c = 1, 2, 3, and a random error signal at the top. With c=2c = 2, the pre-activations and error signals keep roughly the same size through all 50 layers. With c=1c = 1, each layer multiplies the standard deviation by about 1/2\sqrt{1/2}: after 50 layers the pre-activations have shrunk to 1.45×10−81.45 \times 10^{-8} of their size, and the error signal at the first layer to 1.58×10−81.58 \times 10^{-8}. With c=3c = 3, both grow by about 3/2\sqrt{3/2} per layer, to 2.9×1042.9 \times 10^{4} and 1.6×1041.6 \times 10^{4}.

Two plots against layer number from 1 to 50, both with logarithmic vertical axes. a) The size of the pre-activations: a green line stays near 1, an orange line rises steadily to about ten thousand, a blue line falls steadily to about one in a hundred million. b) The size of the error signals: the green line stays near 1, the orange line falls from about ten thousand at layer 1 to about 1 at layer 50, and the blue line rises from about one in a hundred million at layer 1 to about 1 at layer 50.

Figure 8.3 The scale of the initial weights decides whether signals survive 50 layers. A ReLU network with 50 layers of width 100, weights drawn with variance σ2=c/D\sigma^2 = c/D, a batch of 256 random inputs and a random error signal at the last layer. a) The root-mean-square size of the pre-activations fk\mathbf{f}_k in the forward pass. b) The size of the error signals δk\boldsymbol{\delta}_k in the backward pass, which runs from layer 50 down to layer 1. With c=2c = 2 (green, He initialization) both stay near 1, as equations 8.13 and 8.14 predict. With c=1c = 1 (blue) both shrink by a factor of about 2\sqrt{2} per layer, and with c=3c = 3 (orange) both grow by about 1.5\sqrt{1.5} per layer.

A subtlety appears when we look at the weight gradients themselves. By equation 8.7, the gradient of layer kk is δkhk⊤\boldsymbol{\delta}_k\mathbf{h}_k^\top. With c=1c = 1, the activations are small in late layers and the error signals are small in early layers, and the product is small in every layer by about the same overall factor, (c/2)K/2≈3×10−8(c/2)^{K/2} \approx 3 \times 10^{-8}; the simulation measures weight-gradient norms between 5×10−85 \times 10^{-8} and 10−710^{-7} at layers 1, 25 and 50 alike. So in a plain ReLU network with equal widths, a bad scale does not make early layers learn more slowly than late ones. It makes the whole network's outputs and gradients useless, and no single learning rate fixes outputs that are 10−810^{-8} times the size they should be. In other settings the imbalance between layers is real. With sigmoid or tanh units, whose slopes are below 1 almost everywhere, and in recurrent networks, which multiply by the same matrix at every time step, the error signals shrink on the way back while the activations do not, so early layers or early time steps receive tiny gradients. This is the vanishing gradient problem in its classic form [8].

Initialization keeps the signals the right size at the start of training. It does not keep them there as the weights change, and it does not help with a different difficulty: the deep plain network that trains worse than a shallow one (article 7, section 5). Article 11 introduces residual connections, which add an identity path to every layer so that equation 8.12 no longer consists only of products, and normalization layers, which reset the scale of the activations at every layer.

Summary

Backpropagation computes the derivative of the loss with respect to every parameter in one backward pass whose cost is a small multiple of the forward pass. The forward pass stores the intermediate values. The backward pass starts from the derivative of the loss and visits the values in reverse order, multiplying by one local derivative per operation and summing over every use of a value (equation 8.5). For a deep network this gives three equations: the weight gradient is the error signal times the activation it multiplies, an outer product; the error signal moves back past a weight matrix by multiplying with its transpose; and it moves back past ReLU by zeroing inactive units. The backward pass costs about twice the forward pass, and training must keep every layer's activations, which is why it needs much more memory than prediction. For softmax with cross-entropy, the backward pass starts from the predicted probabilities minus the targets. The same algorithm, applied to any program, is reverse-mode automatic differentiation. Finally, the backward pass is a product of one factor per layer, and analysing its variance gives He initialization; the remaining difficulties of training very deep networks are taken up in article 11. Article 9 now turns from fitting the training data to generalizing beyond it.

Notes

History. Reverse-mode differentiation was described by Linnainmaa in 1970 [3] as a way to compute the rounding errors of long computations, and Werbos proposed applying it to neural networks in his 1974 thesis [4]. Rumelhart, Hinton and Williams [2] showed in 1986 that it lets multilayer networks learn useful internal representations, and that paper brought it into wide use. Baydin and colleagues [9] survey automatic differentiation for machine learning.

Second derivatives. Backpropagation gives the gradient. Second derivatives, the Hessian matrix, have P2P^2 entries and are rarely formed for neural networks. Products of the Hessian with a vector can be computed at the cost of a few gradient evaluations by applying forward mode to the backward pass, which is how many analyses of the loss curvature work.

Other initializations. For activations that are linear near zero, such as tanh, equation 8.13 without the factor 1/21/2 suggests σ2=1/D\sigma^2 = 1/D. Glorot and Bengio [10] compromised between the forward and backward conditions with σ2=2/(Dk+Dk+1)\sigma^2 = 2/(D_k + D_{k+1}), often called Xavier initialization. The derivations assume independent weights; orthogonal initialization, which draws each weight matrix as a random rotation, preserves the length of every vector exactly in a linear network.

Non-differentiable points. ReLU has no derivative at 0, and maximum and absolute-value operations have similar kinks. Automatic differentiation picks one value of the derivative there (for ReLU, 0). Because pre-activations are exactly zero with negligible probability, this choice rarely matters in practice.

Reading further. Chapter 7 of Understanding Deep Learning [1] derives backpropagation for the same toy model and for deep networks, and covers initialization. Griewank and Walther [5] is the standard reference on automatic differentiation.

Problems

Problem 8.1 For the chain of section 2, compute ∂ℓ/∂x\partial\ell/\partial x. Why does training never need it? (Answer: ω0 ∂ℓ/∂f0=1.2×(−0.5576)=−0.6691\omega_0\,\partial\ell/\partial f_0 = 1.2 \times (-0.5576) = -0.6691. The input is data, not a parameter, so gradient descent never updates it.)

Problem 8.2 In the network of section 4, change the target to y=3y = 3 and leave everything else unchanged. What are the new gradients? (Answer: the forward pass is unchanged and δ2=2(2.25−3)=−1.5\delta_2 = 2(2.25 - 3) = -1.5. Every gradient is linear in δ2\delta_2, so all of them are multiplied by −1.5/2.5=−0.6-1.5/2.5 = -0.6: for example ∂ℓ/∂Ω2=(−5.25,0)\partial\ell/\partial\boldsymbol{\Omega}_2 = (-5.25, 0) and ∂ℓ/∂Ω0\partial\ell/\partial\boldsymbol{\Omega}_0 has rows (0,0)(0, 0) and (−1.5,−3)(-1.5, -3).)

Problem 8.3 For the scores z=(2.0,0.5,−1.0)\mathbf{z} = (2.0, 0.5, -1.0), compute the error signal of equation 8.11 when the correct class is the second one. Show that the elements of equation 8.11 always sum to zero. (Answer: (0.786,−0.825,0.039)(0.786, -0.825, 0.039). The sum is ∑kpk−1=0\sum_k p_k - 1 = 0.)

Problem 8.4 Let u=1u = 1, v1=2uv_1 = 2u, v2=u2v_2 = u^2 and ℓ=v1v2\ell = v_1 v_2. Compute ∂ℓ/∂u\partial\ell/\partial u with equation 8.5 and check it by writing ℓ\ell as a function of uu. (Answer: ∂ℓ/∂v1=v2=1\partial\ell/\partial v_1 = v_2 = 1 and ∂ℓ/∂v2=v1=2\partial\ell/\partial v_2 = v_1 = 2, so ∂ℓ/∂u=2×1+2u×2=6\partial\ell/\partial u = 2 \times 1 + 2u \times 2 = 6. Directly, ℓ=2u3\ell = 2u^3 and its derivative is 6u2=66u^2 = 6.)

Problem 8.5 How many multiply-adds does one training step of the (784,256,256,10)(784, 256, 256, 10) classifier need for a batch of 256, forward and backward together? (Answer: 256×(268,800+336,896)=155,058,176256 \times (268{,}800 + 336{,}896) = 155{,}058{,}176, about 155 million.)

Problem 8.6 Repeat the forward-variance derivation of section 8 for an activation function that is the identity, a(z)=za(z) = z. Which weight variance keeps the pre-activations the same size? (Answer: without the ReLU, E[h2]=Var(f)\mathbb{E}[h^2] = \mathrm{Var}(f), so Var(fk)=Dkσ2 Var(fk−1)\mathrm{Var}(f_k) = D_k\sigma^2\,\mathrm{Var}(f_{k-1}) and σ2=1/Dk\sigma^2 = 1/D_k.)

Problem 8.7 In the simulation of figure 8.3 with c=1c = 1, by roughly what factor should the size of the pre-activations shrink between layer 1 and layer 50, according to equation 8.13? Compare with the measured 0.9880.988 and 1.45×10−81.45 \times 10^{-8}. (Answer: (1/2)49/2≈4.2×10−8(1/2)^{49/2} \approx 4.2 \times 10^{-8}; the measured ratio is 1.47×10−81.47 \times 10^{-8}, the same order of magnitude. The difference comes from random fluctuations that compound over 49 layers.)

References