Splits channels into groups and normalizes over within each sample, giving BatchNorm-like benefits without any batch dependence, the default for small-batch detection/segmentation.
Equation
For input with group index , let be the set of elements in group of sample :
where are per-channel affine parameters.
From scratch
import torch
from einops import rearrange
def group_norm(x, gamma, beta, groups, eps=1e-5):
# x: (n, c, h, w); gamma, beta: (c,)
xg = rearrange(x, "n (g k) h w -> n g (k h w)", g=groups)
mu = xg.mean(-1, keepdim=True)
var = xg.var(-1, keepdim=True, unbiased=False)
xg = (xg - mu) * torch.rsqrt(var + eps)
y = rearrange(xg, "n g (k h w) -> n (g k) h w", k=x.shape[1] // groups, h=x.shape[2])
return y * gamma.view(1, -1, 1, 1) + beta.view(1, -1, 1, 1)Notes
- recovers LayerNorm over ; recovers InstanceNorm.
- Identical behavior in train and eval: no running statistics.
- Requires ; is the usual default.
- See Normalization Comparison.