Documentation

LeanMlir.Proofs.Training.SgdDescent.CnnFloat

The MNIST CNN descent rungs with the FloatModel binary32 gradient #

SgdDescent.Cnn proves one-step descent for both conv kernels and both conv biases of the Chapter-3 MNIST CNN, assuming the gradient is accurate to η (an oracle). This file replaces that oracle by a proof: cnn_conv2_float_sgd_descends, cnn_conv1_float_sgd_descends, cnn_conv2_bias_float_sgd_descends and cnn_conv1_bias_float_sgd_descends take the FloatModel transcription of the per-example gradient (FloatModel.cnnConv2FloatGrad and its three peers), bound its distance from the certified gradient (cnn_conv2_grad_close and peers, budgets FloatModel.cnnConv2GradBudget and peers), and feed that bound to the real rung. The update is taken in ℝ; only the gradient is float-modelled.

The conv2-output cotangent chain is shared: cnn_conv2_cot_close bounds it at any (float or exact) conv2 input, and the conv1 rungs reuse it at the float conv2 input, adding the rounded transpose conv (convTap_back_close) and the conv1 ReLU mask (mask_scalar_close). cnn_conv1_cot_close is that conv1-output cotangent, shared by the conv1 kernel and bias rungs.

The pool margins here stay MaxPool2MarginQ, with no twins. The proof model's pool backward (MaxPool2IsArgmax) routes the cotangent to every cell attaining the window max, so at a tie it is not the loss gradient, and a float rung needs windows without ties (MaxPool2MarginQ.to_marginQUpTo_flat hands them to the real rungs). The rendered trainers' select_and_scatter routes each window's cotangent to one cell instead; the two agree off ties.

theorem Proofs.mask_scalar_close {zt z xt x ez ex : ℝ} (hz : |zt - z| ≤ ez) (hm : ez < |z|) (hx : |xt - x| ≤ ex) :
|(if zt > 0 then 1 else 0) * xt - (if z > 0 then 1 else 0) * x| ≤ ex

Scalar ReLU-mask freeze — the (if z>0 then 1 else 0)·x peer of reluMask_close. Under the sign margin ez < |z| the float and real masks agree, so the masked value is 1-Lipschitz in x. The conv-output ReLU mask 𝟙[z₂>0] in the conv-2 grad-close sits on a scalar cell (not a Vec), so it needs this rather than the vector reluMask_close.

noncomputable def Proofs.FloatModel.cnnConv2FloatGrad {c h w d₃ d₄ nC kH kW : ℕ} (M : FloatModel) (b₂ : Vec c) (x₁ : Tensor3 c (2 * h) (2 * w)) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (fexp : ℝ → ℝ) (label : Fin nC) (v : Vec (c * c * kH * kW)) :
Vec (c * c * kH * kW)

The binary32 conv-2 weight gradient (FloatModel transcription of the per-example gradient) — the conv peer of mlpInputFloatGrad. At kernel entry (o,cc,kh,kw) it is the float dot of the (exact) padded-input window convPadWin against the float conv-output cotangent slab cotWin c̃Conv o, where the float cotangent c̃Conv rounds every step of the backward — conv-output ReLU mask 𝟙[z̃₂>0], pool argmax selector (read on the FLOAT post-relu), and the head W₃ᵀ·mask(z̃₃)·W₄ᵀ·mask(z̃₄)·W₅ᵀ·(float softmax−onehot) at the float pre-activations. The M-free reluMask/maxPoolFlat/relu are exact in float; M.convF/M.dense/M.softmaxCECotF carry the rounding.

Equations
  • One or more equations did not get rendered due to their size.
Instances For
    @[simp]
    theorem Proofs.FloatModel.cnnConv2FloatGrad_apply {c h w d₃ d₄ nC kH kW : ℕ} (M : FloatModel) (b₂ : Vec c) (x₁ : Tensor3 c (2 * h) (2 * w)) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (fexp : ℝ → ℝ) (label : Fin nC) (v : Vec (c * c * kH * kW)) (o cc : Fin c) (kh : Fin kH) (kw : Fin kW) :
    M.cnnConv2FloatGrad b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ fexp label v (k4Idx o cc kh kw) = M.dot (convPadWin kH kW x₁ cc kh kw) (cotWin (fun (ci : Fin c) (hi : Fin (2 * h)) (wi : Fin (2 * w)) => (if (M.convF (Kernel4.unflatten v) b₂ x₁).flatten (t3Idx ci hi wi) > 0 then 1 else 0) * if MaxPool2IsArgmax (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (M.convF (Kernel4.unflatten v) b₂ x₁).flatten)) ci hi wi then M.dense (fun (j : Fin d₃) (i' : Fin (c * h * w)) => W₃ i' j) (fun (x : Fin (c * h * w)) => 0) (reluMask (M.dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (M.convF (Kernel4.unflatten v) b₂ x₁).flatten))) (M.dense (fun (j : Fin d₄) (i' : Fin d₃) => W₄ i' j) (fun (x : Fin d₃) => 0) (reluMask (M.dense W₄ b₄ (relu d₃ (M.dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (M.convF (Kernel4.unflatten v) b₂ x₁).flatten))))) (M.dense (fun (j : Fin nC) (i' : Fin d₄) => W₅ i' j) (fun (x : Fin d₄) => 0) (M.softmaxCECotF fexp (M.dense W₅ b₅ (relu d₄ (M.dense W₄ b₄ (relu d₃ (M.dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (M.convF (Kernel4.unflatten v) b₂ x₁).flatten))))))) label))))) (t3Idx ci (winRow hi) (winCol wi)) else 0) o)
    noncomputable def Proofs.FloatModel.cnnConv2GradBudget (M : FloatModel) (c h w d₃ d₄ nC kH kW : ℕ) (a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp : ℝ) :

    The conv-2 float-backward grad-close budget — the closed-form η the rounded W₂ gradient stays within of the certified one. Bottom-up: the forward rounding nest (Econv → E₃ → E₄ → δlogit, conv at fan-in c·kH·kW, the dense head at c·h·w / d₃) feeds the head cotErr; the backward then rides two cot_step layerBudgets (W₅/W₄) and the unmasked W₃ layerBudget to econv; finally the spatial dot (fan-in (2h)·(2w)) contributes its Higham γ on the float-cotangent magnitude Ctilde plus the per-entry cotangent drift econv. The conv peer of the MLP's mulErr/layerBudget/cotErr nest, deeper by the pool + the dot.

    Equations
    • One or more equations did not get rendered due to their size.
    Instances For
      noncomputable def Proofs.FloatModel.cnnConv2CotBudget (M : FloatModel) (c h w d₃ d₄ nC kH kW : ℕ) (aX2 eX2 w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp : ℝ) :

      The conv-2-output cotangent error budget, as a function of the conv-2 input magnitude aX2 and rounding eX2 — the e₂ of cnnConv2GradBudget (where aX2 = a, eX2 = 0) and the e₂ inside cnnConv1GradBudget (where aX2 = A₁, eX2 = E₁). Factored so the conv-1 rung reuses the conv-2 cotangent chain at a FLOAT conv-2 input.

      Equations
      • One or more equations did not get rendered due to their size.
      Instances For
        noncomputable def Proofs.FloatModel.cnnConv2CotMag (d₃ d₄ nC : ℕ) (w₃ w₄ w₅ : ℝ) :

        The real conv-2-output cotangent magnitude bound — aX2/eX2-independent (the head cotangent and the two masked Wᵀ steps are magnitude-frozen).

        Equations
        Instances For
          theorem Proofs.cnn_conv2_cot_close {c h w d₃ d₄ nC kH kW : ℕ} (M : FloatModel) (X2 X2F : Tensor3 c (2 * h) (2 * w)) (W₂ : Kernel4 c c kH kW) (b₂ : Vec c) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (label : Fin nC) (fexp : ℝ → ℝ) {aX2 eX2 w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp : ℝ} (haX2 : 0 ≤ aX2) (heX2 : 0 ≤ eX2) (hw₂ : 0 ≤ w₂) (hβ₂ : 0 ≤ β₂) (hw₃ : 0 ≤ w₃) (hβ₃ : 0 ≤ β₃) (hw₄ : 0 ≤ w₄) (hβ₄ : 0 ≤ β₄) (hw₅ : 0 ≤ w₅) (hβ₅ : 0 ≤ β₅) (heexp0 : 0 ≤ eexp) (heexp1 : eexp ≤ 1) (hfexp : ∀ (t : ℝ), |fexp t - Real.exp t| ≤ eexp * Real.exp t) (hρ1 : FloatModel.smRho M.u eexp nC < 1) (hX2 : ∀ (co : Fin c) (i : Fin (2 * h)) (j : Fin (2 * w)), |X2F co i j - X2 co i j| ≤ eX2) (hX2mag : ∀ (co : Fin c) (i : Fin (2 * h)) (j : Fin (2 * w)), |X2 co i j| ≤ aX2) (hW₂ : ∀ (o cc : Fin c) (kh : Fin kH) (kw : Fin kW), |W₂ o cc kh kw| ≤ w₂) (hb₂ : ∀ (o : Fin c), |b₂ o| ≤ β₂) (hW₃ : ∀ (i : Fin (c * h * w)) (j : Fin d₃), |W₃ i j| ≤ w₃) (hb₃ : ∀ (j : Fin d₃), |b₃ j| ≤ β₃) (hW₄ : ∀ (i : Fin d₃) (j : Fin d₄), |W₄ i j| ≤ w₄) (hb₄ : ∀ (j : Fin d₄), |b₄ j| ≤ β₄) (hW₅ : ∀ (i : Fin d₄) (j : Fin nC), |W₅ i j| ≤ w₅) (hb₅ : ∀ (j : Fin nC), |b₅ j| ≤ β₅) (hmarginConv : ∀ (k : Fin (c * (2 * h) * (2 * w))), FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ aX2 eX2 < |(conv2d W₂ b₂ X2).flatten k|) (hmarginPool : MaxPool2MarginQ (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ aX2 eX2) (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ X2).flatten))) (hmargin3 : ∀ (l : Fin d₃), FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ aX2) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ aX2 eX2) < |dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ X2).flatten)) l|) (hmargin4 : ∀ (q : Fin d₄), FloatModel.layerBudget M.u d₃ w₄ β₄ (FloatModel.layerAct (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ aX2)) (FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ aX2) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ aX2 eX2)) < |dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ X2).flatten)))) q|) (co : Fin c) (ho : Fin (2 * h)) (wo : Fin (2 * w)) :
          |((if (M.convF W₂ b₂ X2F).flatten (t3Idx co ho wo) > 0 then 1 else 0) * if MaxPool2IsArgmax (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (M.convF W₂ b₂ X2F).flatten)) co ho wo then M.dense (fun (j : Fin d₃) (i' : Fin (c * h * w)) => W₃ i' j) (fun (x : Fin (c * h * w)) => 0) (FloatModel.reluMask (M.dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (M.convF W₂ b₂ X2F).flatten))) (M.dense (fun (j : Fin d₄) (i' : Fin d₃) => W₄ i' j) (fun (x : Fin d₃) => 0) (FloatModel.reluMask (M.dense W₄ b₄ (relu d₃ (M.dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (M.convF W₂ b₂ X2F).flatten))))) (M.dense (fun (j : Fin nC) (i' : Fin d₄) => W₅ i' j) (fun (x : Fin d₄) => 0) (M.softmaxCECotF fexp (M.dense W₅ b₅ (relu d₄ (M.dense W₄ b₄ (relu d₃ (M.dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (M.convF W₂ b₂ X2F).flatten))))))) label))))) (t3Idx co (winRow ho) (winCol wo)) else 0) - (if (conv2d W₂ b₂ X2).flatten (t3Idx co ho wo) > 0 then 1 else 0) * if MaxPool2IsArgmax (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ X2).flatten)) co ho wo then dense (fun (j : Fin d₃) (i' : Fin (c * h * w)) => W₃ i' j) (fun (x : Fin (c * h * w)) => 0) (FloatModel.reluMask (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ X2).flatten))) (dense (fun (j : Fin d₄) (i' : Fin d₃) => W₄ i' j) (fun (x : Fin d₃) => 0) (FloatModel.reluMask (dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ X2).flatten))))) (dense (fun (j : Fin nC) (i' : Fin d₄) => W₅ i' j) (fun (x : Fin d₄) => 0) fun (k : Fin nC) => softmax nC (dense W₅ b₅ (relu d₄ (dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ X2).flatten))))))) k - oneHot nC label k)))) (t3Idx co (winRow ho) (winCol wo)) else 0| ≤ M.cnnConv2CotBudget c h w d₃ d₄ nC kH kW aX2 eX2 w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp

          The conv-2-output cotangent is float-close at a float conv-2 input — the conv-2 cotangent chain of cnn_conv2_grad_close, factored to take the conv-2 input (X2, X2F) with |X2F − X2| ≤ eX2, |X2| ≤ aX2. The conv-2 rungs instantiate the exact input X2 = X2F = x₁, eX2 = 0; the conv-1 rung X2 = relu(z₁), X2F = relu(z̃₁), eX2 = E₁. The chain: float forward from X2 (convF_close → dense_close×3) → head (softmax_ce_cot_close) → cot_step_close×2 → unmasked W₃ dense_close → pool-back (poolBack_close) → conv-2 ReLU mask (mask_scalar_close).

          theorem Proofs.cnn_conv2_cot_real_abs_le {c h w d₃ d₄ nC kH kW : ℕ} (X2 : Tensor3 c (2 * h) (2 * w)) (W₂ : Kernel4 c c kH kW) (b₂ : Vec c) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (label : Fin nC) {w₃ w₄ w₅ : ℝ} (hw₃ : 0 ≤ w₃) (hw₄ : 0 ≤ w₄) (hw₅ : 0 ≤ w₅) (hW₃ : ∀ (i : Fin (c * h * w)) (j : Fin d₃), |W₃ i j| ≤ w₃) (hW₄ : ∀ (i : Fin d₃) (j : Fin d₄), |W₄ i j| ≤ w₄) (hW₅ : ∀ (i : Fin d₄) (j : Fin nC), |W₅ i j| ≤ w₅) (co : Fin c) (ho : Fin (2 * h)) (wo : Fin (2 * w)) :
          |(if (conv2d W₂ b₂ X2).flatten (t3Idx co ho wo) > 0 then 1 else 0) * if MaxPool2IsArgmax (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ X2).flatten)) co ho wo then dense (fun (j : Fin d₃) (i' : Fin (c * h * w)) => W₃ i' j) (fun (x : Fin (c * h * w)) => 0) (FloatModel.reluMask (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ X2).flatten))) (dense (fun (j : Fin d₄) (i' : Fin d₃) => W₄ i' j) (fun (x : Fin d₃) => 0) (FloatModel.reluMask (dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ X2).flatten))))) (dense (fun (j : Fin nC) (i' : Fin d₄) => W₅ i' j) (fun (x : Fin d₄) => 0) fun (k : Fin nC) => softmax nC (dense W₅ b₅ (relu d₄ (dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ X2).flatten))))))) k - oneHot nC label k)))) (t3Idx co (winRow ho) (winCol wo)) else 0| ≤ FloatModel.cnnConv2CotMag d₃ d₄ nC w₃ w₄ w₅

          The real conv-2-output cotangent is magnitude-bounded by cnnConv2CotMag — the aX2/eX2-independent ℓ∞ bound (the conv-2 ReLU mask and pool selector only shrink, the head cotangent is in [−1,1], the two masked Wᵀ steps and the unmasked W₃ ride layerAct). Used to bound the real conv-1 cotangent ∑ convTap·c₂ in the conv-1 rung.

          theorem Proofs.cnn_conv2_grad_close {c h w d₃ d₄ nC kH kW : ℕ} (M : FloatModel) (b₂ : Vec c) (x₁ : Tensor3 c (2 * h) (2 * w)) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (label : Fin nC) (fexp : ℝ → ℝ) (v : Vec (c * c * kH * kW)) {a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp : ℝ} (ha : 0 ≤ a) (hw₂ : 0 ≤ w₂) (hβ₂ : 0 ≤ β₂) (hw₃ : 0 ≤ w₃) (hβ₃ : 0 ≤ β₃) (hw₄ : 0 ≤ w₄) (hβ₄ : 0 ≤ β₄) (hw₅ : 0 ≤ w₅) (hβ₅ : 0 ≤ β₅) (heexp0 : 0 ≤ eexp) (heexp1 : eexp ≤ 1) (hfexp : ∀ (t : ℝ), |fexp t - Real.exp t| ≤ eexp * Real.exp t) (hρ1 : FloatModel.smRho M.u eexp nC < 1) (hx₁ : ∀ (ci : Fin c) (i : Fin (2 * h)) (j : Fin (2 * w)), |x₁ ci i j| ≤ a) (hv2 : ∀ (idx : Fin (c * c * kH * kW)), |v idx| ≤ w₂) (hb₂ : ∀ (o : Fin c), |b₂ o| ≤ β₂) (hW₃ : ∀ (i : Fin (c * h * w)) (j : Fin d₃), |W₃ i j| ≤ w₃) (hb₃ : ∀ (j : Fin d₃), |b₃ j| ≤ β₃) (hW₄ : ∀ (i : Fin d₃) (j : Fin d₄), |W₄ i j| ≤ w₄) (hb₄ : ∀ (j : Fin d₄), |b₄ j| ≤ β₄) (hW₅ : ∀ (i : Fin d₄) (j : Fin nC), |W₅ i j| ≤ w₅) (hb₅ : ∀ (j : Fin nC), |b₅ j| ≤ β₅) (hmarginConv : ∀ (k : Fin (c * (2 * h) * (2 * w))), FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ a 0 < |(conv2d (Kernel4.unflatten v) b₂ x₁).flatten k|) (hmarginPool : MaxPool2MarginQ (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ a 0) (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten v) b₂ x₁).flatten))) (hmargin3 : ∀ (l : Fin d₃), FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ a) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ a 0) < |dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten v) b₂ x₁).flatten)) l|) (hmargin4 : ∀ (q : Fin d₄), FloatModel.layerBudget M.u d₃ w₄ β₄ (FloatModel.layerAct (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ a)) (FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ a) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ a 0)) < |dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten v) b₂ x₁).flatten)))) q|) (o cc : Fin c) (kh : Fin kH) (kw : Fin kW) :
          |M.cnnConv2FloatGrad b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ fexp label v (k4Idx o cc kh kw) - gradAt (fun (v' : Vec (c * c * kH * kW)) => crossEntropy nC (dense W₅ b₅ (relu d₄ (dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten v') b₂ x₁).flatten))))))) label) v (k4Idx o cc kh kw)| ≤ M.cnnConv2GradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp

          The binary32 conv-2 weight gradient is within an explicit budget of the certified one — the conv-layer peer of mlp_w0_grad_close. With the conv-2 input x₁ exact, the FloatModel W₂ gradient M.cnnConv2FloatGrad … stays within cnnConv2GradBudget of the certified gradAt. The chain: float forward (convF_close → dense_close×3, relu and pool error-transparent) ⟶ head (softmax_ce_cot_close) ⟶ two masked Wᵀ cot_step_close (W₅ under z̃₄, W₄ under z̃₃) ⟶ unmasked W₃ dense_close ⟶ pool-backward freeze (poolBack_close) ⟶ conv-output ReLU mask freeze (mask_scalar_close) ⟶ the spatial dot (dot_perturbed_close). Four quantitative margins are carried (conv-output Econv, pool Econv POST-relu, z̃₃ E₃, z̃₄ E₄); the bridge cnn_conv2_loss_gradAt_reluMask turns the gradAt into the dot the float gradient rounds. Everything up to the dot is cnn_conv2_cot_close at the exact conv-2 input.

          theorem Proofs.cnn_conv2_float_sgd_descends {c h w d₃ d₄ nC kH kW : ℕ} (M : FloatModel) (W₂ : Kernel4 c c kH kW) (b₂ : Vec c) (x₁ : Tensor3 c (2 * h) (2 * w)) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (label : Fin nC) (fexp : ℝ → ℝ) {lr a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp : ℝ} (ha : 0 ≤ a) (hw₂ : 0 ≤ w₂) (hβ₂ : 0 ≤ β₂) (hw₃ : 0 ≤ w₃) (hβ₃ : 0 ≤ β₃) (hw₄ : 0 ≤ w₄) (hβ₄ : 0 ≤ β₄) (hw₅ : 0 ≤ w₅) (hβ₅ : 0 ≤ β₅) (hlr : 0 ≤ lr) (heexp0 : 0 ≤ eexp) (heexp1 : eexp ≤ 1) (hfexp : ∀ (t : ℝ), |fexp t - Real.exp t| ≤ eexp * Real.exp t) (hρ1 : FloatModel.smRho M.u eexp nC < 1) (hx : ∀ (cc : Fin c) (i : Fin (2 * h)) (j : Fin (2 * w)), |x₁ cc i j| ≤ a) (hW₂ : ∀ (o cc : Fin c) (kh : Fin kH) (kw : Fin kW), |W₂ o cc kh kw| ≤ w₂) (hb₂ : ∀ (o : Fin c), |b₂ o| ≤ β₂) (hW₃ : ∀ (i : Fin (c * h * w)) (j : Fin d₃), |W₃ i j| ≤ w₃) (hb₃ : ∀ (j : Fin d₃), |b₃ j| ≤ β₃) (hW₄ : ∀ (i : Fin d₃) (j : Fin d₄), |W₄ i j| ≤ w₄) (hb₄ : ∀ (j : Fin d₄), |b₄ j| ≤ β₄) (hW₅ : ∀ (i : Fin d₄) (j : Fin nC), |W₅ i j| ≤ w₅) (hb₅ : ∀ (j : Fin nC), |b₅ j| ≤ β₅) (hmarginConv : ∀ (k : Fin (c * (2 * h) * (2 * w))), FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ a 0 < |(conv2d W₂ b₂ x₁).flatten k|) (hmarginPool : MaxPool2MarginQ (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ a 0) (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ x₁).flatten))) (hmargin3 : ∀ (l : Fin d₃), FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ a) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ a 0) < |dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ x₁).flatten)) l|) (hmargin4 : ∀ (q : Fin d₄), FloatModel.layerBudget M.u d₃ w₄ β₄ (FloatModel.layerAct (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ a)) (FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ a) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ a 0)) < |dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ x₁).flatten)))) q|) (hm2 : ∀ (k : Fin (c * (2 * h) * (2 * w))), a * stepRadius (cnnConv2KernelLoss b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) W₂.flatten lr (M.cnnConv2GradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp) < |(conv2d W₂ b₂ x₁).flatten k|) (hmq : MaxPool2MarginQ (a * stepRadius (cnnConv2KernelLoss b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) W₂.flatten lr (M.cnnConv2GradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp)) (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ x₁).flatten))) (hm3 : ∀ (l : Fin d₃), w₃ * (↑(2 * h * (2 * w)) * (a * stepRadius (cnnConv2KernelLoss b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) W₂.flatten lr (M.cnnConv2GradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp))) < |dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ x₁).flatten)) l|) (hm4 : ∀ (q : Fin d₄), w₄ * (↑d₃ * (w₃ * (↑(2 * h * (2 * w)) * (a * stepRadius (cnnConv2KernelLoss b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) W₂.flatten lr (M.cnnConv2GradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp))))) < |dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ x₁).flatten)))) q|) (hsmall : 2 * (w₅ * (↑d₄ * (w₄ * (↑d₃ * (w₃ * (↑(2 * h * (2 * w)) * (a * stepRadius (cnnConv2KernelLoss b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) W₂.flatten lr (M.cnnConv2GradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp)))))))) < 1) (h1 : lr * M.cnnConv2GradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp * ∑ idx : Fin (c * c * kH * kW), |gradAt (cnnConv2KernelLoss b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) W₂.flatten idx| ≤ (lr * ∑ idx : Fin (c * c * kH * kW), gradAt (cnnConv2KernelLoss b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) W₂.flatten idx ^ 2) / 4) (h2 : 2 * ↑nC * ↑(2 * h * (2 * w)) ^ 2 * ↑d₃ ^ 2 * ↑d₄ ^ 2 * w₃ ^ 2 * w₄ ^ 2 * w₅ ^ 2 * a ^ 2 / (1 - 2 * (w₅ * (↑d₄ * (w₄ * (↑d₃ * (w₃ * (↑(2 * h * (2 * w)) * (a * stepRadius (cnnConv2KernelLoss b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) W₂.flatten lr (M.cnnConv2GradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp))))))))) * stepRadius (cnnConv2KernelLoss b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) W₂.flatten lr (M.cnnConv2GradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp) ^ 2 ≤ (lr * ∑ idx : Fin (c * c * kH * kW), gradAt (cnnConv2KernelLoss b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) W₂.flatten idx ^ 2) / 4) :
          cnnConv2KernelLoss b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label (W₂.flatten - lr • M.cnnConv2FloatGrad b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ fexp label W₂.flatten) ≤ cnnConv2KernelLoss b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label W₂.flatten - (lr * ∑ idx : Fin (c * c * kH * kW), gradAt (cnnConv2KernelLoss b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) W₂.flatten idx ^ 2) / 2

          One SGD step with the FloatModel binary32 conv-2 kernel gradient decreases one example's cross-entropy loss; the gradient's accuracy is proven, not assumed. The conv peer of mlp_input_float_sgd_descends: the gradient is the FloatModel binary32 W₂ gradient M.cnnConv2FloatGrad …, and its accuracy is proven by cnn_conv2_grad_close (η := cnnConv2GradBudget, discharged per kernel entry via k4Idx_surj), not assumed. The two rounding-margin families are carried as hypotheses: the per-layer ROUND margins (hmarginConv/Pool/3/4, feeding the grad-close) and the gradient-radius STEP margins + hsmall/h1/h2 (feeding cnn_conv2_sgd_descends's drift-freeze and the descent geometry). The conv-2 input x₁ is exact.

          Scope: one example, W₂ moving with every other parameter fixed, and the update taken in ℝ — only the gradient is float-modelled.

          noncomputable def Proofs.FloatModel.cnnConv1CotF {ic c h w d₃ d₄ nC kH kW : ℕ} (M : FloatModel) (W₁ : Kernel4 c ic kH kW) (b₁ : Vec c) (x₀ : Tensor3 ic (2 * h) (2 * w)) (W₂ : Kernel4 c c kH kW) (b₂ : Vec c) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (fexp : ℝ → ℝ) (label : Fin nC) :
          Tensor3 c (2 * h) (2 * w)

          The float conv-1-output cotangent: the conv-1 ReLU mask 𝟙[z̃₁>0] times the float conv-2 backward M.dot (convTap W₂ slab) (float conv-2-output cotangent slab), the conv-2 cotangent taken at the FLOAT conv-2 input relu(z̃₁). The conv-1 kernel and bias gradients (cnnConv1FloatGrad, cnnConv1BiasFloatGrad) are its rounded dot against the padded input window and its rounded sum.

          Equations
          • One or more equations did not get rendered due to their size.
          Instances For
            noncomputable def Proofs.cnnConv1CotR {ic c h w d₃ d₄ nC kH kW : ℕ} (W₁ : Kernel4 c ic kH kW) (b₁ : Vec c) (x₀ : Tensor3 ic (2 * h) (2 * w)) (W₂ : Kernel4 c c kH kW) (b₂ : Vec c) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (label : Fin nC) :
            Tensor3 c (2 * h) (2 * w)

            The certified conv-1-output cotangent, in the reluMask form that cnn_conv1_loss_gradAt_reluMask and cnn_conv1_bias_loss_gradAt_reluMask contract against the padded input window and sum: the conv-1 ReLU mask times the conv-2 backward ∑ convTap·c₂ of the conv-2-output cotangent.

            Equations
            • One or more equations did not get rendered due to their size.
            Instances For
              noncomputable def Proofs.FloatModel.cnnConv1FloatGrad {ic c h w d₃ d₄ nC kH kW : ℕ} (M : FloatModel) (b₁ : Vec c) (x₀ : Tensor3 ic (2 * h) (2 * w)) (W₂ : Kernel4 c c kH kW) (b₂ : Vec c) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (fexp : ℝ → ℝ) (label : Fin nC) (u : Vec (c * ic * kH * kW)) :
              Vec (c * ic * kH * kW)

              The binary32 conv-1 weight gradient (FloatModel transcription of the per-example gradient) — the conv-1 peer of cnnConv2FloatGrad, one conv-backward deeper. At kernel entry (o,cc,kh,kw) it is the float dot of the (exact) padded-input window convPadWin x₀ against the slab of the float conv-1-output cotangent cnnConv1CotF at the conv-1 kernel u. All M-ops carry the rounding; reluMask/maxPoolFlat/relu/convTap are exact.

              Equations
              • One or more equations did not get rendered due to their size.
              Instances For
                @[simp]
                theorem Proofs.FloatModel.cnnConv1FloatGrad_apply {ic c h w d₃ d₄ nC kH kW : ℕ} (M : FloatModel) (b₁ : Vec c) (x₀ : Tensor3 ic (2 * h) (2 * w)) (W₂ : Kernel4 c c kH kW) (b₂ : Vec c) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (fexp : ℝ → ℝ) (label : Fin nC) (u : Vec (c * ic * kH * kW)) (o : Fin c) (cc : Fin ic) (kh : Fin kH) (kw : Fin kW) :
                M.cnnConv1FloatGrad b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ fexp label u (k4Idx o cc kh kw) = M.dot (convPadWin kH kW x₀ cc kh kw) (cotWin (M.cnnConv1CotF (Kernel4.unflatten u) b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ fexp label) o)
                noncomputable def Proofs.FloatModel.cnnConv1CotBudget (M : FloatModel) (ic c h w d₃ d₄ nC kH kW : ℕ) (a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp : ℝ) :

                The conv-1 cotangent drift budget: the conv-2 backward (transpose conv) of the float conv-2-output cotangent, a rounded dot over the slab c·(2h)·(2w) — its Higham γ against the float-cotangent magnitude CP + e₂ plus the per-entry drift e₂, with the conv-2 cotangent chain (cnnConv2CotMag / cnnConv2CotBudget) at the FLOAT conv-2 input (aX2 = A₁, eX2 = E₁).

                Equations
                • One or more equations did not get rendered due to their size.
                Instances For
                  noncomputable def Proofs.FloatModel.cnnConv1GradBudget (M : FloatModel) (ic c h w d₃ d₄ nC kH kW : ℕ) (a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp : ℝ) :

                  The conv-1 float-backward grad-close budget — the conv-2 budget (cnnConv2GradBudget-shaped) deepened by one conv layer: the conv-1 spatial dot (fan-in (2h)·(2w)) rides the conv-1 cotangent drift eback = cnnConv1CotBudget and the float conv-1-cotangent magnitude C1t = c·(2h)·(2w)·w₂·CP + eback.

                  Equations
                  • One or more equations did not get rendered due to their size.
                  Instances For
                    theorem Proofs.convTap_back_close {c h w kH kW : ℕ} (M : FloatModel) (W₂ : Kernel4 c c kH kW) (c2F c2R : Tensor3 c (2 * h) (2 * w)) {w₂ C2t e2 : ℝ} (hw₂ : 0 ≤ w₂) (hW₂ : ∀ (o cc : Fin c) (kh : Fin kH) (kw : Fin kW), |W₂ o cc kh kw| ≤ w₂) (hc2F : ∀ (co : Fin c) (ho : Fin (2 * h)) (wo : Fin (2 * w)), |c2F co ho wo| ≤ C2t) (hc2close : ∀ (co : Fin c) (ho : Fin (2 * h)) (wo : Fin (2 * w)), |c2F co ho wo - c2R co ho wo| ≤ e2) (ci : Fin c) (hi : Fin (2 * h)) (wi : Fin (2 * w)) :
                    |M.dot (Tensor3.flatten fun (co : Fin c) (ho : Fin (2 * h)) (wo : Fin (2 * w)) => convTap W₂ ci hi wi co ho wo) c2F.flatten - ∑ co : Fin c, ∑ ho : Fin (2 * h), ∑ wo : Fin (2 * w), convTap W₂ ci hi wi co ho wo * c2R co ho wo| ≤ ((1 + M.u) ^ (c * (2 * h) * (2 * w) + 1) - 1) * (↑(c * (2 * h) * (2 * w)) * (w₂ * C2t)) + ↑(c * (2 * h) * (2 * w)) * (w₂ * e2)

                    The float conv-2 backward (transpose conv) against a perturbed cotangent. The rounded M.dot of the exact convTap slab against the float conv-2-output cotangent c2F, vs the certified ∑ convTap·c2R — the convTap-flattening (sum_t3) plus dot_perturbed_close (fan-in c·(2h)·(2w), per-entry tap bound w₂, float-cotangent magnitude C2t, drift e₂). Generic in (c2F, c2R) so the conv-1 rung passes the conv-2 cotangent tensors abstractly.

                    theorem Proofs.cnn_conv1_cot_close {ic c h w d₃ d₄ nC kH kW : ℕ} (M : FloatModel) (W₁ : Kernel4 c ic kH kW) (b₁ : Vec c) (x₀ : Tensor3 ic (2 * h) (2 * w)) (W₂ : Kernel4 c c kH kW) (b₂ : Vec c) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (label : Fin nC) (fexp : ℝ → ℝ) {a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp : ℝ} (ha : 0 ≤ a) (hw₁ : 0 ≤ w₁) (hβ₁ : 0 ≤ β₁) (hw₂ : 0 ≤ w₂) (hβ₂ : 0 ≤ β₂) (hw₃ : 0 ≤ w₃) (hβ₃ : 0 ≤ β₃) (hw₄ : 0 ≤ w₄) (hβ₄ : 0 ≤ β₄) (hw₅ : 0 ≤ w₅) (hβ₅ : 0 ≤ β₅) (heexp0 : 0 ≤ eexp) (heexp1 : eexp ≤ 1) (hfexp : ∀ (t : ℝ), |fexp t - Real.exp t| ≤ eexp * Real.exp t) (hρ1 : FloatModel.smRho M.u eexp nC < 1) (hx₀ : ∀ (ci : Fin ic) (i : Fin (2 * h)) (j : Fin (2 * w)), |x₀ ci i j| ≤ a) (hW₁ : ∀ (o : Fin c) (cc : Fin ic) (kh : Fin kH) (kw : Fin kW), |W₁ o cc kh kw| ≤ w₁) (hb₁ : ∀ (o : Fin c), |b₁ o| ≤ β₁) (hW₂ : ∀ (o cc : Fin c) (kh : Fin kH) (kw : Fin kW), |W₂ o cc kh kw| ≤ w₂) (hb₂ : ∀ (o : Fin c), |b₂ o| ≤ β₂) (hW₃ : ∀ (i : Fin (c * h * w)) (j : Fin d₃), |W₃ i j| ≤ w₃) (hb₃ : ∀ (j : Fin d₃), |b₃ j| ≤ β₃) (hW₄ : ∀ (i : Fin d₃) (j : Fin d₄), |W₄ i j| ≤ w₄) (hb₄ : ∀ (j : Fin d₄), |b₄ j| ≤ β₄) (hW₅ : ∀ (i : Fin d₄) (j : Fin nC), |W₅ i j| ≤ w₅) (hb₅ : ∀ (j : Fin nC), |b₅ j| ≤ β₅) (hmargin1 : ∀ (k : Fin (c * (2 * h) * (2 * w))), FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0 < |(conv2d W₁ b₁ x₀).flatten k|) (hmargin2 : ∀ (k : Fin (c * (2 * h) * (2 * w))), FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0) < |(conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten k|) (hmarginPool : MaxPool2MarginQ (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0)) (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten))) (hmargin3 : ∀ (l : Fin d₃), FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a)) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0)) < |dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten)) l|) (hmargin4 : ∀ (q : Fin d₄), FloatModel.layerBudget M.u d₃ w₄ β₄ (FloatModel.layerAct (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a))) (FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a)) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0))) < |dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten)))) q|) (ci : Fin c) (hi : Fin (2 * h)) (wi : Fin (2 * w)) :
                    |M.cnnConv1CotF W₁ b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ fexp label ci hi wi - cnnConv1CotR W₁ b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label ci hi wi| ≤ M.cnnConv1CotBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp ∧ |M.cnnConv1CotF W₁ b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ fexp label ci hi wi| ≤ ↑(c * (2 * h) * (2 * w)) * (w₂ * FloatModel.cnnConv2CotMag d₃ d₄ nC w₃ w₄ w₅) + M.cnnConv1CotBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp

                    The conv-1-output cotangent is float-close — the part cnn_conv1_grad_close and cnn_conv1_bias_grad_close share. Under the five margins, at every conv-1 output cell the float cotangent cnnConv1CotF is within cnnConv1CotBudget of the certified cnnConv1CotR, and its magnitude within c·(2h)·(2w)·w₂·cnnConv2CotMag + cnnConv1CotBudget. The chain: the conv-1 forward closes (convF_close), so the conv-2 input does (relu_close); the conv-2 cotangent chain at that float input (cnn_conv2_cot_close, with its real magnitude cnn_conv2_cot_real_abs_le); the rounded transpose conv (convTap_back_close, with convTap_back_abs_le); the conv-1 ReLU mask freezes (mask_scalar_close).

                    theorem Proofs.cnn_conv1_grad_close {ic c h w d₃ d₄ nC kH kW : ℕ} (M : FloatModel) (b₁ : Vec c) (x₀ : Tensor3 ic (2 * h) (2 * w)) (W₂ : Kernel4 c c kH kW) (b₂ : Vec c) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (label : Fin nC) (fexp : ℝ → ℝ) (u : Vec (c * ic * kH * kW)) {a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp : ℝ} (ha : 0 ≤ a) (hw₁ : 0 ≤ w₁) (hβ₁ : 0 ≤ β₁) (hw₂ : 0 ≤ w₂) (hβ₂ : 0 ≤ β₂) (hw₃ : 0 ≤ w₃) (hβ₃ : 0 ≤ β₃) (hw₄ : 0 ≤ w₄) (hβ₄ : 0 ≤ β₄) (hw₅ : 0 ≤ w₅) (hβ₅ : 0 ≤ β₅) (heexp0 : 0 ≤ eexp) (heexp1 : eexp ≤ 1) (hfexp : ∀ (t : ℝ), |fexp t - Real.exp t| ≤ eexp * Real.exp t) (hρ1 : FloatModel.smRho M.u eexp nC < 1) (hx₀ : ∀ (ci : Fin ic) (i : Fin (2 * h)) (j : Fin (2 * w)), |x₀ ci i j| ≤ a) (hu1 : ∀ (idx : Fin (c * ic * kH * kW)), |u idx| ≤ w₁) (hb₁ : ∀ (o : Fin c), |b₁ o| ≤ β₁) (hW₂ : ∀ (o cc : Fin c) (kh : Fin kH) (kw : Fin kW), |W₂ o cc kh kw| ≤ w₂) (hb₂ : ∀ (o : Fin c), |b₂ o| ≤ β₂) (hW₃ : ∀ (i : Fin (c * h * w)) (j : Fin d₃), |W₃ i j| ≤ w₃) (hb₃ : ∀ (j : Fin d₃), |b₃ j| ≤ β₃) (hW₄ : ∀ (i : Fin d₃) (j : Fin d₄), |W₄ i j| ≤ w₄) (hb₄ : ∀ (j : Fin d₄), |b₄ j| ≤ β₄) (hW₅ : ∀ (i : Fin d₄) (j : Fin nC), |W₅ i j| ≤ w₅) (hb₅ : ∀ (j : Fin nC), |b₅ j| ≤ β₅) (hmargin1 : ∀ (k : Fin (c * (2 * h) * (2 * w))), FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0 < |(conv2d (Kernel4.unflatten u) b₁ x₀).flatten k|) (hmargin2 : ∀ (k : Fin (c * (2 * h) * (2 * w))), FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0) < |(conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten u) b₁ x₀).flatten))).flatten k|) (hmarginPool : MaxPool2MarginQ (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0)) (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten u) b₁ x₀).flatten))).flatten))) (hmargin3 : ∀ (l : Fin d₃), FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a)) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0)) < |dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten u) b₁ x₀).flatten))).flatten)) l|) (hmargin4 : ∀ (q : Fin d₄), FloatModel.layerBudget M.u d₃ w₄ β₄ (FloatModel.layerAct (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a))) (FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a)) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0))) < |dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten u) b₁ x₀).flatten))).flatten)))) q|) (o : Fin c) (cc : Fin ic) (kh : Fin kH) (kw : Fin kW) :
                    |M.cnnConv1FloatGrad b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ fexp label u (k4Idx o cc kh kw) - gradAt (fun (u' : Vec (c * ic * kH * kW)) => crossEntropy nC (dense W₅ b₅ (relu d₄ (dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d (Kernel4.unflatten u') b₁ x₀).flatten))).flatten))))))) label) u (k4Idx o cc kh kw)| ≤ M.cnnConv1GradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp

                    The binary32 conv-1 weight gradient is within an explicit budget of the certified one — the conv-1 peer of cnn_conv2_grad_close, one conv-backward deeper. With x₀ exact, the FloatModel W₁ gradient M.cnnConv1FloatGrad … stays within cnnConv1GradBudget. The conv-2 cotangent chain is reused at a FLOAT conv-2 input relu(z̃₁) (cnn_conv2_cot_close); the conv-2 backward is a rounded dot of the (exact) convTap slab against the float conv-2 cotangent slab (dot_perturbed_close over c·(2h)·(2w)); the conv-1 ReLU mask freezes (mask_scalar_close); the conv-1 weight dot rounds it (dot_perturbed_close over (2h)·(2w)). Five quantitative margins are carried; the bridge cnn_conv1_loss_gradAt_reluMask turns the gradAt into the dot.

                    theorem Proofs.cnn_conv1_float_sgd_descends {ic c h w d₃ d₄ nC kH kW : ℕ} (M : FloatModel) (W₁ : Kernel4 c ic kH kW) (b₁ : Vec c) (x₀ : Tensor3 ic (2 * h) (2 * w)) (W₂ : Kernel4 c c kH kW) (b₂ : Vec c) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (label : Fin nC) (fexp : ℝ → ℝ) {lr a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp : ℝ} (ha : 0 ≤ a) (hw₁ : 0 ≤ w₁) (hβ₁ : 0 ≤ β₁) (hw₂ : 0 ≤ w₂) (hβ₂ : 0 ≤ β₂) (hw₃ : 0 ≤ w₃) (hβ₃ : 0 ≤ β₃) (hw₄ : 0 ≤ w₄) (hβ₄ : 0 ≤ β₄) (hw₅ : 0 ≤ w₅) (hβ₅ : 0 ≤ β₅) (hlr : 0 ≤ lr) (heexp0 : 0 ≤ eexp) (heexp1 : eexp ≤ 1) (hfexp : ∀ (t : ℝ), |fexp t - Real.exp t| ≤ eexp * Real.exp t) (hρ1 : FloatModel.smRho M.u eexp nC < 1) (hx₀ : ∀ (cc : Fin ic) (i : Fin (2 * h)) (j : Fin (2 * w)), |x₀ cc i j| ≤ a) (hW₁ : ∀ (o : Fin c) (cc : Fin ic) (kh : Fin kH) (kw : Fin kW), |W₁ o cc kh kw| ≤ w₁) (hb₁ : ∀ (o : Fin c), |b₁ o| ≤ β₁) (hW₂ : ∀ (o cc : Fin c) (kh : Fin kH) (kw : Fin kW), |W₂ o cc kh kw| ≤ w₂) (hb₂ : ∀ (o : Fin c), |b₂ o| ≤ β₂) (hW₃ : ∀ (i : Fin (c * h * w)) (j : Fin d₃), |W₃ i j| ≤ w₃) (hb₃ : ∀ (j : Fin d₃), |b₃ j| ≤ β₃) (hW₄ : ∀ (i : Fin d₃) (j : Fin d₄), |W₄ i j| ≤ w₄) (hb₄ : ∀ (j : Fin d₄), |b₄ j| ≤ β₄) (hW₅ : ∀ (i : Fin d₄) (j : Fin nC), |W₅ i j| ≤ w₅) (hb₅ : ∀ (j : Fin nC), |b₅ j| ≤ β₅) (hr1 : ∀ (k : Fin (c * (2 * h) * (2 * w))), FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0 < |(conv2d W₁ b₁ x₀).flatten k|) (hr2 : ∀ (k : Fin (c * (2 * h) * (2 * w))), FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0) < |(conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten k|) (hrPool : MaxPool2MarginQ (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0)) (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten))) (hr3 : ∀ (l : Fin d₃), FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a)) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0)) < |dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten)) l|) (hr4 : ∀ (q : Fin d₄), FloatModel.layerBudget M.u d₃ w₄ β₄ (FloatModel.layerAct (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a))) (FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a)) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0))) < |dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten)))) q|) (hm1 : ∀ (k : Fin (c * (2 * h) * (2 * w))), a * stepRadius (cnnConv1KernelLoss b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) W₁.flatten lr (M.cnnConv1GradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp) < |(conv2d W₁ b₁ x₀).flatten k|) (hm2 : ∀ (k : Fin (c * (2 * h) * (2 * w))), ↑(c * kH * kW) * (w₂ * (a * stepRadius (cnnConv1KernelLoss b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) W₁.flatten lr (M.cnnConv1GradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp))) < |(conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten k|) (hmq : MaxPool2MarginQ (↑(c * kH * kW) * (w₂ * (a * stepRadius (cnnConv1KernelLoss b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) W₁.flatten lr (M.cnnConv1GradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp)))) (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten))) (hm3 : ∀ (l : Fin d₃), w₃ * (↑(c * kH * kW) * (w₂ * (↑(2 * h * (2 * w)) * (a * stepRadius (cnnConv1KernelLoss b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) W₁.flatten lr (M.cnnConv1GradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp))))) < |dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten)) l|) (hm4 : ∀ (q : Fin d₄), w₄ * (↑d₃ * (w₃ * (↑(c * kH * kW) * (w₂ * (↑(2 * h * (2 * w)) * (a * stepRadius (cnnConv1KernelLoss b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) W₁.flatten lr (M.cnnConv1GradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp))))))) < |dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten)))) q|) (hsmall : 2 * (w₅ * (↑d₄ * (w₄ * (↑d₃ * (w₃ * (↑(c * kH * kW) * (w₂ * (↑(2 * h * (2 * w)) * (a * stepRadius (cnnConv1KernelLoss b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) W₁.flatten lr (M.cnnConv1GradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp)))))))))) < 1) (h1 : lr * M.cnnConv1GradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp * ∑ idx : Fin (c * ic * kH * kW), |gradAt (cnnConv1KernelLoss b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) W₁.flatten idx| ≤ (lr * ∑ idx : Fin (c * ic * kH * kW), gradAt (cnnConv1KernelLoss b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) W₁.flatten idx ^ 2) / 4) (h2 : 2 * ↑nC * ↑(2 * h * (2 * w)) ^ 2 * ↑(c * kH * kW) ^ 2 * ↑d₃ ^ 2 * ↑d₄ ^ 2 * w₂ ^ 2 * w₃ ^ 2 * w₄ ^ 2 * w₅ ^ 2 * a ^ 2 / (1 - 2 * (w₅ * (↑d₄ * (w₄ * (↑d₃ * (w₃ * (↑(c * kH * kW) * (w₂ * (↑(2 * h * (2 * w)) * (a * stepRadius (cnnConv1KernelLoss b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) W₁.flatten lr (M.cnnConv1GradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp))))))))))) * stepRadius (cnnConv1KernelLoss b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) W₁.flatten lr (M.cnnConv1GradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp) ^ 2 ≤ (lr * ∑ idx : Fin (c * ic * kH * kW), gradAt (cnnConv1KernelLoss b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) W₁.flatten idx ^ 2) / 4) :
                    cnnConv1KernelLoss b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label (W₁.flatten - lr • M.cnnConv1FloatGrad b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ fexp label W₁.flatten) ≤ cnnConv1KernelLoss b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label W₁.flatten - (lr * ∑ idx : Fin (c * ic * kH * kW), gradAt (cnnConv1KernelLoss b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) W₁.flatten idx ^ 2) / 2

                    One SGD step with the FloatModel binary32 conv-1 kernel gradient decreases one example's cross-entropy loss; the gradient's accuracy is proven, not assumed. The conv-1 peer of cnn_conv2_float_sgd_descends: the gradient is the FloatModel binary32 W₁ gradient M.cnnConv1FloatGrad …, accuracy proven by cnn_conv1_grad_close (η := cnnConv1GradBudget, discharged per kernel entry via k4Idx_surj), wired into the abstract cnn_conv1_sgd_descends. Five per-layer ROUND margins feed the grad-close; the gradient-radius STEP margins + hsmall/h1/h2 feed the drift-freeze and descent geometry. Both conv kernels of the Chapter-3 CNN now have a float-gradient descent statement.

                    Scope: one example, W₁ moving with every other parameter fixed, and the update taken in ℝ — only the gradient is float-modelled.

                    noncomputable def Proofs.FloatModel.cnnConv2BiasFloatGrad {c h w d₃ d₄ nC kH kW : ℕ} (M : FloatModel) (W₂ : Kernel4 c c kH kW) (b₂ : Vec c) (x₁ : Tensor3 c (2 * h) (2 * w)) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (fexp : ℝ → ℝ) (label : Fin nC) :
                    Vec c

                    The binary32 conv-2 bias gradient (FloatModel transcription of the per-example gradient) — the bias peer of cnnConv2FloatGrad: at output channel o it is the float SUM M.sum (cotWin c̃Conv o) of the same float conv-2-output cotangent slab (the bias Jacobian is the channel indicator, so there is no convPadWin left operand and no per-slot kernel index — one entry per channel).

                    Equations
                    • One or more equations did not get rendered due to their size.
                    Instances For
                      noncomputable def Proofs.FloatModel.cnnConv2BiasGradBudget (M : FloatModel) (c h w d₃ d₄ nC kH kW : ℕ) (a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp : ℝ) :

                      The conv-2 bias-gradient grad-close budget — cnnConv2GradBudget with the a· input factor stripped (the bias Jacobian carries no input window): the spatial sum's Higham γ over (2h)·(2w) against the float-cotangent magnitude (cnnConv2CotMag + cnnConv2CotBudget) plus the per-entry cotangent drift cnnConv2CotBudget. The cotangent chain is the exact conv-2-input (aX2 = a, eX2 = 0) instance of the factored cnnConv2CotBudget / cnnConv2CotMag.

                      Equations
                      • One or more equations did not get rendered due to their size.
                      Instances For
                        theorem Proofs.cnn_conv2_bias_grad_close {c h w d₃ d₄ nC kH kW : ℕ} (M : FloatModel) (W₂ : Kernel4 c c kH kW) (b₂ : Vec c) (x₁ : Tensor3 c (2 * h) (2 * w)) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (label : Fin nC) (fexp : ℝ → ℝ) {a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp : ℝ} (ha : 0 ≤ a) (hw₂ : 0 ≤ w₂) (hβ₂ : 0 ≤ β₂) (hw₃ : 0 ≤ w₃) (hβ₃ : 0 ≤ β₃) (hw₄ : 0 ≤ w₄) (hβ₄ : 0 ≤ β₄) (hw₅ : 0 ≤ w₅) (hβ₅ : 0 ≤ β₅) (heexp0 : 0 ≤ eexp) (heexp1 : eexp ≤ 1) (hfexp : ∀ (t : ℝ), |fexp t - Real.exp t| ≤ eexp * Real.exp t) (hρ1 : FloatModel.smRho M.u eexp nC < 1) (hx₁ : ∀ (ci : Fin c) (i : Fin (2 * h)) (j : Fin (2 * w)), |x₁ ci i j| ≤ a) (hW₂ : ∀ (o cc : Fin c) (kh : Fin kH) (kw : Fin kW), |W₂ o cc kh kw| ≤ w₂) (hb₂ : ∀ (o : Fin c), |b₂ o| ≤ β₂) (hW₃ : ∀ (i : Fin (c * h * w)) (j : Fin d₃), |W₃ i j| ≤ w₃) (hb₃ : ∀ (j : Fin d₃), |b₃ j| ≤ β₃) (hW₄ : ∀ (i : Fin d₃) (j : Fin d₄), |W₄ i j| ≤ w₄) (hb₄ : ∀ (j : Fin d₄), |b₄ j| ≤ β₄) (hW₅ : ∀ (i : Fin d₄) (j : Fin nC), |W₅ i j| ≤ w₅) (hb₅ : ∀ (j : Fin nC), |b₅ j| ≤ β₅) (hmarginConv : ∀ (k : Fin (c * (2 * h) * (2 * w))), FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ a 0 < |(conv2d W₂ b₂ x₁).flatten k|) (hmarginPool : MaxPool2MarginQ (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ a 0) (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ x₁).flatten))) (hmargin3 : ∀ (l : Fin d₃), FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ a) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ a 0) < |dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ x₁).flatten)) l|) (hmargin4 : ∀ (q : Fin d₄), FloatModel.layerBudget M.u d₃ w₄ β₄ (FloatModel.layerAct (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ a)) (FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ a) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ a 0)) < |dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ x₁).flatten)))) q|) (o : Fin c) :
                        |M.cnnConv2BiasFloatGrad W₂ b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ fexp label o - gradAt (fun (b' : Vec c) => crossEntropy nC (dense W₅ b₅ (relu d₄ (dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b' x₁).flatten))))))) label) b₂ o| ≤ M.cnnConv2BiasGradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp

                        The binary32 conv-2 BIAS gradient is within an explicit budget of the certified one — the bias peer of cnn_conv2_grad_close, built on the factored conv-2 cotangent chain at the exact conv-2 input x₁ (cnn_conv2_cot_close with aX2 = a, eX2 = 0) and the spatial-SUM core sum_perturbed_close. The bridge cnn_conv2_bias_loss_gradAt_reluMask turns the gradAt into the sum the float bias gradient rounds. Four quantitative margins (conv-output, pool POST-relu, z̃₃, z̃₄) freeze the routing.

                        theorem Proofs.cnn_conv2_bias_float_sgd_descends {c h w d₃ d₄ nC kH kW : ℕ} (M : FloatModel) (W₂ : Kernel4 c c kH kW) (b₂ : Vec c) (x₁ : Tensor3 c (2 * h) (2 * w)) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (label : Fin nC) (fexp : ℝ → ℝ) {lr a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp : ℝ} (ha : 0 ≤ a) (hw₂ : 0 ≤ w₂) (hβ₂ : 0 ≤ β₂) (hw₃ : 0 ≤ w₃) (hβ₃ : 0 ≤ β₃) (hw₄ : 0 ≤ w₄) (hβ₄ : 0 ≤ β₄) (hw₅ : 0 ≤ w₅) (hβ₅ : 0 ≤ β₅) (hlr : 0 ≤ lr) (heexp0 : 0 ≤ eexp) (heexp1 : eexp ≤ 1) (hfexp : ∀ (t : ℝ), |fexp t - Real.exp t| ≤ eexp * Real.exp t) (hρ1 : FloatModel.smRho M.u eexp nC < 1) (hx : ∀ (cc : Fin c) (i : Fin (2 * h)) (j : Fin (2 * w)), |x₁ cc i j| ≤ a) (hW₂ : ∀ (o cc : Fin c) (kh : Fin kH) (kw : Fin kW), |W₂ o cc kh kw| ≤ w₂) (hb₂ : ∀ (o : Fin c), |b₂ o| ≤ β₂) (hW₃ : ∀ (i : Fin (c * h * w)) (j : Fin d₃), |W₃ i j| ≤ w₃) (hb₃ : ∀ (j : Fin d₃), |b₃ j| ≤ β₃) (hW₄ : ∀ (i : Fin d₃) (j : Fin d₄), |W₄ i j| ≤ w₄) (hb₄ : ∀ (j : Fin d₄), |b₄ j| ≤ β₄) (hW₅ : ∀ (i : Fin d₄) (j : Fin nC), |W₅ i j| ≤ w₅) (hb₅ : ∀ (j : Fin nC), |b₅ j| ≤ β₅) (hmarginConv : ∀ (k : Fin (c * (2 * h) * (2 * w))), FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ a 0 < |(conv2d W₂ b₂ x₁).flatten k|) (hmarginPool : MaxPool2MarginQ (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ a 0) (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ x₁).flatten))) (hmargin3 : ∀ (l : Fin d₃), FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ a) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ a 0) < |dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ x₁).flatten)) l|) (hmargin4 : ∀ (q : Fin d₄), FloatModel.layerBudget M.u d₃ w₄ β₄ (FloatModel.layerAct (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ a)) (FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ a) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ a 0)) < |dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ x₁).flatten)))) q|) (hm2 : ∀ (k : Fin (c * (2 * h) * (2 * w))), stepRadius (cnnConv2BiasLoss W₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) b₂ lr (M.cnnConv2BiasGradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp) < |(conv2d W₂ b₂ x₁).flatten k|) (hmq : MaxPool2MarginQ (stepRadius (cnnConv2BiasLoss W₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) b₂ lr (M.cnnConv2BiasGradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp)) (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ x₁).flatten))) (hm3 : ∀ (l : Fin d₃), w₃ * (↑(2 * h * (2 * w)) * stepRadius (cnnConv2BiasLoss W₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) b₂ lr (M.cnnConv2BiasGradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp)) < |dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ x₁).flatten)) l|) (hm4 : ∀ (q : Fin d₄), w₄ * (↑d₃ * (w₃ * (↑(2 * h * (2 * w)) * stepRadius (cnnConv2BiasLoss W₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) b₂ lr (M.cnnConv2BiasGradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp)))) < |dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ x₁).flatten)))) q|) (hsmall : 2 * (w₅ * (↑d₄ * (w₄ * (↑d₃ * (w₃ * (↑(2 * h * (2 * w)) * stepRadius (cnnConv2BiasLoss W₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) b₂ lr (M.cnnConv2BiasGradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp))))))) < 1) (h1 : lr * M.cnnConv2BiasGradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp * ∑ o : Fin c, |gradAt (cnnConv2BiasLoss W₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) b₂ o| ≤ (lr * ∑ o : Fin c, gradAt (cnnConv2BiasLoss W₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) b₂ o ^ 2) / 4) (h2 : 2 * ↑nC * ↑(2 * h * (2 * w)) ^ 2 * ↑d₃ ^ 2 * ↑d₄ ^ 2 * w₃ ^ 2 * w₄ ^ 2 * w₅ ^ 2 / (1 - 2 * (w₅ * (↑d₄ * (w₄ * (↑d₃ * (w₃ * (↑(2 * h * (2 * w)) * stepRadius (cnnConv2BiasLoss W₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) b₂ lr (M.cnnConv2BiasGradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp)))))))) * stepRadius (cnnConv2BiasLoss W₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) b₂ lr (M.cnnConv2BiasGradBudget c h w d₃ d₄ nC kH kW a w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp) ^ 2 ≤ (lr * ∑ o : Fin c, gradAt (cnnConv2BiasLoss W₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) b₂ o ^ 2) / 4) :
                        cnnConv2BiasLoss W₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label (b₂ - lr • M.cnnConv2BiasFloatGrad W₂ b₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ fexp label) ≤ crossEntropy nC (dense W₅ b₅ (relu d₄ (dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ x₁).flatten))))))) label - (lr * ∑ o : Fin c, gradAt (cnnConv2BiasLoss W₂ x₁ W₃ b₃ W₄ b₄ W₅ b₅ label) b₂ o ^ 2) / 2

                        One SGD step with the FloatModel binary32 conv-2 bias gradient decreases one example's cross-entropy loss; the gradient's accuracy is proven, not assumed — the bias peer of cnn_conv2_float_sgd_descends: the gradient is the FloatModel binary32 bias gradient M.cnnConv2BiasFloatGrad …, and its accuracy is proven by cnn_conv2_bias_grad_close (η := cnnConv2BiasGradBudget, discharged per output channel — the bias IS a vector, so no flatten/unflatten plumbing), not assumed. The two rounding-margin families are carried as hypotheses, exactly as in the weight rungs. Scope: one example, b₂ moving, update taken in ℝ.

                        noncomputable def Proofs.FloatModel.cnnConv1BiasFloatGrad {ic c h w d₃ d₄ nC kH kW : ℕ} (M : FloatModel) (W₁ : Kernel4 c ic kH kW) (b₁ : Vec c) (x₀ : Tensor3 ic (2 * h) (2 * w)) (W₂ : Kernel4 c c kH kW) (b₂ : Vec c) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (fexp : ℝ → ℝ) (label : Fin nC) :
                        Vec c

                        The binary32 conv-1 bias gradient (FloatModel transcription of the per-example gradient) — the bias peer of cnnConv1FloatGrad: at output channel o it is the float SUM M.sum (cotWin …) of the same float conv-1-output cotangent slab (cnnConv1CotF), with no convPadWin left operand.

                        Equations
                        Instances For
                          noncomputable def Proofs.FloatModel.cnnConv1BiasGradBudget (M : FloatModel) (ic c h w d₃ d₄ nC kH kW : ℕ) (a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp : ℝ) :

                          The conv-1 bias-gradient grad-close budget — cnnConv1GradBudget with the a· input factors stripped (the bias Jacobian carries no input window): the spatial sum's Higham γ over (2h)·(2w) against the float conv-1 cotangent magnitude C1t = c(2h)(2w)·w₂·CP + eback plus the per-entry drift eback = cnnConv1CotBudget.

                          Equations
                          • One or more equations did not get rendered due to their size.
                          Instances For
                            theorem Proofs.cnn_conv1_bias_grad_close {ic c h w d₃ d₄ nC kH kW : ℕ} (M : FloatModel) (W₁ : Kernel4 c ic kH kW) (b₁ : Vec c) (x₀ : Tensor3 ic (2 * h) (2 * w)) (W₂ : Kernel4 c c kH kW) (b₂ : Vec c) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (label : Fin nC) (fexp : ℝ → ℝ) {a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp : ℝ} (ha : 0 ≤ a) (hw₁ : 0 ≤ w₁) (hβ₁ : 0 ≤ β₁) (hw₂ : 0 ≤ w₂) (hβ₂ : 0 ≤ β₂) (hw₃ : 0 ≤ w₃) (hβ₃ : 0 ≤ β₃) (hw₄ : 0 ≤ w₄) (hβ₄ : 0 ≤ β₄) (hw₅ : 0 ≤ w₅) (hβ₅ : 0 ≤ β₅) (heexp0 : 0 ≤ eexp) (heexp1 : eexp ≤ 1) (hfexp : ∀ (t : ℝ), |fexp t - Real.exp t| ≤ eexp * Real.exp t) (hρ1 : FloatModel.smRho M.u eexp nC < 1) (hx₀ : ∀ (ci : Fin ic) (i : Fin (2 * h)) (j : Fin (2 * w)), |x₀ ci i j| ≤ a) (hW₁ : ∀ (o : Fin c) (cc : Fin ic) (kh : Fin kH) (kw : Fin kW), |W₁ o cc kh kw| ≤ w₁) (hb₁ : ∀ (o : Fin c), |b₁ o| ≤ β₁) (hW₂ : ∀ (o cc : Fin c) (kh : Fin kH) (kw : Fin kW), |W₂ o cc kh kw| ≤ w₂) (hb₂ : ∀ (o : Fin c), |b₂ o| ≤ β₂) (hW₃ : ∀ (i : Fin (c * h * w)) (j : Fin d₃), |W₃ i j| ≤ w₃) (hb₃ : ∀ (j : Fin d₃), |b₃ j| ≤ β₃) (hW₄ : ∀ (i : Fin d₃) (j : Fin d₄), |W₄ i j| ≤ w₄) (hb₄ : ∀ (j : Fin d₄), |b₄ j| ≤ β₄) (hW₅ : ∀ (i : Fin d₄) (j : Fin nC), |W₅ i j| ≤ w₅) (hb₅ : ∀ (j : Fin nC), |b₅ j| ≤ β₅) (hmargin1 : ∀ (k : Fin (c * (2 * h) * (2 * w))), FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0 < |(conv2d W₁ b₁ x₀).flatten k|) (hmargin2 : ∀ (k : Fin (c * (2 * h) * (2 * w))), FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0) < |(conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten k|) (hmarginPool : MaxPool2MarginQ (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0)) (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten))) (hmargin3 : ∀ (l : Fin d₃), FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a)) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0)) < |dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten)) l|) (hmargin4 : ∀ (q : Fin d₄), FloatModel.layerBudget M.u d₃ w₄ β₄ (FloatModel.layerAct (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a))) (FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a)) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0))) < |dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten)))) q|) (o : Fin c) :
                            |M.cnnConv1BiasFloatGrad W₁ b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ fexp label o - gradAt (fun (b' : Vec c) => crossEntropy nC (dense W₅ b₅ (relu d₄ (dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b' x₀).flatten))).flatten))))))) label) b₁ o| ≤ M.cnnConv1BiasGradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp

                            The binary32 conv-1 BIAS gradient is within an explicit budget of the certified one — the bias peer of cnn_conv1_grad_close, built on the factored conv-2 cotangent chain at the FLOAT conv-2 input relu(z̃₁) (cnn_conv2_cot_close), the conv-2 backward convTap_back_close, the conv-1 ReLU-mask freeze (mask_scalar_close), and the spatial-SUM core sum_perturbed_close. Five quantitative margins freeze the routing; the bridge cnn_conv1_bias_loss_gradAt_reluMask turns the gradAt into the sum.

                            theorem Proofs.cnn_conv1_bias_float_sgd_descends {ic c h w d₃ d₄ nC kH kW : ℕ} (M : FloatModel) (W₁ : Kernel4 c ic kH kW) (b₁ : Vec c) (x₀ : Tensor3 ic (2 * h) (2 * w)) (W₂ : Kernel4 c c kH kW) (b₂ : Vec c) (W₃ : Mat (c * h * w) d₃) (b₃ : Vec d₃) (W₄ : Mat d₃ d₄) (b₄ : Vec d₄) (W₅ : Mat d₄ nC) (b₅ : Vec nC) (label : Fin nC) (fexp : ℝ → ℝ) {lr a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp : ℝ} (hc : 0 < c) (ha : 0 ≤ a) (hw₁ : 0 ≤ w₁) (hβ₁ : 0 ≤ β₁) (hw₂ : 0 ≤ w₂) (hβ₂ : 0 ≤ β₂) (hw₃ : 0 ≤ w₃) (hβ₃ : 0 ≤ β₃) (hw₄ : 0 ≤ w₄) (hβ₄ : 0 ≤ β₄) (hw₅ : 0 ≤ w₅) (hβ₅ : 0 ≤ β₅) (hlr : 0 ≤ lr) (heexp0 : 0 ≤ eexp) (heexp1 : eexp ≤ 1) (hfexp : ∀ (t : ℝ), |fexp t - Real.exp t| ≤ eexp * Real.exp t) (hρ1 : FloatModel.smRho M.u eexp nC < 1) (hx : ∀ (cc : Fin ic) (i : Fin (2 * h)) (j : Fin (2 * w)), |x₀ cc i j| ≤ a) (hW₁ : ∀ (o : Fin c) (cc : Fin ic) (kh : Fin kH) (kw : Fin kW), |W₁ o cc kh kw| ≤ w₁) (hb₁ : ∀ (o : Fin c), |b₁ o| ≤ β₁) (hW₂ : ∀ (o cc : Fin c) (kh : Fin kH) (kw : Fin kW), |W₂ o cc kh kw| ≤ w₂) (hb₂ : ∀ (o : Fin c), |b₂ o| ≤ β₂) (hW₃ : ∀ (i : Fin (c * h * w)) (j : Fin d₃), |W₃ i j| ≤ w₃) (hb₃ : ∀ (j : Fin d₃), |b₃ j| ≤ β₃) (hW₄ : ∀ (i : Fin d₃) (j : Fin d₄), |W₄ i j| ≤ w₄) (hb₄ : ∀ (j : Fin d₄), |b₄ j| ≤ β₄) (hW₅ : ∀ (i : Fin d₄) (j : Fin nC), |W₅ i j| ≤ w₅) (hb₅ : ∀ (j : Fin nC), |b₅ j| ≤ β₅) (hmargin1 : ∀ (k : Fin (c * (2 * h) * (2 * w))), FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0 < |(conv2d W₁ b₁ x₀).flatten k|) (hmargin2 : ∀ (k : Fin (c * (2 * h) * (2 * w))), FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0) < |(conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten k|) (hmarginPool : MaxPool2MarginQ (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0)) (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten))) (hmargin3 : ∀ (l : Fin d₃), FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a)) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0)) < |dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten)) l|) (hmargin4 : ∀ (q : Fin d₄), FloatModel.layerBudget M.u d₃ w₄ β₄ (FloatModel.layerAct (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a))) (FloatModel.layerBudget M.u (c * h * w) w₃ β₃ (FloatModel.layerAct (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a)) (FloatModel.layerBudget M.u (c * kH * kW) w₂ β₂ (FloatModel.layerAct (ic * kH * kW) w₁ β₁ a) (FloatModel.layerBudget M.u (ic * kH * kW) w₁ β₁ a 0))) < |dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten)))) q|) (hm1 : ∀ (k : Fin (c * (2 * h) * (2 * w))), lr * (∑ idx : Fin c, |gradAt (cnnConv1BiasLoss W₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) b₁ idx| + ↑c * M.cnnConv1BiasGradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp) < |(conv2d W₁ b₁ x₀).flatten k|) (hm2 : ∀ (k : Fin (c * (2 * h) * (2 * w))), ↑(c * kH * kW) * (w₂ * (lr * (∑ idx : Fin c, |gradAt (cnnConv1BiasLoss W₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) b₁ idx| + ↑c * M.cnnConv1BiasGradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp))) < |(conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten k|) (hmq : MaxPool2MarginQ (↑(c * kH * kW) * (w₂ * (lr * (∑ idx : Fin c, |gradAt (cnnConv1BiasLoss W₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) b₁ idx| + ↑c * M.cnnConv1BiasGradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp)))) (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten))) (hm3 : ∀ (l : Fin d₃), w₃ * (↑(c * kH * kW) * (w₂ * (↑(2 * h * (2 * w)) * (lr * (∑ idx : Fin c, |gradAt (cnnConv1BiasLoss W₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) b₁ idx| + ↑c * M.cnnConv1BiasGradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp))))) < |dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten)) l|) (hm4 : ∀ (q : Fin d₄), w₄ * (↑d₃ * (w₃ * (↑(c * kH * kW) * (w₂ * (↑(2 * h * (2 * w)) * (lr * (∑ idx : Fin c, |gradAt (cnnConv1BiasLoss W₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) b₁ idx| + ↑c * M.cnnConv1BiasGradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp))))))) < |dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten)))) q|) (hsmall : 2 * (w₅ * (↑d₄ * (w₄ * (↑d₃ * (w₃ * (↑(c * kH * kW) * (w₂ * (↑(2 * h * (2 * w)) * (lr * (∑ idx : Fin c, |gradAt (cnnConv1BiasLoss W₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) b₁ idx| + ↑c * M.cnnConv1BiasGradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp)))))))))) < 1) (h1 : lr * M.cnnConv1BiasGradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp * ∑ idx : Fin c, |gradAt (cnnConv1BiasLoss W₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) b₁ idx| ≤ (lr * ∑ idx : Fin c, gradAt (cnnConv1BiasLoss W₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) b₁ idx ^ 2) / 4) (h2 : 2 * ↑nC * ↑(2 * h * (2 * w)) ^ 2 * ↑(c * kH * kW) ^ 2 * ↑d₃ ^ 2 * ↑d₄ ^ 2 * w₂ ^ 2 * w₃ ^ 2 * w₄ ^ 2 * w₅ ^ 2 / (1 - 2 * (w₅ * (↑d₄ * (w₄ * (↑d₃ * (w₃ * (↑(c * kH * kW) * (w₂ * (↑(2 * h * (2 * w)) * (lr * (∑ idx : Fin c, |gradAt (cnnConv1BiasLoss W₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) b₁ idx| + ↑c * M.cnnConv1BiasGradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp))))))))))) * stepRadius (cnnConv1BiasLoss W₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) b₁ lr (M.cnnConv1BiasGradBudget ic c h w d₃ d₄ nC kH kW a w₁ β₁ w₂ β₂ w₃ β₃ w₄ β₄ w₅ β₅ eexp) ^ 2 ≤ (lr * ∑ idx : Fin c, gradAt (cnnConv1BiasLoss W₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) b₁ idx ^ 2) / 4) :
                            cnnConv1BiasLoss W₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label (b₁ - lr • M.cnnConv1BiasFloatGrad W₁ b₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ fexp label) ≤ crossEntropy nC (dense W₅ b₅ (relu d₄ (dense W₄ b₄ (relu d₃ (dense W₃ b₃ (maxPoolFlat c h w (relu (c * (2 * h) * (2 * w)) (conv2d W₂ b₂ (Tensor3.unflatten (relu (c * (2 * h) * (2 * w)) (conv2d W₁ b₁ x₀).flatten))).flatten))))))) label - (lr * ∑ idx : Fin c, gradAt (cnnConv1BiasLoss W₁ x₀ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ label) b₁ idx ^ 2) / 2

                            One SGD step with the FloatModel binary32 conv-1 bias gradient decreases one example's cross-entropy loss; the gradient's accuracy is proven, not assumed — the bias peer of cnn_conv1_float_sgd_descends, the deepest descent rung: the gradient is the FloatModel binary32 bias gradient M.cnnConv1BiasFloatGrad …, accuracy proven by cnn_conv1_bias_grad_close (η := cnnConv1BiasGradBudget, discharged per output channel — the bias IS a vector), not assumed. With this, both conv kernels and both conv biases of the Chapter-3 CNN have a float-gradient descent statement. Scope: one example, b₁ moving, update taken in ℝ.