Documentation

LeanMlir.Proofs.Nets.Small.Cifar8BbnStepTieB

The cifar8-BN step tie at BATCH statistics — the un-fused, batched gradient nodes #

Cifar8BnTieG.cifar8Bn_train_step_tiedG ties the per-image renders (cifar8w_bn_*, BN over [2,3], one x : Tensor3 at a time). The artifacts planning/cifar-batch-bn-rerender.md builds — cifar8wb_bbn_{sgd,mom,adam,bf16…}_train_step.mlir, from Proofs/Codegen/CnnBbnRender.lean — are the same 38 parameters with every BatchNorm reducing over [0,2,3]: the batch is coupled, so there is no per-example statement to make. This file states those artifacts' gradient nodes at the batched vocabulary ResNet-34's tie uses (Foundation/GradNodesB, GradNodesBAt, Batched/BackLinks): all 38 parameter tensors, each *GradB node denoting the certified batched Σ_n gradient at the layer's input and the cotangent the rendered backward chain delivers.

What is tied, and how the chain is written #

The chain is the render's, node for node, in CnnBbnRender.lean's emission order:

sm    = softmaxRow(logits)            g    = scaleB(1/B, subB(sm, %onehot))
dyA   = selectPosB(ha, denseRowBack(Wb, g))        dy9 = selectPosB(h9, denseRowBack(Wa, dyA))
dx9   = denseRowBack(W9, dy9)
dac8  = maxPoolBackB(ac8, dx9)        dbn8 = selectPosB(bn8, dac8)      dhc8 = bnBatchBack(g8, hc8, dbn8)
dac7  = convBackBatched(W8, dhc8)     dbn7 = selectPosB(bn7, dac7)      dhc7 = bnBatchBack(g7, hc7, dbn7)
dpool3 = convBackBatched(W7, dhc7)    dac6 = maxPoolBackB(ac6, dpool3)  …

Every forward activation is the den of the forward node the render emits (batchOp (convAt bf16 …), bnBatchF, batchOp relu, batchOp maxPool, batchOp dense), and every cotangent is the den of the backward node — except the BatchNorm link, which is bnInB (the network-layout twin of den bnBatchBack; BackLinks.bnInB_eq_den_bnBatchBack is the identity, and bnInB_eq_bnBackB says it is the certified bnBatchLA VJP). So the statement is about exactly the values the artifact computes, with no symbolic cotangent and no free activation.

What is NOT stated here (the second half ResNet-34's tie has and this net does not yet): that this chain IS the certified whole-net backward — r34IdCotIn_eq_vjp's analogue, which needs the batched-BN cifar8 forward's HasVJPAt and the per-link _eq_vjp lemmas. Each link's den theorem exists (den_maxPoolBackB, den_convBackBatched_eq_cInB, bnInB_eq_bnBackB, the relu mask by rfl), so that half is composition work, listed in the planning note. Numerically the gap is covered by tests/TestCifar8BbnGradCheck.lean and tests/cifar8_bbn_jax_ref.py.

N is a binder, bf16 is a flag. The bf16 artifacts' conv forward, input-VJP and weight gradient are the bf16 kinds; the capstone takes bf16 and reaches them through ConvWTiedBAt (Bf16Erasure: at the identity rounding the bf16 kind denotes its f32 peer). BatchNorm, bias and dense nodes carry no flag because no render switches them.

The loss cotangent is the plain mean softmax-CE's, at a general target t (the graph input %onehot): g = (softmax(logits) − t) / B, as the render composes it from softmaxRow, subB and scaleB. There is no label smoothing in the cifar8 recipe.

The rows := 1 head. The render's head backward uses denseRowBack (rows := 1) and softmaxRow (m := 1), whose operands are typed N * (1 * n); 1 * n is not n definitionally, so the head cotangents are re-indexed with castB1 / unB1 (Nat.one_mul), exactly the reshape the emitted text performs between those nodes and their neighbours.

def Proofs.Cifar8BbnTieB.castB1 (N n : ℕ) (v : Vec (N * n)) :
Vec (N * (1 * n))

Vec (N * n) read at the N * (1 * n) index — the head's rows := 1 layout.

Equations
Instances For
    def Proofs.Cifar8BbnTieB.unB1 (N n : ℕ) (v : Vec (N * (1 * n))) :
    Vec (N * n)

    …and back.

    Equations
    Instances For
      theorem Proofs.Cifar8BbnTieB.cifar8Bbn_train_step_tiedB (N : ℕ) {ic c1 c2 c3 c4 h w d1 nClasses kH kW : ℕ} (bf16 : Bool) (xN vN epsStr cotN sStr : String) (ε invB : ℝ) (W₁ : Kernel4 c1 ic kH kW) (b₁ γ₁ β₁ : Vec c1) (W₂ : Kernel4 c1 c1 kH kW) (b₂ γ₂ β₂ : Vec c1) (W₃ : Kernel4 c2 c1 kH kW) (b₃ γ₃ β₃ : Vec c2) (W₄ : Kernel4 c2 c2 kH kW) (b₄ γ₄ β₄ : Vec c2) (W₅ : Kernel4 c3 c2 kH kW) (b₅ γ₅ β₅ : Vec c3) (W₆ : Kernel4 c3 c3 kH kW) (b₆ γ₆ β₆ : Vec c3) (W₇ : Kernel4 c4 c3 kH kW) (b₇ γ₇ β₇ : Vec c4) (W₈ : Kernel4 c4 c4 kH kW) (b₈ γ₈ β₈ : Vec c4) (W₉ : Mat (c4 * h * w) d1) (b₉ : Vec d1) (Wa : Mat d1 d1) (ba : Vec d1) (Wb : Mat d1 nClasses) (bb : Vec nClasses) (x : Vec (N * (ic * (2 * (2 * (2 * (2 * h)))) * (2 * (2 * (2 * (2 * w))))))) (t : Vec (N * nClasses)) :
      have hc1 := StableHLO.den (StableHLO.SHlo.batchOp (StableHLO.BatchableOp.convAt bf16 id xN xN W₁ b₁) (StableHLO.SHlo.operand xN x)); have bn1 := StableHLO.den (StableHLO.SHlo.bnBatchF vN vN epsStr ε γ₁ β₁ (StableHLO.SHlo.operand vN hc1)); have ac1 := StableHLO.den (StableHLO.SHlo.batchOp StableHLO.BatchableOp.relu (StableHLO.SHlo.operand vN bn1)); have hc2 := StableHLO.den (StableHLO.SHlo.batchOp (StableHLO.BatchableOp.convAt bf16 id xN xN W₂ b₂) (StableHLO.SHlo.operand vN ac1)); have bn2 := StableHLO.den (StableHLO.SHlo.bnBatchF vN vN epsStr ε γ₂ β₂ (StableHLO.SHlo.operand vN hc2)); have ac2 := StableHLO.den (StableHLO.SHlo.batchOp StableHLO.BatchableOp.relu (StableHLO.SHlo.operand vN bn2)); have pool1 := StableHLO.den (StableHLO.SHlo.batchOp StableHLO.BatchableOp.maxPool (StableHLO.SHlo.operand vN ac2)); have hc3 := StableHLO.den (StableHLO.SHlo.batchOp (StableHLO.BatchableOp.convAt bf16 id xN xN W₃ b₃) (StableHLO.SHlo.operand vN pool1)); have bn3 := StableHLO.den (StableHLO.SHlo.bnBatchF vN vN epsStr ε γ₃ β₃ (StableHLO.SHlo.operand vN hc3)); have ac3 := StableHLO.den (StableHLO.SHlo.batchOp StableHLO.BatchableOp.relu (StableHLO.SHlo.operand vN bn3)); have hc4 := StableHLO.den (StableHLO.SHlo.batchOp (StableHLO.BatchableOp.convAt bf16 id xN xN W₄ b₄) (StableHLO.SHlo.operand vN ac3)); have bn4 := StableHLO.den (StableHLO.SHlo.bnBatchF vN vN epsStr ε γ₄ β₄ (StableHLO.SHlo.operand vN hc4)); have ac4 := StableHLO.den (StableHLO.SHlo.batchOp StableHLO.BatchableOp.relu (StableHLO.SHlo.operand vN bn4)); have pool2 := StableHLO.den (StableHLO.SHlo.batchOp StableHLO.BatchableOp.maxPool (StableHLO.SHlo.operand vN ac4)); have hc5 := StableHLO.den (StableHLO.SHlo.batchOp (StableHLO.BatchableOp.convAt bf16 id xN xN W₅ b₅) (StableHLO.SHlo.operand vN pool2)); have bn5 := StableHLO.den (StableHLO.SHlo.bnBatchF vN vN epsStr ε γ₅ β₅ (StableHLO.SHlo.operand vN hc5)); have ac5 := StableHLO.den (StableHLO.SHlo.batchOp StableHLO.BatchableOp.relu (StableHLO.SHlo.operand vN bn5)); have hc6 := StableHLO.den (StableHLO.SHlo.batchOp (StableHLO.BatchableOp.convAt bf16 id xN xN W₆ b₆) (StableHLO.SHlo.operand vN ac5)); have bn6 := StableHLO.den (StableHLO.SHlo.bnBatchF vN vN epsStr ε γ₆ β₆ (StableHLO.SHlo.operand vN hc6)); have ac6 := StableHLO.den (StableHLO.SHlo.batchOp StableHLO.BatchableOp.relu (StableHLO.SHlo.operand vN bn6)); have pool3 := StableHLO.den (StableHLO.SHlo.batchOp StableHLO.BatchableOp.maxPool (StableHLO.SHlo.operand vN ac6)); have hc7 := StableHLO.den (StableHLO.SHlo.batchOp (StableHLO.BatchableOp.convAt bf16 id xN xN W₇ b₇) (StableHLO.SHlo.operand vN pool3)); have bn7 := StableHLO.den (StableHLO.SHlo.bnBatchF vN vN epsStr ε γ₇ β₇ (StableHLO.SHlo.operand vN hc7)); have ac7 := StableHLO.den (StableHLO.SHlo.batchOp StableHLO.BatchableOp.relu (StableHLO.SHlo.operand vN bn7)); have hc8 := StableHLO.den (StableHLO.SHlo.batchOp (StableHLO.BatchableOp.convAt bf16 id xN xN W₈ b₈) (StableHLO.SHlo.operand vN ac7)); have bn8 := StableHLO.den (StableHLO.SHlo.bnBatchF vN vN epsStr ε γ₈ β₈ (StableHLO.SHlo.operand vN hc8)); have ac8 := StableHLO.den (StableHLO.SHlo.batchOp StableHLO.BatchableOp.relu (StableHLO.SHlo.operand vN bn8)); have pool4 := StableHLO.den (StableHLO.SHlo.batchOp StableHLO.BatchableOp.maxPool (StableHLO.SHlo.operand vN ac8)); have h9 := StableHLO.den (StableHLO.SHlo.batchOp (StableHLO.BatchableOp.dense xN xN W₉ b₉) (StableHLO.SHlo.operand vN pool4)); have a9 := StableHLO.den (StableHLO.SHlo.batchOp StableHLO.BatchableOp.relu (StableHLO.SHlo.operand vN h9)); have ha := StableHLO.den (StableHLO.SHlo.batchOp (StableHLO.BatchableOp.dense xN xN Wa ba) (StableHLO.SHlo.operand vN a9)); have aa := StableHLO.den (StableHLO.SHlo.batchOp StableHLO.BatchableOp.relu (StableHLO.SHlo.operand vN ha)); have logits := StableHLO.den (StableHLO.SHlo.batchOp (StableHLO.BatchableOp.dense xN xN Wb bb) (StableHLO.SHlo.operand vN aa)); have sm := StableHLO.den (StableHLO.SHlo.batchOp StableHLO.BatchableOp.softmaxRow (StableHLO.SHlo.operand vN (castB1 N nClasses logits))); have g := StableHLO.den (StableHLO.SHlo.scaleB sStr invB ((StableHLO.SHlo.operand vN (unB1 N nClasses sm)).subB (StableHLO.SHlo.operand cotN t))); have dyA := StableHLO.den (StableHLO.SHlo.selectPosB vN (castB1 N d1 ha) (StableHLO.SHlo.batchOp (StableHLO.BatchableOp.denseRowBack xN Wb) (StableHLO.SHlo.operand cotN (castB1 N nClasses g)))); have dy9 := StableHLO.den (StableHLO.SHlo.selectPosB vN (castB1 N d1 h9) (StableHLO.SHlo.batchOp (StableHLO.BatchableOp.denseRowBack xN Wa) (StableHLO.SHlo.operand cotN dyA))); have dx9 := StableHLO.den (StableHLO.SHlo.batchOp (StableHLO.BatchableOp.denseRowBack xN W₉) (StableHLO.SHlo.operand cotN dy9)); have dac8 := StableHLO.den (StableHLO.SHlo.maxPoolBackB vN ac8 (StableHLO.SHlo.operand cotN (unB1 N (c4 * h * w) dx9))); have dbn8 := StableHLO.den (StableHLO.SHlo.selectPosB vN bn8 (StableHLO.SHlo.operand cotN dac8)); have dhc8 := BackLinks.bnInB N c4 (2 * h) (2 * w) ε γ₈ hc8 dbn8; have dac7 := StableHLO.den (StableHLO.SHlo.convBackBatchedAt bf16 id xN W₈ b₈ (StableHLO.SHlo.operand cotN dhc8)); have dbn7 := StableHLO.den (StableHLO.SHlo.selectPosB vN bn7 (StableHLO.SHlo.operand cotN dac7)); have dhc7 := BackLinks.bnInB N c4 (2 * h) (2 * w) ε γ₇ hc7 dbn7; have dpool3 := StableHLO.den (StableHLO.SHlo.convBackBatchedAt bf16 id xN W₇ b₇ (StableHLO.SHlo.operand cotN dhc7)); have dac6 := StableHLO.den (StableHLO.SHlo.maxPoolBackB vN ac6 (StableHLO.SHlo.operand cotN dpool3)); have dbn6 := StableHLO.den (StableHLO.SHlo.selectPosB vN bn6 (StableHLO.SHlo.operand cotN dac6)); have dhc6 := BackLinks.bnInB N c3 (2 * (2 * h)) (2 * (2 * w)) ε γ₆ hc6 dbn6; have dac5 := StableHLO.den (StableHLO.SHlo.convBackBatchedAt bf16 id xN W₆ b₆ ⋯); have dbn5 := StableHLO.den ⋯; have dhc5 := ⋯; ⋯

      Whole batch-statistics cifar8-BN train step at its gradient nodes. All 38 parameter tensors (8 conv W+b, 8 BN γ+β, 3 dense W+b), at the batched forward the render emits and the cotangent its backward chain delivers: each *GradB node denotes the certified batched Σ_n gradient (the per-layer Jacobian contracted with the arriving cotangent, summed over the batch) — cifar8Bn_train_step_tiedG's statement at batch BN, N free.