Part XX — Embodied AI & Production Systems: VLA Robotics, High-Throughput Serving & MLOps · Chapter 5

Quantization (AWQ, GPTQ, GGUF & BitNet 1.58-bit)

Hook

A weight matrix stored as 32-bit floats moves through memory as 32-bit floats, every time it's used. Store it in 4 bits instead and there's four times less to move — but 4 bits only has 16 distinct values, so most weights can no longer be represented exactly. The question is how much that costs, and whether it's worth paying.

Intuition

-1.6 ÷ scale (0.40) → level -4 → reconstructed -1.60 — exact, zero error

Eight FP32 weights, one shared scale. Pick each one and watch it divide by the scale, round to the nearest integer level, and multiply back — sometimes landing exactly where it started, sometimes a little off.

Formalize

Post-training quantization (the family AWQ, GPTQ, and GGUF all belong to) picks one scale per group of weights, then stores each weight as a small signed integer level:

level(w)=round ⁣(ws)w^=level(w)s\text{level}(w) = \text{round}\!\left(\frac{w}{s}\right) \qquad \hat{w} = \text{level}(w) \cdot s
  • ww — the original FP32 weight.
  • ss — the shared scale for this group of weights.
  • level(w)\text{level}(w) — the weight's rounded 4-bit integer level, one shared FP32 scale away from being a real number again.
  • w^\hat{w} — the dequantized weight actually used at inference time.

A weight only survives round-tripping exactly when it was already a multiple of ss — everything else rounds to the nearest representable level and keeps the difference as error:

error(w)=ww^\text{error}(w) = w - \hat{w}
  1. The scale sets what's exact

    Levels only cover s{8,,7}s \cdot \{-8, \dots, 7\} for 4-bit — 16 evenly spaced values. Any weight in between rounds to whichever is closer.

  2. Compression comes from bit width, not from the scale

    Sixteen weights at 4 bits packed two-per-byte, plus one shared 32-bit scale for the whole group, is close to a flat 8× smaller than the same sixteen weights at 32 bits each — the smaller the group, the more that one shared scale's overhead matters.

Play

The same eight weights, both ways: four bytes each as FP32, versus packed 4-bit levels plus one shared scale. The compression is exact and predictable; the error is the price, and it's exactly as large as the rounding above made it — no more, no less.

Worked example
  1. The scale

    Largest-magnitude weight is 2.8-2.8; the top 4-bit level is 7. Scale s=2.8/7=0.4s = 2.8 / 7 = 0.4.

  2. Most weights round exactly
    • 1.6/0.4=4-1.6 / 0.4 = -4 exactly — level 4-4, dequantized back to 1.6-1.6
    • 2.8/0.4=7-2.8/0.4=-7 exactly
    • 2.0/0.4=52.0/0.4=5 exactly
    • 0.8/0.4=2-0.8/0.4=-2 exactly
    • 0.8/0.4=20.8/0.4=2 exactly
    • 0.4/0.4=1-0.4/0.4=-1 exactly

    All six land exactly on a level, zero error.

  3. Two weights don't
    • 0.5/0.4=1.250.5/0.4=1.25, rounds to level 11, dequantizes to 0.40.4 — off by 0.10.1
    • 1.3/0.4=3.251.3/0.4=3.25, rounds to level 33, dequantizes to 1.21.2 — off by 0.10.1

    It's 0.50.5 and 1.31.3 that land off-grid, each by exactly 0.10.1, giving a mean squared error of (0.12+0.12)/8=0.02/8=0.0025(0.1^2+0.1^2)/8=0.02/8=0.0025 across all eight.

Checkpoint

A fresh weight, 1.1, needs to be quantized with the same scale (0.40). Which 4-bit level does it round to?

Pick a level to try it
Summary
w^=round(w/s)s\hat{w} = \text{round}(w/s)\cdot s

AWQ, GPTQ, and GGUF all sit on top of this same round-trip — they differ in which weights they protect from rounding error. AWQ picks the scale per group to protect the small fraction of "salient" weights activations actually depend on most; GPTQ solves for the rounding order that minimizes the accumulated error layer by layer; GGUF is a storage format for these same integer-plus-scale representations, tuned for fast CPU and mixed-precision inference. All of them are managing the exact trade this chapter's formula makes visible: memory saved is proportional to bits saved, and error is exactly what's left after rounding to the nearest representable level. The next chapter puts a quantized model into an actual serving loop, where the KV-cache — not the weights — becomes the memory bottleneck.