AnyLearn
All lessons
AIintermediate

Neural Networks and Backpropagation

Build intuition for how artificial neurons stack into layers, why nonlinear activations are non-negotiable, and how the chain rule turns a forward pass into exact gradients — illustrated with a tiny numpy forward+backward walk-through.

Not signed in — your progress and quiz score won't be saved.
Lesson progress1 / 10

The artificial neuron

A single neuron takes a vector of inputs xRn\mathbf{x} \in \mathbb{R}^n, computes a weighted sum, adds a bias, and passes the result through a nonlinearity:

y=σ ⁣(wx+b)y = \sigma\!\left(\mathbf{w}^\top \mathbf{x} + b\right)

w\mathbf{w} and bb are the learnable parameters; σ\sigma is the activation function. Without σ\sigma, stacking neurons just produces another linear map — the whole network collapses to a single matrix multiply. The activation is what makes deep networks expressive.

Biologically inspired but only loosely: real neurons fire spikes; artificial ones output a smooth scalar. What matters is the math, not the metaphor.

Full lesson text

All 10 steps on one page — for reading, reference, and search.

Show

1. The artificial neuron

A single neuron takes a vector of inputs xRn\mathbf{x} \in \mathbb{R}^n, computes a weighted sum, adds a bias, and passes the result through a nonlinearity:

y=σ ⁣(wx+b)y = \sigma\!\left(\mathbf{w}^\top \mathbf{x} + b\right)

w\mathbf{w} and bb are the learnable parameters; σ\sigma is the activation function. Without σ\sigma, stacking neurons just produces another linear map — the whole network collapses to a single matrix multiply. The activation is what makes deep networks expressive.

Biologically inspired but only loosely: real neurons fire spikes; artificial ones output a smooth scalar. What matters is the math, not the metaphor.

2. Activation functions: ReLU, sigmoid, tanh

The three workhorses, and when to reach for each:

ActivationFormulaRangeTypical use
Sigmoid1/(1+ez)1/(1+e^{-z})(0,1)(0,1)Binary output, gates
Tanh(ezez)/(ez+ez)(e^z - e^{-z})/(e^z + e^{-z})(1,1)(-1,1)RNNs, zero-centered
ReLUmax(0,z)\max(0, z)[0,)[0, \infty)Hidden layers (default)

ReLU dominates hidden layers: cheap to compute, sparse activations, gradient stays 1 for positive inputs (no vanishing). Its flaw — "dead neurons" (always zero) — is fixed by Leaky ReLU or GELU. Sigmoid and tanh saturate at extremes, causing near-zero gradients; avoid them in deep hidden layers.

3. Layers and the forward pass

Stack neurons in parallel to get a layer: for mm neurons with weight matrix WRm×nW \in \mathbb{R}^{m \times n} and bias bRm\mathbf{b} \in \mathbb{R}^m,

h=σ(Wx+b)\mathbf{h} = \sigma(W\mathbf{x} + \mathbf{b})

A forward pass threads the input through LL such layers in sequence: h(0)=x\mathbf{h}^{(0)} = \mathbf{x}, then h(l)=σ(l)(W(l)h(l1)+b(l))\mathbf{h}^{(l)} = \sigma^{(l)}(W^{(l)}\mathbf{h}^{(l-1)} + \mathbf{b}^{(l)}) for l=1,,Ll = 1, \ldots, L. The final layer's output is the prediction y^\hat{y}.

Every intermediate value h(l)\mathbf{h}^{(l)} (called an activation) must be stored during the forward pass — backpropagation will need them to compute gradients.

4. Why nonlinearity is non-negotiable

Suppose every σ\sigma were the identity. Then:

h(L)=W(L)W(2)W(1)x=Weffx\mathbf{h}^{(L)} = W^{(L)} \cdots W^{(2)} W^{(1)} \mathbf{x} = W_{\text{eff}}\, \mathbf{x}

No matter how many layers you add, the network is a single linear map. It can only fit data that lies on a hyperplane — it cannot learn XOR, spirals, or image classifiers.

The universal approximation theorem guarantees that a two-layer network with enough neurons and a nonlinear σ\sigma can approximate any continuous function on a compact domain to arbitrary precision. Depth gives efficiency: exponentially fewer neurons needed to represent the same function compared to a single-layer network.

5. Loss functions and what we're minimising

The network is only as good as what it's trained to minimize:

  • Mean squared error (regression): L=1Ni(yiy^i)2\mathcal{L} = \frac{1}{N}\sum_i (y_i - \hat{y}_i)^2
  • Cross-entropy (classification): L=1Niyilogy^i\mathcal{L} = -\frac{1}{N}\sum_i y_i \log \hat{y}_i

The loss collapses the full prediction into a single scalar. Training = finding weights {W(l),b(l)}\{W^{(l)}, \mathbf{b}^{(l)}\} that make this scalar small on the training set.

The gradient of L\mathcal{L} with respect to every parameter tells us which direction to move each weight. Computing those gradients efficiently is backpropagation's entire job.

6. The chain rule: backbone of backpropagation

If L\mathcal{L} depends on zz which depends on ww (via z=whz = wh), then:

Lw=Lzzw\frac{\partial \mathcal{L}}{\partial w} = \frac{\partial \mathcal{L}}{\partial z} \cdot \frac{\partial z}{\partial w}

Backpropagation applies this recursively from the output layer back to the first layer. Define the upstream gradient δ(l)=L/z(l)\delta^{(l)} = \partial \mathcal{L}/\partial \mathbf{z}^{(l)} (where z(l)=W(l)h(l1)+b(l)\mathbf{z}^{(l)} = W^{(l)}\mathbf{h}^{(l-1)} + \mathbf{b}^{(l)} is the pre-activation). Then:

δ(l1)=(W(l)δ(l))σ(l1)(z(l1))\delta^{(l-1)} = \left({W^{(l)}}^\top \delta^{(l)}\right) \odot \sigma'^{(l-1)}(\mathbf{z}^{(l-1)})

\odot is elementwise multiply, σ\sigma' is the activation derivative. The weight gradient is then L/W(l)=δ(l)h(l1)\partial \mathcal{L}/\partial W^{(l)} = \delta^{(l)} {\mathbf{h}^{(l-1)}}^\top.

7. Forward + backward in numpy

A minimal two-layer network with ReLU, squared loss, and exact gradients:

import numpy as np

# Data
X = np.array([[1.0, 2.0]])   # (1, 2) input
y = np.array([[0.5]])         # scalar target

# Parameters
W1 = np.random.randn(4, 2) * 0.1
b1 = np.zeros((4, 1))
W2 = np.random.randn(1, 4) * 0.1
b2 = np.zeros((1, 1))

# Forward pass
z1 = W1 @ X.T + b1            # (4,1)
h1 = np.maximum(0, z1)        # ReLU
z2 = W2 @ h1 + b2             # (1,1)
y_hat = z2                    # linear output
loss = 0.5 * (y_hat - y.T)**2

# Backward pass
dL_dz2 = y_hat - y.T          # (1,1)
dL_dW2 = dL_dz2 @ h1.T       # (1,4)
dL_dh1 = W2.T @ dL_dz2       # (4,1)
dL_dz1 = dL_dh1 * (z1 > 0)   # ReLU grad
dL_dW1 = dL_dz1 @ X           # (4,2)

Notice: the ReLU gradient is simply the indicator z1 > 0. Every gradient flows cleanly back via the chain rule.

8. Gradient flow and the vanishing gradient problem

The chain rule multiplies Jacobians across layers. With sigmoid activations, each factor is σ(z)=σ(z)(1σ(z))0.25\sigma'(z) = \sigma(z)(1-\sigma(z)) \le 0.25. Multiply 20 such terms and the gradient at the first layer is 0.25201012\approx 0.25^{20} \approx 10^{-12} — effectively zero. Weights in early layers stop updating: the vanishing gradient problem.

Solutions and their mechanisms:

  • ReLU: gradient is 1 for positive inputs — no shrinkage.
  • Residual connections (ResNet): add a skip h(l)+F(h(l))\mathbf{h}^{(l)} + F(\mathbf{h}^{(l)}) so gradients have a direct path.
  • Batch normalization: keeps activations in a healthy range, stabilizing gradient magnitudes.
  • LSTM gates: learned gating prevents gradients from decaying over time in sequences.

9. Forward and backward pass at a glance

Data flows left to right; gradients flow right to left.

flowchart LR
  X["Input x"]
  Z1["z1 = W1 x + b1"]
  H1["h1 = ReLU(z1)"]
  Z2["z2 = W2 h1 + b2"]
  YHAT["y_hat = z2"]
  L["Loss L"]
  GZ2["dL/dz2"]
  GW2["dL/dW2"]
  GH1["dL/dh1"]
  GZ1["dL/dz1"]
  GW1["dL/dW1"]
  X --> Z1 --> H1 --> Z2 --> YHAT --> L
  L --> GZ2
  GZ2 --> GW2
  GZ2 --> GH1
  GH1 --> GZ1
  GZ1 --> GW1

10. Putting it together: one training step

A single gradient-descent update bundles everything:

  1. Forward pass — compute y^\hat{y} and L\mathcal{L}, cache intermediate activations.
  2. Backward pass — propagate L/W(l)\partial \mathcal{L}/\partial W^{(l)} and L/b(l)\partial \mathcal{L}/\partial \mathbf{b}^{(l)} for every layer.
  3. Parameter updateW(l)W(l)ηL/W(l)W^{(l)} \leftarrow W^{(l)} - \eta \cdot \partial \mathcal{L}/\partial W^{(l)}, where η\eta is the learning rate.

Modern frameworks (PyTorch, JAX) do steps 1–3 automatically via automatic differentiation: they build a computational graph during the forward pass and call .backward() to traverse it in reverse.

Backpropagation doesn't magically find good weights — it's gradient descent that does. Backprop just makes computing the gradients cheap: O(forward pass cost)O(\text{forward pass cost}) rather than the O(P)O(P) forward passes that finite differences would need.

Check your understanding

The lesson ends with a 5-question quiz. Take it in the player above to see your score.

  1. A network with 10 hidden layers uses identity activations throughout. Which statement is true?
    • It can approximate any continuous function given enough neurons per layer.
    • It is equivalent to a single linear transformation regardless of depth.
    • Gradients will vanish because the Jacobian at each layer is the identity.
    • It is more expressive than a network with sigmoid activations.
  2. During backpropagation, why must intermediate activations $h^{(l)}$ be stored from the forward pass?
    • To compute the loss function at each layer independently.
    • To rerun the forward pass faster on the next iteration.
    • Because the weight gradient $\partial\mathcal{L}/\partial W^{(l)} = \delta^{(l)}{h^{(l-1)}}^\top$ requires them.
    • To implement momentum in the optimizer.
  3. Why does the vanishing gradient problem affect sigmoid networks more than ReLU networks?
    • Sigmoid outputs are always positive, so gradients become one-sided.
    • The sigmoid derivative is at most 0.25, shrinking gradients multiplicatively at each layer.
    • ReLU has a larger output range, so gradients are scaled up during backpropagation.
    • Sigmoid saturates only near zero, while ReLU saturates for large inputs.
  4. In the numpy backward pass, `dL_dz1 = dL_dh1 * (z1 > 0)`. What does `(z1 > 0)` represent?
    • A mask that zeroes out dead neurons permanently.
    • The derivative of the ReLU activation with respect to its input.
    • The sign of the weight matrix used in the forward pass.
    • A regularization term that penalizes negative pre-activations.
  5. The universal approximation theorem says a two-layer network can approximate any continuous function. What is the key practical limitation of this result?
    • It requires the activation function to be the sigmoid specifically.
    • It gives no bound on the number of neurons needed, which can be exponential.
    • It only applies to functions defined on infinite domains.
    • It assumes the network is trained with second-order optimizers.

Related lessons