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 biblioteca bitsandbytes ofrece herramientas de cuantización para LLMs a través de un envoltorio ligero de Python alrededor de funciones de aceleradores de hardware. Permite trabajar con modelos grandes utilizando recursos computacionales limitados al reducir su huella de memoria.

En su núcleo, bitsandbytes ofrece:

  • Capas lineales cuantizadas: capas Linear8bitLt y Linear4bit que reemplazan las capas lineales estándar de PyTorch por alternativas cuantizadas eficientes en memoria
  • Optimized Optimizers: 8-bit versions of common optimizers through its optim module, enabling training of large models with reduced memory requirements
  • Multiplicación de matrices: Operaciones de multiplicación de matrices optimizadas que aprovechan el formato cuantizado

bitsandbytes ofrece dos funciones principales de cuantización:

  1. LLM.int8() - Un método de cuantización de 8 bits que hace que la inferencia sea más accesible sin una degradación significativa del rendimiento. A diferencia de la cuantización ingenua, LLM.int8() preserva dinámicamente una mayor precisión para los cálculos críticos, evitando la pérdida de información en las partes sensibles del modelo.

  2. QLoRA - Una técnica de cuantización de 4 bits que comprime los modelos aún más manteniendo su capacidad de entrenamiento mediante la inserción de un pequeño conjunto de pesos de adaptación de bajo rango (LoRA) entrenables.

Nota: Para una experiencia de cuantización más amigable, puedes utilizar el espacio de la comunidad de bitsandbytes.

Ejecute el siguiente comando para instalar bitsandbytes.

pip install --upgrade transformers accelerate bitsandbytes

Para compilar desde el código fuente, siga las instrucciones de la guía de instalación de bitsandbytes.

Compatibilidad con el hardware

bitsandbytes es compatible con GPUs de NVIDIA para versiones de CUDA 11.8 - 13.0, Intel XPU, Intel Gaudi (HPU) y CPU. Existe un esfuerzo en curso para dar soporte a plataformas adicionales. Si te interesa proporcionar comentarios o realizar pruebas, consulta el repositorio de bitsandbytes para obtener más información.

GPUs de NVIDIA (CUDA)

Este backend es compatible con las plataformas Linux x86-64, Linux aarch64 y Windows.

CaracterísticaRequisito mínimo de hardware
Optimizadores de 8 bitsGPUs NVIDIA Pascal (serie GTX 10X0, P100) o más recientes *
LLM.int8()GPUs NVIDIA Turing (serie RTX 20X0, T4) o más recientes
Cuantización NF4/FP4GPUs NVIDIA Pascal (serie GTX 10X0, P100) o más recientes *

GPUs de Intel (XPU)

Este backend se admite en las plataformas Linux x86-64 y Windows x86-64.

Intel Gaudi (HPU)

Este backend es compatible con Linux x86-64 para Gaudi2 y Gaudi3.

CPU

Este backend se admite en las plataformas Linux x86-64, Linux aarch64 y Windows x86-64.

Ejemplos de cuantización

Cuantice un modelo pasando una BitsAndBytesConfig a from_pretrained(). Esto funciona para cualquier modelo de cualquier modalidad, siempre que admita Accelerate y contenga capas torch.nn.Linear.

8-bit
4-bit
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
)

Por defecto, todos los demás módulos, como torch.nn.LayerNorm, se configuran con el dtype de torch predeterminado. Puede cambiar el tipo de datos de estos módulos con el parámetro dtype. Establecer dtype="auto" carga el modelo con el tipo de datos definido en el archivo config.json del modelo.

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

Una vez que un modelo está cuantizado a 8 bits, no se pueden subir los pesos cuantizados al Hub a menos que se esté utilizando la última versión de Transformers y bitsandbytes. Si se tienen las últimas versiones, se puede subir el modelo de 8 bits al Hub con push_to_hub(). Primero se sube el archivo config.json de cuantización, seguido de los pesos del modelo cuantizado.

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

El entrenamiento en 8 y 4 bits solo se admite para entrenar parámetros extra.

Comprueba tu huella de memoria con get_memory_footprint.

print(model.get_memory_footprint())

Cargue modelos cuantizados con from_pretrained() sin un quantization_config.

from transformers import AutoModelForCausalLM, AutoTokenizer

model = AutoModelForCausalLM.from_pretrained("{your_username}/bloom-560m-8bit", device_map="auto")

LLM.int8

Esta sección explora algunas de las características específicas de la cuantización de 8 bits, como el offloading, los umbrales de valores atípicos, el omitir la conversión de módulos y el finetuning.

Descarga

Los modelos de 8 bits pueden descargar los pesos entre la CPU y la GPU para que quepan en memoria modelos muy grandes. Los pesos que se envían a la CPU se almacenan en float32 y no se convierten a 8 bits. Por ejemplo, habilite la descarga para bigscience/bloom-1b7 mediante BitsAndBytesConfig.

from transformers import AutoModelForCausalLM, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(llm_int8_enable_fp32_cpu_offload=True)

Diseña un mapa de dispositivos personalizado para que todo quepa en tu GPU, excepto lm_head, que se despacha a la CPU.

device_map = {
    "transformer.word_embeddings": 0,
    "transformer.word_embeddings_layernorm": 0,
    "lm_head": "cpu",
    "transformer.h": 0,
    "transformer.ln_f": 0,
}

Ahora carga tu modelo con el device_map y el quantization_config personalizados.

model_8bit = AutoModelForCausalLM.from_pretrained(
    "bigscience/bloom-1b7",
    dtype="auto",
    device_map=device_map,
    quantization_config=quantization_config,
)

Umbral de valores atípicos

Un “outlier” es un valor de estado oculto que supera cierto umbral, y estos valores se calculan en fp16. Aunque los valores suelen tener una distribución normal ([-3.5, 3.5]), esta distribución puede ser muy diferente en modelos grandes ([-60, 6] o [6, 60]). La cuantización de 8 bits funciona bien para valores ~5, pero más allá de eso, hay un penalización significativa en el rendimiento. Un valor de umbral por defecto adecuado es 6, pero puede ser necesario un umbral más bajo para modelos más inestables (modelos pequeños o finetuning).

Para encontrar el mejor umbral para tu modelo, experimenta con el parámetro llm_int8_threshold en BitsAndBytesConfig. Por ejemplo, establecer el umbral en 0.0 acelera significativamente la inferencia, a costa de una posible pérdida de precisión.

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,
)

Omitir la conversión de módulos

Para algunos modelos, como Jukebox, no es necesario cuantizar cada módulo a 8 bits, ya que esto puede provocar inestabilidad. En el caso de Jukebox, hay varios módulos lm_head que deben omitirse mediante el parámetro llm_int8_skip_modules en 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,
)

Ajuste fino

La biblioteca PEFT permite el ajuste fino de modelos grandes como flan-t5-large y facebook/opt-6.7b con cuantización de 8 bits. No es necesario pasar el parámetro device_map para el entrenamiento, ya que carga automáticamente el modelo en una GPU. Sin embargo, aún puedes personalizar el mapa de dispositivos con el parámetro device_map (device_map="auto" solo debe usarse para inferencia).

QLoRA

Esta sección explora algunas de las características específicas de la cuantización de 4 bits, como el cambio del tipo de datos de cálculo, el tipo de datos Normal Float 4 (NF4) y la cuantización anidada.

Tipo de datos de cálculo

Cambie el tipo de datos de float32 (el valor predeterminado) a bf16 en BitsAndBytesConfig para acelerar el cálculo.

import torch
from transformers import BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16)

Float 4 normal (NF4)

NF4 es un tipo de datos de 4 bits del artículo QLoRA, adaptado para pesos inicializados desde una distribución normal. Debe utilizar NF4 para entrenar modelos base de 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)

Para la inferencia, el bnb_4bit_quant_type no tiene un gran impacto en el rendimiento. Sin embargo, para mantener la coherencia con los pesos del modelo, debe usar los valores de bnb_4bit_compute_dtype y dtype.

Cuantización anidada

La cuantización anidada puede ahorrar memoria adicional sin un coste de rendimiento extra. Esta característica realiza una segunda cuantización de los pesos ya cuantizados para ahorrar 0,4 bits/parámetro adicionales. Por ejemplo, con cuantización anidada, puedes hacer un ajuste fino de un modelo Llama-13b en una GPU NVIDIA T4 de 16 GB con una longitud de secuencia de 1024, un tamaño de lote de 1 y habilitando la acumulación de gradientes con 4 pasos.

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)

Descomprimir modelos de bitsandbytes

Una vez cuantizado, puedes dequantize() un modelo a la precisión original, aunque esto puede provocar cierta pérdida de calidad. Asegúrate de tener suficiente memoria de GPU para cargar el modelo decuantizado.

from transformers import AutoModelForCausalLM, BitsAndBytesConfig, AutoTokenizer

model = AutoModelForCausalLM.from_pretrained("facebook/opt-125m", BitsAndBytesConfig(load_in_4bit=True))
model.dequantize()

Recursos

Obtenga más información sobre los detalles de la cuantización de 8 bits en A Gentle Introduction to 8-bit Matrix Multiplication for transformers at scale using Hugging Face Transformers, Accelerate and bitsandbytes.

Prueba la cuantización de 4 bits en este cuaderno y conoce más detalles en Making LLMs even more accessible with bitsandbytes, 4-bit quantization and QLoRA.

Update on GitHub