The Chain Rule Intermediate

The chain rule is the mathematical foundation of backpropagation. It tells us how to compute derivatives of composite functions - and a neural network is nothing but a chain of composed functions. Without the chain rule, training deep networks would be impossible.

Chain Rule Basics

If y = f(g(x)), then dy/dx = f'(g(x)) · g'(x). In words: multiply the derivatives along the chain.

Python
import numpy as np

# y = sin(x^2)
# Let u = x^2, then y = sin(u)
# dy/dx = dy/du * du/dx = cos(u) * 2x = cos(x^2) * 2x

def f(x):
    return np.sin(x**2)

def df(x):
    return np.cos(x**2) * 2 * x  # Chain rule applied

x = 1.0
print("Derivative at x=1:", df(x))  # cos(1) * 2 = 1.0806

Backpropagation as Chain Rule

A neural network computes: output = f3(f2(f1(x))). Backpropagation applies the chain rule from the output back to the input:

Python
# Simple 2-layer network backprop
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def sigmoid_deriv(x):
    s = sigmoid(x)
    return s * (1 - s)

# Forward pass
x = np.array([0.5, 0.3])
W1 = np.random.randn(2, 3) * 0.1
W2 = np.random.randn(3, 1) * 0.1

z1 = x @ W1              # Linear layer 1
a1 = sigmoid(z1)          # Activation 1
z2 = a1 @ W2              # Linear layer 2
output = sigmoid(z2)      # Final output

# Backward pass (chain rule!)
y_true = np.array([1.0])
dL_dout = -2 * (y_true - output)         # Loss gradient
dout_dz2 = sigmoid_deriv(z2)             # Activation gradient
dL_dz2 = dL_dout * dout_dz2             # Chain rule
dL_dW2 = a1.reshape(-1, 1) @ dL_dz2.reshape(1, -1)  # Gradient for W2

dL_da1 = dL_dz2 @ W2.T                  # Propagate back
dL_dz1 = dL_da1 * sigmoid_deriv(z1)     # Chain rule again
dL_dW1 = x.reshape(-1, 1) @ dL_dz1.reshape(1, -1)   # Gradient for W1

Automatic Differentiation

Modern frameworks like PyTorch automate the chain rule using computational graphs:

Python
import torch

# PyTorch handles all chain rule computation automatically
x = torch.tensor([2.0], requires_grad=True)

# Forward pass: y = sin(x^2) + x^3
y = torch.sin(x**2) + x**3

# Backward pass: compute dy/dx using chain rule
y.backward()

print("dy/dx =", x.grad)  # Automatic chain rule!
Key Takeaway: You rarely need to compute derivatives by hand. But understanding the chain rule helps you: (1) debug vanishing/exploding gradients, (2) design better architectures, and (3) understand why certain activation functions work better than others.

Next Up: Optimization

Now that you understand how gradients are computed, let's learn how to use them to optimize model parameters effectively.

Next: Optimization →

Ready to Go Deeper?

Live instructor-led courses from our partners. Affiliate disclosure.