MobileNetV2's whole-net input-VJP at TRUE BATCH-NORM (T1, the VJP half) #
MobileNetV2FullB.lean states the batch-BN forward and its typed graph. This file gives that
forward a certified HasVJPAt at the paper depth — the MobileNetV2 peer of
ResNet34FullBVJP.lean, and the second piece of formalization.yaml 4e's port.
No new mathematics, and no new lemma one tier down either #
Every block VJP is already proven at bnBatchLA: mnv2BodyB_has_vjp_at and
mnv2DownBodyB_has_vjp_at (MobileNetV2BackB0.lean) are exactly the two body shapes
mnv2ExpOnlyB / mnv2StridedB unfold to, and residual_has_vjp_at wraps the first for the ten
skip blocks. The bundle lemmas below are delegations in the EfficientNetFullB0 style.
⭐ Where r34 needed a new Foundation lemma, this net needs none. ResNet-34's stem ends in
batchMap N (maxPool3s2Flat …) and a max-pool has no derivative at a tie, so 4.1c had to write
batchMap_has_vjp_at. MobileNetV2 has NO stem pool — the stem is conv-BN-relu6 and downsamples
once — and its head's GAP and dense are smooth, so batchMap_has_vjp (the global one) covers
every batchMap in the net.
⭐ Three shapes are bnRelu6Stage_has_vjp_at at a different inner op, and that lemma is already
generic in it: the stem is that stage at flatConvStride2Xla, the head's first stage is cbrB,
and the expand/depthwise stages are cbrB / dwbrB / dwbrBstrided. The t = 1 block
projB ∘ dwbrB (b1) has no mnv2*BodyB peer; it is dwbrLayer ; projLayer.
The hypothesis budget #
⚠ Pointwise (HasVJPAt), not global, and necessarily. relu6 is kinked on BOTH sides, so each
site carries ≠ 0 ∧ ≠ 6 and a global HasVJP through it is false. That is the repo standard for
the relu-family nets and matches MobileNetV2FullVJP.lean's per-example fold; the axis this file
moves is the BatchNorm world, not the pointwise/global one.
⛔ Two kink clauses per bottleneck, and the second is not r34's. ResNet-34's blocks carry the
body's mid-relu AND a post-residual OUTER relu. MobileNetV2's carry the EXPAND relu6 and the
DEPTHWISE relu6, both inside the body — the linear bottleneck has no activation after project,
so the residual add IS the block output and contributes nothing. Sixteen expand-bearing blocks give
32 clauses, plus b1's single depthwise clause, plus the stem's and the head's: 35 relu6 sites,
bundled into 19 binders.
⭐ The positivity bundles are REUSED, not re-declared: IVPos / IVNoExpPos
(MobileNetV2FullVJP.lean) say 0 < ε at each BatchNorm site and know nothing about which world
reduces it. Only the smoothness bundles need batched peers, because a kink condition names the
activation and bnBatchLA is a different activation from bnPerChannelTensor3.
The running activations are named mnv2PreB0 … mnv2PreB17 so each bundle can be STATED at the
activation entering its block without a seventeen-deep nested application inline; mnv2PreB17
doubles as the trunk, and mobilenetv2ForwardB_full_eq_chain bridges it back to the committed
nested-application forward.
⭐ N is a variable throughout: this tier carries no numerals.
Both relu6 sites of a stride-1 bottleneck are away from BOTH kinks at v, at batch BN: the
expand-BN output and the depthwise-BN output each avoid 0 and 6 in every coordinate.
- hd (k : Fin (N * (mid * h * w))) : StableHLO.bnBatchLA N mid h w q.dε q.dγ q.dβ (StableHLO.batchMap N (depthwiseFlat q.dW q.db) (StableHLO.cbrB N q.eW q.eb q.eε q.eγ q.eβ v)) k ≠ 0 ∧ StableHLO.bnBatchLA N mid h w q.dε q.dγ q.dβ (StableHLO.batchMap N (depthwiseFlat q.dW q.db) (StableHLO.cbrB N q.eW q.eb q.eε q.eγ q.eβ v)) k ≠ 6
Instances For
Both relu6 sites of a stride-2 bottleneck are away from both kinks at v, at batch BN (the
expand runs at the pre-downsample 2h x 2w grid, the XLA-SAME depthwise at h x w).
- hd (k : Fin (N * (mid * h * w))) : StableHLO.bnBatchLA N mid h w q.dε q.dγ q.dβ (StableHLO.batchMap N (depthwiseStride2FlatXla q.dW q.db) (StableHLO.cbrB N q.eW q.eb q.eε q.eγ q.eβ v)) k ≠ 0 ∧ StableHLO.bnBatchLA N mid h w q.dε q.dγ q.dβ (StableHLO.batchMap N (depthwiseStride2FlatXla q.dW q.db) (StableHLO.cbrB N q.eW q.eb q.eε q.eγ q.eβ v)) k ≠ 6
Instances For
The single relu6 site of the t = 1 bottleneck (depthwise-BN output) is away from both
kinks at batch BN.
- hd (k : Fin (N * (ic * h * w))) : StableHLO.bnBatchLA N ic h w q.dε q.dγ q.dβ (StableHLO.batchMap N (depthwiseFlat q.dW q.db) v) k ≠ 0 ∧ StableHLO.bnBatchLA N ic h w q.dε q.dγ q.dβ (StableHLO.batchMap N (depthwiseFlat q.dW q.db) v) k ≠ 6
Instances For
The stem's relu6 is away from both kinks at the input x, at batch BN.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The head's relu6 is away from both kinks at the trunk output v, at batch BN.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Stem VJP: bnRelu6Stage_has_vjp_at at the XLA-SAME strided conv. That lemma takes the inner
op as a parameter, so the stride-2 stem is the same construction as every stride-1 stage.
Equations
- One or more equations did not get rendered due to their size.
Instances For
t = 1 bottleneck VJP (b1): projB ∘ dwbrB, the VJP of dwbrLayer ; projLayer. The one
block shape with no mnv2*BodyB lemma to delegate to.
Equations
Instances For
Stride-1 no-skip bottleneck VJP (b11, b17) — mnv2BodyB_has_vjp_at at the bundle's fields.
Equations
Instances For
Stride-1 skip bottleneck VJP — the body VJP under residual_has_vjp_at. The identity arm is
smooth everywhere, so the skip adds no hypothesis.
Equations
- Proofs.mnv2ResidB_has_vjp_at N h w p hq v hs = Proofs.residual_has_vjp_at (Proofs.mnv2ExpOnlyB N h w p) v ⋯ (Proofs.mnv2ExpOnlyB_has_vjp_at N h w p hq v hs)
Instances For
Stride-2 downsampling bottleneck VJP — mnv2DownBodyB_has_vjp_at at the bundle's fields.
Equations
Instances For
Head VJP: the 1x1 conv-bn-relu6 stage (cbrB, pointwise), then GAP and dense — both smooth,
both batchMap of a per-example op, so both lift with the GLOBAL batchMap_has_vjp.
⚠ Unlike r34's, this head is NOT hypothesis-free: MobileNetV2 puts a relu6 in front of the
pool, so the head carries the net's 35th kink site.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Proofs.mnv2PreB1 N w = Proofs.mnv2NoExpB N 112 112 w.b1 ∘ Proofs.mnv2PreB0 N w
Instances For
Equations
- Proofs.mnv2PreB2 N w = Proofs.mnv2StridedB N 56 56 w.b2 ∘ Proofs.mnv2PreB1 N w
Instances For
Equations
- Proofs.mnv2PreB3 N w = Proofs.mnv2ResidB N 56 56 w.b3 ∘ Proofs.mnv2PreB2 N w
Instances For
Equations
- Proofs.mnv2PreB4 N w = Proofs.mnv2StridedB N 28 28 w.b4 ∘ Proofs.mnv2PreB3 N w
Instances For
Equations
- Proofs.mnv2PreB5 N w = Proofs.mnv2ResidB N 28 28 w.b5 ∘ Proofs.mnv2PreB4 N w
Instances For
Equations
- Proofs.mnv2PreB6 N w = Proofs.mnv2ResidB N 28 28 w.b6 ∘ Proofs.mnv2PreB5 N w
Instances For
Equations
- Proofs.mnv2PreB7 N w = Proofs.mnv2StridedB N 14 14 w.b7 ∘ Proofs.mnv2PreB6 N w
Instances For
Equations
- Proofs.mnv2PreB8 N w = Proofs.mnv2ResidB N 14 14 w.b8 ∘ Proofs.mnv2PreB7 N w
Instances For
Equations
- Proofs.mnv2PreB9 N w = Proofs.mnv2ResidB N 14 14 w.b9 ∘ Proofs.mnv2PreB8 N w
Instances For
Equations
- Proofs.mnv2PreB10 N w = Proofs.mnv2ResidB N 14 14 w.b10 ∘ Proofs.mnv2PreB9 N w
Instances For
Equations
- Proofs.mnv2PreB11 N w = Proofs.mnv2ExpOnlyB N 14 14 w.b11 ∘ Proofs.mnv2PreB10 N w
Instances For
Equations
- Proofs.mnv2PreB12 N w = Proofs.mnv2ResidB N 14 14 w.b12 ∘ Proofs.mnv2PreB11 N w
Instances For
Equations
- Proofs.mnv2PreB13 N w = Proofs.mnv2ResidB N 14 14 w.b13 ∘ Proofs.mnv2PreB12 N w
Instances For
Equations
- Proofs.mnv2PreB14 N w = Proofs.mnv2StridedB N 7 7 w.b14 ∘ Proofs.mnv2PreB13 N w
Instances For
Equations
- Proofs.mnv2PreB15 N w = Proofs.mnv2ResidB N 7 7 w.b15 ∘ Proofs.mnv2PreB14 N w
Instances For
Equations
- Proofs.mnv2PreB16 N w = Proofs.mnv2ResidB N 7 7 w.b16 ∘ Proofs.mnv2PreB15 N w
Instances For
Equations
- Proofs.mnv2PreB17 N w = Proofs.mnv2ExpOnlyB N 7 7 w.b17 ∘ Proofs.mnv2PreB16 N w
Instances For
⭐⭐ MobileNetV2 at TRUE BATCH-NORM has a certified input-VJP at a smooth point — all
seventeen bottlenecks. Chains stem → the [t,c,n,s] ladder → head with vjp_comp_at, one
positivity bundle and one smoothness bundle per block. T1's VJP half for
formalization.yaml 4e's port (the per-example fold it was the batched peer of was retired
2026-09-19).
⚠ Pointwise, and necessarily: relu6 is kinked on both sides. ⛔ Each expand-bearing block
contributes TWO clauses — the expand relu6 and the depthwise relu6, both INSIDE the body —
where ResNet-34's basic block contributes a mid-relu and a post-residual OUTER relu. The
linear bottleneck has no activation after project, so MobileNetV2's residual add is the
block output and adds nothing.
⚠ Unlike r34's, the head is NOT hypothesis-free: its 1x1 conv-BN is followed by a relu6.
⭐ N is a variable: this tier carries no numerals.
Equations
- One or more equations did not get rendered due to their size.
Instances For
⭐ The committed nested-application forward IS the layered chain the VJP is stated on —
the batched peer of the retired per-example shape check, and what lets the VJP be about
mobilenetv2ForwardB_full rather than about a re-spelling of it.
⭐⭐ Public correctness theorem: the seventeen-bottleneck batch-BN backward equals the
pdiv-contracted Jacobian of mobilenetv2ForwardB_full ITSELF — the committed
nested-application forward MobileNetV2FullB.lean defines and
mobilenetv2FwdGraphB_full_faithful proves the typed graph denotes — not of the layered chain
the VJP is assembled on. Tied back through mobilenetv2ForwardB_full_eq_chain.