Documentation

LeanMlir.Proofs.Nets.Small.CifarFold

PoC: the CIFAR-CNN (Chapter 4, no-BN) train step, proof-tied to the certified SGD step #

The Chapter-4 peer of CnnFold — a deeper, two-spatial-scale conv net ((conv→relu)×2 → pool → (conv→relu)×2 → pool → (dense→relu)×2 → dense; 14 params: 4 conv kernels/biases + 3 dense layers). MainCifarVerified trains on verified_mlir/cifar_train_step.mlir; this file makes its parameter updates den-faithful — each emitted SGD op denotes the certified loss-descent step.

Zero new core ops. The conv layers reuse the convWeightSgd/convBiasSgd ops added for cnn (CnnFold); the dense head reuses weightSgd/biasSgd. The only new content is the per-net den = certified capstones below.

Honest residual (same boundary as cnn/mlp/linear) #

Conv layers — generic den = certified (covers all four conv layers) #

theorem Proofs.CifarPoC.convW_den {ic oc h w kH kW : } (xN wN lrStr cotN : String) (b : Vec oc) (x : Tensor3 ic h w) (W : Kernel4 oc ic kH kW) (c : Vec (oc * h * w)) (lr : ) (idx : Fin (oc * ic * kH * kW)) :
StableHLO.den (StableHLO.SHlo.convWeightSgd xN wN lrStr b x W lr (StableHLO.SHlo.operand cotN c)) idx = W.flatten idx - lr * j : Fin (oc * h * w), pdiv (fun (v' : Vec (oc * ic * kH * kW)) => (conv2d (Kernel4.unflatten v') b x).flatten) W.flatten idx j * c j

Any emitted conv weight op = certified. Generic in the conv dims and the cotangent c: the convWeightSgd op denotes flatten W − lr·(certified ∂conv/∂W · c). Instantiated at each layer's (b,x,W,c) it certifies W₁…W₄.

theorem Proofs.CifarPoC.convB_den {ic oc h w kH kW : } (bN lrStr cotN : String) (W : Kernel4 oc ic kH kW) (x : Tensor3 ic h w) (b : Vec oc) (c : Vec (oc * h * w)) (lr : ) (o : Fin oc) :
StableHLO.den (StableHLO.SHlo.convBiasSgd bN lrStr W x b lr (StableHLO.SHlo.operand cotN c)) o = b o - lr * j : Fin (oc * h * w), pdiv (fun (b' : Vec oc) => (conv2d W b' x).flatten) b o j * c j

Any emitted conv bias op = certified. Generic peer of convW_den.

Dense classifier head (W₅/W₆/W₇) — weightSgd/biasSgd, mirrors CnnPoC #

The head pool2 → W₅→relu→W₆→relu→W₇ is a 3-layer MLP; per-layer cotangents are the IR mlpCotOut0/1 (with (W₇,W₆,W₅) playing the MLP's (W₂,W₁,W₀)). Every head op's den = certified is Cifar8PoC.denseW_den / Cifar8PoC.denseB_den at that layer; only the output-layer weight op is stated here, as the tie reads it.

theorem Proofs.CifarPoC.dW7_den {c2 h w d1 nClasses : } (aN lrStr dyN : String) (W₅ : Mat (c2 * h * w) d1) (b₅ : Vec d1) (W₆ : Mat d1 d1) (b₆ : Vec d1) (W₇ : Mat d1 nClasses) (b₇ : Vec nClasses) (pool : Vec (c2 * h * w)) (dy : Vec nClasses) (lr : ) (i : Fin d1) (j : Fin nClasses) :
StableHLO.den (StableHLO.SHlo.weightSgd aN "%W7" lrStr (relu d1 (dense W₆ b₆ (relu d1 (dense W₅ b₅ pool)))) W₇ lr (StableHLO.SHlo.operand dyN dy)) (finProdFinEquiv (i, j)) = W₇ i j - lr * k : Fin nClasses, pdiv (fun (v : Vec (d1 * nClasses)) => dense (Mat.unflatten v) b₇ (relu d1 (dense W₆ b₆ (relu d1 (dense W₅ b₅ pool))))) W₇.flatten (finProdFinEquiv (i, j)) k * dy k

Output-layer weight op W₇ = certified step (cotangent = the loss cotangent dy).

The §1a tie — the conv layers/dense head, tied through the REAL cifar forward #

The conv/dense *_den theorems above hold for a FREE cotangent (convW_den/convB_den are ∀ c; the dense head's mlpCotOut0/1 are ∀ dy). The capstones below pin those cotangents to the ones the real cifar forward + softmax-CE loss actually drives — the cifar peer of CnnFold's last three theorems (cnnLossCot_den / cnn_W5_tied_totalloss / cnn_conv_tied_certified).

cifar is the cnn shape with two conv→conv→pool stages instead of one, so its conv backward chain crosses an extra pool boundary. Three of the four conv-layer cotangents reuse the cnn chain cots verbatim (every one is generic in its downstream cotangent):

Only W₂ needs a new constructor cifarChainCotW2: its cotangent crosses pool₁ at the relu-free conv₃-input boundary, so it is relu₂ mask on maxpool₁-back(conv₃-back(W₃, cotW3)) — a conv input-VJP then a maxpool input-VJP, the step cnn (one pool) never had.

noncomputable def Proofs.CifarPoC.cifarChainCotW2 {c1 c2 h w kH kW : } (W₃ : Kernel4 c2 c1 kH kW) (ac2 : Tensor3 c1 (2 * (2 * h)) (2 * (2 * w))) (hc2 : Vec (c1 * (2 * (2 * h)) * (2 * (2 * w)))) (cotW3 : Vec (c2 * (2 * h) * (2 * w))) :
Vec (c1 * (2 * (2 * h)) * (2 * (2 * w)))

Cotangent the cifar backward chain delivers at conv₂'s output (c1 ch @ 2(2h)): the relu₂ mask on maxpool₁-back(conv₃-back(W₃, cotW3)). conv₃-back (the Back3.conv input-VJP via flatDenote) carries cotW3 from conv₃'s output to pool₁'s output (c1 @ 2h); maxpool₁-back (the Back3.maxpool input-VJP) lifts that to conv₂'s output (c1 @ 2(2h)). ac2 is the pool₁ input (= relu₂ output), hc2 the conv₂ pre-activation (the relu₂ mask).

Equations
  • One or more equations did not get rendered due to their size.
Instances For
    theorem Proofs.CifarPoC.cifarLossCot_den {ic c1 c2 h w d1 nClasses kH kW : } (nlogN ohN : String) (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₅ : Mat (c2 * h * w) d1) (b₅ : Vec d1) (W₆ : Mat d1 d1) (b₆ : Vec d1) (W₇ : Mat d1 nClasses) (b₇ : Vec nClasses) (x : Vec (ic * (2 * (2 * h)) * (2 * (2 * w)))) (label : Fin nClasses) :
    StableHLO.den ((StableHLO.SHlo.operand nlogN (cifarCnnForward W₁ b₁ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ W₆ b₆ W₇ b₇ x)).expe.softmaxDiv.sub (StableHLO.SHlo.operand ohN (oneHot nClasses label))) = fun (j : Fin nClasses) => softmax nClasses (cifarCnnForward W₁ b₁ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ W₆ b₆ W₇ b₇ x) j - oneHot nClasses label j

    The emitted loss-cotangent graph denotes the composed softmax-CE gradient of the cifar forward (= softmax(cifarCnnForward … x) − onehot = ∂CE/∂logits at the real forward logits). The cifar peer of CnnPoC.cnnLossCot_den (same proof, cifarCnnForward for the logits operand).

    theorem Proofs.CifarPoC.cifar_W7_tied_totalloss {ic c1 c2 h w d1 nClasses kH kW : } (aN lrStr dyN : String) (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₅ : Mat (c2 * h * w) d1) (b₅ : Vec d1) (W₆ : Mat d1 d1) (b₆ : Vec d1) (W₇ : Mat d1 nClasses) (b₇ : Vec nClasses) (x : Vec (ic * (2 * (2 * h)) * (2 * (2 * w)))) (label : Fin nClasses) (lr : ) (i : Fin d1) (j : Fin nClasses) :
    StableHLO.den (StableHLO.SHlo.weightSgd aN "%W7" lrStr (relu d1 (dense W₆ b₆ (relu d1 (dense W₅ b₅ (maxPoolFlat c2 h w (relu (c2 * (2 * h) * (2 * w)) (flatConv W₄ b₄ (relu (c2 * (2 * h) * (2 * w)) (flatConv W₃ b₃ (maxPoolFlat c1 (2 * h) (2 * w) (relu (c1 * (2 * (2 * h)) * (2 * (2 * w))) (flatConv W₂ b₂ (relu (c1 * (2 * (2 * h)) * (2 * (2 * w))) (flatConv W₁ b₁ x)))))))))))))) W₇ lr (StableHLO.SHlo.operand dyN fun (k : Fin nClasses) => softmax nClasses (cifarCnnForward W₁ b₁ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ W₆ b₆ W₇ b₇ x) k - oneHot nClasses label k)) (finProdFinEquiv (i, j)) = W₇ i j - lr * pdiv (fun (v : Vec (d1 * nClasses)) (x_1 : Fin 1) => crossEntropy nClasses (dense (Mat.unflatten v) b₇ (relu d1 (dense W₆ b₆ (relu d1 (dense W₅ b₅ (maxPoolFlat c2 h w (relu (c2 * (2 * h) * (2 * w)) (flatConv W₄ b₄ (relu (c2 * (2 * h) * (2 * w)) (flatConv W₃ b₃ (maxPoolFlat c1 (2 * h) (2 * w) (relu (c1 * (2 * (2 * h)) * (2 * (2 * w))) (flatConv W₂ b₂ (relu (c1 * (2 * (2 * h)) * (2 * (2 * w))) (flatConv W₁ b₁ x))))))))))))))) label) W₇.flatten (finProdFinEquiv (i, j)) 0

    Dense output weight W₇, tied to the WHOLE softmax-CE loss through the cifar forward. With the dense-head input = the real cifar forward pool₂ output and the cotangent the emitted loss graph denotes (cifarLossCot_den), the weightSgd for W₇ denotes W₇ − lr·∂(crossEntropy ∘ forward)/∂W₇. The cifar peer of CnnPoC.cnn_W5_tied_totalloss.

    theorem Proofs.CifarPoC.cifar_conv_tied_certified {ic c1 c2 h w d1 nClasses kH kW : } (xN wN bN lrStr cotN : String) (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₅ : Mat (c2 * h * w) d1) (b₅ : Vec d1) (W₆ : Mat d1 d1) (b₆ : Vec d1) (W₇ : Mat d1 nClasses) (b₇ : Vec nClasses) (x : Tensor3 ic (2 * (2 * h)) (2 * (2 * w))) (label : Fin nClasses) (lr : ) :
    have xv := x.flatten; have hc1 := flatConv W₁ b₁ xv; have ac1v := relu (c1 * (2 * (2 * h)) * (2 * (2 * w))) hc1; have ac1 := Tensor3.unflatten ac1v; have hc2 := flatConv W₂ b₂ ac1v; have ac2v := relu (c1 * (2 * (2 * h)) * (2 * (2 * w))) hc2; have ac2 := Tensor3.unflatten ac2v; have zp1 := maxPoolFlat c1 (2 * h) (2 * w) ac2v; have zp1t := Tensor3.unflatten zp1; have hc3 := flatConv W₃ b₃ zp1; have ac3v := relu (c2 * (2 * h) * (2 * w)) hc3; have ac3 := Tensor3.unflatten ac3v; have hc4 := flatConv W₄ b₄ ac3v; have ac4v := relu (c2 * (2 * h) * (2 * w)) hc4; have ac4 := Tensor3.unflatten ac4v; have zp2 := maxPoolFlat c2 h w ac4v; have h5 := dense W₅ b₅ zp2; have h6 := dense W₆ b₆ (relu d1 h5); have g := fun (k : Fin nClasses) => softmax nClasses (cifarCnnForward W₁ b₁ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ W₆ b₆ W₇ b₇ xv) k - oneHot nClasses label k; have cotW4 := cnnChainCotW2 W₅ W₆ W₇ h5 h6 ac4 hc4 g; have cotW3 := cnnChainCotW1 W₄ hc3 cotW4; have cotW2 := cifarChainCotW2 W₃ ac2 hc2 cotW3; have cotW1 := cnnChainCotW1 W₂ hc1 cotW2; ConvWSgdTied xN wN lrStr cotN b₄ ac3 W₄ cotW4 lr ConvBSgdTied bN lrStr cotN W₄ ac3 b₄ cotW4 lr ConvWSgdTied xN wN lrStr cotN b₃ zp1t W₃ cotW3 lr ConvBSgdTied bN lrStr cotN W₃ zp1t b₃ cotW3 lr ConvWSgdTied xN wN lrStr cotN b₂ ac1 W₂ cotW2 lr ConvBSgdTied bN lrStr cotN W₂ ac1 b₂ cotW2 lr ConvWSgdTied xN wN lrStr cotN b₁ x W₁ cotW1 lr ConvBSgdTied bN lrStr cotN W₁ x b₁ cotW1 lr

    Whole cifar conv tail, tied. All four conv kernel/bias ops, at the real cifar forward and the composed softmax-CE cotangent g = softmax(cifarCnnForward … xv) − onehot (cifarLossCot_den), denote the certified loss-descent step. Each den = certified is the generic convW_den/convB_den instantiated at the cotangent the backward chain delivers: cnnChainCotW2 for conv₄ (relu mask on pool₂-back of the dense head), cnnChainCotW1 for conv₃/conv₁ (relu mask on the next conv's input-VJP), and cifarChainCotW2 for conv₂ (relu mask on pool₁-back of conv₃'s input-VJP). Together with the dense head (cifar_W7_tied_totalloss + Cifar8PoC.denseW_den/denseB_den at g) the WHOLE cifar train step is den-composed forward→loss→backward — no free activations, no symbolic cotangent. (Residual: the conv backward is rendered hand-written, so the cotangent SSA ↔ chain-cot correspondence is the per-op trust the whole suite carries — the cnn cnn_conv_tied_certified residual verbatim.)