- Key idea
- Vector quantization with codebooks (additive and lattice codebooks), and ternary weights trained from scratch (BitNet b1.58)
- Real world
- A GIF image can only use 256 colours. A fixed palette (every combination of a few reds, greens and blues) wastes most of its slots on colours the picture never uses; a palette chosen for that picture, a codebook, looks far better with the same 8 bits per pixel.
- In an LLM
- AQLM stores Llama 2 70B at about 2 bits per weight by encoding each group of 8 weights as one index into a learned codebook of 65,536 vectors. BitNet b1.58 takes another route: a 2B-parameter model trained from scratch with every weight equal to −1, 0 or +1, whose weights take about 0.4 GB.
Why rounding fails at 2 bits
At 2 bits a weight has 4 possible values. However well you choose the scale, rounding each weight to one of 4 levels throws away most of what it held, and the errors pile up through dozens of layers. The GGUF scoreboard shows the result: perplexity is nearly unchanged down to about 4 bits per weight, then climbs steeply below 3.
Two observations open a way down:
- Weights aren’t independent. Neighbouring weights in a group have joint structure: some combinations are common, others never happen. Rounding each one separately can’t exploit that; quantizing them together can.
- Training can adapt. A model that is trained knowing its weights will be ternary learns to work with them. A model quantized after training never got that chance.
Vector quantization: codebooks
Vector quantization treats a group of weights as a single point in -dimensional space, and stores it as the index of the nearest entry in a codebook: a list of representative points. With a codebook of entries, each group costs bits, bits per weight.
The point of a codebook is that it can put its entries where the data is. A grid of independently rounded weights spends many of its points on combinations that never occur.
Try it
A fixed “3-3-2” palette gives 8 shades of red, 8 of green and 4 of blue: 256 colours spread evenly over the whole colour cube. A photo of a forest uses mostly greens and browns, so most of those 256 colours are wasted and the greens are banded. An adaptive palette (computed with the same k-means algorithm the widget uses) puts most of its 256 colours among the greens and browns. Same 8 bits per pixel, much better picture.
AQLM splits each weight row into groups of 8 weights. A group is stored as the sum of codewords from one or more codebooks (additive quantization). With one codebook of vectors of length 8, each group costs a 16-bit index: bits per weight, plus a small cost for the codebook and scales. Decoding a group means one table lookup. The codebooks are learned per layer to minimise the layer’s output error on calibration data, and then the whole model is fine-tuned briefly to recover more quality.
Lattice codebooks: QuIP# and llama.cpp’s i-quants
A learned codebook of 65,536 entries per layer is big and slow to search. QuIP# instead uses a codebook built from the E8 lattice, a famously efficient packing of points in 8 dimensions. Its structure means it doesn’t have to be stored in full and can be decoded quickly. QuIP# first applies randomized Hadamard rotations so the weights look like round, featureless Gaussian clouds, which is exactly what a lattice codebook fits best.
llama.cpp’s IQ2 and IQ3 formats borrow the idea. In IQ2_XXS, each group of 8 weights is stored as an 8-bit index into a fixed grid of 256 magnitude patterns drawn from the E8 lattice, plus 7 bits for the signs (the eighth sign is implied by keeping an even number of negatives), and a small scale per 32 weights: 2.06 bits per weight in total. See GGUF.
Ternary weights: BitNet b1.58
The most extreme route is to train with tiny weights from the start. BitNet b1.58 restricts every weight in its linear layers to . Three values carry bits of information, hence the name.
During training, a full-precision copy of the weights is kept and updated by the optimiser, but every forward pass uses the ternary version:
- Compute , the mean absolute value of the weight matrix.
- Divide every weight by , round to the nearest integer, and clip to .
- Gradients pass through the rounding with the straight-through estimator.
Activations are quantized to 8 bits per token. The payoff is that a matrix multiply with ternary weights needs no multiplications: each output is a sum of some inputs minus a sum of others, times one scale.
Try it on one row:
A row of four weights: . Their mean absolute value is . Dividing gives ; rounding and clipping gives . The output for input is
One addition, one subtraction and one multiply by the shared scale, instead of four multiplies. Weight 2 is simply skipped.
A ternary weight is like a three-way switch: off, forward, reverse. One switch can’t express much. But a room with thousands of switches, each set deliberately during design, can produce any lighting you want. That’s the BitNet bet: give a model enough ternary weights, train it knowing that’s all it has, and it can match a model with full-precision weights. Flipping a finished full-precision model’s weights to ternary, by contrast, destroys it.
Results so far: the BitNet b1.58 paper reports matching full-precision LLaMA-style models at 3B parameters and above on perplexity and zero-shot tasks, and the BitNet b1.58 2B4T release (2 billion parameters, 4 trillion training tokens) is competitive with full-precision open models of similar size, with weights taking about 0.4 GB. The catch: it has to be trained this way from the start, and fast inference needs special kernels (Microsoft’s bitnet.cpp), since GPUs have no ternary arithmetic.
Where this shows up
- Hadamard incoherence before lattice codebooks: rotations.
- The IQ formats in GGUF files: GGUF and llama.cpp.
- Training through rounding: PTQ vs QAT.
Vector quantization
For groups and a codebook , quantization is
A codebook is learned by k-means (Lloyd’s algorithm): assign each group to its nearest codeword, move each codeword to the mean of its group, repeat. Scalar quantization with levels per weight is the special case where is the grid .
Additive quantization (AQLM)
AQLM represents each group as a sum of codewords, one from each of codebooks of size :
The codebooks and codes are optimised to minimise the layer’s output error on calibration data, alternating beam search over codes with gradient updates of codebooks, followed by fine-tuning of the whole model.
BitNet b1.58 quantization
with . Activations use per-token absmax INT8.
In papers
- AQLM: Extreme Compression of Large Language Models via Additive Quantization (Egiazarian et al., 2024).
- QuIP# (Tseng et al., 2024): Hadamard incoherence plus the E8P lattice codebook.
- BitNet (Wang et al., 2023): 1-bit (binary) weights trained from scratch.
- The Era of 1-bit LLMs: All Large Language Models are in 1.58 Bits (Ma et al., 2024): ternary BitNet b1.58.
- BitNet b1.58 2B4T Technical Report (Ma et al., 2025): an openly released 2B ternary model trained on 4T tokens.