Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift
Standardize every layer's inputs over each mini-batch, and an ImageNet classifier reaches its original accuracy in 14 times fewer training steps.
Ioffe and Szegedy's 2015 layer subtracts the batch mean, divides by the batch standard deviation, then applies a learned scale and shift. It lets networks train at learning rates 5 to 30 times higher, with less careful weight initialization, and makes sigmoid networks trainable again, though the paper's explanation for why it works has not held up.
Explaining the paperBatch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate ShiftFour lines of arithmetic per feature, the chain rule through a batch average, a second set of statistics for test time, and an argument about weight scale for why the layer tolerates high learning rates.
A deep network is trained by stochastic gradient descent (SGD): take a mini-batch of examples, compute the loss, compute its gradient with respect to every weight, move each weight a small step against its gradient, and repeat for millions of steps. Before 2015, deep networks trained this way needed small learning rates and careful weight initialization, and networks with saturating nonlinearities such as the sigmoid were close to untrainable at depth.
Ioffe and Szegedy attributed much of this to one effect. A layer's input is the previous layer's output, so every update to an early layer changes the distribution of values arriving at every later layer. They named this internal covariate shift and proposed a layer that holds the mean and variance of each input fixed during training. Santurkar et al. (2018) later tested that explanation and found it does not account for the speedup; the last section covers their experiments.
The page runs in dependency order: why a drifting input distribution stalls a sigmoid layer, why normalizing outside the gradient computation fails, the four-line transform itself, how gradients flow through the batch mean and variance, what changes at inference time, why the layer tolerates much higher learning rates, the ImageNet numbers, and what later papers found about the mechanism.
Why deep networks trained slowly: saturation and shifting inputs
The sigmoid maps any real number into . Its derivative is:
which is at , at and at . Backpropagation multiplies the gradient by this slope on the way down, so an example whose pre-activation sits at passes back 38 times less gradient than one at . If most of a batch sits out there, the weights feeding that unit barely change. This is saturation, and the paper's Section 2 lists the usual remedies of the time: ReLU units, careful initialization, and small learning rates.
The pre-activation is , where is the output of the layer below. When the layers below change, the distribution of changes, so a unit that started in the steep middle of the sigmoid can drift into a flat tail during training. The paper calls a change in a model's input distribution covariate shift, a term from Shimodaira (2000), and defines internal covariate shift as "the change in the distribution of network activations due to the change in network parameters during training".
Section 4.1 of the paper shows the effect on MNIST with a small network: 3 fully connected hidden layers of 100 sigmoid units each, weights initialized to small random Gaussian values, 50,000 steps at 60 examples per mini-batch. For one typical unit in the last hidden layer, the 15th, 50th and 85th percentiles of its sigmoid input changed significantly in both mean and variance over training without BN and were much more stable with it, and the BN network reached higher test accuracy.
In the figure below, the drift slider moves the mean of a batch of pre-activations. Watch the gradient-signal readout as the batch moves into a tail, then switch Batch Norm on.
With Batch Norm on, the readout stays near its maximum at every drift, because the normalized batch always has mean 0 and variance 1 before it reaches the sigmoid. The paper's sigmoid ImageNet network depends on this: with BN it reaches 69.8% accuracy, and without BN it stays at chance (the ImageNet section has the details).
Why you can't just normalize outside the gradient
An obvious implementation computes each layer's mean from the data, separately from training, and subtracts it before each step, treating the mean as a constant. Section 2 of the paper shows why this fails, and the authors report that in early experiments the model blew up when the normalization statistics were computed outside the gradient step.
Take a layer that adds a learned bias , so , and normalizes by subtracting the mean over the training data, . If the gradient step treats as a constant, the update to is with , the gradient of the loss with respect to the normalized value. After the update, the normalized output is:
Adding to every raises their mean by exactly , and the subtraction removes it. The output is unchanged, so the loss is unchanged, so is the same at the next step, and the next update moves by the same again. grows linearly, forever, while the loss stays fixed.
Scrub the training steps in the figure. In naive mode climbs while the layer output and the loss stay flat. In aware mode the gradient includes the dependence of the mean on , which is exactly equal and opposite, so the gradient on is 0 and it stays put.
The paper concludes that normalization has to be part of the network, so that backpropagation differentiates through the mean and variance as functions of the parameters. In the paper's notation, the gradient must include (the dependence on the whole batch) as well as . It also means the bias becomes useless inside a normalized layer, since any constant added before the mean subtraction is removed by it.
How batch normalization works
Batch Normalization treats each feature (one unit's pre-activation) separately. For one feature, a mini-batch of examples gives values . Algorithm 1 of the paper computes:
The variance divides by , not ; this biased estimate is the one used in training, and the inference section returns to it. The constant is added to the variance inside the square root so the division is safe when a feature is nearly constant across the batch (PyTorch's default is ). and are learned, one pair per feature.
A worked example with , batch values 1, 2, 4 and 5, , and :
The normalized values have mean 0 and variance 1 (up to ); the outputs have mean 0.5 and standard deviation 2.
Why not stop at ? Forcing every sigmoid input to mean 0 and variance 1 would keep it in the sigmoid's near-linear middle and remove the network's ability to use the saturating parts when they help. The paper requires that the inserted transform can represent the identity, and make it so:
exactly if is neglected. In the worked example, and give back . The network can therefore represent everything it could before, and gradient descent decides how far from the identity to go. Drag and in the figure, or press "set to identity": the middle row never changes, and the bottom row can be placed anywhere.
Equation (2) is a simplified version of whitening, the classical input preprocessing that LeCun et al. (1998) and Wiesler and Ney (2011) found speeds up convergence: transform the inputs to zero mean and unit variance and also decorrelate them. Full whitening of a layer needs the covariance matrix of all its features and that matrix's inverse square root at every step, which is expensive and not everywhere differentiable; and with fewer examples in the batch than features, the batch covariance matrix is singular. The paper makes two simplifications. Each feature is normalized on its own, with no decorrelation. And the statistics come from the current mini-batch rather than the whole training set, so they are functions of the parameters that backpropagation can differentiate, which Figure 2 showed is required.
Where the layer goes, and convolutions
The paper inserts BN immediately before the nonlinearity. A layer becomes:
with the bias dropped, because the mean subtraction cancels it and takes over its role. The paper normalizes rather than the layer input : is the output of another nonlinearity, so its shape keeps changing, while is a sum of many terms and is "more likely to have a symmetric, non-sparse distribution, that is 'more Gaussian'", for which fixing the mean and variance fixes most of the distribution.
In a convolutional layer, a feature map applies the same filter at every position, and BN keeps that property by normalizing every position of a feature map the same way. The statistics for one feature map are pooled over the batch and all positions, an effective batch of values, and there is one pair per feature map. At the paper's batch size of 32 and a feature map (the size at the fourth stage of its Inception network), each mean and variance is computed over values. A convolution with 64 output channels gains 128 parameters, and those two per channel are all BN adds.
Backpropagating through the batch mean and variance
Every quantity in (2) is differentiable, including and . Because they are shared by the whole batch, example 's output depends on every other example's input, and the gradient with respect to has three paths: the direct one through , one through the mean, and one through the variance. The paper gives the chain rule "before simplification":
To simplify (4), write for and for . The second term of contains the sum of the deviations , which is 0 by the definition of the mean, so only its first term survives. In the variance line, each deviation equals . Putting these into the last line of (4), the three paths contribute:
and together:
which is exact, included. Summing (5) over the batch, and summing it weighted by , gives two properties (the first uses that the sum to 0, the second that their squares sum to ):
Adding the same constant to every , which is what a bias does, therefore has zero gradient (the term the naive scheme of Figure 2 left out), and stretching the batch about its mean has almost none.
Continuing the worked example (batch 1, 2, 4, 5 and ), suppose the loss gradient on the outputs is 1 for the first example and 0 for the others:
The four values sum to 0, and a finite-difference check on the forward pass gives the same numbers. Here the loss is itself. Raising or lowers , mostly by raising the batch mean. Raising raises the mean too (a contribution of ) but also widens the batch, which pulls the negative toward 0 (a contribution of ), so its net gradient is positive. If the loss gradient is 1 on every output, every is 0.
In the figure, the incoming gradient is a fixed random pattern plus a shared shift and a scale-shaped part . With all three paths on, move either slider: the top bars change, the bottom bars do not. Cycle the paths button to direct-only and the shift passes straight through.
The gradients for and are the plain sums in the last line of (4). Since the whole layer is a handful of means and elementwise operations, its backward pass costs about as much as its forward pass, and BN works with any gradient method; the paper names SGD with , momentum and Adagrad.
Training mode and inference mode
During training, depends on which other examples share the batch. At inference the paper wants "the output to depend only on the input, deterministically", and a deployed model may see one example at a time. So after training, Algorithm 2 replaces the batch statistics with population statistics:
The expectations are averages over many training mini-batches of size . The factor is Bessel's correction: a ÷ batch variance measures spread around the batch's own mean, which is closer to the batch's points than the true mean is, so on average it comes out low by a factor . For the worked batch, . At the correction is , about 3%; at it doubles the estimate. The asymmetry is deliberate: training uses the ÷ statistic that (2) defines and backprop differentiates, and inference uses the best estimate of the population variance.
The figure draws 40 random batches of size from a feature with mean 3 and variance 4. The top strip shows each batch's ÷ variance and their average; the bottom strip follows one example, , through 40 different batches and shows the normalized value it gets in each. Slide down to 1 and up to 64.
Three things are visible. At the average variance sits near 3, as predicts, and the corrected line near 4. At the example's normalized value is always , because any two distinct numbers standardize to and ; at the batch variance is 0, every is 0, the input is erased, and is undefined, which is why the paper requires . And at every batch size the training values scatter around the inference value 1.00, more widely for small .
That scatter has two consequences. Section 3.4 of the paper treats it as a regularizer: an example is normalized differently each time it appears with different companions, and the authors found Dropout "can be either removed or reduced in strength". Their ImageNet setup also shuffled training data more thoroughly within shards so the same examples stopped landing in a batch together, worth about 1% validation accuracy. The second consequence, noisy statistics at small batch sizes, is the failure mode covered in the last section.
With the statistics frozen, BN at inference is a fixed affine map per feature, and Algorithm 2 folds it together with and :
The folded form costs one multiply and one add per value, and it can be merged into the weights and bias of the preceding linear or convolutional layer, so a deployed BN layer costs nothing extra. The paper notes that moving averages kept during training can replace the after-training average in (6), which lets you measure validation accuracy while the model trains; libraries do this. PyTorch keeps a running average with momentum 0.1 and feeds it the unbiased per-batch variance, applying batch by batch; Keras keeps one with momentum 0.99 of the biased variance and skips the correction. The listing below follows PyTorch and uses (5) for the backward pass.
# Batch norm for ONE feature over a mini-batch x of shape (m,), with m > 1.
# (For a conv layer, x holds one channel's values over batch and positions.)
def bn_forward(x, gamma, beta, run_mean, run_var, training,
momentum=0.1, eps=1e-5):
if training:
m = x.shape[0]
mu = x.mean() # (1/m) sum x_i
var = ((x - mu) ** 2).mean() # biased: divide by m
run_mean = (1 - momentum) * run_mean + momentum * mu
run_var = (1 - momentum) * run_var + momentum * var * m / (m - 1)
else:
mu, var = run_mean, run_var # frozen population stats
s = (var + eps) ** 0.5
x_hat = (x - mu) / s # mean 0, variance ~1
return gamma * x_hat + beta, x_hat, s, run_mean, run_var
def bn_backward(dy, gamma, x_hat, s):
# dy = dloss/dy, shape (m,). Equation (5); eps is inside s.
g = dy * gamma # dloss/dx_hat
dx = (g - g.mean() - x_hat * (g * x_hat).mean()) / s
return dx, (dy * x_hat).sum(), dy.sum() # dx, dgamma, dbetaWhy batch norm allows higher learning rates
In the paper, BN networks train at learning rates 5 and 30 times higher than the original network, while a 5× rate on the original Inception without BN drove its parameters to "machine infinity". Section 3.3 gives an argument from scale. Multiply a layer's weights by a constant and every in the batch is multiplied by , so the mean and standard deviation scale by too and the normalized output does not change:
The gradient passed to the layer below does not depend on the weight scale, and the gradient on the weights shrinks as : doubling the weights halves their gradient. The paper concludes that "larger weights lead to smaller gradients, and Batch Normalization will stabilize the parameter growth".
Two further facts follow from scale invariance. Because the loss does not change when is scaled, its gradient has no component along and is perpendicular to it. A gradient step perpendicular to can only lengthen it; by Pythagoras, with the gradient and the learning rate:
A step of length perpendicular to a vector of length turns it by an angle of about , where itself is proportional to . The direction, the only thing the loss depends on, changes at an effective rate of . A learning rate that is too large makes a big step, which lengthens , which lowers the effective rate for every step after. Later work develops this reading: van Laarhoven (2017) showed that L2 weight decay has no regularizing effect on normalized weights and acts through their scale on the effective learning rate, and Arora, Li and Lyu (2018) analyze BN as automatic tuning of the learning rate.
The figure shows a two-weight unit whose loss depends only on the direction of , with the best direction dashed. At from , the first step overshoots, lengthens to 1.63, and cuts the effective step from 6.0 to 0.57, after which the angle converges. Push to 8: one step takes from 0.5 to 8.26, the effective step drops to 0.117, and the descent still converges, slowly. Then try a small with a large starting , where it barely moves.
Section 3.3 also offers a second, explicitly hedged argument: "We further conjecture that Batch Normalization may lead the layer Jacobians to have singular values close to 1", which would keep gradient magnitudes steady through depth. The derivation assumes the normalized inputs are Gaussian and uncorrelated and the layer is linear, and the paper says the precise effect "remains an area of further study". Yang et al. (2019) settled it the other way for networks at initialization: in the infinite-width limit, BN pushes the singular values away from 1 and gradients explode with depth.
A third view, from Santurkar et al. (2018) and covered in the last section, is that BN makes the loss surface smoother. For intuition on why smoothness allows a larger step: gradient descent on a quadratic with curvature is stable only while the step size is below . The two toy one-parameter landscapes below share a learning rate; the left one has high curvature, the right one low.
At the default rate of 0.45 the left ball bounces between walls and the right one settles. At the maximum, 1.40, both diverge: smoothing raises the largest usable learning rate, and some rate is still too large.
ImageNet results: 14× fewer training steps
The testbed is a variant of Inception, the network that won the 2014 ImageNet classification challenge, on the 1000-class ImageNet task. The variant has 13.6 million parameters, replaces each 5×5 convolution with two 3×3 convolutions, uses ReLU, and has no fully connected layers other than the final softmax. It is trained by SGD with momentum at batch size 32 with an initial learning rate of 0.0015. BN goes before every nonlinearity, applied convolutionally, and the rest of the architecture is unchanged, so the variants differ only in BN and training settings.
Adding BN and nothing else (BN-Baseline) reaches Inception's final 72.2% top-1 validation accuracy (the fraction of held-out images whose highest-scoring class is correct, from a single crop) in 13.3 million steps instead of 31.0 million and tops out at 72.7%. The authors then changed the training setup to use what BN allows. The initial learning rate went up 5×, to 0.0075. Dropout was removed. The L2 weight penalty was reduced by a factor of 5. The learning rate was decayed 6 times faster. Local Response Normalization, an older cross-channel normalization in Inception, was removed. Training examples were shuffled more thoroughly, and photometric distortions of the training images were reduced. That model, BN-x5, reaches 72.2% in 2.1 million steps, 7% of Inception's 31.0 million: the 14× in the abstract. Its best accuracy is 73.0%. The comparison is in training steps; the paper does not report wall-clock time or the extra cost of a BN step.
BN-x30 uses an initial rate of 0.045, 30× Inception's. It trains somewhat slower than BN-x5 at first, needing 2.7 million steps to reach 72.2%, but it keeps improving and reaches 74.8% after 6 million steps. Drag the target line in the figure: at 72.2% the crossing points reproduce the step counts, and above 73.0% only BN-x30 still crosses.
The sigmoid experiment tests the saturation argument directly. BN-x5-Sigmoid, the BN-x5 network with sigmoid in place of ReLU, reaches 69.8%. The original Inception with sigmoid and no BN "never achieves better than 1/1000 accuracy", which is chance for 1000 classes.
An ensemble of 6 networks, each based on BN-x30 with small modifications (among them Dropout at 5% or 10%), reaches 4.9% top-5 validation error and 4.82% top-5 error on the 100,000-image test set, as scored by the ILSVRC server. Top-5 error is the fraction of images whose correct label is not among the model's 5 highest-scoring classes. The previous results in the paper's comparison table are the GoogLeNet ensemble at 6.67% and Deep Image at 5.98%; the text also cites He et al. (2015) at 4.94%. The paper says the ensemble exceeds "the estimated accuracy of human raters", citing Russakovsky et al. (2014). That estimate is one trained annotator's 5.1% top-5 error on 1,500 test images; a second annotator with less training scored about 12.0% on 258 images, and Russakovsky et al. expected humans to stay ahead of the models of the time "only by use of significant effort, expertise, and time".
What later work found about why batch norm works
The paper's title states its explanation: BN accelerates training by reducing internal covariate shift. In 2018, Santurkar, Tsipras, Ilyas and Madry tested that explanation in three ways.
First, they trained BN networks with random noise added after every BN layer, drawn from a distribution with non-zero mean and non-unit variance that changed at every step. The resulting activations were less stable than those of a network without BN at all, and the noisy-BN network trained almost as well as the ordinary BN network, while the same noise added to a network without BN stopped it from training entirely. Second, they defined internal covariate shift through how much a layer's gradient changes when the layers before it are updated, and found that BN networks did not show less of it, and sometimes more; they call the link between BN's performance and internal covariate shift "tenuous, at best". Third, they measured what BN does change: the loss and its gradient vary more slowly with the parameters (better Lipschitz constants and smoothness), so a gradient computed at one point still points in a useful direction over a longer step. They also found that normalizing by the , or norm, none of which produces mean-0, variance-1 activations, trains comparably to BN. Their smoothness theorems hold for specific simplified settings, and their result where normalization beats BN is for deep linear networks.
Santurkar et al. do not claim the gains are illusory or that activation distributions never drift. Their experiments show that keeping the distributions stable is not what makes BN networks train faster, and their smoothness results, together with the scale-invariance argument of Figure 6, account for the higher usable learning rates.
The paper does not discuss batch size. With small batches the statistics are noisy, as Figure 5 showed, and the difference between batch statistics in training and population statistics at inference grows. Wu and He (2018) measured ResNet-50 on ImageNet: validation error with BN rose from 23.6% at 32 images per GPU to 34.7% at 2 images per GPU, while their Group Normalization, which normalizes over groups of channels within each example, stayed at 24.1%. Ioffe's own Batch Renormalization (2017) corrects the batch statistics toward the moving averages during training. Layer Normalization (Ba, Kiros and Hinton, 2016) normalizes over all features of one example, with no batch involved; the Transformer adopted it the following year, and Transformer models have used it since. In convolutional networks BN stayed standard: ResNet applies it after every convolution.
Questions you might still have
If batch norm does not reduce internal covariate shift, why does it work?
The best-supported account (Santurkar et al. 2018) is that it makes the loss and its gradients smoother, so a gradient computed at one point stays accurate over a longer step and a larger learning rate stays stable. Scale invariance adds a second effect: the weight norm grows during training and the effective step size shrinks with it. In the paper, BN alone cut the steps to 72.2% from 31.0 million to 13.3 million; the 14× came after also raising the learning rate 5× and making the other BN-x5 changes.
Why does the layer need γ and β if it then standardizes everything?
Standardizing alone would force every feature to mean 0 and variance 1, which pins a sigmoid to its near-linear middle. γ and β restore any mean and spread the network wants; with γ = √Var[x] and β = E[x] the layer outputs its input unchanged (up to ε). They add 2 parameters per feature, or per channel in a convnet.
Why use the biased variance in training but the unbiased one at test time?
In training the layer divides by the batch’s own ÷m variance, the quantity Algorithm 1 defines and backprop differentiates. At test time it needs an estimate of the population variance, and the average of ÷m batch variances is low by the factor (m−1)/m, which m/(m−1) removes. At m = 32 the correction is about 3%. PyTorch applies it to each batch variance before averaging; Keras skips it.
Why does batch norm fail at small batch sizes?
Each example is normalized with its own batch’s mean and variance. With 2 examples per batch those statistics are very noisy, and they differ a lot from the frozen population statistics used at inference. Wu and He (2018) measured ResNet-50 error rising from 23.6% at 32 images per GPU to 34.7% at 2. Group Normalization, Layer Normalization and Batch Renormalization avoid or correct the batch dependence.
Should BN go before or after the nonlinearity?
The paper puts it before: z = g(BN(Wu)), normalizing the pre-activation Wu because a sum of many terms is closer to symmetric and Gaussian than the output of a nonlinearity. The layer’s own bias b is dropped because mean subtraction cancels it and β takes its place. Placing BN after the activation is a common variant in later code, but it is not what this paper tested.
Does batch norm replace Dropout?
In the paper’s ImageNet runs it did for single networks: BN-x5 removed Dropout and trained faster without more overfitting. The 6-network ensemble still used Dropout at 5% or 10%, against 40% in the original Inception, so the paper reduced it rather than abandoning it everywhere.
Footnotes & further reading
- The paper: Ioffe & Szegedy, Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift (Google, ICML 2015, PMLR 37:448–456). Algorithms 1 and 2 are on pages 3 and 4; the ImageNet table is Figure 3.
- The mechanism re-examined: Santurkar, Tsipras, Ilyas & Madry, How Does Batch Normalization Help Optimization? (NeurIPS 2018): the noise-injection experiment, the gradient-based definition, and the smoothness results.
- The Section 3.3 conjecture, disproved at initialization: Yang, Pennington, Rao, Sohl-Dickstein & Schoenholz, A Mean Field Theory of Batch Normalization (ICLR 2019).
- The small-batch failure and batch-free alternatives: Wu & He, Group Normalization (Table 2); Ioffe, Batch Renormalization; and Ba, Kiros & Hinton, Layer Normalization (explained here).
- Scale invariance and the effective learning rate: van Laarhoven, L2 Regularization versus Batch and Weight Normalization, and Arora, Li & Lyu, Theoretical Analysis of Auto Rate-Tuning by Batch Normalization.
- Running statistics in practice: torch/nn/modules/batchnorm.py (biased variance for normalization, unbiased for the running average, momentum 0.1) and Keras batch_normalization.py (moving variance of the biased estimate, momentum 0.99).
- Foundations the paper builds on: Shimodaira (2000) for "covariate shift"; Glorot & Bengio (2010), Understanding the difficulty of training deep feedforward neural networks; and the human-rater estimate from Russakovsky et al. (2014), the ImageNet challenge paper, Table 9.
How could this explainer be improved? Found an error, or something unclear? I read every message.