A forward pass turns parameters into a loss, but gradient descent needs more, namely the rate at which the loss changes with every single parameter. Nudging each parameter in turn and recomputing the loss would cost two forward passes per parameter, which is hopeless for a network with millions of them. Backpropagation obtains all of these derivatives from one forward pass and one backward pass. This lesson draws a tiny network as a computational graph, applies the multivariable chain rule along its paths, shows how reverse-mode automatic differentiation does the bookkeeping in code, and tests the result with finite differences. All numbers are constructed and dimensionless.
Key terms
Computational graph
Definition The computational graph of a calculation is a directed acyclic graph with one node for each input, parameter and intermediate result, and an edge from each argument of an operation to the node that holds its result. Every node that is not an input applies an elementary operation, such as addition, multiplication, ReLU or squaring, whose partial derivatives with respect to its arguments are known formulas. These are the local derivatives of the graph. Evaluating the nodes in a topological order, in which every node comes after all of its arguments, is the forward pass. When a training loss is differentiated with respect to the parameters, the data nodes, such as the input and the target, are held fixed.
In plain words The graph is the calculation drawn as a diagram of small steps. Each edge carries a simple local rate of change, and every derivative of the loss will be assembled from these rates and the values stored during the forward pass.
Example A tiny network has one input , one hidden ReLU unit, one output and a half squared error loss,
with parameters , , and . Take , , , , and . The forward pass gives , , , the error and the loss . At these values the local derivatives are , , because , , , and . The factor only makes the last local derivative equal to the error.
Multivariable chain rule
Definition Let be a function from to that is differentiable at , with values , and let be a function from to that is differentiable at . Then is differentiable at , and for each
or in matrix form , where is the Jacobian matrix of . Applied node by node in a computational graph whose operations are all differentiable at the current values, it gives the path rule. The derivative of the output with respect to any node equals the sum, over all directed paths from that node to the output, of the product of the local derivatives along the path. The hypothesis is differentiability, which is more than the existence of partial derivatives, and an operation evaluated where it has no derivative, such as ReLU at , breaks it.
In plain words Rates multiply along a chain of dependencies. When a quantity affects the output through several routes, the contributions of the routes add. Leaving out one route gives a wrong derivative even when every factor on the other routes is right.
Example Let at . The variable reaches through the squaring branch, with local derivatives and then , and directly through the addition, with local derivative . The two paths contribute and , so , in agreement with the derivative of the formula. Keeping only the squaring branch would give . Writing the square as the product gives two edges from into the multiplication, each with local derivative , and adding them is the product rule. In the tiny network a single path leads from to , through , and , so
Backpropagation
Definition Backpropagation computes the gradient of a scalar loss with respect to all parameters of a network by one forward pass followed by one backward pass. The forward pass stores every intermediate value. The backward pass visits the nodes in reverse topological order and computes, for each node , its adjoint , the derivative of the final loss with respect to that node’s value. It starts from , and the adjoint of each node is the sum, over the nodes that use it directly, of their adjoint times the local derivative. For a fully connected layer with and this gives, for one example,
where multiplies entry by entry and each adjoint has the shape of its variable. For a loss averaged over a batch, each parameter adjoint is the average of the per-example adjoints. The first formula needs to be differentiable at every entry of . Where a ReLU preactivation is exactly , implementations insert a chosen value, usually , which is a convention and not a derivative.
In plain words Work backward from the loss. Each node receives the sensitivity of the loss to its own value, multiplies it by its local rates and passes the products on to its arguments. One backward sweep, at a cost comparable to the forward pass, yields the derivative for every parameter at once, and that is what makes gradient training of large networks practical.
Example For the tiny network at the values above, start with . Then and , and the hidden value receives . The unit is active because , so , and finally and . In the order the gradient is . A gradient descent step with learning rate gives , , and . A new forward pass gives , , and
down from . That checks this one step. It does not show that every step size lowers the loss, and the loss of a network is in general not convex in its parameters.
Reverse-mode automatic differentiation
Definition Automatic differentiation computes derivatives of a function given as a program by applying the chain rule to the elementary operations the program executes, at the values it computes. Reverse mode records each operation, its arguments and its result during the forward evaluation, sets the adjoint of the scalar output to , and then processes the record in reverse order, adding each operation’s contribution to the adjoints of its arguments. At points where every executed operation is differentiable, the results are the exact derivatives of the executed composition, up to floating-point rounding. For a scalar output the whole gradient costs a small constant multiple of one evaluation, whatever the number of inputs, at the price of storing the intermediate values. Forward mode instead carries a derivative along with each value and yields one directional derivative per pass, so a gradient with respect to parameters takes passes. Automatic differentiation is neither a finite-difference estimate nor a symbolic simplification of a formula. Backpropagation is reverse mode applied to the loss of a neural network.
In plain words The software watches the forward calculation, keeps a list of what it did, and then walks the list backward applying the local rules. A value used in several places collects its adjoint by addition, one contribution per use, which is the path rule in code. The same addition explains a common bug. Frameworks that keep gradients in buffers attached to the parameters add every new backward pass into those buffers, so the buffers must be cleared before the next independent update, unless accumulation over several batches is intended and the loss is scaled for it.
Example The Python sketch below implements reverse mode for addition, multiplication and ReLU. Each node stores its value and, for each argument, the local derivative at the current values.
class Node:
def __init__(self, value, parents=()):
self.value = value # forward value
self.parents = parents # (argument, local derivative)
self.adjoint = 0.0
def add(a, b):
return Node(a.value + b.value, ((a, 1.0), (b, 1.0)))
def mul(a, b):
return Node(a.value * b.value,
((a, b.value), (b, a.value)))
def relu(a):
slope = 1.0 if a.value > 0 else 0.0 # 0 at the kink
return Node(max(0.0, a.value), ((a, slope),))
def backward(out):
order, seen = [], set()
def visit(n): # arguments before results
if id(n) not in seen:
seen.add(id(n))
for p, _ in n.parents:
visit(p)
order.append(n)
visit(out)
for n in order:
n.adjoint = 0.0
out.adjoint = 1.0
for n in reversed(order):
for p, d in n.parents:
# paths that meet add their contributions
p.adjoint += d * n.adjoint
u = Node(2.0)
q = add(mul(u, u), u)
backward(q)
print(u.adjoint) # 5.0Building the tiny network from the same operations, with the error written as and the loss as , gives the adjoints for . If the line with += used = instead, each adjoint would keep only the last contribution it received, and the sketch would report instead of for .
Gradient check
Definition A gradient check compares a computed gradient with finite-difference estimates. For parameter and a step the central difference is
where are the losses after moving parameter alone up or down by , and is the th coordinate vector. If has a continuous third derivative in on the interval from to , the difference between and the true partial derivative equals times that third derivative at some point of the interval. The comparison uses a relative difference such as when the two are not both . Each parameter costs two loss evaluations, so the check is a test on small models or a few coordinates, not a way to train. Too large a step picks up curvature, too small a step loses digits to rounding, and near a kink such as ReLU at the difference need not agree with any derivative convention. A passing check is evidence that the gradient code is right at the tested points, not a proof that it is right everywhere.
In plain words Nudge one parameter up and down, see how much the loss moves, and compare with the gradient the code reports. Agreement on several parameters and points builds confidence. Disagreement usually points to a missing path, a missing factor, a different averaging convention, or a test point at a kink.
Example At the working point of the tiny network with , the four central differences agree with with relative differences below . Near this point , so the loss is a polynomial of degree two in each single parameter, the central difference has no truncation error, and only rounding remains. Now suppose a backward pass forgets the factor on the edge from to and sets . It reports and , while the check gives and , and and still agree. The mismatch is confined to the parameters whose paths pass through the edge from to , which locates the error.
Check yourself
- In the tiny network keep , , , and , but set . Compute the loss and all four parameter derivatives. Does the zero derivative for mean that is at its best value?
Show the answer
The forward pass gives , , , the error and the loss . Backward, , so and . The hidden value receives , but the unit is inactive because , so and therefore and . The gradient in the order is .
The zero for only says that small changes of keep negative and leave the loss unchanged. The loss of is far from its smallest value, and can still lower it, so a step with learning rate moves from to and nothing else. A ReLU unit that is inactive on every training example passes no gradient to its incoming weights in this way.
- A hand-written backward pass for at returns , while a central difference with gives . Which value is right, which path was left out, and what would gradient descent do with the wrong value?
Show the answer
The variable reaches through the squaring branch, which contributes , and through the term , which contributes . The derivative is the sum, , so the backward pass left out the linear path. The central difference agrees, since and differ by , and dividing by gives , exact up to rounding because is quadratic.
With the wrong value , a gradient descent step increases . The true derivative says that increasing increases , so the faulty gradient moves uphill.
- In the tiny network set and keep , , , and . Automatic differentiation with the convention that ReLU has slope at returns , while a central difference with gives about . Is the gradient code broken?
Show the answer
No. Here , exactly at the kink, and the loss has no derivative in at this point. For small the unit is inactive, and , so the slope from the left is . For the loss is , whose slope at from the right is . The central difference is
which is for and tends to , the average of the two one-sided slopes. The value from automatic differentiation is the chosen convention, which here equals the slope from the left. Neither number is a derivative, so the mismatch says nothing about the code. Gradient checks belong at points away from kinks. With this convention a gradient step also leaves at , even though increasing would lower the loss.