KLQ: Geometry-aware LLM quantization, per-direction bit allocation priced by measured KL divergence given injected perturbation.
Several investigations into the geometry of LLM embedding spaces have found their activation space to be extremely anisotropic: a few fixed features consistently spike in magnitude. I confirm this in the eigendecomposition: past a certain layer, one direction dominates the covariance. This makes uniform quantization fragile, as it spends its resources evenly in a naturally uneven space. Random-rotation-based quantizers (QuaRot, QuIP#, SpinQuant…) try to fix this by making the space truly even before quantizing. In contrast, KLQ takes advantage of the model's geometry. For every weight matrix, it pinpoints the important directions by eigendecomposing the covariance matrix of activation samples from a calibration set, then perturbing activations along each direction and measuring the KL divergence from the original model's output distribution to the perturbed one. A causal measure of how important each direction is. KLQ then assigns bits per direction by water-filling, the provably optimal allocation under this model. Prior methods that used PCA to identify important directions either sorted them by variance and applied two-tier quantization regimes (CoQuant) or used this information to flatten the directions further (ResQ, SpinQuant...)
The per-direction quantizer is an interchangeable backend, and this repo ships two deliberately simple ones (uniform-grid RTN and a two-book additive VQ). Stronger codes such as lattices (QuIP#, NestQuant), trellises (QTIP), learned codebooks (AQLM, VPTQ) are drop-in replacements on this axis and orthogonal to our claim. Likewise, learned rotations (SpinQuant, ReSpinQuant) and error-compensating rounding (GPTQ, LDLQ) address the coordinate and rounding axes respectively, not the allocation axis KLQ studies. KLQ remains training-free at the cost of one forward pass per direction per matrix per layer. KLQ-RTN and KLQ-VQ both use FP16 64-sized grouping (taken into account for bpw calculations) and differ in grid-assignment method, RTN uses a uniform grid while VQ uses a additive vector quantization with d=8 and 256 levels.
| Effective W/A/KV | Qwen 2.5 0.5B (Wikitext-2 PPL) | Source | |
|---|---|---|---|
| FP16 | 16/16/16 | 13.07 | Own measure matchesCoQuant's and ResQ's number |
| RTN | 4/4/4 | 23204.3 | |
| QuaRot | 4/4/4 | 204.10 | CoQuant's rerun (consistent w/ ResQ's 219.9) |
| QUIK | 4/4/4 | 38.6 | ResQ's paper |
| ResQ | 4/4/4 | 29.6 | ResQ's paper |
| KLQ-RTN | 4/4/4 | 21.07 | |
| KLQ-RTN | 4/16/16 | 15.9 | |
| ResQ | 4.5/4.5/4.5 | 18.19 | CoQuant rerun |
| CoQuant | 4.5/4.5/4.5 | 17.76 | CoQuant |
| KLQ-RTN | 4.5/4.5/4.5 | 16.33 | |
| KLQ-RTN | 4.5/16/16 | 14.34 |
| Effective W/A/KV | Llama 3.2 1B (Wikitext-2 PPL) | Source | |
|---|---|---|---|
| FP16 | 16/16/16 | 9.75 | |
| QuaRot | 4/4/4 | 14.59 | ReSpinQuant's paper |
| SpinQuant | 4/4/4 | 13.52 | SpinQuant's paper |
| ReSpinQuant | 4/4/4 | 13.09 | ReSpinQuant's paper |
| KLQ-VQ | 4/4/4 | 13.36 | |
| KLQ-VQ | 4/16/16 | 11.56 | |
| QUIK | 4.5/4.5/4.5 | 21.8 | ResQ paper |
| ResQ | 4.5/4.5/4.5 | 12.4 | ResQ paper |
| CoQuant | 4.5/4.5/4.5 | 11.6 | CoQuant paper |
| KLQ-VQ | 4.5/4.5/4.5 | 11.45 | |
| KLQ-VQ | 4.5/16/16 | 10.52 |
The whole Qwen 2.5 0.5B pipeline, including the sampling from each layer, the eigenvalue decomposition, the KL damage measurements using 4 windows and 512 tokens per window, took ∼5 hours to compute on an RTX 3090. This same pipeline for Llama 3.2 1B took ∼10 hours on the same hardware.
Given a transformer model
Each matrix
In a transformer model
Given this disturbed model
The price then will be
If we treat each direction as an information transmission channel and assume directions distort independently we can use the water-filling algorithm to optimally allocate the bit width of each channel using
For the quantization itself we use 2 methods:
- KLQ-RTN uses a simple RTN with
$b_{min}=3$ and$b_{max} = 12$ , 64-sized grouping which adds 0.25bpw to the final quantization numbers. - KLQ-VQ uses additive vector quantization with 2 codebooks,
$d=8$ and 256 levels, this applies only to directions quantized below 2.5 bits. Similarly we use 64-sized grouping and$b_{min}=2$ .
These are deliberately simple choices as the quantization acts as an interchangeable backend, the method only applies to direction priorization and bit-width allocation. While quantizing we also reestimate the eigenbases per block under the already quantized upstream while KL price remain fixed.
For the KV-cache and activations we use the same procedure. Activations are sampled from the input of the MLP and the attention (post and res spaces), the KV is sampled from each layer and head, using a different eigenbasis per head, with the first 4 tokens assumed as sink and kept at full precision.
First of all, the study of the geometry of the model confirms the massive activations,
Most allocation-axis methods use variance as a measure of the importance of a direction. Analyzing variance and causal KL damage turns out the correlation between these two vary wildly, mainly depending on the space we are analyzing within the layer. Interestingly, this correlation is mostly the same, not only within spaces of different layers of the same model, but among different models.
The following table shows the average Spearman coefficient of
| Space | Qwen 2.5 0.5B | Llama 3.2 1B |
|---|---|---|
| QKV | +0.458 | +0.460 |
| Residual stream | +0.871 | +0.833 |
| Post-Attention residual | +0.953 | +0.947 |
| Context Space | +0.769 | +0.717 |
| MLP-in | +0.887 | +0.781 |
| MLP-up (int)* | +0.964 | +0.917 |
*For int, computational tractability on a 3090 required measuring only the top ~20% of directions by eigenvalue, plus a random tail sample. Since KL–variance agreement is strongest at the top of the spectrum, the full-spectrum coefficient would likely be lower.
The following figures plot put each direction in each space of a specific layer of the Qwen 2.5 0.5B model and the Llama 3.2 1B model respectively:
This means that for certain spaces the variance-monotonicity of some directions implies KL-monotonicity of those same directions so ranking by variance would be an efficient heuristic for these spaces (res, post, int) while failing for the others (qkv, ctx). This would solve the problem of finding the most to least important directions, but KLQ not only finds important directions, it also uses how important each direction is related to the rest to assign a bit-width via waterfilling. Turns out that even if the rankings were perfectly monotone with each other, waterfilling with variance would be worse than waterfilling with KL since both measures have very different distributions. KL is typically either more concentrated or more spread out than variance, depending on the space, the following images show the first 512/1024 directions of a few spaces of different layers from Qwen 2.5 0.5B and Llama 3.2 1B.
So, even if
| Method | Quantization | Qwen 2.5 0.5B | Llama 3.2 1B |
|---|---|---|---|
| FP16 | 16/16/16 | 21.82 | 16.94 |
| KLQ-RTN-KL | 4/16/16 | 26.34 | 18.87 |
| KLQ-VQ-KL | 3.5/16/16 | 33.23 | 24.31 |
| KLQ-RTN-Variance | 4/16/16 | 34.45 | 21.55 |
| KLQ-VQ-Variance | 3.5/16/16 | 42.58 | 34.52 |
| Uniform-RTN | 4/16/16 | 44.14 | 627.77 |
KLQ-x-KL uses
Several experiments with lower quantizations have found that the geometry of the model changes significantly as it is actively being quantized. Remeasuring res and post's
| Method | Llama 3.2 1B |
|---|---|
| KLQ-VQ-KL with stale |
|
| KLQ-VQ-KL with fresh |
92.33 |
| KLQ-VQ-Variance with fresh |
1002 |
| KLQ-VQ-KL with fresh |
60.98 |
| + first 4 as activation sink + extended scale floor | 37.13 |
| A3 alone on fp16 weights | 22.72 |
| ReSpinQuant's 3/3/3 | 49.90 |
More experiments on low-bit quantizations reveal how KLQ exhibits superadditive PPL increases that don't follow the usual rule:
| Quantization | Llama 3.2 1B Wikitext-2 PPL | Expected ppl |
|---|---|---|
| 16/3/3 | 23.68 | 29 |
| 3/3/3 | 161.98 | 63 |
| 3/16/3 | 62.31 | 33.6 |
| 16/3/16 | 22.72 | |
| 16/16/3 | 12.5 | |
| 3/16/16 | 26.21 |
We hypothesize this might happen because each forward pass for remeasuring
Overall KLQ proposes a new paradigm for 2 out of the main 4 axes of quantization: Allocation and Basis based on information theory and causally measured damage, while leaving room for composition on the Rounding and Codebook parts of the quantization with other methods such as QuIP# or NestQuant.
As of now this project has several limitations, from most important to least important:
- Better codebooks: KV3 alone is benign (12.5) and A3/KV3 is sub-additive, but on W3-damaged weights KV damage becomes superadditive (W3/KV3 = 62 vs 26 expected and even KV4 doesn't fully recover). Fresh geometry and prices are already applied here so stale geometry shouldn't be a problem. The most promising attack is therefore a cleaner W3 (better codebook), which removes the interaction's cause, plus asymmetric K/V budgets (--k_avg/--v_avg implemented, mostly untested).
- Better rounding: As I mentioned, this repo ships with only VQ and RTN methods for quantizing, other methods such as GPTQ/LDLQ might push the perplexity numbers lower though theoretically in the measured eigenbasis the activation Hessian is diagonal, so GPTQ's cross-dimension error compensation largely degenerates to RTN. Whether compensation in a different basis can still help KLQ-allocated bits is an open research question.
-
Computational cost: Right now the only optimization made on computing
$KL_i$ is using only the top 20% on the massive int space and taking a small sample off the 80% tail. Theoretically, it'd be possible to approximate$KL_i$ analytically for most spaces given only$KL_i$ for res though this goes entirely untested. - Scaling: Theoretically, bigger models have more redundant geometry so this might work in KLQ's benefit, though modern models are trained specifically to eliminate this redundant geometry so that might work against KLQ. Further testing with both bigger and more modern models is needed. One proposed experiment is to apply KLQ to the models introduced in "Outlier-Safe Pre-Training for Robust 4-Bit Quantization of Large Language Models" which provides two different models (both available on HuggingFace), one trained classically which exhibits the uneven space, and another one trained in an outlier-safe regime which exhibits a naturally even space, if the hypothesis made by KLQ are true then the outlier-safe model should benefit from KLQ much less than the classically trained model.
- Real benchmarks: While perplexity is a good proxy for the degradation of a model under quantization a bundle of real benchmarks is still to be run.
- Packed kernels for real quantization: This is not a limitation of the method itself but more so of this repo, currently we use "fake" quantization in which the numbers are rounded realistically but the memory and computational footprint of inference is the same as that of a FP16 model. This is not a big problem since KLQ for now is more a of a theoretical framework.
To quantize a model you can use the provided pipeline ( given the model is Llama-style: MoEs and other architectures go untested and will most likely throw errors), first register the model in config.py. This is the Llama 3.2 1B run:
"llama3_1b": dict(
hf="unsloth/Llama-3.2-1B",
tag="llama3_1b",
NB=16,
D=2048, DI=8192,
H_KV=8, HEAD_DIM=64,
VOCAB=128256,
VAL_DTYPE="uint32",
VAL_BIN=os.path.join(ROOT, "data", "val_llama_1b.bin"),
),
Then take a sample from the calibration dataset:
python stage0_pretokenize.py --model llama3_1b --preset wikitext2 --tokens 4000000
You can also load a local .parquet file or a HuggingFace dataset:
python stage0_pretokenize.py --model llama3_1b --parquet dump.parquet
python stage0_pretokenize.py --model llama3_1b --hf <dataset> --split train --field text
Then stage 1 runs the samples through the model and captures the hidden states directly outputting the eigendecomposition of each space of each layer into spaces_{model}.pt = {space: {"mu": (NB,d), "evals": (NB,d), "evecs": (NB,d,d)}}, this file is usually several GBs.
python stage1_cache.py --model llama3_1b --nwin 8 --seq 512 --pb 8 --wikitext
Stage 2 is the actual causal KL measurement, this is the most compute intensive part of the pipeline. It will output one sens_{space}_{model}.pt file per space. By default if the space that's being probed has more than 2048 dimensions it will probe only the top 1024 by variance and then a random sample of 256 from the rest. You can force the model to probe all directions using the --full flag. You can control the topk and tail directions with --topk int and --tail int flags.
python stage2_sens.py --model llama3_1b --spaces res,qkv,ctx,mlp,int --full --wikitext
Stage 3 is not necessary for the quantization but it's a useful analysis tool, after running stage 2 you can analyze the model's space's KL profile, eigenspectrum and how they relate layer by layer via the Spearman's coefficient.
python stage3_read.py --model llama3_1b --spaces res
Stage 4 is the actual quantization process, weight averages should be lowered 0.25bpw to compensate for the 64-grouping. After quantization it will show the real effective BPW. w_avg might require finetuning from your part to get to the desired amount when using low bits and --vq. To quantize RTN-mode the model to 4/4/4 and evaluate on wikitext:
python stage4_quantize_wakv.py --model llama3_1b --w_avg 3.75 --kv_avg 4.0 --a_avg 4.0 --wikitext
There are many flags, to learn what each one does and recreate different experiments from the findings, run:
python stage4_quantize_wakv.py --help




