Prerequisites. Direct starred prerequisites: Chapter 182. No later core chapter depends on this route.
One evaluation of D𝑡 delivers one directional derivative, by theorem 182.12. For a program 𝑡 of type 𝗋𝖾𝖺𝗅 in a context of 𝑛 variables of type 𝗋𝖾𝖺𝗅, the gradient has 𝑛 components, so obtaining it by the tangent macro costs 𝑛 evaluations of D𝑡, hence about 𝑛 times the cost of evaluating 𝑡. When 𝑡 is a loss function with 𝑛 in the millions, that factor decides whether the program is usable.
The gradient can be computed in a constant multiple of the cost of 𝑡, and the reason is linear algebra rather than programming. Evaluating 𝑡 at a point composes Jacobians, 𝐽 =𝐽𝑘⋯𝐽1; the tangent macro multiplies this product by a column vector from the right, one column at a time, while the gradient is 𝐽𝗍 applied to a single output cotangent, and 𝐽𝗍 =𝐽𝗍1⋯𝐽𝗍𝑘 is a product of transposes in reverse order. So a transformation computing gradients must run the program forward to obtain the points at which the 𝐽𝑖 are taken, and then apply the transposes backward.
Nothing in chapter 182 does this, and no lemma of that chapter is reused here. What must be built is a translation producing, along with the value of 𝑡, a backpropagator: a linear map from cotangents at the output to cotangents at the inputs. This chapter defines that translation, proves that its backpropagator denotes the transposed derivative, imports the corresponding statement for the language with higher-order subterms, and then treats the cost question separately, because the obvious representation of backpropagators is asymptotically wrong and the repair is not a corollary of correctness.
Signature delta
The forward development and the reverse development are two source systems, and the second is not an extension of the first. Before anything is reused, the differences are displayed.
|
Forward chapter |
This chapter |
| Source types |
𝗋𝖾𝖺𝗅, finite products, functions |
𝗋𝖾𝖺𝗅, finite products; functions only inside a term whose interface is first order |
| Target language |
the same language |
the source language extended by a type of linear maps between cotangent spaces |
| Translation |
one macro D on types and terms |
one macro ←D producing a pair: a primal value and a backpropagator |
| Semantics |
sets, with a logical relation on smooth curves |
the same for the first-order fragment proved here; diffeological spaces for the imported theorem |
| Theorem proved here |
theorem 182.12: tangent representation |
theorem 183.5: transposed derivative |
| Theorem imported |
theorem 182.14 (Huot–Staton–Vákár) |
theorem 183.7 (Vákár), theorem 183.9 (Smeding–Vákár) |
No lemma of chapter 182 is applied below. The denotational conventions of definition 182.5 — 𝗋𝖾𝖺𝗅 denotes ℝ, products denote products, each operation symbol denotes a fixed smooth function — are restated because they are the same conventions, not because a result is being transported.
Cotangents and backpropagators
Types are 𝜏,𝜎 ::=𝗋𝖾𝖺𝗅 ∣(𝜏1 ∗⋯ ∗𝜏𝑛) and terms are 𝑒 ::= 𝑥 ∣ op(𝑒1,…,𝑒𝑘) ∣ ⟨𝑒1,…,𝑒𝑛⟩::= ∣ 𝖼𝖺𝗌𝖾 𝑒 𝗈𝖿 ⟨𝑥1,…,𝑥𝑛⟩→𝑒′ ∣ 𝗅𝖾𝗍 𝑥=𝑒 𝗂𝗇 𝑒′, typed as in definition 182.4 and denoted as in definition 182.5; every operation symbol denotes a smooth function and comes with terms 𝜕𝑖op denoting its partial derivatives.
Referenced from 4 locations
For each type put C(𝗋𝖾𝖺𝗅):=ℝ and C(𝜏1 ∗⋯ ∗𝜏𝑛):=C(𝜏1) ×⋯ ×C(𝜏𝑛), and for a context Γ =𝑥1 :𝜏1,…,𝑥𝑛 :𝜏𝑛 put C(Γ):=∏𝑖C(𝜏𝑖). Each C(𝜏) is a real vector space with componentwise addition and a zero element 0𝜏; for Γ and an index 𝑖, write 𝜄𝑖 :C(𝜏𝑖) →C(Γ) for the map placing its argument in slot 𝑖 and 0 elsewhere.
Referenced from 2 locations
Let Γ ⊢𝑒 :𝜏 and 𝛾 ∈[[Γ]]. A backpropagator for 𝑒 at 𝛾 is a linear map 𝑏 :C(𝜏) →C(Γ) such that for every 𝑑 ∈C(𝜏) and every index 𝑖, (𝑏(𝑑))𝑖=∑𝑐𝑑𝑐𝜕[[𝑒]]𝑐𝜕𝑥𝑖(𝛾), the sum running over the scalar components 𝑐 of 𝜏. Equivalently 𝑏 =(𝐷[[𝑒]](𝛾))𝗍, the transpose of the Jacobian of [[𝑒]] at 𝛾.
Referenced from 2 locations
For Γ ⊢𝑒 :𝜏 define a pair ←D(𝑒) =(𝑣𝑒,𝑏𝑒), where 𝑣𝑒 is a term of type 𝜏 in context Γ and 𝑏𝑒 is a term denoting a map C(𝜏) →C(Γ), by induction on the derivation: ←D(𝑥𝑖):=(𝑥𝑖, 𝜆𝑑. 𝜄𝑖(𝑑)),←D(op(𝑒1,…,𝑒𝑘)):=(op(⃗𝑣), 𝜆𝑑. ∑𝑘𝑗=1𝑏𝑗(𝜕𝑗op(⃗𝑣)∗𝑑)),←D(⟨𝑒1,…,𝑒𝑛⟩):=(⟨⃗𝑣⟩, 𝜆⟨⃗𝑑⟩. ∑𝑛𝑗=1𝑏𝑗(𝑑𝑗)),←D(𝗅𝖾𝗍 𝑥=𝑒1 𝗂𝗇 𝑒2):=(𝑣2, 𝜆𝑑. 𝑔+𝑏1(𝑠)),where ⟨𝑔,𝑠⟩=𝑏2(𝑑), writing ⃗𝑣 for 𝑣1,… and ⃗𝑑 for 𝑑1,…, and in the last clause 𝑏2 is the backpropagator term produced for 𝑒2 in the context Γ,𝑥 :𝜎, so that it returns a pair consisting of a C(Γ) component 𝑔 and a C(𝜎) component 𝑠. The clause for 𝖼𝖺𝗌𝖾 is the clause for 𝗅𝖾𝗍 with 𝑛 bound variables in place of one.
Referenced from 11 locations
Each clause is the transpose of the corresponding forward clause, and the reversal of order is visible: in 𝗅𝖾𝗍, the backpropagator of the body runs first and its output cotangent for 𝑥 is then fed to the backpropagator of the bound expression.
Let Γ ⊢𝑒 :𝜏 in the fragment of definition 183.1 and let 𝛾 ∈[[Γ]]. Then [[𝑣𝑒]](𝛾) =[[𝑒]](𝛾) and [[𝑏𝑒]](𝛾) is a backpropagator for 𝑒 at 𝛾; that is, [[𝑏𝑒]](𝛾) =(𝐷[[𝑒]](𝛾))𝗍.
Referenced from 13 locations
Proof of Theorem 183.5 — Correctness of the reverse macro
Proof. Induction on the derivation. In each case the primal claim is immediate from the shape of the clause, so only the backpropagator claim is written.
Variable. [[𝑒]] =𝜋𝑖 has Jacobian the 𝑖-th projection, whose transpose is 𝜄𝑖, which is the clause.
Operation. Write 𝑢:=([[𝑒1]](𝛾),…,[[𝑒𝑘]](𝛾)). The chain rule gives, for each input index 𝑖, 𝜕[[op(𝑒1,…,𝑒𝑘)]]𝜕𝑥𝑖(𝛾)=𝑘∑𝑗=1𝜕[[op]]𝜕𝑦𝑗(𝑢)⋅𝜕[[𝑒𝑗]]𝜕𝑥𝑖(𝛾). Multiplying by 𝑑 and summing over the single output component, equation 183.1 for the composite equals ∑𝑗(𝑏𝑗(𝜕𝑗[[op]](𝑢) ⋅𝑑))𝑖 by the induction hypothesis applied to each 𝑒𝑗 with the cotangent 𝜕𝑗[[op]](𝑢) ⋅𝑑. That is the displayed clause.
Tuple. The Jacobian of ⟨𝑒1,…,𝑒𝑛⟩ stacks the Jacobians of the 𝑒𝑗, so its transpose is the sum of their transposes applied to the corresponding components of the cotangent, which is the clause.
Let. Let Γ ⊢𝑒1 :𝜎 and Γ,𝑥 :𝜎 ⊢𝑒2 :𝜏, and abbreviate 𝛾+:=(𝛾,[[𝑒1]](𝛾)). The denotation of the 𝗅𝖾𝗍 is [[𝑒2]] ∘⟨id,[[𝑒1]]⟩, whose Jacobian at 𝛾 is 𝐽=𝐽Γ2(𝛾+)+𝐽𝑥2(𝛾+)⋅𝐽1(𝛾), where 𝐽Γ2 and 𝐽𝑥2 are the blocks of the Jacobian of [[𝑒2]] corresponding to the variables of Γ and to 𝑥. Transposing, 𝐽𝗍(𝑑) =(𝐽Γ2)𝗍(𝑑) +𝐽𝗍1((𝐽𝑥2)𝗍(𝑑)), and by the induction hypothesis for 𝑒2 the pair ((𝐽Γ2)𝗍(𝑑),(𝐽𝑥2)𝗍(𝑑)) is exactly the pair ⟨𝑔,𝑠⟩ computed by 𝑏2(𝑑); the induction hypothesis for 𝑒1 identifies 𝑏1(𝑠) with 𝐽𝗍1(𝑠). The clause adds the two, which is 𝐽𝗍(𝑑).
Linearity of each constructed map is immediate: 𝜄𝑖 is linear, and the clauses build linear maps from linear maps by composition, addition, and scalar multiplication by values that do not depend on 𝑑. ◻
Let 𝑡𝑛:=𝗅𝖾𝗍 𝑦2 =𝑥1 ∗𝑥2 𝗂𝗇 𝗅𝖾𝗍 𝑦3 =𝑦2 ∗𝑥3 𝗂𝗇⋯𝗅𝖾𝗍 𝑦𝑛 =𝑦𝑛−1 ∗𝑥𝑛 𝗂𝗇 𝑦𝑛, whose denotation is 𝑥1𝑥2⋯𝑥𝑛. Evaluating 𝑡𝑛 costs 𝑛 −1 multiplications.
Forward mode: by theorem 182.12 one evaluation of D𝑡𝑛 with seed 𝑒𝑖 returns 𝜕/𝜕𝑥𝑖, and each evaluation costs 3(𝑛 −1) multiplications and 𝑛 −1 additions, by the operation clause of definition 182.6 at ∗. The full gradient therefore costs 𝑛 such evaluations: about 3𝑛2 multiplications.
Reverse mode: one evaluation of 𝑣𝑡𝑛 costs 𝑛 −1 multiplications, and one run of 𝑏𝑡𝑛 at 𝑑 =1 performs, at each 𝗅𝖾𝗍, two scalar multiplications and one addition of context cotangents. Counting only scalar arithmetic, the gradient costs about 3𝑛 multiplications — one run, not 𝑛. The asymptotic gain is a factor 𝑛, and it is already visible in the count.
Referenced from 3 locations
★☆☆ For 𝑒:=⟨𝑥1 ∗𝑥2, 𝑥1 +𝑥2⟩ compute 𝑣𝑒 and 𝑏𝑒 from definition 183.4, write the Jacobian of [[𝑒]] as a 2 ×2 matrix, and check equation 183.1 on the cotangents (1,0) and (0,1).
Referenced from 2 locations
★★☆ Exchange the two summands in the 𝗅𝖾𝗍 clause of definition 183.4, so that 𝑏1 is applied to the Γ component and 𝑏2’s Γ component is discarded. Exhibit a term on which the resulting map is not the transposed Jacobian, and identify the step of the proof of theorem 183.5 that fails.
Referenced from 2 locations
Higher-order subterms
Theorem 183.5 covers a fragment with no function type at all. The transformation extends to a source language with function types, at the price of a target language with a type of linear maps and a semantics in which higher types are interpreted; and the correctness statement then holds at exactly the same interface as in the forward chapter.
Let the source language have 𝗋𝖾𝖺𝗅𝑛 types, finite products, and function types, and let the target language extend it with a type of linear maps. Write →D(𝑡) =(→D(𝑡)1,→D(𝑡)2) and ←D(𝑡) =(←D(𝑡)1,←D(𝑡)2) for the forward and reverse macros. For every program 𝑥 :𝜏 ⊢𝑡 :𝜎 between first-order types 𝜏 and 𝜎, whose subterms may have higher types, [[→D(𝑡)1]]=[[𝑡]],[[→D(𝑡)2]]=𝐷[[𝑡]],[[←D(𝑡)1]]=[[𝑡]],[[←D(𝑡)2]]=(𝐷[[𝑡]])𝗍, where 𝐷 is the usual derivative and ( −)𝗍 the transpose.
Referenced from 5 locations
This is Theorem 2 of Vákár, Reverse AD at Higher Types: Pure, Principled and Denotationally Correct, arXiv:2007.05283, proved there by a logical-relations argument over a subscone of diffeological spaces, the semantics being needed because Cartesian closure is unavailable in the categories of manifolds. The restriction to first-order 𝜏 and 𝜎 is part of the statement, not an artifact of the proof method: at higher types the transpose of a derivative is not determined by the source term, exactly as in remark 182.13. That paper conjectures, and does not prove, extensions to variant and inductive types and to general recursion; none of those is claimed here.
The cost of a backpropagator
Theorem 183.5 says what 𝑏𝑒 computes and says nothing about what it costs. The gap is real: the representation of backpropagators used in definition 183.4 is asymptotically wrong.
In definition 183.4 every backpropagator returns a full element of C(Γ), a tuple with one slot per variable in scope, and the 𝗅𝖾𝗍 clause adds two such tuples. Consider the family 𝑠𝑚:=𝗅𝖾𝗍 𝑦1=𝑥1∗𝑥1 𝗂𝗇 𝗅𝖾𝗍 𝑦2=𝑦1∗𝑦1 𝗂𝗇⋯𝗅𝖾𝗍 𝑦𝑚=𝑦𝑚−1∗𝑦𝑚−1 𝗂𝗇 𝑦𝑚 in a context of 𝑛 variables 𝑥1,…,𝑥𝑛, of which only 𝑥1 is used. Evaluating 𝑠𝑚 costs 𝑚 multiplications. Running 𝑏𝑠𝑚 performs 𝑚 additions of tuples of length 𝑛, hence Θ(𝑚𝑛) scalar operations, while the gradient has only one nonzero entry. The output is correct by theorem 183.5; the cost is 𝑛 times what the statement of the problem allows.
Referenced from 5 locations
The repair is a change of representation, not of the equations: cotangent tuples are accumulated destructively into one mutable environment, so that a variable’s contribution is a single update rather than an addition of two full tuples, and the zero tuple is created once. With that representation the transformed program admits a cost bound that is linear in the cost of the original.
Let Γ ⊢𝑡 :𝜏 be a program of the first-order source language, with 𝑛 variables in Γ, the 𝑖-th of type 𝜎𝑖. There are constants 𝑐,𝑐′,𝑐″ >0, independent of 𝑡, such that for all inputs and every output cotangent 𝑑, cost(run (snd 𝐷Γ[𝑡] 𝑑) ⟨0𝜎1,…,0𝜎𝑛⟩) ≤ 𝑐′+𝑐⋅cost(𝑡)+𝑐″⋅𝑛+𝑐𝜑⋅size(𝑑), where both costs are taken in one fixed call-by-value cost model, run executes the cotangent-accumulation monad starting from the zero environment, and size(𝑑) is the size of the incoming cotangent.
Referenced from 8 locations
This is Equation (7) of Smeding and Vákár [SV24], derived there from the amortised criterion of their Equation (6) by initialising the accumulator with zeros; the cost model is the paper’s explicitly displayed call-by-value model, and the statement is machine-checked in the accompanying Agda development [SV23]. Three things are not imported with it. The bound is stated for first-order programs, and the paper does not claim it for arbitrary higher-order closure conversion. It says nothing about floating-point stability, which is a numerical property of the primitives, not of the transformation. And it says nothing about checkpointing, which trades memory for recomputation and changes the constant 𝑐 as well as the space usage; that is a separate design with its own analysis.
Linearize, unzip, transpose. A different arrangement of the same material first linearizes a program to a tangent program, then unzips the result into a primal pass and a linear pass, and finally transposes the linear pass. The transposition step is where the reversal happens, and the design keeps it syntactically separate, at the price of a substructurally linear intermediate language in which a linear variable is used exactly once. This is a comparison of designs only: no theorem of that development is imported here, and theorem 183.5 is proved above without any linear intermediate language.
Array implementations. Reverse-mode implementations for parallel array languages report speedups on benchmarks. Benchmarks are execution evidence about particular programs and machines. They do not establish theorem 183.9, whose content is a bound in a displayed cost model, and they are not evidence about the transformation defined in definition 183.4, which is a different program transformation.
Suggested first pass.
None of these problems is a prerequisite for a later chapter. Begin with exercise 183.3, then exercise 183.4; the implementation project exercise 183.6 may be attempted at any time.
★★☆ Prove that for composable first-order programs 𝑒1 and 𝑒2 the backpropagator of 𝗅𝖾𝗍 𝑥 =𝑒1 𝗂𝗇 𝑒2 constructed by definition 183.4 equals the composite 𝐽𝗍1 ∘𝐽𝗍2 when 𝑒2 does not mention the variables of Γ other than 𝑥, and identify the extra summand that appears when it does. Relate the two cases to the block decomposition in the proof of theorem 183.5.
Referenced from 3 locations
★★☆ Count the scalar operations performed by 𝑣𝑡 and by one run of 𝑏𝑡 for 𝑡:=𝗅𝖾𝗍 𝑦 =𝜍(𝑥1 ∗𝑥2) 𝗂𝗇 𝑦 ∗𝑦, using definition 183.4 literally. Then count them again for the version in which the backpropagator accumulates into a mutable environment, and exhibit the difference as a function of the number 𝑛 of variables in scope.
Referenced from 3 locations
★★☆ Let 𝑡 have 𝑛 real inputs and 𝑚 real outputs. Using theorem 182.12, theorem 183.5, state the number of runs of each transformed program needed to obtain the full Jacobian, and determine for which pairs (𝑛,𝑚) forward mode is preferable. Give a term for which the two counts are equal.
Referenced from 2 locations
★★★ Practical project.reverse-cotangent-transposer Implement in Agda or Kappa the fragment of definition 183.1, its evaluator, the macro ←D of definition 183.4, and an operation counter for both the source program and the transformed program. Represent cotangent environments in two interchangeable ways: as tuples added pointwise, and as a sparse accumulator with in-place update.
The invariant to maintain is equation 183.1: for every term, every input, and every output cotangent, the value returned by the backpropagator equals the transposed Jacobian applied to that cotangent. The concrete result is a function taking a term, an input environment, and an output cotangent, and returning the primal value, the input cotangent, and the two operation counts.
Acceptance test. For 𝑒 =⟨𝑥1 ∗𝑥2,𝑥1 +𝑥2⟩ at (3,5), the cotangent (1,0) returns (5,3) and (0,1) returns (1,1); for 𝑡𝑛 of example 183.6 with 𝑛 =6 at all inputs equal to 2, one run returns the gradient (32,32,32,32,32,32) and the reported operation count of the transformed program is at most six times that of the source program; for 𝑠𝑚 of example 183.8 with 𝑚 =8 and 𝑛 =64 variables in scope, the tuple representation reports a count of order 𝑚𝑛 while the accumulator representation reports a count of order 𝑚, and both return the same gradient. A mutation that drops the 𝜄𝑖 in the variable clause, adding the cotangent to every slot, must fail the first test.
The program checks finitely many terms at finitely many points. It illustrates theorem 183.5 and the contrast of example 183.8 with theorem 183.9; it proves neither, and its operation counts are not the cost model of theorem 183.9 unless the two are compared explicitly.
Referenced from 3 locations
Bibliographic notes
The reverse macro of definition 183.4 is the first-order fragment of the CHAD transformation, presented so that the transposition structure is visible in each clause; theorem 183.5 is proved here rather than imported because at that fragment the induction is short and exhibits the mechanism. Theorem 183.7 is Theorem 2 of Vákár, Reverse AD at Higher Types: Pure, Principled and Denotationally Correct, arXiv:2007.05283, whose categorical derivation of both macros from a single indexed structure explains why the forward and reverse clauses are transposes of each other. Logical relations for typed AD in the presence of partial language features are treated by Nunes and Vákár, whose source-language restrictions are explicit and are not weakened here.
Theorem 183.9 is Equation (7) of [SV24], with the machine-checked development [SV23]; the cotangent-accumulation representation described before it is theirs. The functional reverse-mode transformation of Pearlmutter and Siskind [PS08] is the classic implementation-oriented predecessor and is a comparison only. The linearize–unzip–transpose arrangement discussed in the comparison is the design of You Only Linearize Once; it owns no theorem here.