Quantization: Compressing Models to Integers

Reduce memory and bandwidth by storing weights/activations in low-bit integers (INT8/INT4) with careful scaling to limit accuracy loss.

Intermediate · Undergraduate mathematics · about 16 minutes

Reading map and next steps

Intuition

The idea in plain words, before the symbols.

When a large model generates text one token at a time for a small batch, each step reads every weight from memory but does only a little arithmetic per byte read. Speed is then limited by memory bandwidth, not by arithmetic, and moving fewer bytes can raise throughput, though the actual speedup depends on the kernels, the hardware, the batch size and which tensors are quantized.

Quantization stores weights, and sometimes activations, as low-bit integers such as INT8 or INT4, with a scale factor that maps the integers back to approximate floating-point values. Memory falls in proportion to the bits: a 70-billion-parameter model needs about 140 GB for 16-bit weights, 70 GB at 8 bits and 35 GB at 4 bits, before the scales, the activations and the KV cache are counted.

A central difficulty, especially for large language models, is outliers: a few large weights or activations force a large scale, which leaves too few integer levels for all the ordinary values (Dettmers et al., 2022).

Study prompts for this section: Intuition
Study prompts

Each button copies a prompt about this section to your clipboard, for an AI assistant you already use. Nothing is sent by this site.

Mathematics

Definitions, assumptions and the derivation.

Uniform quantization (per-tensor)

Given a tensor of weights with minimum wmin⁡w_{\min} and maximum wmax⁡w_{\max}, choose one step size for the whole tensor and round onto integer levels:

Δ=wmax⁡−wmin⁡2b−1,wq={clip ⁣(round ⁣(w−wmin⁡Δ),0,2b−1),Δ>0,0,Δ=0,w^=wqΔ+wmin⁡.\Delta = \frac{w_{\max}-w_{\min}}{2^b-1},\qquad w_q=\begin{cases} \mathrm{clip}\!\left(\mathrm{round}\!\left(\dfrac{w-w_{\min}}{\Delta}\right),0,2^b-1\right), & \Delta>0,\\ 0, & \Delta=0, \end{cases}\qquad \hat w=w_q\Delta+w_{\min}.

Here bb is the number of bits (8 for INT8, 4 for INT4), an integer from 1 to 16 in the code below, and wmin⁡w_{\min} and wmax⁡w_{\max} are the smallest and largest entries of a nonempty tensor of finite float32 values. This is an asymmetric (min–max) quantizer: the offset wmin⁡w_{\min} shifts the range, so integer level 00 stands for wmin⁡w_{\min} and level 2b−12^b-1 for wmax⁡w_{\max}. Integer-only schemes round the offset to an integer zero point ZZ and write r=S(q−Z)r = S(q - Z), so that the real value 0 is represented exactly (Jacob et al., 2018).

When every entry is equal (a single value, or a row of zeros), wmax⁡=wmin⁡w_{\max}=w_{\min} and the quotient (w−wmin⁡)/Δ(w-w_{\min})/\Delta would be 0/00/0. One level is then enough: wq=0w_q=0 and w^=wmin⁡\hat w=w_{\min} reproduce the tensor exactly. This branch is a definition chosen for that case, not a measured result.

The code below computes this definition in floating point. Three details matter:

  • Rounding. It computes the quotient (w−wmin⁡)/Δ(w-w_{\min})/\Delta in float64 and rounds it to the nearest integer, sending exact halves to the even integer, as np.round does. That rounds the computed quotient, which is not always the exact real one. At b=2b=2, the float32 entries [−1, −10−20, 1][-1,\,-10^{-20},\,1] give a computed quotient of exactly 1.51.5 for the middle entry, so it goes to level 22 (w^=1/3\hat w=1/3), although the exact nearest level is 11 (w^=−1/3\hat w=-1/3).
  • Endpoints. It keeps every reconstructed level inside [wmin⁡,wmax⁡][w_{\min},w_{\max}] and sets the top level to wmax⁡w_{\max} exactly. Without that step, for [−fmax⁡, 1][-f_{\max},\,1], where fmax⁡f_{\max} is the largest float32, the sum wmin⁡+(2b−1)Δw_{\min}+(2^b-1)\Delta loses the 11 to cancellation.
  • Underflow. The final conversion to float32 rounds to nearest, which can turn a tiny level into a subnormal number or zero. This narrowing is the only step where the code allows floating-point underflow.

Finer-grained scaling: per-channel / row-wise

Instead of one scale for the whole matrix, use one scale per output channel/row. For signed symmetric quantization:

qmax⁡=2b−1−1,si=max⁡j∣Wi,j∣qmax⁡,Qi,j={clip ⁣(round ⁣(Wi,jsi),−qmax⁡,qmax⁡),si>0,0,si=0,W^i,j=siQi,j.q_{\max}=2^{b-1}-1,\qquad s_i=\frac{\max_j |W_{i,j}|}{q_{\max}},\qquad Q_{i,j}=\begin{cases} \mathrm{clip}\!\left(\mathrm{round}\!\left(\dfrac{W_{i,j}}{s_i}\right),-q_{\max},q_{\max}\right), & s_i>0,\\ 0, & s_i=0, \end{cases}\qquad \hat W_{i,j}=s_iQ_{i,j}.

This usually improves quality because different channels have different ranges of values. Here bb must be an integer with b≥2b\ge 2: at b=1b=1, qmax⁡=0q_{\max}=0 and there is no nonzero level, which is narrower than the affine rule's 1≤b≤161\le b\le 16. Symmetric quantization keeps the real value 0 at integer level 00 and uses the levels −qmax⁡,…,qmax⁡-q_{\max},\dots,q_{\max}, leaving −2b−1-2^{b-1} unused. An all-zero row has si=0s_i=0; by the same convention as above, Qi,j=0Q_{i,j}=0 and W^i,j=0\hat W_{i,j}=0 exactly, with no division.

The two formulas are different quantizers, not two spellings of one. At b=2b=2, the tensor [1,2,3][1,2,3] reconstructs as [1, 7/3, 3]≈[1, 2.33, 3][1,\,7/3,\,3]\approx[1,\,2.33,\,3] under the affine rule and as [0, 3, 3][0,\,3,\,3] under the symmetric one. Dettmers et al. (2022) describe both families for 8-bit inference, absmax (symmetric) and zeropoint (asymmetric) quantization; these formulas are teaching versions, not the whole LLM.int8() method.

Clipping and rounding

A scale can cause two different errors. A value whose rounded code falls outside [−qmax⁡,qmax⁡][-q_{\max},q_{\max}] is clipped: it is reconstructed at the end of the range, however far beyond the range it lies. A value inside the range is rounded to the nearest level, so it is off by at most half a step, si/2s_i/2. The absmax scale above never clips, because the largest magnitude maps exactly to qmax⁡q_{\max}; the price is that one large value sets the step for every other value that shares its scale. A smaller scale, such as one chosen before an outlier is seen, keeps a fine step for the ordinary values and clips the outlier instead. The practice after the demo works through both errors on a 2×42\times4 example.

Per-row scales let each row pay only for its own range. When every row has the same largest magnitude, each row's absmax scale equals the shared one, so per-row and shared scales give the same result. Group-wise scales, described next, can still help then. If both rows are (−0.7,−0.3,0.3,7)(-0.7,-0.3,0.3,7), both row scales are 11 and the root-mean-square error is 0.54/8≈0.26\sqrt{0.54/8}\approx0.26; with one scale for each group of two weights, 0.10.1 and 11, it falls to 0.18/8=0.15\sqrt{0.18/8}=0.15.

Group-wise scales

At 4 bits even one scale per row is often too coarse. Group-wise quantization splits each row into groups of gg consecutive weights, commonly 64 or 128, and gives each group its own scale. The scales cost memory too: a 16-bit scale for every 128 weights adds 16/128=0.12516/128 = 0.125 bits per weight, so a "4-bit" model stores about 4.125 bits per weight, or more if each group also has a zero point.

Beyond rounding: GPTQ, AWQ and SmoothQuant

Rounding each weight to its nearest level is the simplest choice, not the most accurate one. Three widely used methods for large language models do better with a little calibration data:

  • GPTQ (Frantar et al., 2023) quantizes a layer's weights one column at a time, aiming to keep the layer's outputs on calibration inputs XX (one column per calibration token) close to the original, ∥WX−W^X∥2\lVert WX - \hat WX\rVert^2. After each column it adjusts the columns not yet quantized to compensate for the rounding error, using approximate second-order information (the inverse of H=2XX⊤H = 2XX^\top). It brought 175-billion-parameter models to 3–4 bits per weight in about four GPU hours.
  • AWQ (Lin et al., 2024) quantizes weights only. It observes that about 1% of weight channels matter most, and that they are the ones multiplying large activations, not the ones with the largest weights. It scales those channels up before quantization and divides the matching activations by the same factor, which leaves the product unchanged but reduces their relative rounding error. The scales are chosen from calibration activations, without backpropagation.
  • SmoothQuant (Xiao et al., 2023) targets 8-bit weights and activations. Activation outliers sit in a few channels, which makes activations hard to quantize while weights are easy. Writing the layer as Y=XWY = XW, with one row of XX per token and one column per input channel jj, it moves part of the difficulty into the weights with an equivalent rescaling, Y=(X diag(s)−1)(diag(s) W)Y = \big(X\,\mathrm{diag}(s)^{-1}\big)\big(\mathrm{diag}(s)\,W\big), where sj=max⁡t∣Xt,j∣α/max⁡k∣Wj,k∣1−αs_j = \max_t |X_{t,j}|^{\alpha} / \max_k |W_{j,k}|^{1-\alpha} and α=0.5\alpha = 0.5 is the default balance.
Study prompts for this section: Mathematics
Study prompts

Each button copies a prompt about this section to your clipboard, for an AI assistant you already use. Nothing is sent by this site.

Code

The same calculation as runnable code, in the notation of the derivation.

import numpy as np

rng = np.random.default_rng(0)
w = rng.normal(size=10000).astype(np.float32)

def quantize_uniform(w, bits=8):
    # Affine min-max quantization. Domain: w is a nonempty float32 ndarray (ndim >= 1)
    # of finite values, never converted or modified; bits is an int or NumPy integer
    # from 1 to 16, not a bool. Returns int32 levels, float delta, float32 reconstruction.
    if type(w) is not np.ndarray or w.dtype != np.float32:
        raise TypeError("w must be a float32 ndarray")
    if w.ndim == 0 or w.size == 0 or not np.isfinite(w).all():
        raise ValueError("w must be nonempty, at least 1-D and finite")
    if isinstance(bits, bool) or not isinstance(bits, (int, np.integer)):
        raise TypeError("bits must be an integer")
    if not 1 <= bits <= 16:
        raise ValueError("bits must be from 1 to 16")
    qmax = 2 ** int(bits) - 1
    wmin, wmax = float(w.min()), float(w.max())  # exact: every float32 is a float64
    if wmin == wmax:  # zero range: Delta = 0, every entry at level 0, exact reconstruction
        return np.zeros(w.shape, dtype=np.int32), 0.0, w.copy()
    delta = (wmax - wmin) / qmax
    x = w.astype(np.float64)  # widen the array itself before any arithmetic
    wq = np.clip(np.round((x - wmin) / delta), 0, qmax).astype(np.int32)
    level = np.clip(wq * delta + wmin, wmin, wmax)  # stay inside [wmin, wmax]
    level[wq == qmax] = wmax  # the top level is wmax exactly, even after cancellation
    with np.errstate(under="ignore"):  # only this float64 -> float32 narrowing may underflow
        what = level.astype(np.float32)
    return wq, delta, what

q8, d8, what8 = quantize_uniform(w, bits=8)
q4, d4, what4 = quantize_uniform(w, bits=4)

print("RMSE INT8:", round(float(np.sqrt(((w - what8) ** 2).mean())), 6), "delta:", round(d8, 6))
print("RMSE INT4:", round(float(np.sqrt(((w - what4) ** 2).mean())), 6), "delta:", round(d4, 6))
print("memory reduction: fp16->int8 ~2x, fp16->int4 ~4x (weight storage)")

q, d, what = quantize_uniform(np.array([3.0, 3.0, 3.0], dtype=np.float32), bits=4)
print("constant input: q", q.tolist(), "delta", d, "w_hat", what.tolist())
q, d, what = quantize_uniform(np.array([0.0, 0.5, 1.5, 2.5, 3.0], dtype=np.float32), bits=2)
print("halves round to even: q", q.tolist(), "delta", d)
Study prompts for this section: Code
Study prompts

Each button copies a prompt about this section to your clipboard, for an AI assistant you already use. Nothing is sent by this site.

Demo

Change an input, predict the result, and see which quantities respond.

ExploreChange one control at a time and name what responds.An optional observation guide follows the demo.

Explore Quantization: Compressing Models to Integers

Loading the interactive demo…

Observation guide

Optional and ungraded. Opening a guide saves nothing.

Choose what to inspect in Quantization: Compressing Models to Integers, then open its guide.

The demo below asks you to predict which scaling strategy copes with an outlier before it shows the quantization error. The point is that a single shared scale can spend most integer levels on one large value, while per-channel scales recover resolution for the ordinary rows.

The demo uses the signed symmetric formula, with one absmax scale for the whole matrix or one per row; it does not run the affine code above. Its fixed 4×8 matrix never contains an all-zero row, so the si=0s_i=0 branch is not reached there, and its byte counts cover the stored integers only, not the scales.

Study prompts for this section: Demo
Study prompts

Each button copies a prompt about this section to your clipboard, for an AI assistant you already use. Nothing is sent by this site.

Practice

Quantize eight weights with three choices of 4-bit scale and find which error each makes, clipping or rounding. Then change one weight and compare again.

Loading the exercise…
In focus

Concept: Quantization: Compressing Models to Integers

What is the smallest example of Quantization you can work through by hand, and what does it show?

BeforeEfficiency: Quantization, Distillation, LoRA & Sparse MoENextPruning Weights and Channels
DetailsEfficiency

After the first pass

Go deeper

Optional material for a second reading. Sources are always shown; the other panels open from their headings or from these links, and closing one keeps what you wrote or revealed.
What to look for in each sectionChoose a section and what you expect to see in it, then read short advice.

Section by section

Choose what to look for in each section

Reduce memory and bandwidth by storing weights/activations in low-bit integers (INT8/INT4) with careful scaling to limit accuracy loss.

Choose what to look for (no demo yet)01 / Intuition
Illustration of smooth weights snapped to discrete integer levels with quantization error cues.
What to look for

Start with the picture, metaphor, or geometric mechanism.

Choose first

Choose what you expect to see in this section of Quantization: Compressing Models to Integers.

Questions to ask of the pictureChoose a part of the picture and what you expect, then read short advice.

Looking at the picture

Questions to ask of the picture

Reduce memory and bandwidth by storing weights/activations in low-bit integers (INT8/INT4) with careful scaling to limit accuracy loss.

4 of 4 sections writtenNo live demo yet
Question

Which part of the picture should you look at first?

Choose first

Pick the part of the picture you expect to explain Quantization: Compressing Models to Integers.

Sources

References for this page

A reference shows where an idea comes from; it does not vouch for every step on this page.
paper · 2022LLM.int8(): 8-bit Matrix Multiplication for Transformers at ScaleDettmers et al.
Why it is cited

Shows that large transformers develop a few activation feature dimensions with very large values, which ruin 8-bit quantization with a shared scale; uses vector-wise scales and keeps those outlier dimensions in 16-bit (NeurIPS 2022).

Open source
paper · 2023GPTQ: Accurate Post-Training Quantization for Generative Pre-trained TransformersFrantar et al.
Why it is cited

Quantizes each layer's weights one column at a time, updating the remaining columns to compensate for rounding error with approximate second-order information; 175B-parameter models reach 3–4 bits in about four GPU hours (ICLR 2023).

Open source
paper · 2024AWQ: Activation-aware Weight Quantization for On-Device LLM Compression and AccelerationLin et al.
Why it is cited

Finds that about 1% of weight channels matter most and that they are identified by activation size, then scales those channels up before low-bit weight-only quantization, without backpropagation (MLSys 2024).

Open source
paper · 2023SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language ModelsXiao et al.
Why it is cited

Moves quantization difficulty from activations, which have outlier channels, to weights with an equivalent per-channel rescaling, so both can be stored in 8 bits (ICML 2023).

Open source
paper · 2018Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only InferenceJacob et al.
Why it is cited

Defines the affine scheme r = S(q − Z), with a real-valued scale S and an integer zero point Z, and trains with simulated quantization so inference can run in integer arithmetic (CVPR 2018).

Open source
What each claim rests on1 claim, each with its sources, where it appears on this page, and its caveats.

Claims and sources

Reduce memory and bandwidth by storing weights/activations in low-bit integers (INT8/INT4) with careful scaling to limit accuracy loss.

Checked against the cited passages

The checks were made by this site, not by an independent reviewer.

Quantization maps floating-point tensors to low-bit integer levels with a scale for converting back, which reduces storage and memory traffic but adds rounding error. If an outlier sets a shared scale, ordinary values lose resolution, so finer-grained scales or separate handling of outliers can preserve accuracy.
What the sources support

Dettmers et al. show transformer-scale 8-bit inference needs separate normalization constants and mixed-precision handling for emergent outlier features. Frantar et al. support post-training weight quantizat...

Where to see it on this page
Equation 1
Δ=wmax⁡−wmin⁡2b−1,wq={clip ⁣(round ⁣(w−wmin⁡Δ),0,2b−1),Δ>0,0,Δ=0,w^=wqΔ+wmin⁡.\Delta = \frac{w_{\max}-w_{\min}}{2^b-1},\qquad w_q=\begin{cases} \mathrm{clip}\!\left(\mathrm{round}\!\left(\dfrac{w-w_{\min}}{\Delta}\right),0,2^b-1\right), & \Delta>0,\\ 0, & \Delta=0, \end{cases}\qquad \hat w=w_q\Delta+w_{\min}.
Equation 2
qmax⁡=2b−1−1,si=max⁡j∣Wi,j∣qmax⁡,Qi,j={clip ⁣(round ⁣(Wi,jsi),−qmax⁡,qmax⁡),si>0,0,si=0,W^i,j=siQi,j.q_{\max}=2^{b-1}-1,\qquad s_i=\frac{\max_j |W_{i,j}|}{q_{\max}},\qquad Q_{i,j}=\begin{cases} \mathrm{clip}\!\left(\mathrm{round}\!\left(\dfrac{W_{i,j}}{s_i}\right),-q_{\max},q_{\max}\right), & s_i>0,\\ 0, & s_i=0, \end{cases}\qquad \hat W_{i,j}=s_iQ_{i,j}.
Code example 1import numpy as np rng = np.random.default_rng(0) w = rng.normal(size=10000).astype(np.float3...
Caveat

This covers uniform quantization with scales and the effect of outliers. The page describes GPTQ, AWQ and SmoothQuant in words but does not implement them, and it reports no model accuracy or hardware speedup.

StatusChecked against the cited passages.

Dettmers et al. support 8-bit scaling and dequantization, the loss of precision when one scale must cover an outlier, vector-wise scales, and keeping outlier dimensions in higher precision. Frantar et al. support low-bit weight quantization of GPT models that controls the reconstruction error and reduces memory movement.

Explain it without the pageWrite your own explanation before asking for feedback. Your draft and any hints stay while this page is open.

Practice · Quantization: Compressing Models to Integers

Try the idea in your own words

Reduce memory and bandwidth by storing weights/activations in low-bit integers (INT8/INT4) with careful scaling to limit accuracy loss.

Concept · Selected for practice

Quantization: Compressing Models to Integers

What it rests on: Sources: LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale; GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Tr...

Context and links
Choose a task

Explain the mechanism

For Quantization: Compressing Models to Integers: What is the smallest example of Quantization you can work through by hand, and what does it show? Explain your answer, including what changes, why, and which assumption matters.

No answer yet

A rough first thought is enough. Your draft stays when you change tasks.

Your draft stays on this page and is cleared when you leave or reload.

A little help · Explain

Open one hint at a time. These are suggestions, not your answer or a grade.

0 of 3 hints shown for this question.

    Clearing your answer keeps this help record. Outside help is your own report; this page cannot check it.

    Where am I stuck? (optional)
    Your own description, not an automatic diagnosis

    Choose one, or leave this unspecified. Select it again to clear it.

    Take your draft to a feedback conversation

    No AI feedback runs here. You can copy a prompt to use elsewhere; nothing is sent automatically. Review the text before sharing, and leave out private information.

    Write an attempt before copying a feedback prompt.

    A draft, or an AI reply to it, is not a test of what you have learned. To check that, try a different case later without help.

    Ask about this pagePick one item on this page and copy a prompt about it into an AI assistant you already use. Notes you write here stay in this browser.
    Ask about this pageClose
    ConceptQuantization: Compressing Models to IntegersSources: LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale; GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Tr...rng = np.random.default_rng(0)

    Your question

    Choose what your question is about

    Pick the idea, equation, source, code, claim, misconception or demo state you want to ask about. The prompt you copy includes it, so the answer can stay on that item.
    Next local actionNo local draft saved yet

    Open the draft below to save one note and next action in this browser.

    conceptEfficiency

    Quantization: Compressing Models to Integers

    Starting question

    What is the smallest example of Quantization you can work through by hand, and what does it show?

    SourcesCheck the 5 cited sources listed under Sources.Notes can be saved for this item
    Points of view on this item

    Fixed prompts generated from this item. They are not comments from people or independent reviews.

    Learner’s first stepAsk what would make "Quantization: Compressing Models to Integers" feel predictable rather than familiar.
    Assumption

    The 5 cited sources must support this exact item, not just the surrounding topic.

    Source-checking summary

    Connect the definition to one equation, piece of code or demo before widening the discussion.

    Proposed experiment

    Change one input, then check that the same relationship holds in the mathematics, the code and the demo.

    Next action

    You can state the mechanism in your own words

    Evidence4 checks
    ObservationChecking for a saved observation
    ActionReady for one action
    PromptLearner prompt ready to copy
    Go to this item
    01ObservationChecking what this browser has saved
    02EvidenceChecking for a saved observation
    03SourcesCheck the 5 cited sources listed under Sources.
    04Next stepSave one next action
    Local action draftNo local draft saved yetOpen when you are ready to write one next action
    Local action draft

    This draft stays in this browser and is attached to this item only.

    No local draft saved.
    Evidence to inspect
    • What the 5 cited sources say about this exact item
    • The definition, its prerequisites, and a contrasting concept
    • The equation or code that makes the concept concrete
    • One demo state that shows what stays the same as the inputs change
    What would resolve this
    • You can state the mechanism in your own words
    • You can name the prerequisite that would clear up the confusion
    • You can predict how the result changes when one input changes
    Reference idconcept/concept-notebook/efficiency/quantization concept:efficiency/quantization