Chapitre 2 : Quantification 4 bits avec bitsandbytes
Comprendre et implémenter une quantification efficace
La bibliothèque bitsandbytes permet la quantification en 4 bits et 8 bits pour un chargement et un entraînement de modèles efficaces.
Notions de base sur la quantification
Qu'est-ce que la quantification ?
Conversion de valeurs haute précision en basse précision :
Float16 : 2 octets par paramètre
Int8 : 1 octet par paramètre
Int4 : 0,5 octet par paramètre
Économies de mémoire
# Mémoire du modèle 7B
fp32 = 7e9 * 4 / 1e9 # 28 GB
fp16 = 7e9 * 2 / 1e9 # 14 GB
int8 = 7e9 * 1 / 1e9 # 7 GB
int4 = 7e9 * 0.5 / 1e9 # 3.5 GB
BitsAndBytesConfig
Configuration complète
from transformers import BitsAndBytesConfig
import torch
bnb_config = BitsAndBytesConfig(
# Utiliser la quantification 4 bits
load_in_4bit=True,
# Type de quantification NF4 (recommandé)
bnb_4bit_quant_type="nf4",
# Calculer en bfloat16 pour la stabilité
bnb_4bit_compute_dtype=torch.bfloat16,
# Double quantification pour des économies supplémentaires
bnb_4bit_use_double_quant=True,
)
Explications des paramètres
| Paramètre | Options | Recommandation |
|---|---|---|
load_in_4bit | True/False | True pour QLoRA |
bnb_4bit_quant_type | "nf4", "fp4" | "nf4" (meilleure qualité) |
bnb_4bit_compute_dtype | torch.bfloat16, torch.float16 | bfloat16 (plus stable) |
bnb_4bit_use_double_quant | True/False | True (plus d'économies) |
NF4 vs FP4
NF4 (NormalFloat4)
- Conçu pour les poids normalement distribués
- Valeurs égales dans chaque bin de quantification
- Meilleure qualité pour les réseaux neuronaux
FP4 (Float4)
- Quantification uniforme
- Plus simple mais moins optimal pour les poids
# NF4 recommandé
bnb_4bit_quant_type="nf4"
Chargement d'un modèle quantifié
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3.1-8B",
quantization_config=bnb_config,
device_map="auto",
torch_dtype=torch.bfloat16,
)
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.1-8B")
# Vérifier la mémoire
print(f"Memory: {torch.cuda.memory_allocated() / 1e9:.2f} GB")
Préparation pour l'entraînement
from peft import prepare_model_for_kbit_training
# Étapes de préparation nécessaires :
# 1. Activer le gradient checkpointing
# 2. Convertir les normes de couche en float32
# 3. Activer les gradients d'entrée
model = prepare_model_for_kbit_training(model)
Ce que fait prepare_model_for_kbit_training
- Active le gradient checkpointing pour l'efficacité mémoire
- Convertit les normes de couche en float32 pour la stabilité
- Définit requires_grad de manière appropriée
- Gère les embeddings pour les gradients d'entrée
Configuration complète de QLoRA
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
# 1. Configuration de quantification
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_use_double_quant=True,
)
# 2. Charger le modèle quantifié
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3.1-8B",
quantization_config=bnb_config,
device_map="auto",
)
# 3. Préparer pour l'entraînement
model = prepare_model_for_kbit_training(model)
# 4. Ajouter LoRA
lora_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
lora_dropout=0.05,
task_type="CAUSAL_LM",
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
Points clés à retenir
✅ bitsandbytes permet la quantification 4 bits/8 bits
✅ NF4 est optimal pour les poids des réseaux neuronaux
✅ La double quantification ajoute ~11% d'économies supplémentaires
✅ Utilisez prepare_model_for_kbit_training avant d'ajouter LoRA
✅ Le type de calcul doit être bfloat16 pour la stabilité
Continuez vers le Chapitre 3 : Entraînement économe en mémoire →