AI / ML Theory
Chapter 2 · 16 min

2.7 — Backprop, part 3: weight and bias gradients

Goal: Express the gradient of the loss w.r.t. each layer's weights and biases in terms of the layer's delta and its input activation.

1. Why this session exists

Sessions 2.5 and 2.6 gave us δ(ℓ)\delta^{(\ell)} at every layer. The last step of backprop is to convert these deltas into the gradients we update with: ∂L/∂W(ℓ)\partial L / \partial W^{(\ell)} and ∂L/∂b(ℓ)\partial L / \partial b^{(\ell)}. The conversion is one line each, and the pattern is the same "residual × input" outer product we saw in 1.3 and 1.8 — just applied at every layer of the network.[1]


2. Per-example formula

At layer ℓ\ell, the pre-activation is

z(ℓ)  =  W(ℓ)a(ℓ−1)+b(ℓ).z^{(\ell)} \;=\; W^{(\ell)} a^{(\ell-1)} + b^{(\ell)}.

Entry by entry, zi(ℓ)=∑jWi,j(ℓ) aj(ℓ−1)+bi(ℓ)z^{(\ell)}_i = \sum_j W^{(\ell)}_{i, j}\, a^{(\ell-1)}_j + b^{(\ell)}_i. So

∂zi(ℓ)∂Wi,j(ℓ)=aj(ℓ−1),∂zp(ℓ)∂Wi,j(ℓ)=0 for p≠i.\frac{\partial z^{(\ell)}_i}{\partial W^{(\ell)}_{i, j}} = a^{(\ell-1)}_j, \qquad \frac{\partial z^{(\ell)}_p}{\partial W^{(\ell)}_{i, j}} = 0 \text{ for } p \ne i.

By the chain rule with δ(ℓ)=∂L/∂z(ℓ)\delta^{(\ell)} = \partial L / \partial z^{(\ell)},

∂L∂Wi,j(ℓ)  =  ∑p∂L∂zp(ℓ)⋅∂zp(ℓ)∂Wi,j(ℓ)  =  δi(ℓ)⋅aj(ℓ−1).\frac{\partial L}{\partial W^{(\ell)}_{i, j}} \;=\; \sum_p \frac{\partial L}{\partial z^{(\ell)}_p} \cdot \frac{\partial z^{(\ell)}_p}{\partial W^{(\ell)}_{i, j}} \;=\; \delta^{(\ell)}_i \cdot a^{(\ell-1)}_j.

Stacking entries (i,j)(i, j) into a matrix,

 ∂L∂W(ℓ)  =  δ(ℓ) (a(ℓ−1))⊤  ∈  Rdℓ×dℓ−1. \boxed{\ \frac{\partial L}{\partial W^{(\ell)}} \;=\; \delta^{(\ell)}\, \bigl(a^{(\ell-1)}\bigr)^\top \;\in\; \mathbb{R}^{d_\ell \times d_{\ell-1}}.\ }

Outer product: delta column at layer ℓ\ell times activation row at layer ℓ−1\ell - 1.

For the bias, ∂zp(ℓ)/∂bi(ℓ)=δpi\partial z^{(\ell)}_p / \partial b^{(\ell)}_i = \delta_{pi}, so

 ∂L∂b(ℓ)  =  δ(ℓ)  ∈  Rdℓ. \boxed{\ \frac{\partial L}{\partial b^{(\ell)}} \;=\; \delta^{(\ell)} \;\in\; \mathbb{R}^{d_\ell}.\ }

3. Batched form

For a mini-batch of BB examples, with Δ(ℓ)∈RB×dℓ\Delta^{(\ell)} \in \mathbb{R}^{B \times d_\ell} and A(ℓ−1)∈RB×dℓ−1A^{(\ell-1)} \in \mathbb{R}^{B \times d_{\ell-1}} as before, the weight gradient is the sum of per-example outer products, scaled by 1/B1 / B:

 ∂Lbatch∂W(ℓ)  =  1B (Δ(ℓ))⊤ A(ℓ−1)  ∈  Rdℓ×dℓ−1. \boxed{\ \frac{\partial L_{\text{batch}}}{\partial W^{(\ell)}} \;=\; \frac{1}{B}\, (\Delta^{(\ell)})^\top\, A^{(\ell-1)} \;\in\; \mathbb{R}^{d_\ell \times d_{\ell-1}}.\ }

(Recover the per-example case by inspecting one row of Δ\Delta and one row of AA; the matrix product over BB rows is the sum of outer products.)

The bias gradient is the column-wise average of Δ(ℓ)\Delta^{(\ell)}:

 ∂Lbatch∂b(ℓ)  =  1B ∑i=1BΔi,:(ℓ)  ∈  Rdℓ. \boxed{\ \frac{\partial L_{\text{batch}}}{\partial b^{(\ell)}} \;=\; \frac{1}{B}\, \sum_{i=1}^B \Delta^{(\ell)}_{i, :} \;\in\; \mathbb{R}^{d_\ell}.\ }

In PyTorch this is Delta.T @ A / B for the weight and Delta.mean(dim=0) for the bias.


4. Shape sanity check

  • W(ℓ)W^{(\ell)} is dℓ×dℓ−1d_\ell \times d_{\ell-1}.
  • Δ(ℓ)\Delta^{(\ell)} is B×dℓB \times d_\ell, A(ℓ−1)A^{(\ell-1)} is B×dℓ−1B \times d_{\ell-1}.
  • (Δ(ℓ))⊤A(ℓ−1)(\Delta^{(\ell)})^\top A^{(\ell-1)} is dℓ×dℓ−1d_\ell \times d_{\ell-1} ✓ (matches W(ℓ)W^{(\ell)}).
  • Δ(ℓ)\Delta^{(\ell)} summed over rows is dℓd_\ell ✓ (matches b(ℓ)b^{(\ell)}).

A gradient must be the same shape as the parameter it differentiates. If you ever see a transposed result, you've swapped the order in the outer product.


5. The full forward + backward picture

End-to-end picture of one training step on a mini-batch.

Forward (vectorised): for ℓ=1,…,L\ell = 1, \dots, L,

Z(ℓ)=A(ℓ−1)(W(ℓ))⊤+b(ℓ),A(ℓ)=g(ℓ)(Z(ℓ)).Z^{(\ell)} = A^{(\ell-1)} (W^{(\ell)})^\top + b^{(\ell)}, \qquad A^{(\ell)} = g^{(\ell)}(Z^{(\ell)}).

Compute LbatchL_{\text{batch}}.

Backward (vectorised):

  1. Initialise Δ(L)\Delta^{(L)} at the output layer (2.5; for softmax + CE it is 1B(Y^−Y)\tfrac{1}{B}(\hat Y - Y)).
  2. For ℓ=L−1,L−2,…,1\ell = L - 1, L - 2, \dots, 1, recurse Δ(ℓ)=(Δ(ℓ+1)W(ℓ+1))⊙g′(ℓ)(Z(ℓ))\Delta^{(\ell)} = (\Delta^{(\ell+1)} W^{(\ell+1)}) \odot g'^{(\ell)}(Z^{(\ell)}) (2.6).
  3. For each ℓ\ell, compute ∂L/∂W(ℓ)=(Δ(ℓ))⊤A(ℓ−1)\partial L / \partial W^{(\ell)} = (\Delta^{(\ell)})^\top A^{(\ell-1)} and ∂L/∂b(ℓ)=Δ(ℓ) sum over batch axis\partial L / \partial b^{(\ell)} = \Delta^{(\ell)}\, \text{sum over batch axis}.

(The 1/B1/B factor lives wherever you decide; standard practice folds it into the output delta or the loss itself.)

Update. For each layer,

W(ℓ)←W(ℓ)−α ∂L∂W(ℓ),b(ℓ)←b(ℓ)−α ∂L∂b(ℓ).W^{(\ell)} \leftarrow W^{(\ell)} - \alpha\, \frac{\partial L}{\partial W^{(\ell)}}, \qquad b^{(\ell)} \leftarrow b^{(\ell)} - \alpha\, \frac{\partial L}{\partial b^{(\ell)}}.

One training step ≈ three forward passes' worth of FLOPs. Convergence is the topic of Chapter 3.


6. Takeaways

  • ∂L/∂W(ℓ)=δ(ℓ)(a(ℓ−1))⊤\partial L / \partial W^{(\ell)} = \delta^{(\ell)} (a^{(\ell-1)})^\top. Outer product: delta × input.
  • ∂L/∂b(ℓ)=δ(ℓ)\partial L / \partial b^{(\ell)} = \delta^{(\ell)}.
  • Batched: ∂L/∂W(ℓ)=1B(Δ(ℓ))⊤A(ℓ−1)\partial L / \partial W^{(\ell)} = \tfrac{1}{B} (\Delta^{(\ell)})^\top A^{(\ell-1)}, bias is the batch-mean of Δ(ℓ)\Delta^{(\ell)}.
  • Combined with 2.5 and 2.6, you now have the complete backprop algorithm.

Self-test

(a) Derive the weight gradient identity from scratch using the chain rule on z(ℓ)=W(ℓ)a(ℓ−1)+b(ℓ)z^{(\ell)} = W^{(\ell)} a^{(\ell-1)} + b^{(\ell)}. Check that the result is an outer product.

(b) For the MNIST MLP of 2.4 §4 (widths (784,256,128,10)(784, 256, 128, 10)) and batch B=32B = 32, compute the FLOP count of one forward pass and of the corresponding backward pass. Verify backward ≈ forward.

(c) Suppose two examples in the same mini-batch have very different deltas — one δ=+5\delta = +5, another δ=−5\delta = -5. How does the mean gradient over the batch behave? Why is this a feature, not a bug? (Hint: noise averaging in SGD.)

(d) For layer 1, the input is the data itself: a(0)=xa^{(0)} = x. Write out ∂L/∂W(1)\partial L / \partial W^{(1)} explicitly in terms of δ(1)\delta^{(1)} and the raw input.


References

  1. [1]

    Rumelhart, D. E., Hinton, G. E., & Williams, R. J. (1986). "Learning representations by back-propagating errors". Nature, 323(6088), 533–536. — Backpropagation (2.5–2.7).

    ↩