Part IV · Applied concepts · Chapter 39
Quantisation
A trained model is billions of numbers, usually stored with 16 bits each. Quantisation stores them with fewer bits, 8 or 4, so the model takes less memory and often runs faster, at the price of small rounding errors. This chapter shows exactly how a weight is rounded, why one large weight can spoil its neighbours, and how much memory each choice saves.
Whether a model fits on a laptop, a phone or one GPU is mostly a question of bits per weight. Knowing the arithmetic lets you read a model card, predict the memory bill and know what quality checks to run.
Number formats
| Format | Bits | How the bits are used | Notes |
|---|---|---|---|
| fp32 | 32 | 1 sign, 8 exponent, 23 fraction | Training default for decades |
| fp16 | 16 | 1 sign, 5 exponent, 10 fraction | Largest value 65,504, so big values can overflow |
| bf16 | 16 | 1 sign, 8 exponent, 7 fraction | fp32's range with less precision; common for training |
| int8 | 8 | 256 whole numbers plus a shared scale | Close to 16-bit quality for many models |
| int4 | 4 | 16 whole numbers plus a shared scale | Needs care: per-group scales, smarter methods |
| NF4 | 4 | 16 levels placed to suit bell-shaped weights | Introduced with QLoRA (2023) |
Floating-point formats (fp, bf) keep their own exponent per number. Integer formats store whole numbers and one shared scale that turns them back into real values; that shared scale is where both the savings and the errors come from.
How a weight is quantised
Symmetric: pick a scale so the largest weight maps to the largest integer, divide, round, store the integer. To use it, multiply back.
Worked: weights −0.62, 0.10, 0.31, 1.27. For 8 bits the integers run from −127 to 127, so the scale is 1.27 / 127 = 0.01. Dividing gives −62, 10, 31, 127, all whole already, so nothing is lost. For 4 bits the integers run from −7 to 7 and the scale is 1.27 / 7 ≈ 0.1814:
| weight | weight / scale | stored integer | scaled back | error |
|---|---|---|---|---|
| −0.62 | −3.42 | −3 | −0.5443 | 0.0757 |
| 0.10 | 0.55 | 1 | 0.1814 | 0.0814 |
| 0.31 | 1.71 | 2 | 0.3629 | 0.0529 |
| 1.27 | 7.00 | 7 | 1.2700 | 0 |
Rounding is never off by more than half a step, so the worst possible error is scale / 2 ≈ 0.091.
Asymmetric: when the weights are not centred on zero, map the smallest weight to 0 and the largest to the top integer, and store a zero point as well. For the same four weights at 4 bits (integers 0 to 15): scale = (1.27 − (−0.62)) / 15 = 0.126, zero point = round(0.62 / 0.126) = 5, and the errors fall to 0.010, 0.026, 0.058 and 0.010: a mean of 0.026 instead of 0.053, because no levels are wasted below −0.62.
In symbols, symmetric with b bits: qmax = 2b−1 − 1, s = max|w| / qmax, q = round(w / s), ŵ = q · s, and |w − ŵ| ≤ s / 2.
Outliers and groups
The scale is set by the largest weight. Put one outlier of 6.0 among the four weights above and the 4-bit scale becomes 6 / 7 ≈ 0.857: now 0.10 and 0.31 both round to 0 and −0.62 becomes −0.857. One large value has erased its neighbours. Real models do have such outliers, which is why practical methods:
- use a separate scale per small group of weights (often 32 to 128), so an outlier spoils only its own group;
- keep the few outlier features in 16 bits (the idea behind LLM.int8(), 2022);
- choose rounding to minimise the error of each layer's output, not each weight (GPTQ, 2022), or protect the weights that matter most for the activations (AWQ, 2023).
Memory arithmetic
Memory for weights = parameters × bits per weight / 8 bytes. For a 7-billion-parameter model:
| Format | Sum | Weights |
|---|---|---|
| fp32 | 7 × 109 × 4 bytes | 28 GB |
| fp16 or bf16 | 7 × 109 × 2 bytes | 14 GB |
| int8 | 7 × 109 × 1 byte | 7 GB |
| int4 | 7 × 109 × 0.5 bytes | 3.5 GB |
| int4, one 16-bit scale per 128 weights | 4 + 16/128 = 4.125 bits | 3.6 GB |
Running the model needs more than the weights: the key and value cache grows with context length and with the number of requests in flight. Fewer bits also mean less data to move from memory for every token, which is often what limits speed.
Checking quality
Quantisation is a trade, so measure it: compare the quantised model against the original on your own tasks, not only on a general score such as perplexity. Small models and low bit counts lose more. A model quantised during training (quantisation-aware training) usually holds up better than one rounded afterwards.
Check the label against the file. A model name with "Q" or "int8" in it is a claim, not a measurement. Read the data type of the weight tensors and count bytes: the number of weights times the bits per weight, divided by 8, should match the file size. Worked: a file called "Q8" holds 100 million weights and is 200 MB. That is 2 bytes, or 16 bits, per weight; a true 8-bit file would be close to 100 MB. Check again whenever the library or the download source changes.
Ask what precision serves a hosted model. When you call a model through a provider, the provider decides how it is stored unless you say otherwise. Some gateways let you restrict a request to providers that serve at least a given precision (say 8-bit floating point or integer, or higher) and to refuse "unknown". A direct call to the model's maker usually carries no such setting, so there the provider decides.
Quantise 0.45, −0.25, 0.10, −1.0 to 4 bits, symmetric. Give the scale, the stored integers and the largest error.
Answer
Scale = 1.0 / 7 ≈ 0.1429. Divided: 3.15, −1.75, 0.70, −7, rounded to 3, −2, 1, −7. Scaled back: 0.4286, −0.2857, 0.1429, −1.0. Errors 0.0214, 0.0357, 0.0429, 0; the largest is 0.0429, within the bound 0.1429 / 2 ≈ 0.071.
Self-check
Why does bf16 suit training better than fp16?
It keeps fp32's 8 exponent bits, so large and small values do not overflow or vanish; it gives up fraction precision instead.
At 8 bits symmetric, the largest weight is 2.54. What is the scale?
2.54 / 127 = 0.02.
Why do per-group scales help with outliers?
An outlier sets the scale only for its own small group, so the other groups keep fine steps.
How much memory do the weights of a 70-billion-parameter model need at 4 bits?
70 × 109 × 0.5 bytes = 35 GB, plus a little for the scales.
Further reading
- A Visual Guide to Quantization article beginner
Maarten Grootendorst's illustrated tour of number formats, int8/int4, GPTQ, GGUF and more. - Overview (Hugging Face Transformers quantization docs) docs intermediate
Compares the quantisation backends Transformers supports and when to pick each. - LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale (2022) paper advanced
Shows outlier features break naive int8 and handles them separately to keep accuracy. - GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers (2022) paper advanced
One-shot 3 to 4-bit weight quantisation using approximate second-order information.
Free, checked on 2026-10-21. All resources for this chapter and 4 more.