datarekha

Dropout, BatchNorm, LayerNorm

The three regularization and stabilization tricks every modern network uses — what each does, why it works, and when to reach for which.

7 min read Intermediate Deep Learning Lesson 14 of 28

What you'll learn

  • Why dropout works (and what it actually does)
  • The difference between batch norm and layer norm — and why transformers picked layer norm
  • When you can skip these entirely

Before you start

Three techniques show up in almost every modern deep network: dropout, batch normalization, and layer normalization. They solve different problems but are easy to confuse. Here’s what each one actually does and when to use it.

Dropout — averaging over subnetworks

At training time, dropout randomly zeros out a fraction p of activations (say 10–50%). At test time (inference), it does nothing — all neurons are active. A common mistake is forgetting model.eval(), which leaves dropout on and makes predictions non-deterministic.

import numpy as np

rng = np.random.default_rng(42)

def dropout(x, p, training=True):
    if not training or p == 0:
        return x
    # Inverted dropout: scale by 1/(1-p) so expected magnitude is unchanged
    mask = (rng.random(x.shape) > p).astype(x.dtype)
    return x * mask / (1 - p)

x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0])
print("input:        ", x)
print("dropout p=0.5:", dropout(x, 0.5, training=True))
print("dropout p=0.5:", dropout(x, 0.5, training=True))   # different mask each call
print("eval mode:    ", dropout(x, 0.5, training=False))
input:         [1. 2. 3. 4. 5. 6. 7. 8.]
dropout p=0.5: [ 2.  0.  6.  8.  0. 12. 14. 16.]
dropout p=0.5: [ 0.  0.  0.  8. 10. 12.  0.  0.]
eval mode:     [1. 2. 3. 4. 5. 6. 7. 8.]

Two things to notice:

  1. The mask changes every call. Each training step sees a different “thinned” network. You’re effectively training an ensemble of exponentially many subnetworks, all sharing weights.
  2. Survivors get scaled up by 1/(1-p). This keeps the expected activation magnitude the same as without dropout — so you don’t need to change anything at inference time.

Why it regularizes: a feature can’t rely on any single co-adapted upstream feature (it might be dropped). The network spreads useful work across many features — more robust representations.

Dropout: random neurons off in training, all on at inferenceTraining (p ≈ 0.5)Inference (all on)survivors are scaled by 1/(1−p) so the expected output is unchanged

Batch normalization — normalize per minibatch

BatchNorm normalizes each feature channel across the batch dimension: subtract the batch mean, divide by the batch std, then apply a learnable scale + shift.

y = γ · (x − μ_batch) / sqrt(σ²_batch + ε) + β

It was the breakthrough that made deep CNN training stable in 2015. Two big advantages:

  • Activations stay roughly mean-0, variance-1 throughout the network.
  • You can use much higher learning rates without divergence.

Two big downsides:

  • Different behavior in train vs eval mode. During training, you normalize with batch statistics. At eval, you use running averages accumulated during training. This means batch size affects your results.
  • Awful for small batches. With batch size 1 or 2, batch statistics are noisy. With batch size 8, they’re still iffy.

BatchNorm is still dominant in vision CNNs (ResNet, ConvNeXt). It’s mostly out of fashion in transformers and small-batch training.

Layer normalization — normalize per sample

LayerNorm normalizes each sample across the feature dimension:

y = γ · (x − μ_features) / sqrt(σ²_features + ε) + β

The key difference: no dependence on other samples in the batch. Same behavior at train and eval. Works with batch size 1. Doesn’t care if your minibatch is small.

import numpy as np

# (batch, features) = (3, 4)
x = np.array([
    [1.0, 2.0, 3.0, 4.0],
    [10.0, 0.0, 5.0, 5.0],
    [-1.0, -2.0, -3.0, -4.0],
])

# LayerNorm: normalize each ROW (across feature axis)
mean = x.mean(axis=-1, keepdims=True)
std = x.std(axis=-1, keepdims=True) + 1e-5
layer_norm = (x - mean) / std

# BatchNorm: normalize each COLUMN (across batch axis)
mean_b = x.mean(axis=0, keepdims=True)
std_b = x.std(axis=0, keepdims=True) + 1e-5
batch_norm = (x - mean_b) / std_b

print("LayerNorm (each row mean≈0, std≈1):")
print(layer_norm.round(2))
print("BatchNorm (each col mean≈0, std≈1):")
print(batch_norm.round(2))
LayerNorm (each row mean≈0, std≈1):
[[-1.34 -0.45  0.45  1.34]
 [ 1.41 -1.41  0.    0.  ]
 [ 1.34  0.45 -0.45 -1.34]]
BatchNorm (each col mean≈0, std≈1):
[[-0.49  1.22  0.39  0.58]
 [ 1.39  0.    0.98  0.83]
 [-0.91 -1.22 -1.37 -1.41]]

Same operation, different axis. The axis choice changes everything:

BatchNormLayerNorm
Normalizes acrossbatch axisfeature axis
Train ≠ Eval?yes (uses running stats)no
Works with batch=1?noyes
Sensitive to batch size?yesno
Used inCNNsTransformers, RNNs

RMSNorm — the modern variant

Modern LLMs increasingly use RMSNorm — LayerNorm without the mean subtraction:

y = γ · x / sqrt(mean(x²) + ε)

Slightly cheaper (no mean, no bias), empirically just as good — and now the default in essentially every open LLM (Llama, Mistral, Qwen, Gemma, DeepSeek). Where it sits relative to the residual connection (pre-norm) is covered in inside the transformer block.

Putting it in PyTorch

# CNN: BatchNorm after conv, before activation
nn.Sequential(
    nn.Conv2d(64, 128, 3, padding=1),
    nn.BatchNorm2d(128),
    nn.ReLU(),
    nn.Dropout(0.1),
)

# Transformer block: LayerNorm in pre-norm position (modern standard)
nn.Sequential(
    nn.LayerNorm(d_model),
    nn.Linear(d_model, d_ff),
    nn.GELU(),
    nn.Linear(d_ff, d_model),
)

model.train() and model.eval() flip dropout and batch-norm’s behavior. Forgetting to call model.eval() before inference is a classic bug — predictions become non-deterministic and BatchNorm uses the wrong statistics.

In one breath

  • Dropout randomly zeros a fraction p of activations in training (off at inference), scaling survivors by 1/(1−p) — it trains an ensemble of subnetworks so no feature can lean on a single co-adapted neighbor.
  • It’s standard for fine-tuning and smaller models but often near-zero in large LLM pretraining, which is data-bottlenecked, not overfitting.
  • BatchNorm normalizes each feature across the batch — great for vision CNNs and high learning rates — but differs train vs eval and breaks on tiny batches.
  • LayerNorm normalizes each sample across its features — no batch dependence, same in train and eval, works at batch size 1 — which is why transformers use it.
  • Modern LLMs use RMSNorm (LayerNorm minus the mean-subtraction): cheaper, just as good. Always call model.eval() before inference, or dropout and BatchNorm misbehave.

Quick check

Quick check

0/2
Q1You run inference with `model.train()` left on. What goes wrong?
Q2Why do transformers use LayerNorm instead of BatchNorm?

Sign in to track your progress

Completed lessons, your XP, level, and streak save to your account — it's free and takes a few seconds.

Practice this in an interview

All questions
What is batch normalisation, and why does it help training?

Batch normalisation normalises each feature across the mini-batch to zero mean and unit variance, then applies learnable scale and shift parameters. It stabilises internal activation distributions — reducing internal covariate shift — which allows higher learning rates, reduces dependence on careful weight initialisation, and provides mild regularisation through the noise in batch statistics.

What is data augmentation in computer vision and which techniques are most effective?

Data augmentation artificially expands the training set by applying label-preserving transformations to existing images, improving generalisation and regularisation without collecting more data. Geometric transforms (flip, crop, rotation) and colour jitter are universally effective; stronger methods like CutMix, MixUp, and RandAugment consistently improve accuracy on top of basic augmentation.

How does dropout work, and why must it behave differently during training and inference?

Dropout randomly zeroes each neuron's output with probability p during training, forcing the network to learn redundant representations and preventing co-adaptation of neurons. At inference, dropout is disabled and all neurons are active — but to keep expected activations the same as during training, outputs are scaled by 1/(1−p). Forgetting to switch modes produces incorrect, noisy predictions.

What is early stopping, and how does it prevent overfitting?

Early stopping monitors validation loss after each epoch and halts training when it has not improved for a set number of epochs (the patience). It prevents the model from memorising training data past the point of best generalisation, acting as a free regulariser that requires no change to the model or loss function.

What is L2 regularisation (weight decay), and how does it reduce overfitting?

L2 regularisation adds a penalty equal to the sum of squared weights multiplied by a coefficient λ to the loss function, which encourages the optimiser to keep weights small. This penalises large, specialised weights and pushes the model toward simpler solutions that generalise better. In SGD it is equivalent to shrinking weights by a constant factor each step (hence weight decay), though in Adam the two diverge — requiring AdamW for correct decoupled decay.

What causes overfitting in deep neural networks and how do you fight it?

Deep nets overfit when they memorize training examples rather than learning generalizable patterns — usually because the model has far more parameters than the signal in the data can constrain. The fix is a layered defence: regularization, data augmentation, early stopping, and architecture choices.

Why does training loss keep falling while validation loss rises?

This divergence is the signature of overfitting: the model has enough capacity to memorise training-set specifics — noise, label errors, dataset-specific patterns — that do not generalise. Training loss measures fit to what has already been seen; validation loss measures generalisation to held-out data. As the model memorises rather than learns structure, it scores better on training data and worse on everything else.

What regularization techniques do you know for deep networks, and how do they prevent overfitting?

Common techniques include L1 and L2 weight penalties, dropout (randomly zeroing activations), early stopping, data augmentation, and label smoothing. They reduce overfitting by constraining model capacity or adding noise so the network cannot memorize the training set.

Related lessons

Explore further

Skip to content