Quantization-Aware Training (QAT) & Post-Training Quantization (PTQ)
Summary: Quantization reduces model precision from FP16/BF16 to INT8/INT4, shrinking memory 2-4× and accelerating inference. QAT simulates quantization during training to preserve accuracy; PTQ quantizes after training with calibration data. QLoRA combines 4-bit PTQ with LoRA fine-tuning.
Quantization Basics
In plain English: Neural network weights are typically 16-bit floats (FP16). Quantization maps them to 8-bit or 4-bit integers:
q = round(w / scale + zero_point). This makes models 2-4× smaller and faster on integer-optimized hardware.
Quantization Types
| Aspect | PTQ (Post-Training) | QAT (Quantization-Aware Training) |
|---|---|---|
| When | After full-precision training | During training |
| Data needed | Small calibration set (128-1024 samples) | Full training data |
| Accuracy drop | 1-5% (larger for INT4) | <1% (often recovers) |
| Complexity | Simple | Requires fake-quant ops |
| Time | Minutes | Full training time |
Symmetric vs Asymmetric
Symmetric (INT8, INT4):
q = clip(round ≤ ft((w)/(s)), -2^{b-1}, 2^{b-1}-1right)
- Zero-point = 0
- Used for weights (GPTQ, AWQ, NF4)
Asymmetric (UINT8):
q = clip(round ≤ ft((w)/(s) + z), 0, 2^b-1
- Zero-point
z≠ 0 - Used for activations (inputs/outputs)
PTQ Methods
1. GPTQ (Gradient-based PTQ) — Frantar et al., 2023
- Per-layer optimization: Minimize
||W - hat{W}||^2via Hessian-weighted error - Algorithm: Iterative quantization using inverse Hessian diagonal
- Supports: INT3, INT4, INT8
- Slow but high accuracy; ~hours for LLaMA-7B
2. AWQ (Activation-aware Weight Quantization) — Lin et al., 2023
- Key insight: Not all weights equally important; protect weights for salient activations
- Metric:
S = abs(W) × abs(X)_{mean}— weight × activation magnitude - Per-channel scaling: Different scale per output channel
- Fast: No Hessian, just calibration data pass
3. RTN (Round-to-Nearest) — Baseline
- Simple per-tensor or per-channel scaling
- Poor for INT4 (<50% accuracy on LLMs)
QAT Methods
Fake Quantization (Straight-Through Estimator)
def fake_quant(x, scale, zero_point, bits=8):
# Forward: quantize + dequantize
x_q = torch.round(x / scale + zero_point).clamp(qmin, qmax)
x_dq = (x_q - zero_point) * scale
return x_dq
# Backward: gradient passes through unchanged (STE)
# x.grad = x_dq.grad
Training Flow
- Start from pretrained FP16 model
- Insert fake-quant modules after each weight/activation
- Fine-tune with quantization simulation
- Export quantized weights (remove fake-quant)
Learned Quantization Parameters
- Scales: Learnable per-channel/per-tensor
- Zero-points: Learnable (asymmetric)
- Bit-width: Can be mixed-precision (sensitive layers → higher bits)
4-bit Quantization: NF4 (NormalFloat)
QLoRA's 4-bit NF4 (Dettmers et al., 2023)
- Block-wise quantization: 64-element blocks
- NF4 datatype: Optimized for normal distribution
N(0,1) - Double quantization: Quantize quantization constants (saves 0.5 bits/param)
NF4 Values (16 levels)
Level: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Value: -1.0 -0.7 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 1.0
(Approximate quantiles of standard normal)
Memory Savings
| Model | FP16 | 4-bit NF4 | Reduction |
|---|---|---|---|
| LLaMA-7B | 13.5 GB | 3.5 GB | 3.9× |
| LLaMA-13B | 25 GB | 6.5 GB | 3.8× |
| LLaMA-70B | 135 GB | 35 GB | 3.9× |
Mixed Precision Strategies
W8A8 (Weights INT8, Activations INT8)
- Both weights and activations quantized
- Requires QAT or advanced PTQ for accuracy
- Tensor Cores: DP4A/DOT2 (INT8) → 2× FP16 throughput
W4A16 (Weights INT4, Activations FP16)
- Common for LLM inference (weights bottleneck memory)
- Dequantize weights on-the-fly:
W_{deq} = (W_q - z) × s - Used by: QLoRA, GPTQ-4bit, AWQ-4bit
W4A4 (Both INT4)
- Maximum compression
- Significant accuracy drop without QAT
- Emerging: QAT for W4A4 (e.g., LLM-QAT, ZeroQuant-V2)
Hardware Support
| Hardware | INT8 | INT4 | FP8 |
|---|---|---|---|
| Ampere (A100, RTX 30) | ✅ DP4A | ❌ | ❌ |
| Hopper (H100) | ✅ DP4A | ✅ DP4A (via MMA) | ✅ Tensor Cores |
| Ada Lovelace (RTX 40) | ✅ DP4A | ✅ DP4A | ✅ Tensor Cores |
| Blackwell (B100/RTX 50) | ✅ | ✅ Native | ✅ Native |
Consumer GPU note: RTX 3090/4090 lack native INT4 tensor cores — use bitsandbytes CUDA kernels (dequant on-the-fly).
Accuracy Impact (Typical)
| Task | FP16 | W8A8 (PTQ) | W4A16 (PTQ) | W4A16 (QAT) |
|---|---|---|---|---|
| Perplexity (WikiText2) | 5.2 | 5.4 (+4%) | 6.1 (+17%) | 5.3 (+2%) |
| MMLU (7B) | 45% | 44% | 41% | 44% |
| GSM8K (7B) | 30% | 29% | 25% | 29% |
Deployment Libraries
| Library | Method | Backend | Notes |
|---|---|---|---|
| bitsandbytes | PTQ (8/4-bit) + QLoRA | CUDA | Research standard |
| GPTQ-for-LLaMA | PTQ (GPTQ) | CUDA | Fast inference |
| AutoAWQ | PTQ (AWQ) | CUDA | Fast, accurate |
| llama.cpp / GGML | PTQ (k-quant) | CPU/Apple Silicon | Edge deployment |
| TensorRT-LLM | PTQ/QAT | TensorRT | Production NVIDIA |
| ONNX Runtime | PTQ/QAT | ONNX | Cross-platform |
Best Practices
- Start with W4A16 PTQ (AWQ/GPTQ) — fastest path
- If accuracy drop >2%: Try QAT with learned scales
- Mixed precision: Keep sensitive layers (embedding, output, attention) at INT8
- Calibration data: Use 512-1024 diverse samples from target domain
- Evaluate end-to-end: Perplexity ≠ downstream task accuracy
Related Concepts
- lora-qloра — QLoRA = 4-bit PTQ + LoRA
- flash-attention — Combine with quantized attention
- transformer-architecture — Where quantization applies
Sources
- arxiv-2305.14314: QLoRA paper (NF4, double quantization, paged optimizer)
- Frantar et al., "GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers" (2023)
- Lin et al., "AWQ: Activation-aware Weight Quantization for LLM Compression" (2023)