Automatic differentiation evaluates exact derivatives of a program by applying
the chain rule to its computational graph, one primitive operation at a time. It
is not symbolic differentiation, which manipulates formulas and can blow up in
size, and it is not numerical differentiation, which perturbs inputs and pays a
truncation and rounding cost. AD works at machine precision and comes in two
sweeps of the same graph, forward and reverse.1
The computational graph
Take y=sin(x1)+x1x2 evaluated at (x1,x2)=(1,2). Break it into
primitives, giving intermediate variables v1,…,v5:
Every edge vi→vj carries a known local partial ∂vj/∂vi.
Both modes reuse these same locals; they differ only in the direction they are
chained.
Forward mode: propagate tangents
Pick a direction in input space and carry a tangent v˙i=∂vi/∂xj
alongside each value. Seed the input you want, x˙1=1 and x˙2=0,
then push tangents input-to-output by the chain rule
v˙j=∑i→j(∂vj/∂vi)v˙i:
One pass gives the derivative with respect to the seeded input only. To get
∂y/∂x2 you rerun with x˙2=1. Forward mode is cheap
when there are few inputs.
Reverse mode: propagate adjoints
Now run the values forward first, then sweep back carrying an adjoint
vˉi=∂y/∂vi, the sensitivity of the output to each node.
Seed the output, vˉ5=1, and push adjoints output-to-input by
vˉi=∑i→jvˉj(∂vj/∂vi):
Note vˉ1 accumulates two contributions, one from each edge leaving v1.
A single reverse pass returns the derivative with respect to every input at once,
∂y/∂x1 and ∂y/∂x2 together. Reverse mode
is cheap when there is one scalar output and many inputs. This backward sweep is
exactly backpropagation, the subject of the next article.
Forward vs reverse ADinteractive
seed
nodeopvaluev̇
v₁x₁11
v₂x₂··
v₃sin··
v₄×··
v₅+··
step 1/5 · forward · seed
v₁ = x₁ = 1
v̇₁ = 1 (seed)
Forward: one pass per input.
seed v̇₁=1 → ∂y/∂x₁ = 2.5403
the other input needs a second pass: n inputs ⇒ n passes.
The graph of y = sin(x1) + x1*x2 at (1, 2). Forward mode carries each node's value and tangent (v-dot) input-to-output; switch the seed to see it returns one derivative per pass. Reverse mode runs the forward pass for values, seeds v-bar = 1 at the output, then accumulates adjoints backward, returning both derivatives in one pass. The panel shows the arithmetic of the highlighted step.
Which mode, and why
For a function f:Rn→Rm with Jacobian J∈Rm×n,
forward mode seeded with x˙=ej returns Jej, the j-th column, so
building all of J costs n passes. Reverse mode seeded with yˉ=ei
returns ei⊤J, the i-th row, so all of J costs m passes:
forward∼n passes,reverse∼m passes.
A machine-learning loss is the extreme case m=1 with n in the millions: one
reverse pass yields the full gradient, while forward mode would need one pass per
parameter. When instead the map has few inputs and many outputs, forward wins.
Same locals, same graph; the only choice is which direction to chain.1