Transformers documentation
Bitsandbytes
Bitsandbytes
La bibliothèque bitsandbytes fournit des outils de quantification pour les LLM via un wrapper Python léger autour des fonctions des accélérateurs matériels. Elle permet de travailler avec de grands modèles en disposant de ressources de calcul limitées, en réduisant leur empreinte mémoire.
Au cœur de bitsandbytes, on trouve :
- Couches linéaires quantifiées : les couches
Linear8bitLtetLinear4bitqui remplacent les couches linéaires standard de PyTorch par des alternatives quantifiées plus économes en mémoire - Optimized Optimizers: 8-bit versions of common optimizers through its
optimmodule, enabling training of large models with reduced memory requirements - Multiplication de matrices : Opérations de multiplication de matrices optimisées qui exploitent le format quantifié
bitsandbytes propose deux fonctionnalités principales de quantification :
LLM.int8() – Une méthode de quantification en 8 bits qui rend l'inférence plus accessible sans dégradation significative des performances. Contrairement à une quantification naïve, LLM.int8() conserve dynamiquement une précision plus élevée pour les calculs critiques, évitant ainsi la perte d'informations dans les parties sensibles du modèle.
QLoRA - Une technique de quantification sur 4 bits qui compresse encore davantage les modèles tout en conservant leur capacité d'entraînement, en insérant un petit ensemble de poids d'adaptation de faible rang (LoRA) entraînables.
Remarque : Pour une expérience de quantification conviviale, vous pouvez utiliser l'espace communautaire
bitsandbytes.
Exécutez la commande ci-dessous pour installer bitsandbytes.
pip install --upgrade transformers accelerate bitsandbytes
Pour compiler à partir du code source, suivez les instructions du guide d'installation de bitsandbytes.
Compatibilité matérielle
bitsandbytes est pris en charge sur les GPU NVIDIA pour les versions CUDA 11.8 - 13.0, les XPU Intel, les Gaudi Intel (HPU) et le CPU. Des efforts sont en cours pour prendre en charge d'autres plateformes. Si vous souhaitez donner votre avis ou effectuer des tests, consultez le dépôt bitsandbytes pour plus d'informations.
GPU NVIDIA (CUDA)
Ce backend est pris en charge sur les plateformes Linux x86-64, Linux aarch64 et Windows.
| Fonctionnalité | Exigence matérielle minimale |
|---|---|
| Optimiseurs 8 bits | GPU NVIDIA Pascal (série GTX 10X0, P100) ou plus récent * |
| LLM.int8() | GPU NVIDIA Turing (série RTX 20X0, T4) ou plus récent |
| Quantification NF4/FP4 | GPU NVIDIA Pascal (série GTX 10X0, P100) ou plus récent * |
GPU Intel (XPU)
Ce backend est pris en charge sur les plateformes Linux x86-64 et Windows x86-64.
Intel Gaudi (HPU)
Ce backend est pris en charge sur Linux x86-64 pour Gaudi2 et Gaudi3.
CPU
Ce backend est pris en charge sur les plateformes Linux x86-64, Linux aarch64 et Windows x86-64.
Exemples de quantification
Quantifiez un modèle en passant une BitsAndBytesConfig à from_pretrained(). Cela fonctionne pour n'importe quel modèle de n'importe quelle modalité, à condition qu'il prenne en charge Accelerate et qu'il contienne des couches torch.nn.Linear.
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_8bit=True)
model_8bit = AutoModelForCausalLM.from_pretrained(
"bigscience/bloom-1b7",
device_map="auto",
quantization_config=quantization_config
)Par défaut, tous les autres modules, tels que torch.nn.LayerNorm, sont définis sur le type de données torch par défaut. Vous pouvez modifier le type de données de ces modules à l’aide du paramètre dtype. La valeur dtype="auto" charge le modèle dans le type de données défini dans le fichier config.json du modèle.
import torch
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_8bit=True)
model_8bit = AutoModelForCausalLM.from_pretrained(
"facebook/opt-350m",
device_map="auto",
quantization_config=quantization_config,
dtype="auto"
)
model_8bit.model.decoder.layers[-1].final_layer_norm.weight.dtypeUne fois un modèle quantisé en 8 bits, vous ne pouvez pas envoyer les poids quantisés sur le Hub à moins d’utiliser les dernières versions de Transformers et bitsandbytes. Si vous disposez des dernières versions, vous pouvez envoyer le modèle 8 bits sur le Hub à l’aide de push_to_hub(). Le fichier de configuration de quantization config.json est envoyé en premier, suivi des poids du modèle quantisé.
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_8bit=True)
model = AutoModelForCausalLM.from_pretrained(
"bigscience/bloom-560m",
device_map="auto",
quantization_config=quantization_config
)
model.push_to_hub("bloom-560m-8bit")from transformers import AutoModelForCausalLM, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_4bit=True)
model_4bit = AutoModelForCausalLM.from_pretrained(
"bigscience/bloom-1b7",
device_map="auto",
quantization_config=quantization_config
)Par défaut, tous les autres modules, tels que torch.nn.LayerNorm, sont convertis en torch.float16. Vous pouvez modifier le type de données de ces modules à l’aide du paramètre dtype. La valeur dtype="auto" charge le modèle dans le type de données défini dans le fichier config.json du modèle.
import torch
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_4bit=True)
model_4bit = AutoModelForCausalLM.from_pretrained(
"facebook/opt-350m",
device_map="auto",
quantization_config=quantization_config,
dtype="auto"
)
model_4bit.model.decoder.layers[-1].final_layer_norm.weight.dtypeAssurez-vous de disposer de la dernière version de bitsandbytes afin de pouvoir sérialiser les modèles 4 bits et les pousser sur le Hub à l’aide de push_to_hub(). Utilisez save_pretrained() pour enregistrer le modèle 4 bits localement.
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_4bit=True)
model = AutoModelForCausalLM.from_pretrained(
"bigscience/bloom-560m",
device_map="auto",
quantization_config=quantization_config
)
model.push_to_hub("bloom-560m-4bit")L'entraînement en 8 et 4 bits n'est pris en charge que pour l'entraînement de paramètres extra.
Vérifiez votre empreinte mémoire avec get_memory_footprint.
print(model.get_memory_footprint())Charger des modèles quantifiés avec from_pretrained() sans quantization_config.
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("{your_username}/bloom-560m-8bit", device_map="auto")LLM.int8
Cette section explore certaines fonctionnalités spécifiques de la quantification 8 bits, telles que le déchargement, les seuils de valeurs aberrantes, le saut de la conversion de modules et l’ajustement fin.
Offloading
Les modèles 8 bits peuvent décharger les poids entre le CPU et le GPU pour faire tenir des modèles très volumineux en mémoire. Les poids déchargés sur le CPU sont stockés en float32 et ne sont pas convertis en 8 bits. Par exemple, activez le déchargement pour bigscience/bloom-1b7 via BitsAndBytesConfig.
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(llm_int8_enable_fp32_cpu_offload=True)Concevez une carte de périphériques personnalisée pour tout placer sur votre GPU, à l’exception de lm_head, qui est affecté au CPU.
device_map = {
"transformer.word_embeddings": 0,
"transformer.word_embeddings_layernorm": 0,
"lm_head": "cpu",
"transformer.h": 0,
"transformer.ln_f": 0,
}Chargez maintenant votre modèle avec le device_map et le quantization_config personnalisés.
model_8bit = AutoModelForCausalLM.from_pretrained(
"bigscience/bloom-1b7",
dtype="auto",
device_map=device_map,
quantization_config=quantization_config,
)Seuil des valeurs aberrantes
Un « outlier » est une valeur d’état caché supérieure à un certain seuil, et ces valeurs sont calculées en fp16. Bien que les valeurs soient généralement distribuées normalement ([-3,5, 3,5]), cette distribution peut être très différente pour les grands modèles ([-60, 6] ou [6, 60]). La quantification 8 bits fonctionne bien pour des valeurs ~5, mais au-delà, il y a une pénalité de performance significative. Une valeur de seuil par défaut appropriée est 6, mais un seuil plus bas peut être nécessaire pour les modèles plus instables (petits modèles ou finetuning).
Pour trouver le meilleur seuil pour votre modèle, expérimentez avec le paramètre llm_int8_threshold dans BitsAndBytesConfig. Par exemple, définir le seuil à 0.0 accélère considérablement l'inférence, au prix potentiel d'une légère perte de précision.
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
model_id = "bigscience/bloom-1b7"
quantization_config = BitsAndBytesConfig(
llm_int8_threshold=0.0,
llm_int8_enable_fp32_cpu_offload=True
)
model_8bit = AutoModelForCausalLM.from_pretrained(
model_id,
dtype="auto",
device_map=device_map,
quantization_config=quantization_config,
)Passer la conversion du module
Pour certains modèles, comme Jukebox, il n’est pas nécessaire de quantiser chaque module en 8 bits, car cela peut en réalité provoquer une instabilité. Avec Jukebox, plusieurs modules lm_head doivent être ignorés à l’aide du paramètre llm_int8_skip_modules dans BitsAndBytesConfig.
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
model_id = "bigscience/bloom-1b7"
quantization_config = BitsAndBytesConfig(
llm_int8_skip_modules=["lm_head"],
)
model_8bit = AutoModelForCausalLM.from_pretrained(
model_id,
dtype="auto",
device_map="auto",
quantization_config=quantization_config,
)Affinage
La bibliothèque PEFT prend en charge l’ajustement fin de grands modèles comme flan-t5-large et facebook/opt-6.7b avec une quantification 8 bits. Il n’est pas nécessaire de passer le paramètre device_map pour l’entraînement, car le modèle est automatiquement chargé sur un GPU. Toutefois, vous pouvez toujours personnaliser la carte des appareils à l’aide du paramètre device_map (device_map="auto" ne doit être utilisé que pour l’inférence).
QLoRA
Cette section explore certaines fonctionnalités spécifiques de la quantification 4 bits, telles que le changement du type de données de calcul, le type de données Normal Float 4 (NF4) et la quantification imbriquée.
Type de données de calcul
Changez le type de données de float32 (la valeur par défaut) en bf16 dans BitsAndBytesConfig pour accélérer les calculs.
import torch
from transformers import BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16)Float 4 normal (NF4)
NF4 est un type de données sur 4 bits issu de l'article QLoRA, adapté aux poids initialisés à partir d'une distribution normale. Vous devez utiliser NF4 pour l'entraînement de modèles de base sur 4 bits.
from transformers import BitsAndBytesConfig
nf4_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
)
model_nf4 = AutoModelForCausalLM.from_pretrained(model_id, dtype="auto", quantization_config=nf4_config)Pour l’inférence, le bnb_4bit_quant_type n’a pas d’impact majeur sur les performances. Toutefois, pour rester cohérent avec les poids du modèle, vous devez utiliser les valeurs de bnb_4bit_compute_dtype et de dtype.
Quantification imbriquée
La quantification imbriquée permet d’économiser de la mémoire supplémentaire sans surcoût en termes de performances. Cette fonctionnalité effectue une seconde quantification des poids déjà quantifiés afin d’économiser 0,4 bit/paramètre supplémentaires. Par exemple, avec la quantification imbriquée, vous pouvez effectuer un fine-tuning d’un modèle Llama-13b sur un GPU NVIDIA T4 de 16 Go avec une longueur de séquence de 1024, une taille de lot de 1 et l’accumulation de gradients activée sur 4 étapes.
from transformers import BitsAndBytesConfig
double_quant_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_use_double_quant=True,
)
model_double_quant = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-13b-chat-hf", dtype="auto", quantization_config=double_quant_config)Déquantisation des modèles bitsandbytes
Une fois le modèle quantisé, vous pouvez le dequantize() pour revenir à la précision d'origine, mais cela peut entraîner une perte de qualité. Assurez-vous de disposer de suffisamment de mémoire GPU pour charger le modèle déquantisé.
from transformers import AutoModelForCausalLM, BitsAndBytesConfig, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("facebook/opt-125m", BitsAndBytesConfig(load_in_4bit=True))
model.dequantize()Ressources
En savoir plus sur les détails de la quantification 8 bits dans A Gentle Introduction to 8-bit Matrix Multiplication for transformers at scale using Hugging Face Transformers, Accelerate and bitsandbytes.
Essayez la quantification 4 bits dans ce notebook et en apprenez plus sur ses détails dans Making LLMs even more accessible with bitsandbytes, 4-bit quantization and QLoRA.
Update on GitHub