Hoppa till innehållet
AI-grafen
F· AI engineeringinferens-optimering· ca 90 min· volatil — kontrolleras ofta· verifierad 2026-09-20

Kvantisering

Kunna förklara int8/int4-kvantisering, mäta kvalitetsförlust och minnesvinst, och köra en kvantiserad modell lokalt.

Förkunskaper

Intuition

En 7B-modell i float16 tar 14 GB. I int4 tar den 3,5–4 GB och får plats på en laptop. Kvantisering = lagra vikter med färre bitar.

Recept (linjär kvantisering): för en grupp vikter, hitta max-absolutvärde → skala s = max/127 (int8). Lagra q = round(w/s) som heltal; vid beräkning w ≈ q·s. Med nollpunkt kan man använda hela intervallet asymmetriskt. Finare grupper (per kanal, per 64–128 vikter) → mindre fel, lite mer metadata.

Vad förloras? Per-token-perplexitet stiger något: int8 nästan gratis, int4 ofta +1–3 % PPL, int3 och lägre gör skada. Outliers (enstaka jättevikter/aktiveringar) är huvudproblemet — därför metoder som GPTQ/AWQ som kvantiserar «smart» med kalibreringsdata.

Kvantisering ger också snabbare inferens när minnesbandbredd är flaskhalsen (vilket den är vid dekodning): färre byte att läsa per token.

Kod

import numpy as np

def quantize(w, bits=8, group=64):
    """Symmetrisk per-grupp-kvantisering. Returnerar (q int, skalor)."""
    qmax = 2 ** (bits - 1) - 1
    w = w.reshape(-1, group)
    s = np.abs(w).max(axis=1, keepdims=True) / qmax
    s[s == 0] = 1e-8
    q = np.clip(np.round(w / s), -qmax - 1, qmax).astype(np.int8 if bits <= 8 else np.int16)
    return q, s

def dequantize(q, s, shape):
    return (q.astype(np.float32) * s).reshape(shape)

rng = np.random.default_rng(0)
W = rng.normal(0, 0.02, (4096, 4096)).astype(np.float32); W[0, 0] = 1.0   # en outlier
for bits in (8, 4):
    q, s = quantize(W, bits)
    err = np.linalg.norm(W - dequantize(q, s, W.shape)) / np.linalg.norm(W)
    mb = q.size * bits / 8 / 1e6 + s.size * 2 / 1e6
    print(bits, "relfel", round(float(err), 4), "MB", round(mb, 1), "vs fp16", W.size * 2 / 1e6)
# 8 relfel ~0.002  MB 16.9  vs fp16 33.6
# 4 relfel ~0.04   MB 8.5

Lokalt: llama.cpp med GGUF (Q4_K_M ≈ 4,5 bit/vikt) eller bitsandbytes i transformers (load_in_4bit=True).

Formellt

Affin kvantisering: q=clamp(⌊w/s⌉+z, 0, 2b−1)q = \text{clamp}(\lfloor w/s \rceil + z,\, 0,\, 2^b-1), w^=s(q−z)\hat w = s(q - z). Kvantiseringsbrus för likformig rundning har varians s2/12s^2/12; relativt fel skalar med max⁡∣w∣/σw\max|w|/\sigma_w i gruppen, vilket är varför outliers förstör och små grupper hjälper. GPTQ minimerar ∥WX−W^X∥2\|WX - \hat W X\|^2 lagervis med Hessian-information (H=XX⊤H = XX^\top) från kalibreringsdata; AWQ skalar kanaler så att viktiga (aktiveringstunga) vikter får mindre relativt fel. Aktiveringskvantisering (W8A8) kräver hantering av aktiverings-outliers (SmoothQuant). Minnesbandbredd: dekodning av token läser alla vikter en gång → tid ≈ bytes/bandbredd; halverade bytes ≈ dubbel hastighet tills beräkning blir flaskhals.

Behärskning innebär

  • Förklarar int8/int4-kvantisering: skala, nollpunkt, per-kanal/grupp
  • Mäter minnesvinst och kvalitetsförlust
  • Kör en kvantiserad modell lokalt

Logga in för att göra övningarna och bygga upp din behärskning.

Källor

Alla källor och licenser