Documentation

LeanMlir.Proofs.Nets.Small.MlpFold

PoC: the MNIST-MLP train step, proof-tied to the certified SGD step #

The MLP analogue of LinearFold. MainMnistMlpVerified trains on verified_mlir/mlp_train_step.mlir; this file makes the whole module pretty(provenGraph) — forward (denseF/reluF), the loss cotangent, the backward chain (dotOut/selectPos), and the six parameter SGD updates as the weightSgd/biasSgd SHlo ops added in LinearFold's core extension — and proves each output's den equals the certified fderiv-derived loss-descent step, reusing mlp_render_{W,b}*_certified (the per-layer bridges) and mlpCotOut{0,1}_denote (the explicit chain cotangents).

No new core SHlo ops are needed: the backward chain uses the existing dotOut/selectPos, and the param updates reuse weightSgd/biasSgd.

Residual (as for linear): per-op pretty lexing; B=1 (the emitted module batch-contracts; den is per-example); the ReLU smooth-point hypotheses are inherited from the bridges; ℝ→Float32.

The backward-chain cotangent subgraphs denote the proven mlpCotOut* #

The emitted selectPos/dotOut chain — what the faithful renderer prints for the per-layer pre-activation cotangents — denotes exactly mlpCotOut{1,0}.denote g.

theorem Proofs.MlpPoC.cot1_den {d₀ d₁ d₂ d₃ : } (W₀ : Mat d₀ d₁) (b₀ : Vec d₁) (W₁ : Mat d₁ d₂) (b₁ : Vec d₂) (W₂ : Mat d₂ d₃) (x : Vec d₀) (g : Vec d₃) (p₁name dyName : String) :
StableHLO.den (StableHLO.SHlo.selectPos p₁name (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))) (StableHLO.SHlo.dotOut "%W2" W₂ (StableHLO.SHlo.operand dyName g))) = (IR.mlpCotOut1 W₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote g

Layer-1 cotangent subgraph selectPos p₁ (dotOut W₂ dy) denotes mlpCotOut1.denote g.

theorem Proofs.MlpPoC.cot0_den {d₀ d₁ d₂ d₃ : } (W₀ : Mat d₀ d₁) (b₀ : Vec d₁) (W₁ : Mat d₁ d₂) (b₁ : Vec d₂) (W₂ : Mat d₂ d₃) (x : Vec d₀) (g : Vec d₃) (p₀name c1name : String) :
StableHLO.den (StableHLO.SHlo.selectPos p₀name (dense W₀ b₀ x) (StableHLO.SHlo.dotOut "%W1" W₁ (StableHLO.SHlo.operand c1name ((IR.mlpCotOut1 W₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote g)))) = (IR.mlpCotOut0 W₁ W₂ (dense W₀ b₀ x) (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote g

Layer-0 cotangent subgraph selectPos p₀ (dotOut W₁ cot1) denotes mlpCotOut0.denote g.

The six emitted parameter ops denote the certified SGD step #

Each weightSgd/biasSgd op, fed the right activation (x field) and the cotangent the chain delivers (the .operand value), denotes θ − lr·(certified per-layer Jacobian · cotangent) — via the op den = emitWeightGrad/emitBiasGrad (outer / reduce) and the mlp_render_*_certified bridges.

theorem Proofs.MlpPoC.W2_den_certified {d₀ d₁ d₂ d₃ : } (W₀ : Mat d₀ d₁) (b₀ : Vec d₁) (W₁ : Mat d₁ d₂) (b₁ : Vec d₂) (W₂ : Mat d₂ d₃) (b₂ : Vec d₃) (x : Vec d₀) (g : Vec d₃) (lr : ) (aN lrStr dyN : String) (i : Fin d₂) (j : Fin d₃) :
StableHLO.den (StableHLO.SHlo.weightSgd aN "%W2" lrStr (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))) W₂ lr (StableHLO.SHlo.operand dyN g)) (finProdFinEquiv (i, j)) = W₂ i j - lr * k : Fin d₃, pdiv (fun (v : Vec (d₂ * d₃)) => dense (Mat.unflatten v) b₂ (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) W₂.flatten (finProdFinEquiv (i, j)) k * g k

Output-layer weight op weightSgd a1 W₂ (cot = dy) = certified W₂ step.

theorem Proofs.MlpPoC.W1_den_certified {d₀ d₁ d₂ d₃ : } (W₀ : Mat d₀ d₁) (b₀ : Vec d₁) (W₁ : Mat d₁ d₂) (b₁ : Vec d₂) (W₂ : Mat d₂ d₃) (x : Vec d₀) (g : Vec d₃) (lr : ) (aN lrStr cN : String) (i : Fin d₁) (j : Fin d₂) :
StableHLO.den (StableHLO.SHlo.weightSgd aN "%W1" lrStr (relu d₁ (dense W₀ b₀ x)) W₁ lr (StableHLO.SHlo.operand cN ((IR.mlpCotOut1 W₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote g))) (finProdFinEquiv (i, j)) = W₁ i j - lr * k : Fin d₂, pdiv (fun (v : Vec (d₁ * d₂)) => dense (Mat.unflatten v) b₁ (relu d₁ (dense W₀ b₀ x))) W₁.flatten (finProdFinEquiv (i, j)) k * (IR.mlpCotOut1 W₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote g k

Hidden-layer weight op weightSgd a0 W₁ (cot = mlpCotOut1) = certified W₁ step.

theorem Proofs.MlpPoC.W0_den_certified {d₀ d₁ d₂ d₃ : } (W₀ : Mat d₀ d₁) (b₀ : Vec d₁) (W₁ : Mat d₁ d₂) (b₁ : Vec d₂) (W₂ : Mat d₂ d₃) (x : Vec d₀) (g : Vec d₃) (lr : ) (lrStr cN : String) (i : Fin d₀) (j : Fin d₁) :
StableHLO.den (StableHLO.SHlo.weightSgd "%x" "%W0" lrStr x W₀ lr (StableHLO.SHlo.operand cN ((IR.mlpCotOut0 W₁ W₂ (dense W₀ b₀ x) (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote g))) (finProdFinEquiv (i, j)) = W₀ i j - lr * k : Fin d₁, pdiv (fun (v : Vec (d₀ * d₁)) => dense (Mat.unflatten v) b₀ x) W₀.flatten (finProdFinEquiv (i, j)) k * (IR.mlpCotOut0 W₁ W₂ (dense W₀ b₀ x) (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote g k

Input-layer weight op weightSgd x W₀ (cot = mlpCotOut0) = certified W₀ step.

theorem Proofs.MlpPoC.b2_den_certified {d₀ d₁ d₂ d₃ : } (W₀ : Mat d₀ d₁) (b₀ : Vec d₁) (W₁ : Mat d₁ d₂) (b₁ : Vec d₂) (W₂ : Mat d₂ d₃) (b₂ : Vec d₃) (x : Vec d₀) (g : Vec d₃) (lr : ) (lrStr dyN : String) (i : Fin d₃) :
StableHLO.den (StableHLO.SHlo.biasSgd "%b2" lrStr b₂ lr (StableHLO.SHlo.operand dyN g)) i = b₂ i - lr * j : Fin d₃, pdiv (fun (b' : Vec d₃) => dense W₂ b' (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) b₂ i j * g j

Output-layer bias op = certified b₂ step.

theorem Proofs.MlpPoC.b1_den_certified {d₀ d₁ d₂ d₃ : } (W₀ : Mat d₀ d₁) (b₀ : Vec d₁) (W₁ : Mat d₁ d₂) (b₁ : Vec d₂) (W₂ : Mat d₂ d₃) (x : Vec d₀) (g : Vec d₃) (lr : ) (lrStr cN : String) (i : Fin d₂) :
StableHLO.den (StableHLO.SHlo.biasSgd "%b1" lrStr b₁ lr (StableHLO.SHlo.operand cN ((IR.mlpCotOut1 W₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote g))) i = b₁ i - lr * j : Fin d₂, pdiv (fun (b' : Vec d₂) => dense W₁ b' (relu d₁ (dense W₀ b₀ x))) b₁ i j * (IR.mlpCotOut1 W₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote g j

Hidden-layer bias op = certified b₁ step.

theorem Proofs.MlpPoC.b0_den_certified {d₀ d₁ d₂ d₃ : } (W₀ : Mat d₀ d₁) (b₀ : Vec d₁) (W₁ : Mat d₁ d₂) (b₁ : Vec d₂) (W₂ : Mat d₂ d₃) (x : Vec d₀) (g : Vec d₃) (lr : ) (lrStr cN : String) (i : Fin d₁) :
StableHLO.den (StableHLO.SHlo.biasSgd "%b0" lrStr b₀ lr (StableHLO.SHlo.operand cN ((IR.mlpCotOut0 W₁ W₂ (dense W₀ b₀ x) (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote g))) i = b₀ i - lr * j : Fin d₁, pdiv (fun (b' : Vec d₁) => dense W₀ b' x) b₀ i j * (IR.mlpCotOut0 W₁ W₂ (dense W₀ b₀ x) (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote g j

Input-layer bias op = certified b₀ step.

Fully tied — the top loss cotangent is the composed softmax-CE of the forward #

The six *_den_certified above hold ∀ g (a symbolic top loss cotangent). The renderer feeds the cotangent the EMITTED loss graph sub(softmaxDiv(expe(logits)), onehot) produces, where logits is the real forward output. The lemma below pins that graph's den to the composed softmax-CE gradient of the forward (∂CE/∂logits, the mlp analogue of lossCotGraph_isCEgrad); instantiating the six certified theorems at it ties the train step forward→loss→backward, with the output layer folding to the WHOLE-loss gradient ∂CE/∂W₂ (mlp_output_total_loss_grad).

theorem Proofs.MlpPoC.mlpLossCot_den {d₀ d₁ d₂ d₃ : } (W₀ : Mat d₀ d₁) (b₀ : Vec d₁) (W₁ : Mat d₁ d₂) (b₁ : Vec d₂) (W₂ : Mat d₂ d₃) (b₂ : Vec d₃) (x : Vec d₀) (nlogN ohN : String) (label : Fin d₃) :
StableHLO.den ((StableHLO.SHlo.operand nlogN (mnistLinear W₂ b₂ (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))))).expe.softmaxDiv.sub (StableHLO.SHlo.operand ohN (oneHot d₃ label))) = fun (j : Fin d₃) => softmax d₃ (mnistLinear W₂ b₂ (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) j - oneHot d₃ label j

The emitted loss-cotangent graph denotes the composed softmax-CE gradient of the forward (= softmax(logits) − onehot = ∂CE/∂logits at the real forward logits).

theorem Proofs.MlpPoC.mlp_W2_tied_totalloss {d₀ d₁ d₂ d₃ : } (W₀ : Mat d₀ d₁) (b₀ : Vec d₁) (W₁ : Mat d₁ d₂) (b₁ : Vec d₂) (W₂ : Mat d₂ d₃) (b₂ : Vec d₃) (x : Vec d₀) (lr : ) (aN lrStr dyN : String) (label : Fin d₃) (i : Fin d₂) (j : Fin d₃) :
StableHLO.den (StableHLO.SHlo.weightSgd aN "%W2" lrStr (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))) W₂ lr (StableHLO.SHlo.operand dyN fun (k : Fin d₃) => softmax d₃ (mnistLinear W₂ b₂ (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) k - oneHot d₃ label k)) (finProdFinEquiv (i, j)) = W₂ i j - lr * pdiv (fun (v : Vec (d₂ * d₃)) (x_1 : Fin 1) => crossEntropy d₃ (dense (Mat.unflatten v) b₂ (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) label) W₂.flatten (finProdFinEquiv (i, j)) 0

Output-layer weight op, fully tied to the WHOLE softmax-CE loss. Fed the cotangent the emitted loss graph denotes (mlpLossCot_den), the weightSgd for W₂ denotes W₂ − lr·∂(crossEntropy ∘ forward)/∂W₂ — the certified TOTAL-loss-descent step, composed forward→softmax-CE→gradient, no symbolic cotangent.

theorem Proofs.MlpPoC.mlp_train_step_tied_certified {d₀ d₁ d₂ d₃ : } (W₀ : Mat d₀ d₁) (b₀ : Vec d₁) (W₁ : Mat d₁ d₂) (b₁ : Vec d₂) (W₂ : Mat d₂ d₃) (b₂ : Vec d₃) (x : Vec d₀) (lr : ) (lrStr aN dyN cN : String) (label : Fin d₃) :
(∀ (i : Fin d₂) (j : Fin d₃), StableHLO.den (StableHLO.SHlo.weightSgd aN "%W2" lrStr (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))) W₂ lr (StableHLO.SHlo.operand dyN fun (k : Fin d₃) => softmax d₃ (mnistLinear W₂ b₂ (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) k - oneHot d₃ label k)) (finProdFinEquiv (i, j)) = W₂ i j - lr * pdiv (fun (v : Vec (d₂ * d₃)) (x_1 : Fin 1) => crossEntropy d₃ (dense (Mat.unflatten v) b₂ (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) label) W₂.flatten (finProdFinEquiv (i, j)) 0) (∀ (i : Fin d₃), StableHLO.den (StableHLO.SHlo.biasSgd "%b2" lrStr b₂ lr (StableHLO.SHlo.operand dyN fun (k : Fin d₃) => softmax d₃ (mnistLinear W₂ b₂ (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) k - oneHot d₃ label k)) i = b₂ i - lr * j : Fin d₃, pdiv (fun (b' : Vec d₃) => dense W₂ b' (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) b₂ i j * (fun (k : Fin d₃) => softmax d₃ (mnistLinear W₂ b₂ (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) k - oneHot d₃ label k) j) (∀ (i : Fin d₁) (j : Fin d₂), StableHLO.den (StableHLO.SHlo.weightSgd aN "%W1" lrStr (relu d₁ (dense W₀ b₀ x)) W₁ lr (StableHLO.SHlo.operand cN ((IR.mlpCotOut1 W₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote fun (k : Fin d₃) => softmax d₃ (mnistLinear W₂ b₂ (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) k - oneHot d₃ label k))) (finProdFinEquiv (i, j)) = W₁ i j - lr * k : Fin d₂, pdiv (fun (v : Vec (d₁ * d₂)) => dense (Mat.unflatten v) b₁ (relu d₁ (dense W₀ b₀ x))) W₁.flatten (finProdFinEquiv (i, j)) k * (IR.mlpCotOut1 W₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote (fun (k : Fin d₃) => softmax d₃ (mnistLinear W₂ b₂ (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) k - oneHot d₃ label k) k) (∀ (i : Fin d₂), StableHLO.den (StableHLO.SHlo.biasSgd "%b1" lrStr b₁ lr (StableHLO.SHlo.operand cN ((IR.mlpCotOut1 W₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote fun (k : Fin d₃) => softmax d₃ (mnistLinear W₂ b₂ (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) k - oneHot d₃ label k))) i = b₁ i - lr * j : Fin d₂, pdiv (fun (b' : Vec d₂) => dense W₁ b' (relu d₁ (dense W₀ b₀ x))) b₁ i j * (IR.mlpCotOut1 W₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote (fun (k : Fin d₃) => softmax d₃ (mnistLinear W₂ b₂ (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) k - oneHot d₃ label k) j) (∀ (i : Fin d₀) (j : Fin d₁), StableHLO.den (StableHLO.SHlo.weightSgd "%x" "%W0" lrStr x W₀ lr (StableHLO.SHlo.operand cN ((IR.mlpCotOut0 W₁ W₂ (dense W₀ b₀ x) (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote fun (k : Fin d₃) => softmax d₃ (mnistLinear W₂ b₂ (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) k - oneHot d₃ label k))) (finProdFinEquiv (i, j)) = W₀ i j - lr * k : Fin d₁, pdiv (fun (v : Vec (d₀ * d₁)) => dense (Mat.unflatten v) b₀ x) W₀.flatten (finProdFinEquiv (i, j)) k * (IR.mlpCotOut0 W₁ W₂ (dense W₀ b₀ x) (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote (fun (k : Fin d₃) => softmax d₃ (mnistLinear W₂ b₂ (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) k - oneHot d₃ label k) k) ∀ (i : Fin d₁), StableHLO.den (StableHLO.SHlo.biasSgd "%b0" lrStr b₀ lr (StableHLO.SHlo.operand cN ((IR.mlpCotOut0 W₁ W₂ (dense W₀ b₀ x) (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote fun (k : Fin d₃) => softmax d₃ (mnistLinear W₂ b₂ (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) k - oneHot d₃ label k))) i = b₀ i - lr * j : Fin d₁, pdiv (fun (b' : Vec d₁) => dense W₀ b' x) b₀ i j * (IR.mlpCotOut0 W₁ W₂ (dense W₀ b₀ x) (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x)))).denote (fun (k : Fin d₃) => softmax d₃ (mnistLinear W₂ b₂ (relu d₂ (dense W₁ b₁ (relu d₁ (dense W₀ b₀ x))))) k - oneHot d₃ label k) j

Whole mlp train step, tied. With the top loss cotangent g pinned to the composed softmax-CE gradient of the forward (mlpLossCot_den), all six emitted parameter ops denote the certified loss-descent step — the output weight W₂ folded to the WHOLE-loss gradient ∂CE/∂W₂ (mlp_W2_tied_totalloss), the other five to θ − lr·(certified ∂layer/∂θ · the backward-chain cotangent the real loss drives) (the *_den_certified at the composed g). No symbolic cotangent remains; the forward is shared (single render, correctly-threaded SSAs).