Quantisation Grids, Scale and Zero Point
The affine map between floating point and integers, why granularity is the single most consequential choice, and how clipping and rounding errors trade against each other.
Quantisation is a change of number system, and almost everything that goes wrong with it goes wrong in the same place: a single scale factor is asked to cover a range it cannot cover. Getting the arithmetic right is easy. Deciding how many scale factors to use, and over which groups of numbers, is where the accuracy lives.
The affine map
An integer grid of \(b\) bits holds \(2^b\) levels. Mapping a real value \(x\) onto it requires a scale \(s\) and an integer zero point \(z\):
Symmetric quantisation fixes \(z = 0\) and uses a range centred on zero, so \(s = \max|x| / q_{\max}\). Multiplication becomes a plain integer multiply, which is why weights, whose distributions are roughly zero-centred, almost always use it.
Asymmetric quantisation lets \(z\) float, so the grid can cover a range that does not straddle zero. Post-ReLU activations, which are non-negative, waste half their levels under a symmetric scheme, so they use it. The cost is a cross term in the integer matmul: expanding \((q_w - z_w)(q_a - z_a)\) produces extra terms that must be folded into the accumulator, which is why asymmetric weight quantisation is less common than the accuracy argument alone would suggest.
Granularity is the real decision
Per-tensor uses one scale for an entire weight matrix. It is the cheapest and it fails on transformers, because a single outlier channel with values ten times larger than the rest forces \(s\) up, and every other channel then quantises into a handful of levels.
Per-channel uses one scale per output channel, which is free in the matmul because the scale factors out along the accumulation dimension. This is standard for weights and it costs one fp16 value per row.
Per-group subdivides each row further, typically into groups of 64 or 128 elements along the input dimension. It is what makes 4-bit weight quantisation viable, and its overhead is real: at group size 128 with an fp16 scale and a 4-bit zero point, the metadata adds roughly 0.16 bits per weight, so a nominally 4-bit model stores about 4.16 bits. At group size 32 that rises to about 0.6 bits, which is a sixth of the budget, and this is exactly why very small groups stop paying for themselves.
Activations are harder because their range depends on the input. Static quantisation calibrates scales once on a sample set; dynamic quantisation computes them per tensor at runtime, which is more accurate and adds a reduction pass per activation.
Two errors, pulled in opposite directions
Rounding error is bounded by \(s/2\) per element and shrinks as \(s\) shrinks. Clipping error appears when the true value lies outside the representable range and grows as \(s\) shrinks. Choosing \(s\) is choosing where to sit between them, and simply taking \(s = \max|x|/q_{\max}\), which eliminates clipping entirely, is usually the wrong answer: one outlier drags the scale up and imposes rounding error on every other value.
Calibration methods search for a clipping threshold that minimises a chosen error measure, typically the KL divergence between the original and quantised value distributions, or plain mean squared error. Percentile clipping at 99.9 percent is the crude version and is often within a fraction of a point of the searched optimum.
When it breaks
Outliers in transformer activations are not a tail, they are a structure. From roughly 6B parameters, specific hidden dimensions carry values one to two orders of magnitude larger than the rest, consistently across inputs, and they matter for accuracy. Clipping them destroys the model; keeping them destroys the scale. Mixed-precision decomposition, which keeps outlier dimensions in fp16, and rotation-based methods, which spread the outlier energy across dimensions before quantising, are the two families of response.
Quantising the wrong tensor is the common bug. Weights, activations, the KV cache and the accumulator are four separate decisions with different sensitivities. Weight-only quantisation with fp16 activations is nearly free in quality and only helps memory-bound decoding; quantising activations too is what unlocks integer tensor-core throughput and costs much more accuracy.
Perplexity is a poor detector. A 4-bit model can sit within a percent of its fp16 parent on perplexity and lose several points on multi-step reasoning or code generation, because those tasks compound small per-token errors. Evaluation has to include the task class you care about, measured on long outputs.
Rounding to nearest is not optimal. Nearest rounding is optimal per weight and not for the layer, because errors interact through the matmul. Methods that round adaptively while compensating on the remaining weights recover most of the gap at 4 bits and below, which is why the naive baseline collapses at bit widths where GPTQ-style methods still work.
16 flashcards for this concept
Click a card to reveal the answer.