Normalization (LayerNorm, RMSNorm, BatchNorm)

Normalization rescales a layer's activations to a stable mean and scale so deep networks train faster. How BatchNorm, LayerNorm and RMSNorm differ.

Published Updated

On this page

Definition

Normalization is a step inserted between the layers of a neural network that rescales the numbers flowing through it — the activations — so that they have a controlled mean and scale instead of values that drift and grow as the network gets deeper. Concretely it takes a vector of activations, subtracts a mean and divides by a measure of spread, so the next layer always receives numbers centered near zero with a predictable magnitude.

That matters because depth is unstable without it. Each layer's output is the next layer's input, so a small tendency to grow compounds layer after layer until the numbers are large enough that gradients either explode or vanish and training stalls. Normalization interrupts that feedback: no matter what the previous layer produced, the next one sees a well-behaved range. Ioffe and Szegedy's 2015 batch-normalization paper is the sharpest illustration of the payoff — a normalized network reached the same accuracy as their Inception baseline in 14 times fewer training steps, and trained stably at 30 times the learning rate that drove the un-normalized network's parameters "to machine infinity". Normalization is not a nicety; it is what makes very deep and very wide networks trainable at all, and it is the most-used component in modern architectures that has no single agreed-upon form — which is why there are three of them worth knowing.

How It Works

Every normalization scheme is the same three-step recipe applied over a different set of numbers: compute a mean, compute a spread, then rescale. What changes between BatchNorm, LayerNorm and RMSNorm is which numbers you average over and whether you subtract the mean at all.

Take a single activation vector — the four outputs a small layer might produce for one input:

x = [2, 4, 6, 8]

Layer normalization works entirely within this one vector. First the mean:

mean = (2 + 4 + 6 + 8) / 4 = 5

Subtract it to get the deviations [-3, -1, 1, 3], then compute the variance (the mean of the squared deviations):

variance = (9 + 1 + 1 + 9) / 4 = 20 / 4 = 5 std = sqrt(5) ≈ 2.236

Dividing each deviation by that standard deviation gives the normalized vector:

x_hat = [-3, -1, 1, 3] / 2.236 = [-1.342, -0.447, 0.447, 1.342]

Those four numbers now have a mean of exactly 0 and a standard deviation of exactly 1, whatever the layer originally produced. A tiny constant ε (epsilon, around 1e-5) is added inside the square root so the division is safe when the spread is near zero; here it changes nothing at four decimals.

There is one more step. Forcing every layer's output to mean 0 and variance 1 would throw away information the network might want, so normalization ends with two learnable parameters per feature — a scale γ (gamma) and a shift β (beta) — giving y = γ · x_hat + β. The network can learn γ = std and β = mean to undo the normalization entirely if that turns out to be best, so normalization removes the instability without removing any representational power.

RMSNorm runs the same vector through a shorter recipe: it skips the mean subtraction and divides by the root mean square instead of the standard deviation. On the same x = [2, 4, 6, 8]:

rms = sqrt((4 + 16 + 36 + 64) / 4) = sqrt(30) ≈ 5.477 x_hat = [2, 4, 6, 8] / 5.477 = [0.365, 0.730, 1.095, 1.461]

Notice the output is not centered — its mean is 0.913, not 0 — because RMSNorm never subtracts the mean. It keeps only the re-scaling and drops the re-centering. That is the whole idea: computing one statistic (the RMS) instead of two (mean and variance). Zhang and Sennrich's 2019 paper reported this cut running time by 7 to 64 percent across models with no loss of accuracy, on the hypothesis that "re-centering invariance in LayerNorm is dispensable".

Batch normalization uses the identical mean-and-variance formula but averages over a different axis. Instead of normalizing one example's feature vector, it takes one feature and averages it across every example in the mini-batch. So for a batch of 64 images, BatchNorm computes 64-value means and variances, one pair per channel. This is the source of both its power and its problems: the statistics now depend on the other examples in the batch, and on how many there are.

Types

Three normalizers dominate practice, and they differ only in the axis they average over and whether they center.

  • Batch Normalization (BatchNorm) — normalizes each feature across the batch dimension. Because its statistics come from the whole mini-batch, training and inference behave differently: during training it uses the current batch's mean and variance, but at inference it uses a running average accumulated during training, since a single prediction has no batch to average over. Getting that train/eval switch wrong is a classic bug. It shines in convolutional networks for vision, where batches are large and fixed-size.
  • Layer Normalization (LayerNorm) — normalizes each example across its feature dimension, subtracting the mean and dividing by the standard deviation. Its statistics come from one example alone, so batch size is irrelevant and a batch of one behaves exactly like a batch of a thousand. This independence is why it, not BatchNorm, became standard in transformers and recurrent networks.
  • Root Mean Square Normalization (RMSNorm) — LayerNorm with the mean-centering removed, dividing only by the root mean square. It has one learnable parameter vector (γ) rather than two (no β), computes one statistic rather than two, and matches LayerNorm's accuracy while running faster.

Real-World Applications

Convolutional vision networks — BatchNorm. ResNet, Inception and the image classifiers that followed are built around BatchNorm between their convolutional and activation layers. Vision training uses large, fixed-size batches of images, exactly the regime BatchNorm was designed for, and its mild regularizing side-effect — each example's normalization is perturbed by the random other members of its batch — is a genuine bonus there.

The original Transformer and early large language models — LayerNorm. The 2017 "Attention Is All You Need" architecture, and GPT-2 and BERT after it, place LayerNorm around every attention and feed-forward sublayer. The switch away from BatchNorm was forced by the data: language comes in variable-length sequences and is generated one token at a time at inference, where a per-batch statistic is unstable or undefined. LayerNorm's per-token normalization sidesteps that entirely.

Recent large language models — RMSNorm. LLaMA and the Llama family, T5, and most large models trained since roughly 2020 use RMSNorm in place of LayerNorm. At the scale of hundreds of billions of parameters, a normalizer applied twice per layer across dozens of layers is run trillions of times during training, so shaving one statistic off each call — the change RMSNorm makes — is worth the wall-clock time it saves.

Key Concepts

Why BatchNorm breaks for sequences and small batches. BatchNorm's mean and variance are only as reliable as the batch they are estimated from. Shrink the batch — to the size of 2 or 4 that a large model's memory forces, or to the single example of online inference — and the statistics become noisy or, for a batch of one, undefined (a single number has zero variance). Sequences make it worse: padding variable-length inputs to a common length pollutes the per-feature averages with meaningless padding positions. LayerNorm and RMSNorm have neither problem because they never look across the batch; each token is normalized using only its own vector, so the result does not depend on batch size or on what the neighbours happen to be.

Pre-norm versus post-norm placement. Normalization in a transformer sits alongside a residual connection — the shortcut that adds a sublayer's input back to its output — and where you place it relative to that addition matters enormously. The original transformer is post-norm: it computes x + Sublayer(x) and then normalizes the sum. Modern models are almost all pre-norm: they normalize first and add the raw input back afterwards, as x + Sublayer(Norm(x)). The difference is that pre-norm leaves a clean, un-normalized identity path running the full depth of the network, so a signal can travel from the last layer to the first without being repeatedly rescaled. That makes deep pre-norm transformers trainable without the delicate learning-rate warmup that post-norm models need, which is why the field moved to it — at the cost of slightly worse final quality that larger models more than absorb.

Challenges

BatchNorm's train/inference gap is a real bug source. Because the layer uses batch statistics while training but stored running averages at inference, forgetting to switch modes (the model.eval() call in PyTorch) makes a model that scored well in training produce garbage predictions, or leaks information across a batch at test time. The two behaviours are the same layer computing different things, and nothing in the forward pass warns you.

Choosing the wrong normalizer for the data shape. BatchNorm on a language model with tiny batches, or LayerNorm bolted onto a convolutional vision network where BatchNorm's cross-batch regularization was doing real work, both underperform quietly — the network still trains, just worse, with no error to point at. The axis a normalizer averages over has to match where the redundancy in your data actually lives.

Placement interacts with the rest of the recipe. Post-norm transformers can fail to train at all without a carefully tuned learning-rate warmup, and swapping between pre-norm and post-norm changes which learning rates and initializations are safe. Normalization is not a drop-in module you can move around freely; its position is part of the architecture's stability budget.

Code Example

The whole of LayerNorm and RMSNorm fits in a few lines. This reproduces the worked example above exactly:

import numpy as np

def layernorm(x, gamma, beta, eps=1e-5):
    mu = x.mean()
    var = x.var()                        # population variance
    x_hat = (x - mu) / np.sqrt(var + eps)
    return gamma * x_hat + beta

def rmsnorm(x, gamma, eps=1e-5):
    rms = np.sqrt((x ** 2).mean() + eps)
    return gamma * (x / rms)

x = np.array([2.0, 4.0, 6.0, 8.0])
g, b = np.ones_like(x), np.zeros_like(x)

print("LayerNorm:", np.round(layernorm(x, g, b), 4),
      "mean", round(float(layernorm(x, g, b).mean()), 4))
print("RMSNorm:  ", np.round(rmsnorm(x, g), 4),
      "mean", round(float(rmsnorm(x, g).mean()), 4))

Running this prints:

LayerNorm: [-1.3416 -0.4472  0.4472  1.3416] mean 0.0
RMSNorm:   [ 0.3651  0.7303  1.0954  1.4606] mean 0.9129

The two lines make the one conceptual difference visible: LayerNorm's output is centered on zero because it subtracted the mean; RMSNorm's is not, because it only rescaled. Everything else — the learnable γ and β, the ε guard — is shared machinery.

Frequently Asked Questions

It rescales the activations flowing between layers so that each layer receives numbers with a stable mean and scale, rather than values that drift and blow up as the network gets deeper. That keeps gradients in a usable range, which lets you train with a much higher learning rate and far fewer steps.
BatchNorm computes its mean and variance across the batch dimension — over all the examples in a mini-batch for each feature — so its statistics depend on batch size and on the other examples. LayerNorm computes them across the feature dimension of a single example, so it is independent of batch size and of neighbouring examples, which is why transformers use it.
Language models process variable-length sequences, often with a batch size of one at inference, and BatchNorm's per-batch statistics are unstable or undefined in those conditions. LayerNorm and RMSNorm normalize each token's own vector, so they behave identically whether the batch holds one sequence or a thousand.
RMSNorm divides each activation vector by its root mean square and skips subtracting the mean that LayerNorm does. Removing that mean-centering computes one statistic instead of two; the 2019 paper measured 7 to 64 percent less running time with no loss of accuracy, which is why most recent large language models adopted it.
Post-norm (the original transformer) applies normalization after the residual addition; pre-norm applies it inside the residual branch, before the sublayer. Pre-norm keeps a clean identity path through the network, which makes deep transformers trainable without a learning-rate warmup, so nearly all modern models use it.

Continue Learning

Explore our use-case guides and prompts to deepen your AI knowledge.