Documentation

LeanMlir.Proofs.Training.SgdDescentCifar

CIFAR-8 last-conv SGD descent — the first non-MNIST provable descent (A2 probe) #

planning/archive/tier23_float_and_syntactic_faithfulness.md A2 asked the genuinely-uncertain question: does the segment-Lipschitz SGD-descent argument (proven for the MNIST CNN, SgdDescentCnn.lean) reach a CIFAR net? This file answers it.

The finding. CIFAR-8's tail — its last conv W₈ (c4→c4) → relu → maxpool → three denses → CE — is byte-for-byte the program cnn_conv2_sgd_descends proves descent for. So descent at the LAST conv layer reaches CIFAR-8 for free, with the SAME non-vacuous admissible lr as MNIST: it is an instance of the MNIST lemma at the frozen earlier-layer features. Made rigorous in two steps:

The honest stop (why this is the ceiling). Descent through the depth of all eight conv layers is NOT proved, by design: cnn_conv2_sgd_descends's admissible-lr condition hsmall is a PRODUCT of the per-layer operator-norm factors (the three dense bounds × spatial). Each additional conv layer would multiply another (spatial · weight-bound) factor into that product, so the admissible lr shrinks geometrically with depth ⇒ vacuous in any realistic regime. This is the SAME compounding mechanism that puts deep-net descent off-limits. So last-conv descent is the honest reach of provable descent for CIFAR; full-depth / end-to-end CIFAR descent stays open.

noncomputable def Proofs.cifar8Head {c4 h w d1 nClasses : } (W₉ : Mat (c4 * h * w) d1) (b₉ : Vec d1) (Wa : Mat d1 d1) (ba : Vec d1) (Wb : Mat d1 nClasses) (bb : Vec nClasses) :
Vec (c4 * (2 * h) * (2 * w))Vec nClasses

The CIFAR-8 classifier head (everything after the last conv's relu): maxpool → 3 denses.

Equations
Instances For
    noncomputable def Proofs.cifar8Prefix7 {ic c1 c2 c3 c4 h w kH kW : } (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) :
    Vec (ic * (2 * (2 * (2 * (2 * h)))) * (2 * (2 * (2 * (2 * w)))))Vec (c4 * (2 * h) * (2 * w))

    The CIFAR-8 first-7-conv feature extractor (everything before the last conv W₈).

    Equations
    • One or more equations did not get rendered due to their size.
    Instances For
      theorem Proofs.cifarCnn8Forward_factor {ic c1 c2 c3 c4 h w d1 nClasses kH kW : } (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) :
      cifarCnn8Forward W₁ b₁ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ W₆ b₆ W₇ b₇ W₈ b₈ W₉ b₉ Wa ba Wb bb = cifar8Head W₉ b₉ Wa ba Wb bb (relu (c4 * (2 * h) * (2 * w)) flatConv W₈ b₈) cifar8Prefix7 W₁ b₁ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ W₆ b₆ W₇ b₇

      CIFAR-8 factors at the last convcifarCnn8Forward = head ∘ (relu ∘ flatConv W₈) ∘ prefix7. Pure rfl (same -chain, regrouped; Function.comp is definitionally associative).

      theorem Proofs.cifar8_lastConv_sgd_descends {ic c1 c2 c3 c4 h w d1 nClasses kH kW : } (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) (image : Vec (ic * (2 * (2 * (2 * (2 * h)))) * (2 * (2 * (2 * (2 * w)))))) (x₁ : Tensor3 c4 (2 * h) (2 * w)) (label : Fin nClasses) (gh : Vec (c4 * c4 * kH * kW)) (hx₁ : x₁ = Tensor3.unflatten (cifar8Prefix7 W₁ b₁ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ W₆ b₆ W₇ b₇ image)) (hc4 : 0 < c4) (hh : 0 < h) (hw : 0 < w) {lr η a w₉ wa wb : } (ha : 0 a) (hx : ∀ (cc : Fin c4) (i : Fin (2 * h)) (j : Fin (2 * w)), |x₁ cc i j| a) (hw₉ : 0 w₉) (hW₉ : ∀ (i : Fin (c4 * h * w)) (j : Fin d1), |W₉ i j| w₉) (hwa : 0 wa) (hWa : ∀ (i j : Fin d1), |Wa i j| wa) (hwb : 0 wb) (hWb : ∀ (i : Fin d1) (j : Fin nClasses), |Wb i j| wb) (hlr : 0 lr) ( : 0 η) (hgh : ∀ (idx : Fin (c4 * c4 * kH * kW)), |gh idx - gradAt (fun (v' : Vec (c4 * c4 * kH * kW)) => crossEntropy nClasses (dense Wb bb (relu d1 (dense Wa ba (relu d1 (dense W₉ b₉ (maxPoolFlat c4 h w (relu (c4 * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten v') b₈ x₁).flatten))))))) label) W₈.flatten idx| η) (hm2 : ∀ (k : Fin (c4 * (2 * h) * (2 * w))), a * (lr * (idx : Fin (c4 * c4 * kH * kW), |gradAt (fun (v' : Vec (c4 * c4 * kH * kW)) => crossEntropy nClasses (dense Wb bb (relu d1 (dense Wa ba (relu d1 (dense W₉ b₉ (maxPoolFlat c4 h w (relu (c4 * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten v') b₈ x₁).flatten))))))) label) W₈.flatten idx| + ↑(c4 * c4 * kH * kW) * η)) < |(conv2d W₈ b₈ x₁).flatten k|) (hmq : MaxPool2MarginQ (a * (lr * (idx : Fin (c4 * c4 * kH * kW), |gradAt (fun (v' : Vec (c4 * c4 * kH * kW)) => crossEntropy nClasses (dense Wb bb (relu d1 (dense Wa ba (relu d1 (dense W₉ b₉ (maxPoolFlat c4 h w (relu (c4 * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten v') b₈ x₁).flatten))))))) label) W₈.flatten idx| + ↑(c4 * c4 * kH * kW) * η))) (Tensor3.unflatten (relu (c4 * (2 * h) * (2 * w)) (conv2d W₈ b₈ x₁).flatten))) (hm3 : ∀ (l : Fin d1), w₉ * (↑(2 * h * (2 * w)) * (a * (lr * (idx : Fin (c4 * c4 * kH * kW), |gradAt (fun (v' : Vec (c4 * c4 * kH * kW)) => crossEntropy nClasses (dense Wb bb (relu d1 (dense Wa ba (relu d1 (dense W₉ b₉ (maxPoolFlat c4 h w (relu (c4 * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten v') b₈ x₁).flatten))))))) label) W₈.flatten idx| + ↑(c4 * c4 * kH * kW) * η)))) < |dense W₉ b₉ (maxPoolFlat c4 h w (relu (c4 * (2 * h) * (2 * w)) (conv2d W₈ b₈ x₁).flatten)) l|) (hm4 : ∀ (q : Fin d1), wa * (d1 * (w₉ * (↑(2 * h * (2 * w)) * (a * (lr * (idx : Fin (c4 * c4 * kH * kW), |gradAt (fun (v' : Vec (c4 * c4 * kH * kW)) => crossEntropy nClasses (dense Wb bb (relu d1 (dense Wa ba (relu d1 (dense W₉ b₉ (maxPoolFlat c4 h w (relu (c4 * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten v') b₈ x₁).flatten))))))) label) W₈.flatten idx| + ↑(c4 * c4 * kH * kW) * η)))))) < |dense Wa ba (relu d1 (dense W₉ b₉ (maxPoolFlat c4 h w (relu (c4 * (2 * h) * (2 * w)) (conv2d W₈ b₈ x₁).flatten)))) q|) (hsmall : 2 * (wb * (d1 * (wa * (d1 * (w₉ * (↑(2 * h * (2 * w)) * (a * (lr * (idx : Fin (c4 * c4 * kH * kW), |gradAt (fun (v' : Vec (c4 * c4 * kH * kW)) => crossEntropy nClasses (dense Wb bb (relu d1 (dense Wa ba (relu d1 (dense W₉ b₉ (maxPoolFlat c4 h w (relu (c4 * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten v') b₈ x₁).flatten))))))) label) W₈.flatten idx| + ↑(c4 * c4 * kH * kW) * η))))))))) < 1) (h1 : lr * η * idx : Fin (c4 * c4 * kH * kW), |gradAt (fun (v' : Vec (c4 * c4 * kH * kW)) => crossEntropy nClasses (dense Wb bb (relu d1 (dense Wa ba (relu d1 (dense W₉ b₉ (maxPoolFlat c4 h w (relu (c4 * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten v') b₈ x₁).flatten))))))) label) W₈.flatten idx| (lr * idx : Fin (c4 * c4 * kH * kW), gradAt (fun (v' : Vec (c4 * c4 * kH * kW)) => crossEntropy nClasses (dense Wb bb (relu d1 (dense Wa ba (relu d1 (dense W₉ b₉ (maxPoolFlat c4 h w (relu (c4 * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten v') b₈ x₁).flatten))))))) label) W₈.flatten idx ^ 2) / 4) (h2 : 2 * nClasses * ↑(2 * h * (2 * w)) ^ 2 * d1 ^ 2 * d1 ^ 2 * w₉ ^ 2 * wa ^ 2 * wb ^ 2 * a ^ 2 / (1 - 2 * (wb * (d1 * (wa * (d1 * (w₉ * (↑(2 * h * (2 * w)) * (a * (lr * (idx : Fin (c4 * c4 * kH * kW), |gradAt (fun (v' : Vec (c4 * c4 * kH * kW)) => crossEntropy nClasses (dense Wb bb (relu d1 (dense Wa ba (relu d1 (dense W₉ b₉ (maxPoolFlat c4 h w (relu (c4 * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten v') b₈ x₁).flatten))))))) label) W₈.flatten idx| + ↑(c4 * c4 * kH * kW) * η)))))))))) * (lr * (idx : Fin (c4 * c4 * kH * kW), |gradAt (fun (v' : Vec (c4 * c4 * kH * kW)) => crossEntropy nClasses (dense Wb bb (relu d1 (dense Wa ba (relu d1 (dense W₉ b₉ (maxPoolFlat c4 h w (relu (c4 * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten v') b₈ x₁).flatten))))))) label) W₈.flatten idx| + ↑(c4 * c4 * kH * kW) * η)) ^ 2 (lr * idx : Fin (c4 * c4 * kH * kW), gradAt (fun (v' : Vec (c4 * c4 * kH * kW)) => crossEntropy nClasses (dense Wb bb (relu d1 (dense Wa ba (relu d1 (dense W₉ b₉ (maxPoolFlat c4 h w (relu (c4 * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten v') b₈ x₁).flatten))))))) label) W₈.flatten idx ^ 2) / 4) :
      crossEntropy nClasses (cifarCnn8Forward W₁ b₁ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ W₆ b₆ W₇ b₇ (Kernel4.unflatten (W₈.flatten - lr gh)) b₈ W₉ b₉ Wa ba Wb bb image) label crossEntropy nClasses (cifarCnn8Forward W₁ b₁ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ W₆ b₆ W₇ b₇ (Kernel4.unflatten W₈.flatten) b₈ W₉ b₉ Wa ba Wb bb image) label - (lr * idx : Fin (c4 * c4 * kH * kW), gradAt (fun (v' : Vec (c4 * c4 * kH * kW)) => crossEntropy nClasses (dense Wb bb (relu d1 (dense Wa ba (relu d1 (dense W₉ b₉ (maxPoolFlat c4 h w (relu (c4 * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten v') b₈ x₁).flatten))))))) label) W₈.flatten idx ^ 2) / 2

      CIFAR-8 last-conv SGD descent. One SGD step on the LAST conv W₈ of the actual cifarCnn8Forward net (the earlier seven conv layers held fixed — their output on image is the frozen feature map x₁) decreases the CIFAR-8 cross-entropy loss by at least lr·‖∇‖²/2, under the segment-margin conditions that freeze the ReLU/MaxPool routing along the step. Because CIFAR-8's tail (W₈ → relu → maxpool → 3 denses) is byte-for-byte the architecture cnn_conv2_sgd_descends proves descent for, this is an INSTANCE of that lemma at the frozen features x₁, via cifarCnn8Forward_factor — the admissible lr is the same non-vacuous MNIST regime. The genuinely-distinct case (descent through the DEPTH of all eight conv layers) stays open by design: each extra layer multiplies another operator-norm factor into hsmall's admissible-lr product, so it compounds to vacuity — the same honest stop as the deep nets.