The Chain Rule in Computational Graphs
The chain rule is the way to compute gradients of a loss function with respect to those parameters in a computational graph.
Why One Input Is Not Enough
For a function of one variable, asking how fast the output changes is straightforward: you look at one input and one output. Machine learning rarely works that way. A model usually depends on many parameters at once, and its quality is summarized by a loss value that depends on all of them together. To decide how to adjust those parameters, we need a way to describe how the output responds to each input, and then a way to package all of those responses into one object.
This article builds that object step by step. We start with a single slice of a function, move to the full collection of slices, and then see how the chain rule and PyTorch's autograd engine compute these quantities for a loss function. Along the way you will be asked to predict a gradient before the code reveals it, so keep a pencil nearby.
Partial Derivatives With Other Inputs Frozen
A partial derivative measures how a multivariate function changes along one input while the other inputs are held fixed.
Take a function f that accepts several inputs, such as x and y. The partial derivative with respect to x answers this question: if I nudge x a little and hold every other input fixed, how much does the output move per unit of nudge? The same logic applies to y. Each partial derivative is therefore a one-dimensional view of a higher-dimensional surface, taken along the direction of one chosen variable.
f(x, y) = x^{2} y at x = 2, y = 3 gives f = 12x = 2, y = 3, output 12
Nudge x to 2.01, keep y = 3 gives f = 12.12
x = 2.01, y = 3, output about 12.12
In the nudge above, the output rose by about 0.12 for a change of 0.01 in x, so the slope along x is roughly 12 at this point. Notice that y did not move at all during the nudge. If we had instead nudged y and frozen x, the output would have changed at a different rate. That is the whole point of a partial derivative: it reports change along one axis and ignores the others.
Computing the partial derivatives of x squared times y
Let f(x, y) = x^{2} y. Find the partial derivative with respect to x and the partial derivative with respect to y, then evaluate both at x = 2, y = 3.
- 1Partial with respect to x
Treat y as a constant. The expression x^{2} y is then a constant multiple of x^{2}, so the derivative is $\frac{\partial f}{\partial x} = 2xy$.
- 2Partial with respect to y
Now treat x as the constant. The expression is x^{2} times y, and the derivative of y is 1, so $\frac{\partial f}{\partial y} = x^{2}$.
- 3Evaluate at x = 2, y = 3
$\frac{\partial f}{\partial x} = 2 \cdot 2 \cdot 3 = 12$ and $\frac{\partial f}{\partial y} = 2^{2} = 4$.
At (2, 3) the slope along x is 12 and the slope along y is 4. These match the nudge experiment: moving x changed the output by about 12 per unit.
Gathering Partial Derivatives Into a Gradient
Individual partial derivatives are useful, but a function with many inputs produces many of them, and keeping them in a loose list is awkward. The gradient packages them into one object. A gradient is a vector containing all of a multivariate function's partial derivatives, giving one entry per input variable.
The position of each entry tells you which input it belongs to. The first entry is always the partial with respect to the first input, and so on. The gradient is therefore a compact record of how the function responds to every input at once, describing the rate of change with respect to all of its variables in a single object.
Notice that the two entries can behave differently. The entry for x depends on where you are, because the slope along x changes as x changes. For $f(x, y) = x^{2} y$ the y entry is $x^{2}$, which is also location-dependent here. Both entries are still just partial derivatives, each measured along its own axis. A function with ten inputs has a gradient with ten entries, and the same reading applies to each one.
Why a Loss Needs Gradients With Respect to Parameters
In training a model, the quantity we usually care about is a loss, a single number that serves as a proxy for how well the model performs. The loss depends on the model's parameters. The chain rule is the way to compute gradients of a loss function with respect to those parameters in a computational graph.
Those gradients provide the information needed to update each parameter so that the loss goes down. A method such as gradient descent uses them to decide the direction and rough size of each adjustment. Because the loss is a function of many parameters, the gradient with respect to all of them is exactly the multivariate object introduced earlier.
Tracing a Loss Back Through a Graph
Real losses are not single formulas written in one step. They are built from a sequence of smaller operations, each feeding its result into the next. A parameter enters near the start, is combined with data, passes through further operations, and finally produces the loss. Following this path is what the chain rule does: it links how a parameter affects an intermediate result, and how that intermediate result affects the loss.
In this illustrative graph, changing w1 changes y, which changes the difference, which changes the squared loss. The chain rule multiplies these local sensitivities together along the path. This is how the gradient of the loss with respect to w1 is obtained even though w1 appears several steps before the loss.
Multiplying local sensitivities along one path
Using the graph y = w1 times x, d = y minus t, L = d squared, with x = 2, t = 5, and w1 = 1, find the gradient of L with respect to w1.
- 1Forward pass
y = 1 times 2 = 2, then d = 2 minus 5 = minus 3, then L = (minus 3) squared = 9.
- 2Local sensitivity of L to d
$\frac{dL}{dd} = 2d = 2 \cdot (-3) = -6$.
- 3Local sensitivity of d to y
$\frac{dd}{dy} = 1$, because d is y minus a constant.
- 4Local sensitivity of y to w1
$\frac{dy}{dw_{1}} = x = 2$, because y is w1 times a constant.
- 5Multiply along the path
$\frac{dL}{dw_{1}} = (-6)(1)(2) = -12$.
The gradient of the loss with respect to w1 is -12 at this point. Checking directly: L = (2 w1 minus 5) squared, so dL/dw1 = 4(2 w1 minus 5), which equals -12 when w1 = 1.
Letting Autograd Compute the Same Gradient
You do not have to write the chain rule by hand in PyTorch. The source explains that PyTorch's autograd engine constructs a computational graph in the background by tracking every operation performed on tensors. When you compute the loss, the operations that produced it are already recorded, so the engine can walk back through them and produce gradients for the tracked parameters.
What do you think happens?
Before running the code: for the same graph (y = w1 times x, d = y minus t, L = d squared, with x = 2, t = 5, w1 = 1), what will w1.grad be after L.backward()?
Reveal answer
-12
The backward pass multiplies the local sensitivities along the single path from L back to w1: (-6) times 1 times 2 equals -12.
tensor(-12.)- x and t are plain inputs, so no gradient is tracked for them
- w1 is marked
requires_grad=True, so autograd tracks operations that use it - Each line builds part of the graph as a side effect of running
L.backward()walks back through the recorded operations- The gradient is stored on w1.grad, the attribute the source describes
The printed value matches the hand calculation exactly. The engine did not need a special formula for this graph. It applied the same local-sensitivity multiplication you performed above, one recorded operation at a time, and deposited the result on the parameter. Calling backward on the loss is what produces the gradients for tracked parameters.
Mistakes With Partial Derivatives and Backward
Common mistake Moving several inputs together when computing a partial derivative
What it looks likeComputing the change in f(x, y) = x^{2} y when x and y both increase by 0.01
Why it failsA partial derivative isolates one variable and holds the others fixed. Moving both inputs measures a different quantity.
Do this insteadFreeze every other input, then measure the change along one axis at a time.
Common mistake Skipping intermediate nodes and treating the parameter as acting directly on the loss
What it looks likeTrying to differentiate L directly with respect to w1 without noticing that y and d sit between them
Why it failsThe parameter influences the loss through a chain of operations, and each link contributes a local sensitivity.
Do this insteadTrace the path from the parameter to the loss, compute each local derivative, and multiply them along that path.
Common mistake Expecting w1.grad to exist before backward is called
Why it failsThe gradient is produced by the backward pass, so reading it earlier gives no computed value.
Do this insteadCall backward on the loss first, then read the gradient from the parameter's grad attribute.
Common mistake Treating the gradient as a loose list of unrelated numbers
Why it failsEach entry is tied to one specific input by its position, and the entries together describe the function's response to every input.
Do this insteadKeep the entries in input order and read each one as the slope along its own variable.
Practice Computing a Gradient
Let f(x, y) = 3x + x y squared. Find the gradient of f, then evaluate it at x = 1, y = 2. Write the result as a vector, with the x entry first.
Hints
- Treat y as a constant when differentiating with respect to x. The term x y squared is then a constant multiple of x.
- Treat x as a constant when differentiating with respect to y. The term x y squared is then a constant multiple of y squared.
- The expected result is (3 + 4, 4), so check that the x entry is 3 plus y squared, and the y entry is 2 x y.
Key Takeaways
- A partial derivative measures how a multivariate function changes along one input while the other inputs are held fixed.
- A gradient is a vector holding all of a multivariate function's partial derivatives, with one entry per input variable and position identifying which input each entry belongs to.
- In a computational graph, the chain rule computes the gradient of a loss with respect to a parameter by multiplying local sensitivities along each path from the parameter to the loss.
- PyTorch's autograd engine records tensor operations in the background, so calling backward on a loss produces the gradients for tracked parameters, which you read from the grad attribute.