VerifiedarXiv:1502.0316728 min
Training · Optimization

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 ShiftIoffe, Szegedy · Google · ICML 2015 · arXiv:1502.03167 ↗

Four 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 g(x)=1/(1+e−x)g(x) = 1/(1+e^{-x}) maps any real number into (0,1)(0,1). Its derivative is:

g′(x)=g(x) (1−g(x))g'(x) = g(x)\,\big(1 - g(x)\big)

which is 0.250.25 at x=0x = 0, 0.01770.0177 at x=4x = 4 and 0.00660.0066 at x=5x = 5. Backpropagation multiplies the gradient by this slope on the way down, so an example whose pre-activation sits at x=5x = 5 passes back 38 times less gradient than one at x=0x = 0. 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 x=Wu+bx = Wu + b, where uu is the output of the layer below. When the layers below change, the distribution of uu 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.

Figure 1 · saturation and the moving distribution
μ = 3.2
A mini-batch of pre-activations on a sigmoid. Drag the drift μ: as the batch slides into a flat tail, the slope g′g' falls toward zero and the gradient signal readout drops. With Batch Norm on, the batch is re-centered to the steep middle at any drift. The faint curve is where the layers below put the batch; the arrow shows the re-centering.

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 bb, so x=u+bx = u + b, and normalizes by subtracting the mean over the training data, x^=x−E[x]\hat{x} = x - \mathrm{E}[x]. If the gradient step treats E[x]\mathrm{E}[x] as a constant, the update to bb is Δb\Delta b with Δb∝−∂ℓ/∂x^\Delta b \propto -\partial\ell/\partial\hat{x}, the gradient of the loss with respect to the normalized value. After the update, the normalized output is:

(u+b+Δb)−E[u+b+Δb]  =  (u+b)−E[u+b](u + b + \Delta b) - \mathrm{E}[u + b + \Delta b] \;=\; (u + b) - \mathrm{E}[u + b]
(1)

Adding Δb\Delta b to every xx raises their mean by exactly Δb\Delta b, and the subtraction removes it. The output is unchanged, so the loss is unchanged, so ∂ℓ/∂x^\partial\ell/\partial\hat{x} is the same at the next step, and the next update moves bb by the same Δb\Delta b again. bb grows linearly, forever, while the loss stays fixed.

Scrub the training steps in the figure. In naive mode bb climbs while the layer output and the loss stay flat. In aware mode the gradient includes the dependence of the mean on bb, which is exactly equal and opposite, so the gradient on bb is 0 and it stays put.

Figure 2 · the bias that runs away
step 0
Top panel: the bias bb. Bottom panel: the layer output and the loss. With the gradient in naive mode (mean treated as a constant), b climbs without bound and the output and loss never move. Switch to aware and bb stays at its starting value.

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 ∂ Norm/∂X\partial\,\mathrm{Norm}/\partial X (the dependence on the whole batch) as well as ∂ Norm/∂x\partial\,\mathrm{Norm}/\partial x. It also means the bias bb 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 B\mathcal{B} of mm examples gives mm values x1,…,xmx_1, \dots, x_m. Algorithm 1 of the paper computes:

μB=1m∑i=1mxibatch meanσB2=1m∑i=1m(xi−μB)2batch variancex^i=xi−μBσB2+ϵnormalizeyi=γ x^i+βscale and shift\begin{aligned} \mu_{\mathcal B} &= \frac{1}{m}\sum_{i=1}^m x_i & &\text{batch mean} \\[4pt] \sigma_{\mathcal B}^2 &= \frac{1}{m}\sum_{i=1}^m (x_i-\mu_{\mathcal B})^2 & &\text{batch variance} \\[4pt] \hat{x}_i &= \frac{x_i-\mu_{\mathcal B}}{\sqrt{\sigma_{\mathcal B}^2+\epsilon}} & &\text{normalize} \\[4pt] y_i &= \gamma\,\hat{x}_i + \beta & &\text{scale and shift} \end{aligned}
(2)

The variance divides by mm, not m−1m-1; this biased estimate is the one used in training, and the inference section returns to it. The constant ϵ\epsilon 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 10−510^{-5}). γ\gamma and β\beta are learned, one pair per feature.

A worked example with m=4m = 4, batch values 1, 2, 4 and 5, γ=2\gamma = 2, β=0.5\beta = 0.5 and ϵ=10−5\epsilon = 10^{-5}:

μB=(1+2+4+5)/4=3σB2=(4+1+1+4)/4=2.5σB2+ϵ≈1.5811x^≈(−1.265,  −0.632,  0.632,  1.265)y=2x^+0.5≈(−2.030,  −0.765,  1.765,  3.030)\begin{aligned} \mu_{\mathcal B} &= (1+2+4+5)/4 = 3 \\[2pt] \sigma^2_{\mathcal B} &= (4+1+1+4)/4 = 2.5 \\[2pt] \sqrt{\sigma^2_{\mathcal B}+\epsilon} &\approx 1.5811 \\[2pt] \hat{x} &\approx (-1.265,\; -0.632,\; 0.632,\; 1.265) \\[2pt] y = 2\hat{x} + 0.5 &\approx (-2.030,\; -0.765,\; 1.765,\; 3.030) \end{aligned}

The normalized values have mean 0 and variance 1 (up to ϵ\epsilon); the outputs have mean 0.5 and standard deviation 2.

Why not stop at x^\hat{x}? 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 γ,β\gamma, \beta make it so:

γ=Var[x],β=E[x]⟹yi=xi\gamma = \sqrt{\mathrm{Var}[x]}, \quad \beta = \mathrm{E}[x] \quad\Longrightarrow\quad y_i = x_i
(3)

exactly if ϵ\epsilon is neglected. In the worked example, γ=2.5≈1.581\gamma = \sqrt{2.5} \approx 1.581 and β=3\beta = 3 give back (1,2,4,5)(1, 2, 4, 5). The network can therefore represent everything it could before, and gradient descent decides how far from the identity to go. Drag γ\gamma and β\beta in the figure, or press "set to identity": the middle row never changes, and the bottom row can be placed anywhere.

Figure 3 · normalize, then scale and shift
One mini-batch through equation (2). The raw batch x has an arbitrary mean and spread; x̂ always has mean 0 and spread 1; y = γx̂ + β takes spread γ and mean β. "Set to identity" picks γ=σ\gamma=\sigma, β=μ\beta=\mu, which reproduces the raw batch.

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 z=g(Wu+b)z = g(Wu + b) becomes:

z=g(BN(Wu))z = g\big(\mathrm{BN}(Wu)\big)

with the bias bb dropped, because the mean subtraction cancels it and β\beta takes over its role. The paper normalizes WuWu rather than the layer input uu: uu is the output of another nonlinearity, so its shape keeps changing, while WuWu 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 p×qp \times q positions, an effective batch of m′=m⋅p⋅qm' = m\cdot p\cdot q values, and there is one (γ,β)(\gamma, \beta) pair per feature map. At the paper's batch size of 32 and a 14×1414 \times 14 feature map (the size at the fourth stage of its Inception network), each mean and variance is computed over 32⋅14⋅14=6,27232 \cdot 14 \cdot 14 = 6{,}272 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 μB\mu_{\mathcal B} and σB2\sigma^2_{\mathcal B}. Because they are shared by the whole batch, example ii's output depends on every other example's input, and the gradient with respect to xix_i has three paths: the direct one through x^i\hat{x}_i, one through the mean, and one through the variance. The paper gives the chain rule "before simplification":

∂ℓ∂x^i=∂ℓ∂yi⋅γ∂ℓ∂σB2=∑i=1m∂ℓ∂x^i (xi−μB)⋅−12 (σB2+ϵ)−3/2∂ℓ∂μB=(∑i=1m∂ℓ∂x^i⋅−1σB2+ϵ)+∂ℓ∂σB2⋅∑i=1m−2(xi−μB)m∂ℓ∂xi=∂ℓ∂x^i⋅1σB2+ϵ+∂ℓ∂σB2⋅2(xi−μB)m+∂ℓ∂μB⋅1m∂ℓ∂γ=∑i=1m∂ℓ∂yi x^i,∂ℓ∂β=∑i=1m∂ℓ∂yi\begin{aligned} \frac{\partial \ell}{\partial \hat{x}_i} &= \frac{\partial \ell}{\partial y_i}\cdot \gamma \\[4pt] \frac{\partial \ell}{\partial \sigma_{\mathcal B}^2} &= \sum_{i=1}^m \frac{\partial \ell}{\partial \hat{x}_i}\,(x_i-\mu_{\mathcal B})\cdot \tfrac{-1}{2}\,(\sigma_{\mathcal B}^2+\epsilon)^{-3/2} \\[4pt] \frac{\partial \ell}{\partial \mu_{\mathcal B}} &= \Big(\sum_{i=1}^m \frac{\partial \ell}{\partial \hat{x}_i}\cdot \tfrac{-1}{\sqrt{\sigma_{\mathcal B}^2+\epsilon}}\Big) + \frac{\partial \ell}{\partial \sigma_{\mathcal B}^2}\cdot \frac{\sum_{i=1}^m -2(x_i-\mu_{\mathcal B})}{m} \\[4pt] \frac{\partial \ell}{\partial x_i} &= \frac{\partial \ell}{\partial \hat{x}_i}\cdot \tfrac{1}{\sqrt{\sigma_{\mathcal B}^2+\epsilon}} + \frac{\partial \ell}{\partial \sigma_{\mathcal B}^2}\cdot \frac{2(x_i-\mu_{\mathcal B})}{m} + \frac{\partial \ell}{\partial \mu_{\mathcal B}}\cdot \frac{1}{m} \\[4pt] \frac{\partial \ell}{\partial \gamma} &= \sum_{i=1}^m \frac{\partial \ell}{\partial y_i}\,\hat{x}_i, \qquad \frac{\partial \ell}{\partial \beta} = \sum_{i=1}^m \frac{\partial \ell}{\partial y_i} \end{aligned}
(4)

To simplify (4), write ss for σB2+ϵ\sqrt{\sigma^2_{\mathcal B} + \epsilon} and gig_i for ∂ℓ/∂x^i\partial\ell/\partial\hat{x}_i. The second term of ∂ℓ/∂μB\partial\ell/\partial\mu_{\mathcal B} contains the sum of the deviations xi−μBx_i - \mu_{\mathcal B}, which is 0 by the definition of the mean, so only its first term survives. In the variance line, each deviation xi−μBx_i - \mu_{\mathcal B} equals s x^is\,\hat{x}_i. Putting these into the last line of (4), the three paths contribute:

direct:gi / sthrough μB:−1m∑jgj / sthrough σB2:−x^i 1m∑jgjx^j / s\begin{aligned} \text{direct:}&\quad g_i\,/\,s \\[2pt] \text{through } \mu_{\mathcal B}\text{:}&\quad -\tfrac{1}{m}\textstyle\sum_j g_j\,/\,s \\[2pt] \text{through } \sigma^2_{\mathcal B}\text{:}&\quad -\hat{x}_i\,\tfrac{1}{m}\textstyle\sum_j g_j\hat{x}_j\,/\,s \end{aligned}

and together:

∂ℓ∂xi  =  1s(gi  −  1m∑jgj⏟mean path  −  x^i 1m∑jgj x^j⏟variance path)\frac{\partial \ell}{\partial x_i} \;=\; \frac{1}{s}\Big( g_i \;-\; \underbrace{\tfrac{1}{m}\textstyle\sum_j g_j}_{\text{mean path}} \;-\; \hat{x}_i\,\underbrace{\tfrac{1}{m}\textstyle\sum_j g_j\,\hat{x}_j}_{\text{variance path}} \Big)
(5)

which is exact, ϵ\epsilon included. Summing (5) over the batch, and summing it weighted by x^i\hat{x}_i, gives two properties (the first uses that the x^i\hat{x}_i sum to 0, the second that their squares sum to m σB2/(σB2+ϵ)m\,\sigma^2_{\mathcal B}/(\sigma^2_{\mathcal B}+\epsilon)):

∑i=1m∂ℓ∂xi=0,∑i=1mx^i ∂ℓ∂xi=ϵσB2+ϵ⋅1s∑j=1mgjx^j≈0\sum_{i=1}^m \frac{\partial \ell}{\partial x_i} = 0, \qquad \sum_{i=1}^m \hat{x}_i\,\frac{\partial \ell}{\partial x_i} = \frac{\epsilon}{\sigma^2_{\mathcal B}+\epsilon}\cdot\frac{1}{s}\sum_{j=1}^m g_j\hat{x}_j \approx 0

Adding the same constant to every xix_i, 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 γ=2\gamma = 2), suppose the loss gradient on the outputs is 1 for the first example and 0 for the others:

∂ℓ/∂y=(1,  0,  0,  0)g=γ ∂ℓ/∂y=(2,  0,  0,  0)1m∑jgj=0.5,1m∑jgjx^j=2⋅(−1.265)/4=−0.632∂ℓ/∂x≈(0.443,  −0.569,  −0.063,  0.190)\begin{aligned} \partial\ell/\partial y &= (1,\; 0,\; 0,\; 0) \\[2pt] g = \gamma\,\partial\ell/\partial y &= (2,\; 0,\; 0,\; 0) \\[2pt] \tfrac{1}{m}\textstyle\sum_j g_j = 0.5, &\quad \tfrac{1}{m}\textstyle\sum_j g_j\hat{x}_j = 2\cdot(-1.265)/4 = -0.632 \\[2pt] \partial\ell/\partial x &\approx (0.443,\; -0.569,\; -0.063,\; 0.190) \end{aligned}

The four values sum to 0, and a finite-difference check on the forward pass gives the same numbers. Here the loss is y1y_1 itself. Raising x2x_2 or x3x_3 lowers y1y_1, mostly by raising the batch mean. Raising x4x_4 raises the mean too (a contribution of −0.316-0.316) but also widens the batch, which pulls the negative x^1\hat{x}_1 toward 0 (a contribution of +0.506+0.506), so its net gradient is positive. If the loss gradient is 1 on every output, every ∂ℓ/∂xi\partial\ell/\partial x_i is 0.

In the figure, the incoming gradient is a fixed random pattern plus a shared shift cc and a scale-shaped part k x^ik\,\hat{x}_i. 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.

Figure 4 · what the mean and variance paths remove
0.800.00
Eight examples, ordered by their normalized value x^i\hat{x}_i (numbers under the columns). Top: gradient arriving from the layer above. Bottom: gradient passed to the layer below, with the incoming bars outlined for comparison. The two sums above the plot turn teal when they are zero. Drag c and k, and cycle the paths.

The gradients for γ\gamma and β\beta 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 m>1m > 1, momentum and Adagrad.

Training mode and inference mode

During training, BN(xi)\mathrm{BN}(x_i) 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:

x^=x−E[x]Var[x]+ϵ,E[x]=EB[μB],Var[x]=mm−1 EB ⁣[σB2]\hat{x} = \frac{x - \mathrm{E}[x]}{\sqrt{\mathrm{Var}[x]+\epsilon}}, \qquad \mathrm{E}[x] = \mathrm{E}_{\mathcal B}[\mu_{\mathcal B}], \qquad \mathrm{Var}[x] = \frac{m}{m-1}\,\mathrm{E}_{\mathcal B}\!\left[\sigma_{\mathcal B}^2\right]x^=x−E[x]Var[x]+ϵ,E[x]=EB[μB],Var[x]=mm−1 EB ⁣[σB2]\begin{gathered} \hat{x} = \frac{x - \mathrm{E}[x]}{\sqrt{\mathrm{Var}[x]+\epsilon}}, \\ \mathrm{E}[x] = \mathrm{E}_{\mathcal B}[\mu_{\mathcal B}], \qquad \mathrm{Var}[x] = \frac{m}{m-1}\,\mathrm{E}_{\mathcal B}\!\left[\sigma_{\mathcal B}^2\right] \end{gathered}
(6)

The expectations are averages over many training mini-batches of size mm. The factor m/(m−1)m/(m-1) is Bessel's correction: a ÷mm 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 (m−1)/m(m-1)/m. For the worked batch, 2.5×4/3=3.332.5 \times 4/3 = 3.33. At m=32m = 32 the correction is 32/3132/31, about 3%; at m=2m = 2 it doubles the estimate. The asymmetry is deliberate: training uses the ÷mm 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 mm from a feature with mean 3 and variance 4. The top strip shows each batch's ÷mm variance and their average; the bottom strip follows one example, x=5x = 5, through 40 different batches and shows the normalized value it gets in each. Slide mm down to 1 and up to 64.

Figure 5 · batch statistics as estimates
m = 4
Top: 40 batch variances (÷mm), their average, the average after × m/(m−1), and the true variance 4 (dotted). Bottom: the normalized value of the example x=5x = 5 in 40 different training batches, against its single inference value, 1.00. Draw new batches resamples.

Three things are visible. At m=4m = 4 the average variance sits near 3, as (m−1)/m⋅4(m-1)/m \cdot 4 predicts, and the corrected line near 4. At m=2m = 2 the example's normalized value is always ±1\pm 1, because any two distinct numbers standardize to −1-1 and +1+1; at m=1m = 1 the batch variance is 0, every x^\hat{x} is 0, the input is erased, and m/(m−1)m/(m-1) is undefined, which is why the paper requires m>1m > 1. And at every batch size the training values scatter around the inference value 1.00, more widely for small mm.

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 γ\gamma and β\beta:

y=γVar[x]+ϵ x+(β−γ E[x]Var[x]+ϵ)y = \frac{\gamma}{\sqrt{\mathrm{Var}[x]+\epsilon}}\,x + \left(\beta - \frac{\gamma\,\mathrm{E}[x]}{\sqrt{\mathrm{Var}[x]+\epsilon}}\right)
(7)

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 m/(m−1)m/(m-1) 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, dbeta

Why 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 a>0a > 0 and every xix_i in the batch is multiplied by aa, so the mean and standard deviation scale by aa too and the normalized output does not change:

BN(Wu)=BN((aW)u),∂ BN((aW)u)∂u=∂ BN(Wu)∂u,∂ BN((aW)u)∂(aW)=1a⋅∂ BN(Wu)∂W\mathrm{BN}(Wu) = \mathrm{BN}\big((aW)u\big), \qquad \frac{\partial\,\mathrm{BN}((aW)u)}{\partial u} = \frac{\partial\,\mathrm{BN}(Wu)}{\partial u}, \qquad \frac{\partial\,\mathrm{BN}((aW)u)}{\partial (aW)} = \frac{1}{a}\cdot\frac{\partial\,\mathrm{BN}(Wu)}{\partial W}BN(Wu)=BN((aW)u),∂ BN((aW)u)∂u=∂ BN(Wu)∂u,∂ BN((aW)u)∂(aW)=1a⋅∂ BN(Wu)∂W\begin{gathered} \mathrm{BN}(Wu) = \mathrm{BN}\big((aW)u\big), \\ \frac{\partial\,\mathrm{BN}((aW)u)}{\partial u} = \frac{\partial\,\mathrm{BN}(Wu)}{\partial u}, \\ \frac{\partial\,\mathrm{BN}((aW)u)}{\partial (aW)} = \frac{1}{a}\cdot\frac{\partial\,\mathrm{BN}(Wu)}{\partial W} \end{gathered}
(8)

The gradient passed to the layer below does not depend on the weight scale, and the gradient on the weights shrinks as 1/a1/a: 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 WW is scaled, its gradient has no component along WW and is perpendicular to it. A gradient step perpendicular to WW can only lengthen it; by Pythagoras, with ∇\nabla the gradient and η\eta the learning rate:

∥W−η∇∥2=∥W∥2+η2∥∇∥2\|W - \eta\nabla\|^2 = \|W\|^2 + \eta^2\|\nabla\|^2

A step of length η∥∇∥\eta\|\nabla\| perpendicular to a vector of length ∥W∥\|W\| turns it by an angle of about η∥∇∥/∥W∥\eta\|\nabla\|/\|W\|, where ∥∇∥\|\nabla\| itself is proportional to 1/∥W∥1/\|W\|. The direction, the only thing the loss depends on, changes at an effective rate of η/∥W∥2\eta/\|W\|^2. A learning rate that is too large makes a big step, which lengthens WW, 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 ww, with the best direction dashed. At η=1.5\eta = 1.5 from ∥w∥=0.5\|w\| = 0.5, the first step overshoots, lengthens ww to 1.63, and cuts the effective step from 6.0 to 0.57, after which the angle converges. Push η\eta to 8: one step takes ∥w∥\|w\| from 0.5 to 8.26, the effective step drops to 0.117, and the descent still converges, slowly. Then try a small η\eta with a large starting ∥w∥\|w\|, where it barely moves.

Figure 6 · larger weights, smaller steps
step 40
1.50
0.50
Weight plane of a scale-invariant unit: the loss is constant along rays and lowest along the dashed ray (brighter wedges have higher loss). The path is plain gradient descent. Every step is perpendicular to ww, so ∥w∥\|w\| grows each step and the effective step η/∥w∥2\eta/\|w\|^2 in the readout shrinks. Play or scrub the 40 steps; change η and the starting norm.

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 κ\kappa is stable only while the step size is below 2/κ2/\kappa. The two toy one-parameter landscapes below share a learning rate; the left one has high curvature, the right one low.

Figure 7 · a higher rate the smooth landscape can take
lr = 0.45
Two one-parameter loss curves descended at the same learning rate. The high-curvature curve (left) overshoots and diverges at rates the smooth curve (right) still descends. At the top of the slider both diverge. These are illustrative curves, not measured landscapes.

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.

Figure 8 · steps to a target accuracy
72.2%
Validation accuracy against training steps for Inception and four batch-normalized variants. Drag the dashed target line on the plot or use the slider; each crossing gives the steps to reach that accuracy, listed above the plot. The curves are smooth fits through the step counts and maximum accuracies in the paper's Figure 3 table, not training logs; BN-x5-Sigmoid's rise rate is illustrative.

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 ℓ1\ell_1, ℓ2\ell_2 or ℓ∞\ell_\infty 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 ℓ1\ell_1 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.

Provenance Verified against primary literatureHow we verify
Santurkar et al. (2018)Noise injected after every BN layer (non-zero mean, non-unit variance, changing each step) barely hurts training; under a gradient-based definition BN may not reduce internal covariate shift at all. BN does make the loss and its gradients smoother (better Lipschitz and beta-smoothness), and l1, l2 and l-infinity normalizations help comparably.
Yang et al. (2019)Disproves the Sec. 3.3 conjecture that BN keeps layer-Jacobian singular values near 1: at initialization, in the infinite-width limit, BN pushes them away from 1 and gradients explode with depth.
Wu & He (2018) · Ioffe (2017)Not in the paper: ResNet-50 ImageNet error with BN rises from 23.6% at 32 images per GPU to 34.7% at 2; Group Norm stays at 24.1%. Batch Renormalization is the author’s own follow-up for small or non-i.i.d. batches.
PyTorch · Keras sourceAlgorithm 2 averages batch statistics after training. PyTorch (torch/nn/modules/batchnorm.py) keeps a running average, momentum 0.1, of the unbiased per-batch variance; Keras (keras/src/layers/normalization/batch_normalization.py, moving-statistics update) keeps one of the biased variance, momentum 0.99, with no m/(m-1).
Russakovsky et al. (2014), Table 9The 5.1% human top-5 error is one trained annotator (A1, 1500 test images); a second annotator with less training (A2, 258 images) scored about 12.0%.
Shimodaira (2000)Origin of “covariate shift”, a change in the input distribution between training and test, which the paper extends to a network’s internal layers.
Glorot & Bengio (2010)The initialization paper the BN paper cites for careful initialization. The BN paper prints the author order reversed, as “Bengio & Glorot”.
correctionThe mechanism in the title, internal covariate shift, is the paper’s motivation and not an established explanation: Santurkar et al. (2018) re-injected large, changing distribution shifts after every BN layer and training was almost unaffected, and they measured no reliable reduction of internal covariate shift by BN. This page teaches the operation as the paper specifies it and gives the loss-smoothing account alongside. The Sec. 3.3 claim that BN keeps Jacobian singular values near 1 is the paper’s own hedged conjecture, and Yang et al. (2019) showed the opposite at initialization. “Exceeds the estimated accuracy of human raters” means one trained annotator’s 5.1% top-5 estimate; a second annotator scored about 12%. The paper cites Glorot & Bengio (2010) with the author order reversed. Kept on purpose, not errors: training normalizes with the biased (÷m) batch variance and inference uses the unbiased m/(m−1) estimate.

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

  1. 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.
  2. 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.
  3. The Section 3.3 conjecture, disproved at initialization: Yang, Pennington, Rao, Sohl-Dickstein & Schoenholz, A Mean Field Theory of Batch Normalization (ICLR 2019).
  4. 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).
  5. 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.
  6. 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).
  7. 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.