Quantification
Quantification avancée des LLM
GGUF K-quants, nomenclature Q4_K_M et UD-Q5_K_XL, GPTQ, AWQ, EXL2/EXL3, REAP : panorama des méthodes de quantification et de leurs compromis.
La quantification réduit la précision des poids d’un modèle (de 32 bits à 4 bits, par exemple) pour diminuer l’empreinte mémoire et accélérer l’inférence. Plusieurs méthodes coexistent, chacune avec ses compromis entre taille, vitesse et qualité.
Pourquoi quantifier ?
Un modèle de 7 milliards de paramètres en précision FP16 (16 bits) occupe environ 14 Go de mémoire. Quantifié en 4 bits, ce même modèle ne nécessite plus que ~4 Go, le rendant exécutable sur du matériel grand public.
Taille mémoire = Nb_paramètres × (bits_par_poids / 8) + overhead
| Métrique | Valeur |
|---|---|
| Réduction mémoire (FP16 → 4 bits) | -75 % |
| Accélération inférence | 2 à 5x |
| Perte qualité (Q4_K_M) | < 1 % |
Sur un modèle moderne comme Qwen3.6-27B (dense) ou Qwen3.6-35B-A3B (MoE, 3B actifs par token), ces ratios se retrouvent quasiment à l’identique.
GPTQ — quantification post-training précise
GPTQ (GPT Quantization) est une méthode de quantification post-entraînement qui utilise des informations de second ordre (matrice hessienne) pour minimiser l’erreur de quantification couche par couche.
- Calibration : utilise un petit dataset (128 segments de 2048 tokens du dataset C4) pour analyser les activations.
- Quantification par couche : chaque ligne de la matrice de poids est quantifiée indépendamment.
- Optimisation hessienne : minimise l’erreur quadratique moyenne via les informations de courbure.
- Compensation : les erreurs sont compensées sur les colonnes suivantes (ordre d’activation).
L’option --act-order quantifie les colonnes par ordre décroissant de magnitude d’activation, améliorant significativement la qualité (par exemple, perplexité de 7,15 → 6,09 sur Llama 7B).
Avantages : excellente précision à 4 bits, inférence rapide via ExLlama, bien supporté (AutoGPTQ). Inconvénients : quantification lente (plusieurs heures), nécessite une calibration, GPU NVIDIA uniquement.
AWQ — Activation-Aware Weight Quantization
AWQ est une méthode développée par le MIT Han Lab qui identifie et protège les poids « saillants » (importants) en se basant sur la distribution des activations, et non sur la magnitude des poids eux-mêmes.
Tous les poids ne sont pas égaux : protéger seulement 1 % des poids saillants réduit drastiquement l’erreur de quantification. L’importance est déterminée par l’amplitude des activations, pas des poids.
1. Collecter les statistiques d'activation (offline)
2. Identifier les canaux avec les plus grandes activations
3. Scaler UP ces canaux saillants avant quantification
4. Scaler DOWN les activations de manière équivalente
→ Transformation mathématiquement équivalente
→ Mais erreur de quantification réduite sur les poids importants
Avantages : meilleure précision que GPTQ, pas de backpropagation, bonne généralisation, MLSys 2024 Best Paper Award. Inconvénients : VRAM plus élevée que GPTQ, GPU NVIDIA requis, vitesse légèrement inférieure.
EXL2 — quantification mixte optimisée
EXL2 est le format de quantification d’ExLlamaV2, offrant un contrôle fin sur le compromis taille/qualité grâce à une quantification à bits-per-weight (bpw) variable.
- Précision mixte par couche : chaque couche peut avoir un bpw différent.
- Calibration par hessienne : optimise la distribution des bits selon l’importance.
- Contrôle fin : on spécifie le bpw cible (4.0, 4.25, 4.65, 5.0…).
- Performance GPU : kernels CUDA optimisés, le plus rapide en full GPU.
Si le modèle tient entièrement en VRAM, EXL2 est souvent le meilleur choix : il offre les meilleures performances en vitesse et en qualité. AWQ 4 bits égale EXL2 4.0 bpw en qualité, surpassant tous les quants GGUF, y compris Q8.
EXL3 — la nouvelle génération
EXL3 est le format de quantification d’ExLlamaV3, une réécriture complète utilisant la technique QTIP (Quantization with Trellis-coded Inference Pairs) de Cornell RelaxML.
- Codebook procédural : structures de treillis « tail-biting » pour encoder les vecteurs.
- Conversion ultra-rapide : quelques minutes pour les petits modèles, quelques heures pour 70B+ (contre 720 GPU-heures pour AQLM).
- Excellente qualité low-bitrate : Llama-3.1-70B reste cohérent à seulement 1,6 bpw.
- Moins de 16 Go : un 70B utilisable avec un cache de 4096 tokens.
| Métrique | Valeur |
|---|---|
| Llama 70B cohérent | 1,6 bpw |
| VRAM pour 70B inférence | < 16 Go |
| Vitesse vs AQLM | ~100x |
HQQ — Half-Quadratic Quantization
HQQ est une méthode développée par Mobius Labs qui se distingue par sa rapidité : aucune calibration nécessaire, quantification en quelques minutes même pour les plus grands modèles.
Contrairement à GPTQ/AWQ qui minimisent l’erreur sur les activations de sortie, HQQ se concentre sur la minimisation directe de l’erreur sur les poids, avec une approche « half-quadratic » à solutions en forme fermée, évitant le calcul de gradients.
| Métrique | Valeur |
|---|---|
| Quantification Llama-2-70B | < 5 min |
| Vitesse vs GPTQ | 50x |
| Précisions supportées | 1 à 8 bits |
from transformers import AutoModelForCausalLM, HqqConfig
quant_config = HqqConfig(
nbits=4, # 4-bit quantization
group_size=64, # Taille des groupes
axis=1 # Axe de quantification
)
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen3.6-27B-Instruct",
quantization_config=quant_config,
device_map="auto"
)
Marlin — kernel CUDA optimisé pour GPTQ
Marlin n’est pas une méthode de quantification mais un kernel CUDA ultra-optimisé pour exécuter les modèles GPTQ. Il utilise les mêmes poids GPTQ mais avec des optimisations avancées (async-copy, optimisation cache L2) pour atteindre des performances exceptionnelles.
- Async-copy : transferts mémoire asynchrones masquant la latence.
- Cache L2 : réutilisation optimale des données en cache.
- Fusion d’opérations : moins de passes kernel, plus d’efficacité.
Pour la production avec vLLM, Marlin est souvent le meilleur choix : c’est la seule méthode qui dépasse les performances du baseline FP16 tout en réduisant la mémoire de 75 %.
from vllm import LLM
llm = LLM(
model="TheBloke/Llama-2-13B-GPTQ",
quantization="marlin", # Active le kernel optimisé
dtype="half"
)
BitsandBytes — quantification à la volée
BitsandBytes quantifie les modèles à la volée pendant le chargement, sans nécessiter de modèle pré-quantifié. Elle utilise NF4 (NormalFloat 4-bit), optimisé pour les distributions normales des poids : les niveaux de quantification sont placés là où la majorité des poids se concentrent (près de zéro).
Avantages : meilleure qualité (perplexité +1,7 %), pas de modèle pré-quantifié requis, setup le plus simple, double quantification possible. Inconvénients : plus lent que le baseline (~0,4x), quantification à chaque chargement, GPU NVIDIA uniquement.
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4", # NormalFloat 4-bit
bnb_4bit_compute_dtype="float16",
bnb_4bit_use_double_quant=True # Double quantification
)
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen3.6-27B-Instruct",
quantization_config=bnb_config,
device_map="auto"
)
BitsandBytes est idéal pour l’expérimentation : on peut tester n’importe quel modèle Hugging Face en 4 bits sans chercher de version pré-quantifiée. Pour la production à haut débit, on préfère Marlin ou EXL2.
REAP — pruning d’experts pour modèles MoE
REAP (Router-weighted Expert Activation Pruning) est une technique de compression de Cerebras Research conçue spécifiquement pour les modèles Mixture of Experts (MoE) comme Qwen3.6-35B-A3B, Qwen3-Coder, Kimi-K2, DeepSeek-V3 ou MiniMax-M2.
Contrairement aux idées reçues, le pruning d’experts est supérieur au merging pour les tâches génératives : le merging cause un « effondrement du sous-espace fonctionnel », car le routeur perd son contrôle indépendant sur chaque expert.
REAP calcule un score de saillance pour chaque expert :
saillance = router_gate_value × activation_norm
- Calibration : passage de samples représentatifs à travers le modèle.
- Analyse : enregistrement des experts activés et de leur magnitude.
- Scoring : calcul de la saillance (poids du routeur × norme d’activation).
- Pruning : suppression des experts à faible saillance.
Attention : les experts sont spécialisés par tâche (code, JSON, multi-turn…). Si les données de calibration ne contiennent pas de code, les experts spécialisés en code seront prunés. Il faut utiliser un mix représentatif du cas d’usage.
| Compression | Experts restants | Taille (MiniMax-M2) | Perte qualité |
|---|---|---|---|
| 25 % | ~120 | ~620 Go | Minimale |
| 40 % | ~96 | ~500 Go | Faible |
| 50 % | ~80 | ~420 Go | Near-lossless* |
*Near-lossless sur les tâches de génération de code et tool-calling avec une calibration appropriée.
pip install llmcompressor
python -m llmcompressor.transformers.oneshot \
--model_id "MiniMax/MiniMax-M2" \
--compression-ratio 0.50 \
--prune-method reap \
--distance_measure cosine \
--calibration_dataset "evol-codealpaca-v1,xlam-function-calling-60k" \
--output_dir "./MiniMax-M2-REAP-50"
K-Quants GGUF — la famille Q4_K_M
Les K-quants sont les méthodes de quantification natives de llama.cpp/GGUF, utilisant une précision mixte intelligente pour optimiser le rapport qualité/taille.
Qwen3.6-27B-Instruct-Q4_K_M.gguf
| | |
| | +-- M = Medium (mix de précision)
| +------ K = K-quant (méthode avancée)
+----------- Q4 = 4-bit (précision)
Précision (Q2 à Q8)
- Q2 (2 bits) : très petit, perte de qualité importante.
- Q3 (3 bits) : petit, perte notable.
- Q4 (4 bits) : bon équilibre taille/qualité (recommandé).
- Q5 (5 bits) : excellente qualité, taille raisonnable.
- Q6 (6 bits) : très bonne qualité.
- Q8 (8 bits) : quasi identique au FP16.
Méthode de quantification (0, 1, K)
_0: symétrique — un seul scale par bloc (legacy, simple mais moins précis)._1: asymétrique — scale + zero-point par bloc (legacy, meilleur pour distributions non centrées)._K: K-quant — schéma à deux niveaux avec super-blocs, le standard moderne.
Les K-quants utilisent une hiérarchie à deux niveaux : les poids sont groupés en blocs de 32, eux-mêmes regroupés en super-blocs de 256. Chaque niveau a son propre scale, permettant une approximation affine par morceaux qui capture mieux les variations locales et globales. C’est pourquoi Q4_K_M surpasse Q4_0/Q4_1 malgré un bpw similaire.
Variantes de mix (S, M, L) et XL
Les suffixes S/M/L indiquent le niveau de précision mixte entre les tenseurs :
_S(Small) : presque tout en 4 bits, fichier compact._M(Medium) : tenseurs sensibles (attention, couches finales) en 5-6 bits — recommandé._L(Large) : encore plus de tenseurs en précision élevée.
Certains curateurs publient des variantes « dynamiques » comme UD-Q5_K_XL (Unsloth Dynamic) : le suffixe XL pousse encore plus loin la sélectivité de la précision par tenseur, en gardant en haute précision les couches les plus sensibles. C’est ce type de quant qui se révèle souvent optimal en pratique (voir l’expérience plus bas).
TQ1_0 — quantification ternaire
Pour les très grands modèles comme DeepSeek-V3, on trouve parfois des versions TQ1_0 qui encodent les poids en ternaire (valeurs {−1, 0, +1}), atteignant ~1,6-1,7 bpw : la compression maximale possible tout en gardant un modèle fonctionnel.
Importance matrix (imatrix)
L’importance matrix (imatrix) est une technique de calibration qui améliore significativement la qualité des quantifications GGUF, particulièrement pour les quants agressifs (Q2, Q3, IQ2, IQ3). Elle analyse un dataset de calibration pour mesurer l’importance réelle de chaque poids lors de l’inférence : les poids fréquemment activés avec de fortes magnitudes reçoivent plus de précision.
Modèle FP16 + dataset → llama-imatrix → fichier .imatrix → llama-quantize --imatrix → GGUF optimisé
# 1. Générer l'importance matrix (calibration)
llama-imatrix \
-m model-f16.gguf \
-f calibration_data.txt \
-o model.imatrix \
--chunks 500
# 2. Quantifier en utilisant l'imatrix
llama-quantize \
--imatrix model.imatrix \
model-f16.gguf \
model-Q4_K_M.gguf Q4_K_M
- Fortement recommandé pour : IQ1, IQ2, IQ3, Q2, Q3.
- Amélioration notable pour : Q4_K_S, Q4_K_M, IQ4_XS.
- Gain marginal pour : Q5, Q6, Q8 (déjà très précis).
Attention : deux modèles avec le même label (par exemple IQ3_XS) peuvent différer si l’un a été calibré avec un dataset généraliste et l’autre avec un dataset trop spécifique. Un dataset trop spécialisé réduira la qualité sur les tâches générales. Les bons curateurs utilisent des datasets diversifiés (wiki, code, conversations).
I-Quants — quantification non-linéaire
Les I-quants (IQ2_XXS, IQ2_XS, IQ2_S, IQ2_M, IQ3_, IQ4_) vont au-delà de l’affine en utilisant des lookup tables et des règles de déquantification non-linéaires, permettant un meilleur fit des distributions non-gaussiennes des poids.
| Critère | IQ4_XS | Q4_K_M |
|---|---|---|
| Bits/weight | ~4,25 bpw | ~4,89 bpw |
| Taille (8B) | ~4,2 Go | ~4,6 Go |
| Génération | Un peu plus rapide | Standard |
| Prompt processing | Un peu plus lent | Plus rapide |
| Sensibilité imatrix | Élevée | Modérée |
| Recommandation | VRAM limitée | Défaut fiable |
IQ4_NL est une variante non-linéaire (~4,5 bpw) à blocs plus petits, optimisée pour les performances CPU.
Sur Hugging Face, les principaux curateurs de GGUF de qualité sont Unsloth (quants dynamiques avec imatrix), Bartowski (large catalogue) et, historiquement, TheBloke.
Tableau comparatif des méthodes
| Méthode | Calibration | Temps quant. | Vitesse inf. | Qualité 4-bit | Hardware |
|---|---|---|---|---|---|
| GGUF K-quants | Non | Minutes | ★★★ | ★★★★ | CPU/GPU universel |
| GPTQ | Oui (C4) | Heures | ★★★★ | ★★★★ | GPU NVIDIA |
| AWQ | Oui | Heures | ★★★★ | ★★★★★ | GPU NVIDIA |
| EXL2 | Oui | Heures | ★★★★★ | ★★★★★ | GPU NVIDIA |
| EXL3 | Oui | Minutes-Heures | ★★★★★ | ★★★★★ | GPU NVIDIA |
| HQQ | Non | Minutes | ★★★★ | ★★★★ | GPU NVIDIA |
| Marlin (kernel) | Non (GPTQ) | — | ★★★★★+ | ★★★★ | GPU NVIDIA |
| BitsandBytes | Non (à la volée) | Au chargement | ★★★ | ★★★★★ | GPU NVIDIA |
| REAP (MoE) | Oui | Minutes-Heures | ★★★★ | ★★★★★ | GPU (pruning experts) |
Benchmark vLLM (H200, Qwen2.5-32B)
Benchmarks réalisés par JarvisLabs sur GPU H200 avec Qwen2.5-32B-Instruct. TTFT = Time To First Token. Perplexité : plus bas = meilleur.
| Méthode | Perplexité | HumanEval | Throughput | TTFT |
|---|---|---|---|---|
| Baseline FP16 | 6,56 | 56,1 % | 461 tok/s | 57,7 ms |
| BitsandBytes | 6,67 | 51,8 % | 168 tok/s | 135 ms |
| AWQ | 6,84 | 51,8 % | 68 tok/s | 278 ms |
| GPTQ | 6,90 | 46,3 % | 277 tok/s | 107 ms |
| Marlin | 6,97 | 45,7 % | 712 tok/s | 52 ms |
| GGUF Q4_K_M | 7,02 | 54,3 % | 81 tok/s | 1178 ms |
GGUF dans vLLM est lent car optimisé pour llama.cpp. À retenir : Marlin utilise les mêmes poids que GPTQ mais tourne 2,6x plus vite grâce à ses kernels CUDA. Les kernels comptent souvent plus que l’algorithme.
Benchmark llama.cpp (RTX 3090, 7B)
Source : benchmark oobabooga. Un écart de perplexité < 0,1 est imperceptible.
| Type | Perplexité | VRAM | Tokens/s | Taille disque |
|---|---|---|---|---|
| EXL2-4.9bpw | 4,31 | 8,89 Go | 52-57 | 6,98 Go |
| AWQ-4bit | 4,33 | 9,62 Go | 39-41 | 6,67 Go |
| Q4_K_M.gguf | 4,33 | 8,99 Go | 31-35 | 3,80 Go |
| GPTQ-4bit | 4,34 | 7,94 Go | 64 (ExLlama) | 6,50 Go |
Quel quant en pratique ? L’expérience SoberCloud
Sur Strix Halo (AMD Ryzen AI MAX+ 395, iGPU gfx1151, 128 Gio UMA, bandwidth-bound), nous avons mesuré un sweep de quants GGUF dynamiques pour Qwen3.6-35B-A3B (MoE) via llama.cpp Vulkan. Les scores correspondent à trois suites internes BenchLocal : Tool-Calling / Instruction-Following / Data-Extraction.
| Quant | Taille | Tool / Instr / Extract | Débit |
|---|---|---|---|
| Q4_K_XL | 22,9 Go | 93 / 74 / 59 | 63 t/s |
| Q5_K_XL | 27 Go | 100 / 80 / 91 | ~73 t/s |
| Q6_K_XL | 32,6 Go | 100 / 80 / 93 | ~58 t/s |
| Q8_K_XL | 39,1 Go | 100 / 80 / 91 | ~51 t/s |
Deux enseignements forts :
- Q4 casse l’extraction de données : le score chute à 59. Le gain de mémoire ne vaut pas la régression de fiabilité.
- En régime bandwidth-bound, plus de bits = moins de débit. Q5_K_XL est le point retenu sur le front de Pareto : qualité au plafond (ou presque) et meilleur débit (~73 t/s) que Q6/Q8 plus lourds. Q6 grappille un point d’extraction mais coûte 5,6 Go et 15 t/s.
C’est exactement le type d’arbitrage que la nomenclature seule ne suffit pas à trancher : il faut mesurer sur sa propre charge.
Recommandations par cas d’usage
| Priorité | Meilleur choix | Runtime | Notes |
|---|---|---|---|
| Production vLLM | Marlin (GPTQ) | vLLM | Plus rapide que FP16, -75 % VRAM |
| Qualité maximale | BitsandBytes / AWQ | Transformers / vLLM | Perplexité la plus proche du baseline |
| Local (Apple/CPU) | GGUF Q4_K_M | llama.cpp / Ollama | Seul format avec offload CPU efficace |
| Expérimentation | BitsandBytes | Transformers | Pas de modèle pré-quantifié requis |
| Full GPU (desktop) | EXL2 / EXL3 | ExLlamaV2/V3 | Meilleur compromis vitesse/qualité |
| Low bitrate extrême | EXL3 / GGUF IQ2 | ExLlamaV3 / llama.cpp | 70B en < 16 Go VRAM |
| MoE (DeepSeek, Qwen) | REAP | vLLM / Transformers | Pruning experts, -50 % taille |