Normalization is what made deep networks trainable
Normalization layers stabilize training by re-centering and re-scaling activations. Three common variants — and they're not interchangeable; pick by what shape you're working with:
- BatchNorm2d — normalizes across the batch for each channel. Standard in CNNs. Needs reasonably large batch sizes (typically 16+) to estimate stats well. Has a behavior switch on
train()vseval(): training uses batch stats, eval uses running mean / running var (the buffers). - LayerNorm — normalizes per sample, across the feature dim. Standard in Transformers because batch size doesn't matter and inference behavior is stable.
- GroupNorm — splits channels into groups and normalizes within each group. Works at any batch size including 1. Used in object detection (COCO, where batch=2 per GPU is common) and some vision Transformers.
Why not just BatchNorm everywhere?
BatchNorm leaks information across samples in a batch (each sample's normalization depends on the others), which is bad for some setups (RNN steps, multi-task learning, contrastive learning where you don't want batch coupling). It's also fragile at small batch size and at inference time on a single sample. LayerNorm sidesteps all of this — that's why Transformers settled on it.
Pooling
MaxPool2d picks the max in each window, AvgPool2d averages. AdaptiveAvgPool2d(out_size) is the modern hero — it figures out the right window size to produce the requested output. Set AdaptiveAvgPool2d(1) at the end of a CNN backbone to get a single feature vector regardless of input image size.