EfficientNet — MBConv with Squeeze-Excite, end-to-end VJP #
The hardest of the three flagship CNN VJPs in this stack (alongside the
ResNet cnn_has_vjp_at and the MobileNet depthwise chain), because the
squeeze-excite gate is a genuine fan-out sub-network multiplied back
into the main path. We reuse seBlock_has_vjp (SE.lean), which already
carries the product-rule fan-in for x ⊙ gate(x); here we supply the
concrete gate (seGate) — a real Vec → Vec differentiable map with its
own composed VJP — plus its differentiability.
What this file provides #
sigmoid/sigmoid_has_vjp— smooth logistic activation (chosen over the kinked h-sigmoid so the gate is differentiable everywhere; same diagonal-Jacobian proof template asswish/geluinLayerNorm.lean).broadcastFlat/broadcastFlat_has_vjp— per-channel scalar broadcast to spatial layout (the adjoint reindex ofglobalAvgPoolFlat).seGate/seGate_has_vjp— the concrete squeeze-excite gatebroadcast ∘ sigmoid ∘ dense ∘ swish ∘ dense ∘ GAP, assembled with the chain rule; fed intoseBlock_has_vjpto giveseBlockFull_has_vjp(the fullx ⊙ gate(x)).mbconvBody/mbconvBody_has_vjp— one MBConv block bodyproject(1×1 conv-bn) ∘ SE ∘ depthwise(bn-swish) ∘ expand(1×1 conv-bn-swish), smooth everywhere (globalHasVJP).mbconvResidual_has_vjp_at— the stride-1,cin = coutblock wrapped in the identity residual skip.efficientnet_has_vjp_at/_correct— a representative end-to-end EfficientNet (stem → MBConv-with-SE-and-residual → MBConv-with-SE → globalAvgPool → dense head), built byvjp_comp_at, exposing thepdiv-contracted Jacobian. Spatial dims held constant (stride-1; the separable striding/pooling plumbing is already inCNN.lean). Only the0 < εbatch-norm hypotheses are required — swish and sigmoid are smooth, so there are no relu-style kink hypotheses anywhere in the block.
Instances For
Equations
- Proofs.sigmoid n x i = Proofs.sigmoidScalar (x i)
Instances For
Equations
Instances For
Equations
- Proofs.sigmoid_has_vjp n = { backward := fun (x dy : Proofs.Vec n) (i : Fin n) => dy i * Proofs.sigmoidScalarDeriv (x i), correct := ⋯ }
Instances For
Broadcast a per-channel vector back to spatial layout.
broadcastFlat c h w v idx = v (flatChannel c h w idx) — every spatial
cell of channel k receives v k. This is the reindex map along
flatChannel, i.e. the adjoint of globalAvgPoolFlat (up to the
1/(h·w) scale). Vec c → Vec (c*h*w).
Equations
- Proofs.broadcastFlat c h w v idx = v (Proofs.flatChannel c h w idx)
Instances For
Broadcast VJP — linear reindex; backward sums each channel's spatial cotangents (the adjoint of broadcast = sum-over-spatial).
Equations
- One or more equations did not get rendered due to their size.
Instances For
The squeeze-excite gate. Maps Vec (c*h*w) → Vec (c*h*w):
broadcast ∘ sigmoid ∘ dense(W₂,b₂) ∘ swish ∘ dense(W₁,b₁) ∘ GAP
Squeeze (GAP c·h·w → c), reduce (dense c → r), swish, expand
(dense r → c), sigmoid gate, broadcast back to spatial. Every
stage is smooth everywhere (swish/sigmoid smooth, dense/GAP/broadcast
linear-affine), so the gate is differentiable everywhere and has a
global HasVJP.
Equations
- Proofs.seGate W₁ b₁ W₂ b₂ = Proofs.broadcastFlat c h w ∘ Proofs.sigmoid c ∘ Proofs.dense W₂ b₂ ∘ Proofs.swish r ∘ Proofs.dense W₁ b₁ ∘ Proofs.globalAvgPoolFlat c h w
Instances For
The full SE block with the concrete gate: x ⊙ seGate(x).
Equations
- Proofs.seBlockFull W₁ b₁ W₂ b₂ = Proofs.seBlock (Proofs.seGate W₁ b₁ W₂ b₂)
Instances For
Equations
- Proofs.seBlockFull_has_vjp W₁ b₁ W₂ b₂ = Proofs.seBlock_has_vjp (Proofs.seGate W₁ b₁ W₂ b₂) ⋯ (Proofs.seGate_has_vjp W₁ b₁ W₂ b₂)
Instances For
conv → bn → swish block — everywhere VJP. Like convBnRelu but
with swish (smooth) instead of relu, so no smoothness hypothesis is
needed; this is a global HasVJP. Vec (ic*h*w) → Vec (oc*h*w).
Equations
- One or more equations did not get rendered due to their size.
Instances For
depthwise → bn → swish block — everywhere VJP. Depthwise conv
keeps channel count c; bn over c*h*w; swish smooth. Global
HasVJP. Vec (c*h*w) → Vec (c*h*w).
Equations
- One or more equations did not get rendered due to their size.
Instances For
MBConv block body (EfficientNet MBConv with squeeze-excite), in
flattened Vec space:
project(1×1 conv-bn) ∘ seBlockFull ∘ depthwise(bn-swish) ∘ expand(1×1 conv-bn-swish)
Channels: cin → cmid (expand 1×1), depthwise keeps cmid, SE keeps
cmid, project cmid → cout (1×1). Spatial h, w constant
(stride 1). Every stage is smooth everywhere (swish/sigmoid smooth;
convs/bn/depthwise/SE differentiable), so the body has a global
HasVJP. Vec (cin*h*w) → Vec (cout*h*w).
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Residual MBConv VJP (global). When stride is 1 and cin = cout = c,
the MBConv body's input and output shapes match, so the identity skip
applies: residual (mbconvBody …). The body is differentiable
everywhere (global HasVJP), so the residual VJP is global too.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Residual MBConv VJP at a point — the global witness restricted to a
point. Kept for downstream _at consumers.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Architectural choices (documented).
We assemble a representative EfficientNet, all in flattened Vec space,
spatial dims held constant (stride-1 throughout — pooling/striding is a
separable concern already covered by maxPoolFlat/strided conv in
CNN.lean; the VJP plumbing is identical):
stem (3×3 conv-bn-swish, ic → c)
→ MBConv₁ with SE, residual (stride-1, c → c identity skip)
→ MBConv₂ with SE, no skip (channel change c → cout)
→ globalAvgPool (cout·h·w → cout)
→ dense head (cout → nClasses)
MBConv₁ is the headline block: a genuine squeeze-excite gate
(seBlockFull) inside an identity residual. MBConv₂ exercises the
channel-changing path (no skip). Both blocks are smooth everywhere
(swish + sigmoid + convs + bn + SE), so only the 0 < ε batch-norm
hypotheses are needed — no relu-style kink hypotheses.
Equations
- One or more equations did not get rendered due to their size.
Instances For
End-to-end EfficientNet VJP (global). Every block is smooth
everywhere (swish + sigmoid SE gate + convs + BN, no ReLU/maxpool), so
the only hypotheses are the 0 < ε batch-norm conditions and the VJP
holds at every input — putting EfficientNet alongside
vit_full_has_vjp and convnext_has_vjp as an unconditional
whole-network VJP. Chained through the global vjp_comp.
Equations
- One or more equations did not get rendered due to their size.
Instances For
End-to-end EfficientNet VJP at a point — the global witness
restricted to a point. Kept for downstream _at consumers and the
comparator.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Public correctness theorem for efficientnet_has_vjp (global) — the
full EfficientNet's backward equals the pdiv-contracted Jacobian
(Jacobian-transpose on the cotangent), at every input x. The
unconditional EfficientNet analogue of vit_full_has_vjp_correct.
Public correctness theorem for efficientnet_has_vjp_at — exposes
the witness's .correct field: the full EfficientNet's backward equals
the pdiv-contracted Jacobian (Jacobian-transpose on the cotangent).
EfficientNet analogue of cnn_has_vjp_at_correct.