Automatic differentiation over frames
How a straight-line program is differentiated by composing each step's derivative maps over its computation graph, forward with frames of tangents, backwards over its backpropagation graph with frames of cotangents, and forward-over-reverse for Hessian products.
Automatic differentiation computes the derivatives of a program exactly, up to rounding, from the derivatives of the steps it is made of. This note states the three ways of composing them that a library needs (pushing tangents forward, pulling cotangents back, and differentiating the pull-back once more for second order), each over a frame of several directions at once.
Programs and their computation graphs#
A straight-line program has slots , each holding a vector, and runs a sequence of steps
each writing one slot from slots written earlier. Each step’s map is smooth, with partial Jacobians , one per input, of shape (output dimension) by (dimension of input ). When an input is not differentiated, its partial Jacobian is simply never used.
A program is pictured by its computation graph. Its nodes are the slots, and it has an edge from each input of a step to that step’s output, so a node with incoming edges is computed by the step that writes it, from the nodes those edges come from. Because each step reads only slots written before it, the computation graph has no cycles, and the order of the steps is one of its topological orders. Its roots, the nodes with no incoming edge and so no ancestor, are the slots no step writes: the program’s inputs, the variables we differentiate with respect to. Some nodes are targets, the values to differentiate, . A node with several outgoing edges is a slot read by several steps.
- Root (an input)
- Slot written by a step
- input of a step
A frame is a matrix whose columns are directions: a tangent frame at a slot of dimension is a matrix of tangent vectors, and a cotangent frame a matrix whose columns are linear functionals, written as columns. Below, and are the frames held at slot .
Forward: pushing tangent frames#
Seed each root with a tangent frame (missing means zero), and run the steps in order, each pushing its inputs’ frames forward along the computation graph’s edges by its Jacobian–vector product:
By the chain rule, the frame reaching a target is : one pass with a frame of columns gives directional derivatives, and seeding the columns of an identity gives the whole Jacobian.
Reverse: pulling cotangent frames over the backpropagation graph#
The reverse pass runs on the backpropagation graph: the same nodes as the computation graph, with every edge reversed and labelled by the pull-back of the step it came from. Since reversing the edges swaps incoming for outgoing, a node is a root of the computation graph if and only if it is a leaf of the backpropagation graph, a node with no outgoing edge. Cotangents enter at the targets, flow along its edges, and end at those leaves, the program’s inputs. A node with several incoming edges, a slot read by several steps, receives a cotangent along each, and holds their sum.
- Root (an input)
- Slot written by a step
- pull-back
Seed each target with a cotangent frame , every other slot with zero, and run the steps backwards, each adding its vector–Jacobian product, the pull-back of its output’s cotangent, into each input:
The accumulation, which sums the cotangents arriving along every incoming edge of the backpropagation graph, is the chain rule for a slot with several consumers. When the steps are done, each root holds . For a scalar target seeded with , that is the gradient , whatever the number of roots.
Each column of a frame costs a small multiple of one evaluation of the program, in either direction. A Jacobian with few rows is cheaper in reverse, one with few columns forward.
Forward-over-reverse: Hessian products#
For second derivatives, differentiate the reverse pass itself along a path . Run the forward pass of (2) with velocities seeded at the roots, so that every slot holds its value and its velocity , then run the reverse pass over the backpropagation graph carrying two cotangents per slot: , as in (3), and , its derivative along the path. One column of is one path; a frame of columns runs paths at once, and then is a frame of columns while is the same for all of them. (A cotangent frame of several columns together with a velocity frame of several columns would make a three-way array; the passes here take one cotangent column.)
Differentiating (3) along the path by the product rule gives
The first term is the step’s own second-order map, which depends on the velocities of its inputs; the second is the step’s ordinary pull-back, applied to . A library writes the first for each step and the program applies the rule. Two consequences are useful when writing for a step. If a step is linear, its partial Jacobians are constant and its is zero. If the pull-back into input does not involve input , then the velocity of input contributes nothing to .
Let be a scalar target, seed its cotangent with and , and seed the roots with velocities . Then the reverse recurrences deliver, at every root ,
The cotangents are functions of the roots: the reverse recurrence holds as an identity in , with every evaluated at the slot values the program computes from . Differentiate that identity along for one column . By the product rule, satisfies (4), because the slot values move with the velocities the forward pass computed, and the seeds and are the value and the derivative of a constant. At a root, identically in , so its derivative along the path is .
∎With all roots stacked into one vector, : a frame of velocities gives columns of the Hessian for about times the cost of a gradient, and the identity frame gives all of it.
Built on by
- Derivatives in tangent charts The derivative of a map between manifolds, its gradient and its Hessian product, all read in the tangent charts a retraction provides, and why automatic differentiation computes them unchanged.
- The problem The mathematics the core rests on, from quantities, their charts and their products, through operations and their derivatives of first and second order composed over programs, to queries, terms, importance weights, random keys and retirement.