Vibe Engines is free, interactive AI engineering & system design — runs in your browser. Pick a learning path →
Batch Normalization,
explained.
Before this paper, training a deep network was a superstition-ridden ordeal of careful initialization and tiny learning rates. Then came one deceptively simple layer: at each step, re-center and re-scale a layer's outputs so the next layer always sees a stable distribution. Training sped up, learning rates went up, and depth got easier. Here's the whole transform — and the learnable knob that keeps it from throwing away information.
What changes against dropout: the target stops moving
Dropout (rung 1) accepts the optimisation problem as given and adds noise to stop the network memorising. Batch norm changes the optimisation problem itself. Every layer in a deep network is trying to learn a function of its input, and that input is the output of the layer below, which is still changing — so each layer is fitting a target that keeps moving as the layers beneath it update.
The change: normalise each feature to zero mean and unit variance across the examples in the mini-batch, as a layer, inside the network, on every forward pass. Because forcing that distribution would also destroy what the layer can express, it then applies a learned scale γ and shift β per feature — so the layer can recover any distribution it wants, including the unnormalised one, but it has to ask for it.
Stated in rung 1's units: dropout adds one hyperparameter and zero parameters; batch norm adds two parameters per feature (γ and β) and, more importantly, buys back a hyperparameter you were already spending — the learning rate. Normalised activations let you raise it by an order of magnitude without diverging, which is where most of the reported speed-up comes from. It also makes initialisation much less delicate, and it regularises hard enough that many recipes dropped rung 1 entirely when they adopted it.
The shifting-target problem
A deep network is a stack of layers, each learning to transform the outputs of the one below. But those outputs are a moving target: as the lower layer's weights update, the distribution of what it feeds upward keeps shifting — different mean, different spread, step after step. Every layer is chasing a target that won't hold still. The paper named this internal covariate shift, and argued it forces you to use tiny learning rates and careful initialization to keep the whole tower from diverging.
The fix is direct: don't let the distribution wander. After a layer computes its outputs, normalize them — re-center to zero mean and re-scale to unit variance — before passing them on. Now the layer above always receives inputs in a predictable range, no matter how the layer below drifts, and it can learn against a stable target.
Standardize each layer's outputs so the next layer always sees the same well-behaved distribution — then give the network a learnable knob to rescale if it needs to.
Normalize across the batch
The normalization is computed per feature, across the mini-batch. For a given feature, take its values over all examples in the current batch, compute their mean and variance, subtract the mean, divide by the standard deviation. A tiny ε in the denominator guards against a feature that happens to be constant (zero variance) in the batch.
Because the statistics come from the batch, batch norm couples the examples in a batch together — a subtle but important property. It also means very small batches give noisy statistics, which is one of batch norm's real limitations.
The learnable scale and shift
Forcing every layer to output exactly zero-mean, unit-variance activations would be too restrictive — sometimes a layer genuinely needs a different scale, or a nonzero mean to reach the useful part of its activation function. So batch norm adds two learnable parameters per feature, a scale γ and a shift β, applied after standardizing. The full transform:
y = γ · x̂ + β ⇒ 𝔼[y] = β , Var[y] = γ²
Crucially, this does not cost expressiveness. If the optimal thing is to undo the normalization entirely, the network can learn γ = √(σ²B + ε) and β = μB, recovering the original activations exactly. Normalization sets a stable default the network can override — it removes the difficulty without removing the freedom. The runnable version below confirms both halves: standardizing yields mean≈0/var≈1, and γ, β restore any target mean and standard deviation.
Train vs test statistics
There is a catch at inference. During training, the mean and variance come from the current batch. But at test time you may be classifying a single image — there is no batch — and, more importantly, a prediction should never depend on which other examples happen to share its batch. So batch norm keeps a running average of the mean and variance seen during training (an exponential moving average), and uses those fixed statistics at test time:
This is the single most common batch-norm bug in practice: run the model in "training" mode at evaluation and it will normalize with batch statistics — leaking information across test examples and quietly wrecking your metrics. Every framework has an explicit train/eval switch precisely because of this layer.
How batch normalization is placed, computed and frozen
Ioffe and Szegedy add the transform as a layer between a linear map and its nonlinearity, and they pin down five things about how it runs.
- Normalize the pre-activation, not the layer input. For z = g(Wu + b), the layer becomes z = g(BN(Wu)). The input u is the output of another nonlinearity and its distribution keeps changing shape, while Wu is more likely to be symmetric, non-sparse and close to Gaussian, so fixing its first two moments gives a steadier distribution. The bias b is dropped, because mean subtraction would cancel it; β takes over its role.
- Compute statistics per activation over the mini-batch. For each dimension k, the mean μB and variance σ²B are taken over the m examples of the mini-batch, each value is standardized with a small ε added to the variance, and a learned pair γ^(k), β^(k) scales and shifts the result.
- In convolutional layers, pool over space too. To keep the convolutional property that every location of a feature map is treated alike, one channel's mean and variance are computed jointly over the batch and all spatial positions: m examples with p × q maps give an effective batch of m′ = m·p·q values per channel, and γ and β are learned per feature map rather than per activation.
- Backpropagate through the statistics. μB and σ²B depend on every example in the batch, so the gradient for one example depends on the others. The paper shows why this is required: if the normalization is treated as a constant outside the gradient step, an update to a bias is undone by the next mean subtraction, neither the output nor the loss changes, and the bias grows without bound.
- Freeze the layer for inference. After training, the batch statistics are replaced by population statistics: the average of μB over many training mini-batches, and the average of σ²B multiplied by m/(m − 1) to make the variance unbiased. The layer then becomes a fixed linear map per dimension, γ/√(Var[x] + ε) · x + (β − γE[x]/√(Var[x] + ε)), and the paper notes that moving averages can track these statistics while the model trains.
The network it was tested in
The ImageNet experiments use a variant of Inception with 13.6 million parameters: each 5 × 5 convolution is replaced by two stacked 3 × 3 convolutions, the 28 × 28 stage gets a third Inception module, and there are no fully connected layers apart from the final softmax. It was trained with SGD with momentum on mini-batches of 32 in a distributed setup, with BN before every nonlinearity. Inserting BN was only the start; the authors then rebuilt the training recipe around it:
- raise the learning rate, with 5× and 30× variants;
- remove dropout, which sped up training without increasing overfitting;
- cut the L2 weight penalty by a factor of 5;
- decay the learning rate 6 times faster;
- remove local response normalization;
- shuffle training examples within shards so the same examples stop sharing mini-batches, worth about 1% validation accuracy;
- reduce photometric distortions, since a faster-training network sees each image fewer times.
Backpropagating through the batch statistics
The paper derives the gradient of the loss ℓ through μB and σ²B with the chain rule, in six formulas. Writing gi = ∂ℓ/∂yi and collecting terms gives one line per example:
m·gi— the direct path, the gradient as if the statistics were fixed numbers.−Σ gj— the path through μB: it subtracts the batch total of the incoming gradient, because shifting every xi by the same amount cannot change x̂.−x̂i Σ gjx̂j— the path through σ²B: it removes the part of the gradient that points along x̂, because stretching all deviations equally cannot change x̂ either.γ/√(σ²B + ε)— the same rescaling the forward pass applied.
At the extremes: if every gj is equal, the bracket is zero and nothing reaches x. With m = 1, x − μB = 0, the layer outputs β whatever its input and the gradient to x vanishes, which is why a batch of one cannot train it. The paper adds a scale property, BN((aW)u) = BN(Wu) with ∂BN((aW)u)/∂(aW) = (1/a)·∂BN(Wu)/∂W: larger weights receive proportionally smaller gradients.
What batch norm did to Inception's training
A first test on MNIST used three fully connected hidden layers of 100 sigmoid units, trained for 50,000 steps on mini-batches of 60: the BN network reached higher test accuracy, and the inputs to its sigmoids kept a stable distribution through training. The main test is single-crop ImageNet validation accuracy for the Inception variant, measured against the steps the original needed to reach its best:
| Model | Learning rate | Steps to 72.2% | Best accuracy |
|---|---|---|---|
| Inception, no BN | 0.0015 | 31.0 million | 72.2% |
| BN-Baseline (BN added, nothing else) | 0.0015 | 13.3 million | 72.7% |
| BN-x5 (new recipe) | 0.0075 | 2.1 million | 73.0% |
| BN-x30 (new recipe) | 0.045 | 2.7 million | 74.8% |
| BN-x5-Sigmoid | 0.0075 | not reached | 69.8% |
Adding BN alone cut the steps by more than half; the fourteenfold saving needed the higher learning rate and the other recipe changes. BN-x30 starts slower than BN-x5 but keeps improving, reaching 74.8% after about 6 million steps. The sigmoid run is the sharpest ablation: with BN it trains to 69.8%, while the same sigmoid network without BN never exceeded one-in-a-thousand accuracy, which is chance for 1,000 classes.
A single BN network scored 7.82% top-5 validation error with one crop and 5.82% with many crops; an ensemble of six reached 4.9% on validation and 4.82% on the test server, which the authors note beats the reported accuracy of human raters. Even that ensemble kept a little dropout: some members used 5% or 10%, against 40% in the original Inception.
What the authors admit, and what happened next
The paper is explicit about the ugliest consequence, and it is the one that bites in production: the layer behaves differently at training and at inference. At training time the statistics come from the batch; at inference there is no batch, so the layer uses running averages accumulated during training. Forgetting to switch modes is a defect that produces a model which scores well in the training loop and badly when served, with no error message.
What the paper claims and does not establish is the mechanism. It attributes the gain to reducing "internal covariate shift" — the drift in each layer's input distribution. That explanation is contested: Santurkar and colleagues argued in 2018 that covariate shift is not what batch norm fixes, and demonstrated networks where the shift is deliberately reintroduced after normalisation and training is fast anyway; their account is that it smooths the loss surface. The layer works; the stated reason for why it works is not settled.
How it held up: it made very deep convolutional networks routine, and rung 4 is hard to imagine landing without it. But its dependence on the batch is a structural limit, not a detail — with a batch of one, or with sequences of different lengths where "the same feature across the batch" is not a well-defined set of numbers, the statistics are either unavailable or meaningless. That limit is precisely why rung 5 exists, and why the normaliser inside every transformer is not this one.
The transform, and what it preserves
The whole batch-norm transform in a handful of functions, with its two guarantees made checkable. Standardizing a batch gives mean ≈ 0 and variance ≈ 1; the normalization is invariant to any rescaling or shifting of the inputs (so the next layer is shielded from the previous layer's drift); the learnable γ and β restore an arbitrary mean and standard deviation (γ=5, β=3 → std 5, mean 3), proving no expressiveness is lost; the running-stat EMA is what test time uses; and ε keeps a constant feature finite. Change the batch, γ, β, or ε and watch it hold.
Write the body of normalize. Everything else in the file is
already written; this is the function the paper is about. Press ▶ Run to check it against
the 5 assertions below — they start red.
- Standardizing gives ~zero mean and unit variance
- Normalization is invariant to scale and shift
- Gamma and beta restore an arbitrary mean and std
- The running-stat EMA moves toward the batch
- Epsilon keeps a zero-variance feature finite
Why it helps so much
The measured effects were dramatic — the paper reached the same ImageNet accuracy in a fraction of the training steps — and they compound:
| Effect | Why it happens |
|---|---|
| Faster training | Stable input distributions let gradients flow cleanly; fewer steps to converge. |
| Higher learning rates | Normalization bounds activation scale, so large steps don't blow up — a major speedup. |
| Less init-sensitivity | The layer re-centers regardless of how weights were initialized, forgiving bad starts. |
| Mild regularization | Batch statistics add noise per example, a small dropout-like effect (sometimes reducing the need for dropout). |
Interestingly, the original "internal covariate shift" explanation is now debated — later work argued batch norm mainly helps by smoothing the loss landscape, making the optimization surface less jagged. The mechanism is still studied; that it works is not in doubt.
Batch norm's descendants
Batch norm's dependence on the batch is also its weakness: tiny batches give noisy statistics, and sequence models or distributed training make batch statistics awkward. That spawned a family of alternatives that normalize over different axes. Layer norm normalizes across a single example's features (no batch dependence) — which is why it, not batch norm, is standard in transformers and RNNs. Group norm and instance norm split the difference for vision, and RMSNorm strips layer norm down further for large language models.
But the core insight is universal and permanent: keeping activations at a controlled scale, with a learnable way to opt out, makes deep networks trainable. Nearly every modern architecture has a normalization layer of some kind in every block, and every one of them descends from this paper.
At inference, batch norm's linear transform can be folded into the preceding convolution or linear layer's weights — so it costs literally nothing at test time, a common deployment optimization.
Questions people ask about Batch Normalization
How do you backpropagate through batch normalization?
Treat the batch mean and variance as functions of every input and apply the chain rule through them; the paper writes out the six resulting formulas. Collected, the gradient for example i is gamma divided by m times the batch standard deviation, multiplied by m times its own upstream gradient, minus the sum of all upstream gradients, minus its normalized value times the sum of each gradient multiplied by its normalized value. The second term removes any component that would only shift the batch, the third any component that would only rescale it. The gradients for gamma and beta are the sums of the upstream gradient times x-hat, and of the upstream gradient alone.
How does batch normalization work in convolutional layers?
It normalizes per channel instead of per activation. For a mini-batch of m images whose feature maps are p by q, each channel's mean and variance are computed over all m·p·q values in that channel, so every spatial position is normalized in the same way and the layer still behaves as a convolution. One gamma and one beta are learned per channel, so a 64-channel layer adds 128 parameters whatever the image size. The paper argues this keeps the convolutional property that different locations of a map are treated alike. At inference, each channel uses population statistics gathered during training instead of the current batch.
Why is the bias removed from a layer that feeds batch normalization?
Adding a bias b shifts every example's value of that unit by the same amount, and the batch-mean subtraction removes exactly that shift, so b cannot affect the output or the loss. Its gradient is in fact exactly zero, because the gradients flowing into a batch norm layer's inputs always sum to zero over the batch. The paper therefore normalizes Wu rather than Wu + b and lets the learned shift beta play the bias's role after normalization. Keeping the bias does no harm beyond wasted parameters, which is why convolutions followed by batch norm are usually created with the bias switched off.
Should batch norm go before or after the activation function?
The paper puts it before the nonlinearity, normalizing the pre-activation Wu and then applying the activation, z = g(BN(Wu)). Its argument is about distributions: a layer's input is the output of another nonlinearity and its shape keeps changing, while Wu tends to be symmetric and close to Gaussian, so standardizing its mean and variance is more likely to give a stable distribution. ResNet follows the same order of convolution, batch norm, then ReLU. Placing it after the activation also appears in practice, and the paper offers a distributional argument for its choice rather than a proof, so the alternative is an empirical question for a given model.
Why does batch normalization allow higher learning rates?
The paper gives a scale argument. Batch norm's output does not change if the weights feeding it are multiplied by a constant a, and the gradient with respect to those weights is divided by a. So if a large step inflates the weights, their next gradients shrink and the growth limits itself, while the layer's Jacobian is unaffected by the weight scale, which keeps small parameter changes from being amplified as they pass through many layers. In the Inception experiments, learning rates 5 and 30 times the original trained fine: BN-x5 reached the original's best accuracy in 2.1 million steps instead of 31 million, and BN-x30 went on to 74.8%.
Does batch normalization replace dropout?
In the paper's main network it largely did. Removing dropout from the batch-normalized Inception sped up training without increasing overfitting, and the authors attribute part of batch norm's regularizing effect to the noise of batch statistics, since each example's normalization depends on the other examples in its mini-batch. It was not removed everywhere, though: some members of the paper's six-network ensemble kept dropout at 5% or 10%, compared with 40% in the original Inception. Later convolutional networks such as ResNet were trained with batch norm and no dropout at all, while dropout stayed common elsewhere, for example in transformer blocks.
4 questions to test what you just read
Work each one out before you open it — a number, a prediction or a reason, not a definition. Producing the answer is what makes it stick. Your progress is kept on this device.
A convolutional layer outputs a batch of 32 images with 64 channels of 14 × 14. How many means does batch norm compute, over how many values each, and how many parameters does it add?
Show answer
64 means, one per channel, each over 32 × 14 × 14 = 6,272 values (the effective batch m′ = m·p·q). It adds one γ and one β per channel: 128 parameters, independent of the image size.
How much total gradient would a bias b added before batch norm receive over a batch, and why?
Show answer
Zero. Summing ∂ℓ/∂xi over the batch gives m·Σg − m·Σg − (Σx̂i)(Σgjx̂j), and Σx̂i = 0. Adding b shifts every xi equally and the mean subtraction removes the shift, so the loss cannot depend on b; β does its job.
A large update doubles every weight in W feeding a batch-normalized layer. What happens to the layer's output and to the next gradient with respect to W?
Show answer
The output is unchanged, since BN((2W)u) = BN(Wu). The gradient halves, because ∂BN((aW)u)/∂(aW) = (1/a)·∂BN(Wu)/∂W with a = 2. Oversized weights automatically take smaller steps, part of why BN tolerated a 30× learning rate.
From the step counts, how much of BN-x5's speed-up came from adding BN alone, and how much from the new recipe?
Show answer
BN alone took 31.0 million steps to 13.3 million, about 2.3×. The new recipe with a 5× learning rate took that to 2.1 million, a further 6.3×. Together that is about 14.8×, the paper's fourteenfold reduction.
Making deep nets train
Seven papers that turned "deeper is better in theory" into a network that actually converges. Every later architecture paper assumes all of them.
- 1Dropout2014
- 2Batch Normalization2015
- 3Adam2015
- 4ResNet2016
- 5LayerNorm & RMSNorm2016
- 6mixup2018
- 7The Lottery Ticket Hypothesis2019
Explore the topic
See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.
More Paper Breakdowns
- Attention Is All You NeedThe paper that introduced the Transformer — the architecture underneath GPT, BERT, Claude, and Gemini. Self-attention, Query/Key/Value, multi-head attention, positional encoding, and the real BLEU results, explained in depth with analogies and animated visuals, not just equations.Read →
- Word2VecHow words became math. Dense word vectors learned from the company a word keeps, so king − man + woman lands near queen. Skip-gram, CBOW, the distributional hypothesis, and the origin of every embedding model powering search and RAG.Read →
- ResNetThe skip connection that made deep learning deep. Why stacking layers made networks worse, and how residual learning let them reach 150+ layers and win ImageNet — the identity shortcut every Transformer still uses inside every block.Read →
- Vision Transformer (ViT)When an image became 16×16 words. Cut a picture into patches, treat each patch as a token, and feed them to a plain Transformer — no convolutions. Patch embeddings, the class token, and why data scale lets attention beat the CNNs that ruled computer vision for a decade.Read →
- Latent DiffusionThe paper behind Stable Diffusion. Compress an image into a small latent space with a VAE, run the diffusion denoising there instead of on pixels for a tens-of-times efficiency win, and steer it with text via cross-attention. The architecture that put text-to-image generation on consumer GPUs.Read →
- DDPMThe original denoising diffusion math — the paper that made diffusion work. A fixed forward process adds Gaussian noise over many steps; a U-Net learns the reverse. The masterstroke: train the network to simply predict the added noise with a plain MSE loss. The foundation under every modern image generator.Read →