Transformers documentation

Bitsandbytes

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

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 Linear8bitLt et Linear4bit qui 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 optim module, 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 :

  1. 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.

  2. 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 bitsGPU 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/FP4GPU 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.

8 bits
4 bits
Quantizing a model in 8-bit halves the memory-usage, and for large models, set `device_map="auto"` to efficiently distribute the weights across all available GPUs.
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.dtype

Une 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")

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