SqueezeLLM (Dense-and-Sparse Quantization)#
TL;DR — SqueezeLLM combine deux innovations : la quantification non-uniforme sensible à l'importance des poids (les poids critiques reçoivent plus de précision) et la décomposition dense+sparse (les outliers sont extraits et stockés séparément en haute précision). Résultat : une compression 3-bit quasi lossless avec accélération de 2.3× sur GPU.
Le problème fondamental (expliqué pour un néophyte)#
Deux problèmes se posent quand on quantifie un LLM à très basse précision (3-bit) :
-
Tous les poids ne sont pas égaux : certains poids sont critiques pour la qualité du modèle, d'autres peuvent être approximés sans dommage. Une quantification uniforme traite tout le monde pareil — c'est suboptimal.
-
Les outliers ruinent la quantification : quelques poids avec des valeurs extrêmes (outliers) forcent l'échelle de quantification à s'étaler, réduisant la précision pour la majorité des poids « normaux ».
· · · · · ·"] --> S2["Scale petite
→ bonne résolution"] end subgraph AVEC["Avec outliers"] direction TB A1["Distribution étalée
· · · · · · ·"] --> A2["Scale ÉNORME
(à cause des · outliers)
→ résolution médiocre
pour 99% des poids"] end
SqueezeLLM résout les deux :
- Non-uniform quantization : alloue plus de bins aux poids sensibles (fonction de leur second ordre / Hessienne)
- Dense+Sparse decomposition : extrait les outliers dans une représentation sparse séparée, libérant l'espace de quantification pour les poids normaux
Papier source#
| Élément | Détail |
|---|---|
| Titre | SqueezeLLM: Dense-and-Sparse Quantization |
| Auteurs | Sehoon Kim, Coleman Hooper, Amir Gholami, Zhen Dong, Xiuyu Li, Sheng Shen, Michael W. Mahoney, Kurt Keutzer (UC Berkeley / SqueezeAILab) |
| Date | Juin 2023 |
| Publication | ICML 2024 |
| arXiv | 2306.07629 |
| Code | github.com/SqueezeAILab/SqueezeLLM |
Mécanisme#
Niveau néophyte#
Imagine que tu dois peindre un tableau avec un nombre limité de couleurs (tes « bins » de quantification). Tu pourrais répartir ces couleurs uniformément (quantification uniforme) — mais ce serait gaspiller des couleurs dans des zones que personne ne regarde.
SqueezeLLM fait deux choses intelligentes :
1. Concentre les couleurs là où ça compte : les zones du tableau les plus détaillées (poids sensibles) reçoivent plus de nuances de couleur.
2. Sépare les couleurs extrêmes : les quelques taches de couleur très différentes (outliers) sont peintes séparément avec des tubes de précision, pour ne pas perturber la palette principale.
Niveau intermédiaire#
SqueezeLLM repose sur deux piliers techniques :
1. Sensitivity-based non-uniform quantization
Au lieu d'utiliser des bins également espacés (quantification uniforme), SqueezeLLM calcule la sensibilité de chaque poids via la diagonale de la Hessienne et alloue les bins de quantification proportionnellement :
Uniforme (GPTQ, AWQ) : bins |-|-|-|-|-|-|-|-| → espacement régulier.
Non-uniforme (SqueezeLLM) : bins |--|-|-|---|--|-|-|--| → plus de bins où les poids sont sensibles (concentrés près de certaines valeurs).
Les poids sensibles (où une petite erreur cause une grande perte de qualité) reçoivent une résolution plus fine. C'est l'analogue de l'allocation optimale de bits en théorie de l'information (comme le companding en audio).
2. Dense-and-Sparse decomposition
Avant la quantification, SqueezeLLM sépare les poids en deux composantes :
W = W_dense + W_sparse
W_dense : ~99% des poids, distribution « normale »
→ quantifiés en 3-4 bit
W_sparse : ~1% des poids = outliers
→ stockés en FP16 dans un format sparse
(seuls les indices et valeurs non-zéros sont stockés)
Cette décomposition élimine les outliers de la distribution dense, permettant une quantification beaucoup plus précise de la majorité des poids.
Niveau tech avancé#
Non-uniform quantization via Lloyd-Max optimisé
SqueezeLLM détermine les bins de quantification en minimisant l'erreur attendue pondérée par la sensibilité :
Minimiser : Σᵢ sᵢ · (wᵢ − q(wᵢ))²
où sᵢ = [H⁻¹]ᵢᵢ (sensibilité du poids i, dérivée de la Hessienne)
q(wᵢ) = valeur quantifiée
L'optimisation des bins utilise un algorithme de type Lloyd-Max modifié pour incorporer les poids de sensibilité :
- Initialiser les bins (estimation statistique)
- Assigner chaque poids au bin le plus proche (pondéré par sᵢ)
- Mettre à jour les centres de bins (moyenne pondérée)
- Répéter jusqu'à convergence
Sélection des outliers
Les outliers sont identifiés par leur sensibilité (et non simplement par leur magnitude) : un poids avec une valeur modérée mais une très haute sensibilité (la Hessienne indique que ce poids est critique) peut aussi être extrait vers la composante sparse. Le critère :
Poids i est outlier si : sᵢ · (wᵢ − q(wᵢ))² > seuil
→ on extrait les poids dont l'erreur de quantification pondérée
par la sensibilité dépasse un seuil
Résultat : seuls ~0.45% des poids sont extraits en sparse, mais ces poids captent l'essentiel de l'erreur de quantification potentielle.
Illustration : la décomposition Dense+Sparse#
avec outliers ● qui écrasent l'échelle de quantification"] --> DECOMP DECOMP["Dense + Sparse Decomposition"] --> DENSE DECOMP --> SPARSE subgraph DENSE["W_dense (~99% des poids, sans outliers)"] DQ["Quantification 3-bit non-uniforme
(Lloyd-Max pondéré)"] end subgraph SPARSE["W_sparse (~1% = outliers)"] SS["Stockage format sparse
● (row, col, value_FP16)
Précision: FP16 complète
Overhead minime car < 1% des poids"] end DENSE --> RECON SPARSE --> RECON RECON["Reconstruction à l'inférence
W_reconstruit = déquant(W_dense_3bit) + W_sparse_FP16
✅ Erreur totale minimisée"]
Process complet SqueezeLLM#
Calculer la Hessienne diagonale par couche
→ Sensibilité de chaque poids"] --> S2 S2["2. Outlier Detection
Identifier les poids dont sᵢ · (wᵢ − q(wᵢ))² dépasse le seuil
→ ~0.45% des poids extraits"] --> SPLIT SPLIT --> DENSE SPLIT --> SPARSE DENSE["W_dense (99% des poids)"] --> QUANT QUANT["3. Non-uniform Quantization
Lloyd-Max pondéré par sensibilité
→ 3-bit"] --> MERGE SPARSE["W_sparse (0.45% outliers)"] --> MERGE MERGE["4. Modèle quantifié SqueezeLLM
W_dense_3bit + W_sparse_FP16
Kernels GPU custom → 2.3× speedup sur A6000"]
Bits / Formats supportés#
| Composante | Bits | Format | Supporté | Notes |
|---|---|---|---|---|
| Dense | 3-bit | Non-uniform (Lloyd-Max) | ✅ | Configuration principale |
| Dense | 4-bit | Non-uniform | ✅ | Configuration conservative |
| Sparse | 16-bit | FP16 sparse | ✅ | Toujours FP16 pour les outliers |
| Dense | 2-bit | Non-uniform | ⚠️ | Possible mais dégradation notable |
Le bitrate effectif est : ~3 bits pour la partie dense + ~0.1 bit/poids pour la partie sparse = ~3.1 bits par poids au total.
Résultats#
Llama (perplexité sur WikiText2 — plus bas = mieux)#
| Bits/poids | FP16 (ref) | SqueezeLLM | GPTQ | AWQ |
|---|---|---|---|---|
| 16 (ref) | 5.47 | — | — | — |
| ~3 | — | ~5.8–6.0 | 6.62 | 6.40 |
SqueezeLLM réduit le gap de perplexité (vs FP16) de 2.1× par rapport au SOTA à mémoire équivalente.
Métriques clés#
| Métrique | Valeur | Contexte |
|---|---|---|
| Réduction du gap de PPL | 2.1× | vs SOTA à mémoire équivalente |
| Speedup GPU | 2.3× | Sur NVIDIA A6000 |
| Compression | ~4–5× | FP16 → 3-bit dense + sparse |
| Qualité 3-bit | Quasi lossless | Perte < 1% vs FP16 |
Le gain de la décomposition dense+sparse#
●···· ···· ··● ······"] --> NS2["Outliers étalent l'échelle
→ résolution médiocre
❌ PPL dégradée"] end subgraph AVEC["Quantification 3-bit AVEC dense+sparse (SqueezeLLM)"] direction TB AV1["Dense (sans outliers)
···· ···· ··· ······"] --> AV2["Échelle resserrée
→ excellente résolution"] AV3["Sparse (outliers isolés)
● ● ● (en FP16)"] --> AV4["Aucune perte
sur les poids critiques"] AV2 --> AV5["✅ PPL quasi identique
au modèle FP16 original"] AV4 --> AV5 end
Avantages et inconvénients#
| ✅ Avantages | ❌ Inconvénients |
|---|---|
| Réduit le gap de perplexité de 2.1× vs SOTA à mémoire équivalente | Format sparse complexe à gérer |
| Compression 3-bit quasi lossless | Implémentation GPU custom nécessaire |
| Speedup de 2.3× sur GPU | Moins universellement supporté que GPTQ/AWQ |
| Quantification non-uniforme théoriquement optimale | Overhead de la décomposition dense+sparse |
| Outliers traités sans compromis (FP16) | Calibration requise (Hessienne) |
| Sensibilité adaptative par poids | Moins flexible dans le choix de bits |
Outils et implémentations#
SqueezeLLM (SqueezeAILab)#
# Cloner le repository
git clone https://github.com/SqueezeAILab/SqueezeLLM.git
cd SqueezeLLM
# Installer
pip install -e .
Quantification#
# 1. Générer les données de sensibilité (Hessienne)
python squeeze_llm/generate_sensitivity_data.py \
--model meta-llama/Llama-2-7b-hf \
--output_dir ./sensitivity_data
# 2. Détection des outliers
python squeeze_llm/get_outliers.py \
--model meta-llama/Llama-2-7b-hf \
--sensitivity_data ./sensitivity_data \
--output_dir ./outlier_data
# 3. Quantification dense+sparse 3-bit
python squeeze_llm/quantization.py \
--model meta-llama/Llama-2-7b-hf \
--sensitivity_data ./sensitivity_data \
--outlier_data ./outlier_data \
--nbits 3 \
--output_dir ./llama-7b-squeezellm-3bit
Exemple pratique#
Quantifier Llama-2-7B avec SqueezeLLM#
# 1. Installer
git clone https://github.com/SqueezeAILab/SqueezeLLM.git
cd SqueezeLLM
pip install -e .
# 2. Pipeline complet de quantification
# Étape A : sensibilité (Hessienne)
python squeeze_llm/generate_sensitivity_data.py \
--model meta-llama/Llama-2-7b-hf \
--output_dir ./sens
# Étape B : outliers
python squeeze_llm/get_outliers.py \
--model meta-llama/Llama-2-7b-hf \
--sensitivity_data ./sens \
--output_dir ./outliers
# Étape C : quantification 3-bit
python squeeze_llm/quantization.py \
--model meta-llama/Llama-2-7b-hf \
--sensitivity_data ./sens \
--outlier_data ./outliers \
--nbits 3 \
--output_dir ./llama-2-7b-squeezellm
# 3. Résultat attendu
# ┌──────────────────────────────────────────────────┐
# │ Llama-2-7b FP16 : 13.5 GB │
# │ Llama-2-7b SqueezeLLM : ~3.2 GB (−76%) │
# │ Outliers extraits : ~0.45% des poids │
# │ Speedup inférence : 2.3× sur A6000 │
# │ PPL WikiText2 : ~5.8–6.0 │
# └──────────────────────────────────────────────────┘
Inférence avec le modèle quantifié#
# Inférence avec les kernels SqueezeLLM
python eval.py \
--model ./llama-2-7b-squeezellm \
--task wikitext \
--benchmark
# Résultat :
# Throughput : 2.3× plus rapide que FP16 baseline
# PPL : ~5.8 (vs 5.47 FP16 → perte < 6%)
Comparaison avec les alternatives#
| Méthode | Approche | Bits optimaux | Gestion des outliers | Calibration | PPL 3-bit |
|---|---|---|---|---|---|
| SqueezeLLM | Non-uniform + dense/sparse | 3-bit | ✅ Extraction sparse (FP16) | ✅ | ~5.8 |
| GPTQ | Uniforme + Hessienne | 4-bit | ❌ Dans la masse | ✅ | 6.62 |
| AWQ | Uniforme + scaling | 3-4 bit | ❌ Scaling partiel | ✅ | 6.40 |
| SpQR | Dense/sparse + GPTQ | 3-4 bit | ✅ Extraction sparse (FP16) | ✅ | ~5.7 |
| LLM.int8() | Mixed-precision | 8-bit | ✅ Séparation FP16 | ❌ | N/A |
SqueezeLLM et SpQR partagent l'idée de décomposition dense+sparse. SqueezeLLM y ajoute la quantification non-uniforme sensible à l'importance des poids, tandis que SpQR utilise GPTQ pour la partie dense.
Références#
- Papier SqueezeLLM — Kim et al., "SqueezeLLM: Dense-and-Sparse Quantization", ICML 2024 — arXiv:2306.07629
- Code officiel — github.com/SqueezeAILab/SqueezeLLM
- SqueezeAILab — github.com/SqueezeAILab — Laboratoire de recherche UC Berkeley spécialisé dans la compression de modèles
- Méthode comparable — Voir SpQR pour une approche dense+sparse similaire avec GPTQ
- Quantification non-uniforme — Lloyd-Max quantization, base théorique de l'allocation optimale de bins
- Page de référence — Voir aussi Quantification LLM pour le panorama complet