EfficientNet Item D — the batched backward (cotangent) math, step by step #
The batched analogue of MobileNetV2ChainClose (and of ResNet-34's per-example close, deleted 2026-09-08). The forward graph (Item A,
EfficientNetRenderPC.lean) lives at the batched index N·(c·h·w); here we sort the backward
math at that same index — proving the per-block gradient (HasVJP) by composing the proven per-op
VJPs, lifted to the batch.
The genuinely-new lemma is batchMap_has_vjp: a batch-separable op batchMap N f (every spatial op
in the forward graph) has a block-diagonal VJP — f's VJP applied per example. This is what lets
seBlockFull_has_vjp, the conv/depthwise/dense VJPs, etc. lift from one example to the whole batch.
Mechanically it reuses the existing row-wise machinery: batchMap N f IS Mat.flatten ∘ (apply f to each row) ∘ Mat.unflatten, so rowwise_has_vjp_mat + hasVJPMat_to_hasVJP (Tensor.lean) close it.
(The one batch-coupled op, true batch-norm, is handled separately by the proven bnBatchTensor4_has_vjp
— it is NOT a batchMap. swish/sigmoid are pointwise, so swish_has_vjp/sigmoid_has_vjp apply
directly at the batched index. Step-by-step, per the plan: batchMap VJP first, then bnBatchLA, then
the per-block chains.)
batchMap N f is the flattened row-wise application of f. Reading the output at flat index
idx (decoding to example m, coord c) gives f (row m of the input) c on both sides — the
Mat.flatten/unflatten row-major convention is exactly batchMap's finProdFinEquiv split.
batchMap N f is differentiable when f is — it is f applied independently per example.
batchMap N f VJP — block-diagonal (the genuinely-new lemma). A batch-separable op's VJP
applies f's proven VJP independently per example. The backward, like the forward, reshapes to
[N, ·] and runs f.backward row-wise. Reuses rowwise_has_vjp_mat + hasVJPMat_to_hasVJP. This
is seBlockFull_has_vjp / the conv-depthwise-dense VJPs "lifted by batchMap" to the whole batch.
Equations
- Proofs.batchMap_has_vjp f hf hf_diff = ⋯ ▸ Proofs.hasVJPMat_to_hasVJP (Proofs.rowwise_has_vjp_mat hf hf_diff)
Instances For
Generic reindex VJP. reindexCLM σ (gather y ↦ y ∘ σ) is linear; its backward scatters each
output cotangent back to the inputs that map to it (the adjoint). Generalizes the manual reindex
VJPs (broadcastFlat_has_vjp, bnchwFwd/Back_has_vjp).
Equations
- Proofs.reindex_has_vjp σ = { backward := fun (_v : Proofs.Vec a) (dy : Proofs.Vec b) (i : Fin a) => ∑ k : Fin b, if i = σ k then dy k else 0, correct := ⋯ }
Instances For
bnBatchLA is the proven bnBatchTensor4, conjugated by the mul_assoc reindex. Both reindex
maps are reindexCLM (Fin.cast …); the middle is the genuinely batch-coupled true batch-norm.
True batch-norm VJP at the network's flat index. bnBatchLA's backward is the proven
bnBatchTensor4 VJP (batch-coupled — NOT a batchMap), conjugated by the reindex isos.
Equations
- One or more equations did not get rendered due to their size.
Instances For
flatConv W b VJP — the per-example 1×1/3×3 conv input-VJP (the HasVJP3-bridged conv2d).
Equations
Instances For
Differentiability of a batched conv/depthwise → bn → swish stage.
VJP of a batched conv/depthwise → bn → swish stage: lift op's VJP per example, then the proven
true-BN VJP, then the pointwise swish VJP.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Differentiability of a batched conv → bn stage (project bottleneck, no swish).
VJP of a batched conv → bn stage.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Proofs.cbsB_has_vjp N W b ε hε γ β = Proofs.bnSwishStage_has_vjp N (Proofs.flatConv W b) ⋯ (Proofs.flatConv_has_vjp W b) ε hε γ β
Instances For
Equations
- Proofs.stemB_has_vjp N W b ε hε γ β = Proofs.bnSwishStage_has_vjp N (Proofs.flatConvStride2Xla W b) ⋯ (Proofs.flatConvStride2Xla_has_vjp W b) ε hε γ β
Instances For
Equations
- Proofs.dwbsB_has_vjp N W b ε hε γ β = Proofs.bnSwishStage_has_vjp N (Proofs.depthwiseFlat W b) ⋯ (Proofs.depthwiseFlat_has_vjp W b) ε hε γ β
Instances For
Equations
- Proofs.dwbsSB_has_vjp N W b ε hε γ β = Proofs.bnSwishStage_has_vjp N (Proofs.depthwiseStride2Flat W b) ⋯ (Proofs.depthwiseStride2Flat_has_vjp W b) ε hε γ β
Instances For
Equations
- Proofs.seB_has_vjp N W₁ b₁ W₂ b₂ = Proofs.batchMap_has_vjp (Proofs.seBlockFull W₁ b₁ W₂ b₂) (Proofs.seBlockFull_has_vjp W₁ b₁ W₂ b₂) ⋯
Instances For
Equations
- Proofs.projB_has_vjp N W b ε hε γ β = Proofs.bnStage_has_vjp N (Proofs.flatConv W b) ⋯ (Proofs.flatConv_has_vjp W b) ε hε γ β
Instances For
MBConv1 (no expand) gradient. dw-bn-swish → SE → project-bn.
Equations
- One or more equations did not get rendered due to their size.
Instances For
MBConv6 strided gradient. expand-bn-swish → strided dw-bn-swish → SE → project-bn.
Equations
- One or more equations did not get rendered due to their size.
Instances For
MBConv6 residual gradient. x + (project-bn ∘ SE ∘ dw-bn-swish ∘ expand-bn-swish)(x).
Equations
- One or more equations did not get rendered due to their size.
Instances For
The representative batched EfficientNet-B0 has a (correct) VJP. Chained from the per-block
gradients — stem → MBConv1 → MBConv6-strided → MBConv6-residual → head — via vjp_comp. The
backward is genuinely composed from the proven per-op VJPs, batchMap-lifted to the batch and
crossing the batch-coupled true batch-norm; HasVJP.correct pins it to the true Jacobian-transpose.
The batched, true-batch-norm + SE analogue of efficientnet_has_vjp (EfficientNet.lean).
Stated on the ∘-composition of the blocks — which IS efficientnetForwardB (its nested-application
spelling, used by the forward proof, is definitionally this composition); vjp_comp builds exactly
this composition, so the proof closes structurally without re-reducing the whole net.
Equations
- One or more equations did not get rendered due to their size.
Instances For
⭐⭐ THE SHAPE CHECK — efficientnetForwardB IS the ∘-chain efficientnetForwardB_has_vjp
is stated on. The committed forward is written in nested-application form so its faithfulness
proof closes by pure delta; the apex above is stated on the composition vjp_comp builds. Until
now the bridge between the two lived in that apex's docstring — "its nested-application
spelling … is definitionally this composition".
⛔ A justification in a docstring is what stops anyone re-checking it. Every whole-net tie
takes its blocks OPAQUE so the isDefEq compares variables, which means the tie's subject is a
chain of variables and nothing in it says which net they are — that is how ResNet-34's tie
reversed the 2×2 pool for a month while the committed forward pooled 3×3/s2, and it moved a
committed number 4×. The peers are mobilenetv2Forward_full_pc_eq_chain,
convNextForwardTCh_eq_chain, resnet34Forward_full_pc_eq_chain and, for the 16-block net,
efficientnetForwardB_full_eq_chain — this is the same theorem for the 3-block batched
representative, which is the net efficientnetInputGradB reverses.
⚠ PROOF SHAPE MATTERS, and efficientnetForwardB_full_eq_chain records why: the equation-lemma
rw plus one Function.comp_apply per stage closes syntactically, where a simp/rfl of the
same statement makes the kernel reduce the block bodies and time out.