ViT Item D — pinning the attention-block cotangent chain #
ViTClose.lean (Item C) certifies each ViT param output for any cotangent dy at that
site's output. This file pins dy to the cotangent the actual backward chain delivers
— the ViT analogue of ConvNeXtChainClose (planning/archive/vit_close.md Item D). Pure-Lean,
batch-1 — everything in a ViT is per-example separable.
The chain composes the rendered backward denotations — exactly the Item B render's
backward tokens: per-token dense input-VJP (denseRowBack's denotation
rowDenseBackFlat = rowwise dX = W·dy), the GELU mask (dy ⊙ geluScalarDeriv at the
saved pre-GELU), the rowwise scalar-LN input-VJP (lnRowBack's denotation
rowLNBackFlat = rowwise bn_grad_input), the row-softmax backward (softmaxRowBack's
denotation rowSoftmaxBackFlat, recomputing the weights from the saved pre-softmax
scores), and the SDPA matmuls spelled with the forward matmulF/transposeF on
cotangents (matMulFlat/transposeFlat):
block: bout = h + fc2(gelu(fc1(LN₂ h))), h = x + Wo·SDPA(Wq·LN₁x, Wk·LN₁x, Wv·LN₁x)
The MLP residual passes dyOut straight to the fc2 output AND down the LN₂ branch
(vitCotH = dyOut + LN₂-back(…)); the attention residual likewise
(vitCotXin = cotH + LN₁-back(…)). The new wrinkle vs all prior nets is the three-way
fan-in at LN₁'s output — the Q/K/V dense-backs all read from LN₁ x, so their three
cotangents SUM (vitCotLn1), the biPath fan-in at width 3.
The substantive new ties (vitCotD{Q,K,V}_eq_sdpa_back_{Q,K,V}): at the pinned saved
activations (pre-softmax scores = the scaled Q·Kᵀ, post-softmax weights =
sdpa_weights), the matmul-spelled chain segments ARE the proven closed forms
sdpa_back_{Q,K,V} (Attention.lean) — dP = dO·Vᵀ → softmax-back → ·1/√d → dQ = dS·K / dK = dSᵀ·Q / dV = Pᵀ·dO, flattened. So the rendered attention backward is pinned to the
audited SDPA backward suite, and each param output denotes
θ − lr·(certified ∂/∂θ · the actual-chain cotangent). 3-axiom clean.
Cotangent at the GELU output (= the fc2 input): the MLP residual passes the
block cotangent dyOut straight to the fc2 output (bout = h + fc2(…), no
post-add activation), and fc2's input-VJP is the per-token dX = W·dy
(denseRowBack's denotation).
Equations
- Proofs.vitCotG Wfc2 dyOut = Proofs.StableHLO.rowDenseBackFlat Np1 mlpDim D Wfc2 dyOut
Instances For
Cotangent at the fc1 output (pre-GELU): the GELU mask at the saved
pre-activation m1 (geluBack's denotation).
Equations
- Proofs.vitCotM1 Wfc2 m1 dyOut i = Proofs.vitCotG Wfc2 dyOut i * Proofs.geluScalarDeriv (m1 i)
Instances For
Cotangent at the LN₂ output (= the fc1 input): fc1's per-token input-VJP.
Equations
- Proofs.vitCotLn2 Wfc1 Wfc2 m1 dyOut = Proofs.StableHLO.rowDenseBackFlat Np1 D mlpDim Wfc1 (Proofs.vitCotM1 Wfc2 m1 dyOut)
Instances For
Cotangent at the attention-sublayer output h: the MLP residual fan-in —
dyOut (the skip) plus the LN₂ input-VJP (lnRowBack's denotation, recomputing
x̂/istd from the saved pre-LN₂ input h).
Equations
- Proofs.vitCotH ε γ2 Wfc1 Wfc2 h m1 dyOut i = dyOut i + Proofs.StableHLO.rowLNBackFlat Np1 D ε γ2 h (Proofs.vitCotLn2 Wfc1 Wfc2 m1 dyOut) i
Instances For
Cotangent at the SDPA output att (= the out-proj input): Wo's per-token
input-VJP of vitCotH.
Equations
- Proofs.vitCotAtt ε γ2 Wo Wfc1 Wfc2 h m1 dyOut = Proofs.StableHLO.rowDenseBackFlat Np1 D D Wo (Proofs.vitCotH ε γ2 Wfc1 Wfc2 h m1 dyOut)
Instances For
dP = dAtt·Vᵀ — the rendered matmulF/transposeF on the cotangent against the
saved v.
Equations
- Proofs.vitCotDP v dAtt = Proofs.StableHLO.matMulFlat Np1 D Np1 dAtt (Proofs.StableHLO.transposeFlat Np1 D v)
Instances For
dS — softmaxRowBack's denotation at the saved pre-softmax scaled scores ss.
Equations
- Proofs.vitCotDS ss v dAtt = Proofs.StableHLO.rowSoftmaxBackFlat Np1 Np1 ss (Proofs.vitCotDP v dAtt)
Instances For
dQ = (1/√d · dS)·K against the saved k.
Equations
- Proofs.vitCotDQ d ss k v dAtt = Proofs.StableHLO.matMulFlat Np1 Np1 D (fun (i : Fin (Np1 * Np1)) => Proofs.sdpa_scale d * Proofs.vitCotDS ss v dAtt i) k
Instances For
dV = Pᵀ·dAtt against the saved post-softmax weights p.
Equations
- Proofs.vitCotDV p dAtt = Proofs.StableHLO.matMulFlat Np1 Np1 D (Proofs.StableHLO.transposeFlat Np1 Np1 p) dAtt
Instances For
The three-way fan-in at LN₁'s output: the Q/K/V dense-backs all read from
LN₁ x, so their cotangents SUM — the biPath fan-in at width 3, the new
structural wrinkle vs every prior net.
Equations
- Proofs.vitCotLn1 Wq Wk Wv dQ dK dV i = Proofs.StableHLO.rowDenseBackFlat Np1 D D Wq dQ i + Proofs.StableHLO.rowDenseBackFlat Np1 D D Wk dK i + Proofs.StableHLO.rowDenseBackFlat Np1 D D Wv dV i
Instances For
Cotangent at the block input: the attention residual fan-in — the
LN₁ input-VJP of the three-way fan-in, plus the skip's cotH. This is what the
block hands upstream (the previous block's dyOut; at block 1, the cotangent the
embed params contract with).
Equations
- Proofs.vitCotXin ε γ1 Wq Wk Wv xin dQ dK dV cotH i = cotH i + Proofs.StableHLO.rowLNBackFlat Np1 D ε γ1 xin (Proofs.vitCotLn1 Wq Wk Wv dQ dK dV) i
Instances For
Cotangent at the final-LN output: classifier-back (dotOut's denotation
Mat.mulVec Wcls) scattered to row 0 (clsPadF's denotation clsPadFlat).
Equations
- Proofs.vitCotFl N D nClasses Wcls dy = Proofs.StableHLO.clsPadFlat N D (Wcls.mulVec dy)
Instances For
Cotangent at block 2's output: the final-LN input-VJP at the saved pre-LN
input b2out, of vitCotFl.
Equations
- Proofs.vitCotB2out N D nClasses ε γF Wcls b2out dy = Proofs.StableHLO.rowLNBackFlat (N + 1) D ε γF b2out (Proofs.vitCotFl N D nClasses Wcls dy)
Instances For
dP-segment tie: the rendered matmulF(dOut, transposeF V) is the proven
sdpa_dWeights V dOut = dOut·Vᵀ, flattened.
dV tie: at the saved post-softmax weights (sdpa_weights Q K), the rendered
matmulF(transposeF P, dOut) IS the proven sdpa_back_V = weightsᵀ·dOut.
dS-segment tie: softmaxRowBack's denotation, recomputing the weights from the
saved pre-softmax scaled scores, applied to the flattened sdpa_dWeights, IS the
proven sdpa_dScaled (the per-row pᵢ⊙(dwᵢ − ⟨pᵢ,dwᵢ⟩) closed form).
dQ tie: at the saved activations, the rendered
matmulF(scaleF(softmaxRowBack(matmulF(dOut, transposeF V))), K) IS the proven
sdpa_back_Q = (1/√d · softmax-back(dOut·Vᵀ))·K.
dK tie: likewise the rendered transposed chain IS the proven
sdpa_back_K = (1/√d · softmax-back(dOut·Vᵀ))ᵀ·Q.
fc2 W, chain-certified. The chain cotangent at the fc2 output IS the block
cotangent dyOut (the MLP residual is the outermost op, no post-add activation);
the saved GELU output g is the layer input.
fc2 b, chain-certified.
fc1 W, chain-certified at vitCotM1 (fc2-back → GELU mask); the saved LN₂
output ln2 is the layer input.
fc1 b, chain-certified.
LN₂ γ, chain-certified at vitCotLn2 (fc2-back → GELU mask → fc1-back), with
the saved attention-sublayer output h as the LN input.
LN₂ β, chain-certified.
Wo, chain-certified at vitCotH (the MLP-sublayer residual fan-in), with the
saved SDPA output att as the layer input.
bo, chain-certified.
Wq, chain-certified at vitCotDQ of the full chain (out-proj back → SDPA
backward at the saved activations), with the saved LN₁ output as the layer input.
Wk, chain-certified at vitCotDK.
Wv, chain-certified at vitCotDV.
LN₁ γ, chain-certified at vitCotLn1 — the THREE-WAY fan-in of the Q/K/V
dense-backs (the structural wrinkle no prior net had), with the saved block input
xin as the LN input.
LN₁ β, chain-certified.
Final-LN γ, chain-certified at vitCotFl (classifier-back scattered to row 0),
with the saved block-2 output as the LN input.
pos-embed, chain-certified at the block-1 input cotangent vitCotXin — the
cotangent the whole chain delivers at the embed output.
CLS token, chain-certified — the row-0 slice of the block-1 input cotangent.
Patch kernel, chain-certified — the patch-grid reduce at the block-1 input cotangent.