ResNet-34 at TRUE BATCH-NORM — the whole net's forward and graph #
ResNet-34's whole-net ℝ forward, its typed forward graph, and the faithfulness tying them, at
batch BatchNorm: bnBatchLA (= the proven bnBatchTensor4 at the network's left-assoc index),
reduce [0,2,3] — one mu/var per channel across the batch, the one op that couples examples.
Every committed ResNet-34 forward and train-step artifact (resnet34_fwd.mlir,
resnet34_sgd_train_step.mlir, resnet34in_mom256_train_step.mlir, the Adam/momentum steps)
reduces [0,2,3]; the *_fwd_eval artifacts normalise with running statistics.
What is new here, and what is not #
Nothing about the blocks is new. The batched stages (cbReluB, cbReluStridedB,
projStridedB in Foundation/Batched/StageLayers.lean, and projB in
Foundation/Batched/Stages.lean), their _at VJPs and their backward-graph faithfulness are all at
bnBatchLA, and ResNet34BackB0 assembles them into the two block kinds. This file adds the
level above: a net-level ℝ forward, a net-level forward graph, and the faithfulness tying them.
Padding is symmetric at every stride-2 site, as ResNet-34's render emits and as the
PyTorch-origin convention requires (.convStrided, NOT .convStridedXla — B0's stem is the
XLA-SAME one and the two tokens have identical types). scripts/gates/convention_audit.py checks this
at the artifact tier and nothing checks it here, so it is stated: stem 7x7/s2, the three
downsample conv1s and the three 1x1 projections are all flatConvStride2.
The stem pool is 3x3/s2 (maxPool3s2Flat), not 2x2. Same type, different function, so a
swap type-checks.
Precision is a flag on the graph. Every conv site is .convAt bf16 id … / .convStridedAt bf16 id … (StableHLO.PrecisionSwitch, the renderers' own switch), so one builder describes
the f32 artifact (bf16 := false) and the bf16 one (bf16 := true, the kinds
resnet34in_momdp64bf16 emits); BatchNorm, relu, pool and head carry no flag because no render
switches them. The faithfulness theorems hold at either value through Bf16Erasure
(Bf16Fold.denOp_convAt_id: the bf16 kind at the identity rounding is its f32 peer), so the typed graph
denotes resnet34ForwardBFull whichever precision the text declares. The rounding itself is not
modelled here, as it is not at f32: den is over ℝ at both values.
Conventions this net runs at #
| depth | [3,4,6,3] basic blocks, 64 to 512 |
| BatchNorm | batch (bnBatchLA, reduce [0,2,3], width N*h*w) |
| activation | relu (one kink), TWO per block — the body's mid-relu and the post-residual one |
| stride-2 padding | symmetric at all seven sites |
| stem | 7x7/s2 conv-bn-relu, then 3x3/s2 max-pool |
| head | GAP then dense, generic in the class count |
| artifacts | resnet34_sgd_train_step, resnet34_adam*, resnet34in_mom* |
The head is generic in nCls, so one statement covers the 10-class Imagenette artifacts and the
1000-class resnet34in ones.
N stays a variable throughout: the batch size is never pinned here (the 224-px resolution and
the 64…512 widths are literals); it is pinned only where a Maps envelope turns a width into a
rational. On the data-parallel artifacts the render's N is the PER-REPLICA batch; their
BatchNorm is synchronised, and ResNet34SyncB is this file's twin for them: replica
r's forward graph denotes shard r of resnet34ForwardBFull (R * N), this file's forward at
the global batch.
References #
- He, Zhang, Ren, Sun 2016, Deep Residual Learning for Image Recognition. https://arxiv.org/abs/1512.03385
Weights of one downsample basic block: strided 3x3 (ic -> oc, halves spatial), 3x3, and the
1x1 stride-2 option-B projection on the skip. BatchNorm after each of the three.
- W₁ : Kernel4 oc ic 3 3
- b₁ : Vec oc
- ε₁ : ℝ
- γ₁ : Vec oc
- β₁ : Vec oc
- W₂ : Kernel4 oc oc 3 3
- b₂ : Vec oc
- ε₂ : ℝ
- γ₂ : Vec oc
- β₂ : Vec oc
- Wp : Kernel4 oc ic 1 1
- bp : Vec oc
- εp : ℝ
- γp : Vec oc
- βp : Vec oc
Instances For
Every ResNet-34 parameter: stem (7x7/s2, 3->64) + the [3,4,6,3] basic blocks + dense head. Generic in the class count.
- sW : Kernel4 64 3 7 7
- sb : Vec 64
- sε : ℝ
- sγ : Vec 64
- sβ : Vec 64
- a0 : R34IdW 64
- a1 : R34IdW 64
- a2 : R34IdW 64
- d2 : R34DownW 64 128
- b0 : R34IdW 128
- b1 : R34IdW 128
- b2 : R34IdW 128
- d3 : R34DownW 128 256
- c0 : R34IdW 256
- c1 : R34IdW 256
- c2 : R34IdW 256
- c3 : R34IdW 256
- c4 : R34IdW 256
- d4 : R34DownW 256 512
- e0 : R34IdW 512
- e1 : R34IdW 512
- Wd : Mat 512 nCls
- bd : Vec nCls
Instances For
Batched identity basic block relu(F(x) + x), F = projB . cbReluB. The outer relu after the
residual add is ResNet's structural difference from MobileNetV2/EfficientNet, whose residual
add IS the block output — and it is why every r34 block carries TWO smoothness clauses.
Equations
- Proofs.r34IdB N h w p = Proofs.relu (N * (c * h * w)) ∘ Proofs.residual (Proofs.projB N p.W₂ p.b₂ p.ε₂ p.γ₂ p.β₂ ∘ Proofs.StableHLO.cbReluB N p.W₁ p.b₁ p.ε₁ p.γ₁ p.β₁)
Instances For
Batched downsample basic block relu(F_s(x) + proj_s(x)): body strided-conv1 then conv2,
skip a 1x1 stride-2 projection. Both stride-2 sites are SYMMETRIC padding.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Batched stem: 7x7/s2 conv -> bn -> relu, then He et al.'s 3x3/s2 max-pool.
Equations
- Proofs.r34StemB N h w Ws bs εs γs βs = Proofs.StableHLO.batchMap N (Proofs.maxPool3s2Flat oc h w) ∘ Proofs.StableHLO.cbReluStridedB N Ws bs εs γs βs
Instances For
The stem, APPLIED: the pool of the strided conv-BN-relu.
Batched head: global average pool, then the dense classifier.
Equations
- Proofs.r34HeadB N h w Wd bd = Proofs.StableHLO.batchMap N (Proofs.dense Wd bd) ∘ Proofs.StableHLO.batchMap N (Proofs.globalAvgPoolFlat c h w)
Instances For
ResNet-34's GAP-and-dense tail, APPLIED.
The full batch-BN ResNet-34 forward, N*(3*224*224) -> N*nCls. Nested-application form,
as efficientnetForwardBFull and mobilenetv2ForwardBFull both are, so a whole-net proof can
peel it one block at a time.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Identity basic-block graph: relu(addV(bn(conv(relu(bn(conv e)))), e)). The skip reuses the
block-input subtree e in both addV operands, as the render does.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Downsample basic-block graph: relu(addVB(body, projection)) — body first, the order the
render emits (so pretty of this graph is the rendered block's text); residualProj proj body
adds them the other way round, which the faithfulness proof absorbs with add_comm. Both
branches read the block-input subtree e; both stride-2 convs are .convStrided (symmetric
padding).
Equations
- One or more equations did not get rendered due to their size.
Instances For
Stem graph: 7x7/s2 conv -> bn -> relu -> 3x3/s2 max-pool.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The full batch-BN ResNet-34 forward graph. Block prefixes are the render's
(s1b0/d2/s2b0/... ), so the typed graph diffs against resnet34_fwd's batched peers
name for name. bf16 selects the conv kinds at every site (.convAt / .convStridedAt).
Equations
- One or more equations did not get rendered due to their size.
Instances For
Forward-graph faithfulness for ResNet-34 at batch BN: the typed graph denotes the
whole-net forward, at either precision — bf16 := false is the f32 artifacts' graph,
bf16 := true the bf16 ones' (resnet34in_momdp64bf16's kinds), and the right-hand side is
the same resnet34ForwardBFull.