Aller au contenu principal

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ètreOptionsRecommandation
load_in_4bitTrue/FalseTrue pour QLoRA
bnb_4bit_quant_type"nf4", "fp4""nf4" (meilleure qualité)
bnb_4bit_compute_dtypetorch.bfloat16, torch.float16bfloat16 (plus stable)
bnb_4bit_use_double_quantTrue/FalseTrue (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​

  1. Active le gradient checkpointing pour l'efficacité mémoire
  2. Convertit les normes de couche en float32 pour la stabilité
  3. Définit requires_grad de manière appropriée
  4. 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 →