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

A biblioteca bitsandbytes fornece ferramentas de quantização para LLMs por meio de um wrapper Python leve em torno de funções de aceleradores de hardware. Ela permite trabalhar com modelos grandes usando recursos computacionais limitados, reduzindo sua pegada de memória.

No seu núcleo, o bitsandbytes fornece:

  • Camadas lineares quantizadas: camadas Linear8bitLt e Linear4bit que substituem as camadas lineares padrão do PyTorch por alternativas quantizadas com uso eficiente de memória
  • Otimizadores otimizados: versões de 8 bits de otimizadores comuns por meio do módulo optim, permitindo o treinamento de modelos grandes com requisitos de memória reduzidos
  • Multiplicação de matrizes: Operações de multiplicação de matrizes otimizadas que aproveitam o formato quantizado

bitsandbytes oferece dois recursos principais de quantização:

  1. LLM.int8() - Um método de quantização de 8 bits que torna a inferência mais acessível sem uma degradação significativa de desempenho. Diferentemente da quantização ingênua, o LLM.int8() preserva dinamicamente uma precisão maior para cálculos críticos, evitando a perda de informações em partes sensíveis do modelo.

  2. QLoRA - Uma técnica de quantização de 4 bits que comprime os modelos ainda mais, mantendo a treinabilidade ao inserir um pequeno conjunto de pesos treináveis de adaptação de baixo rank (LoRA).

Observação: Para uma experiência de quantização mais amigável, você pode usar o espaço da comunidade do bitsandbytes.

Execute o comando abaixo para instalar o bitsandbytes.

pip install --upgrade transformers accelerate bitsandbytes

Para compilar a partir do código-fonte, siga as instruções no guia de instalação do bitsandbytes.

Compatibilidade de Hardware

O bitsandbytes é compatível com GPUs NVIDIA para versões de CUDA 11.8 - 13.0, Intel XPU, Intel Gaudi (HPU) e CPU. Há um esforço contínuo para suportar outras plataformas. Se você tiver interesse em fornecer feedback ou realizar testes, consulte o repositório do bitsandbytes para mais informações.

GPUs da NVIDIA (CUDA)

Este backend é suportado nas plataformas Linux x86-64, Linux aarch64 e Windows.

RecursoRequisito Mínimo de Hardware
Otimizadores de 8 bitsGPUs NVIDIA Pascal (série GTX 10X0, P100) ou mais recentes *
LLM.int8()GPUs NVIDIA Turing (série RTX 20X0, T4) ou mais recentes
Quantização NF4/FP4GPUs NVIDIA Pascal (série GTX 10X0, P100) ou mais recentes *

GPUs da Intel (XPU)

Este backend é suportado nas plataformas Linux x86-64 e Windows x86-64.

Intel Gaudi (HPU)

Este backend é suportado no Linux x86-64 para Gaudi2 e Gaudi3.

CPU

Este backend é suportado nas plataformas Linux x86-64, Linux aarch64 e Windows x86-64.

Exemplos de Quantização

Quantize um modelo passando um BitsAndBytesConfig para from_pretrained(). Isso funciona para qualquer modelo em qualquer modalidade, desde que ele suporte Accelerate e contenha camadas 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 padrão, todos os outros módulos, como torch.nn.LayerNorm, são definidos com o dtype padrão do torch. Você pode alterar o tipo de dados desses módulos com o parâmetro dtype. Definir dtype="auto" carrega o modelo no tipo de dados definido no arquivo config.json do 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

Uma vez que um modelo é quantizado para 8 bits, você não pode enviar os pesos quantizados para o Hub, a menos que esteja usando as versões mais recentes de Transformers e bitsandbytes. Se você tiver as versões mais recentes, pode enviar o modelo de 8 bits para o Hub com push_to_hub(). O arquivo de configuração de quantização config.json é enviado primeiro, seguido pelos pesos quantizados do modelo.

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

O treinamento em 8 e 4 bits é suportado apenas para o treinamento de parâmetros extra.

Verifique a sua pegada de memória com get_memory_footprint.

print(model.get_memory_footprint())

Carregue modelos quantizados com from_pretrained() sem um quantization_config.

from transformers import AutoModelForCausalLM, AutoTokenizer

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

LLM.int8

Esta seção explora alguns dos recursos específicos da quantização de 8 bits, como offloading, limiares de outliers, omissão da conversão de módulos e finetuning.

Offloading

Modelos de 8 bits podem transferir pesos entre a CPU e a GPU para caber modelos muito grandes na memória. Os pesos enviados para a CPU são armazenados em float32 e não são convertidos para 8 bits. Por exemplo, ative o offloading para bigscience/bloom-1b7 por meio de BitsAndBytesConfig.

from transformers import AutoModelForCausalLM, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(llm_int8_enable_fp32_cpu_offload=True)

Projete um mapa de dispositivos personalizado para caber tudo na sua GPU, exceto o lm_head, que é despachado para a CPU.

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

Agora, carregue seu modelo com o device_map e o quantization_config personalizados.

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

Limiar de outlier

Um “outlier” é um valor de estado oculto maior que um determinado limiar, e esses valores são calculados em fp16. Embora os valores geralmente sigam uma distribuição normal ([-3,5, 3,5]), essa distribuição pode ser muito diferente em modelos grandes ([-60, 6] ou [6, 60]). A quantização de 8 bits funciona bem para valores ~5, mas, além disso, há uma penalidade significativa de desempenho. Um bom valor de limiar padrão é 6, mas um limiar menor pode ser necessário para modelos mais instáveis (modelos pequenos ou finetuning).

Para encontrar o melhor limiar para o seu modelo, experimente com o parâmetro llm_int8_threshold em BitsAndBytesConfig. Por exemplo, definir o limiar como 0.0 acelera significativamente a inferência, com o possível custo de alguma perda de precisão.

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

Pular a conversão de módulos

Para alguns modelos, como o Jukebox, não é necessário quantizar todos os módulos para 8 bits, pois isso pode causar instabilidade. No Jukebox, há vários módulos lm_head que devem ser ignorados usando o parâmetro llm_int8_skip_modules em 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

A biblioteca PEFT suporta o ajuste fino de modelos grandes, como flan-t5-large e facebook/opt-6.7b, com quantização de 8 bits. Não é necessário passar o parâmetro device_map para o treinamento, pois o modelo é carregado automaticamente em uma GPU. No entanto, você ainda pode personalizar o mapa de dispositivos com o parâmetro device_map (device_map="auto" deve ser usado apenas para inferência).

QLoRA

Esta seção explora alguns dos recursos específicos da quantização de 4 bits, como a alteração do tipo de dados de computação, o tipo de dados Normal Float 4 (NF4) e a quantização aninhada.

Tipo de dados de computação

Alterne o tipo de dados de float32 (o valor padrão) para bf16 em BitsAndBytesConfig para acelerar o 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 é um tipo de dados de 4 bits do paper QLoRA, adaptado para pesos inicializados a partir de uma distribuição normal. Você deve usar NF4 para treinar 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 inferência, o bnb_4bit_quant_type não tem um grande impacto no desempenho. No entanto, para manter a consistência com os pesos do modelo, você deve usar os valores de bnb_4bit_compute_dtype e dtype.

Quantização aninhada

A quantização aninhada pode economizar memória adicional sem custo de desempenho extra. Esse recurso realiza uma segunda quantização dos pesos já quantizados para economizar mais 0,4 bits/parâmetro. Por exemplo, com a quantização aninhada, é possível fazer o ajuste fino de um modelo Llama-13b em uma GPU NVIDIA T4 de 16GB com comprimento de sequência de 1024, tamanho de lote de 1 e acúmulo de gradiente habilitado com 4 etapas.

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)

Desquantizar modelos bitsandbytes

Uma vez quantizado, você pode dequantize() um modelo para a precisão original, mas isso pode resultar em alguma perda de qualidade. Certifique-se de ter memória de GPU suficiente para acomodar o modelo dequantizado.

from transformers import AutoModelForCausalLM, BitsAndBytesConfig, AutoTokenizer

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

Recursos

Saiba mais sobre os detalhes da quantização de 8 bits em A Gentle Introduction to 8-bit Matrix Multiplication for transformers at scale using Hugging Face Transformers, Accelerate and bitsandbytes.

Experimente a quantização de 4 bits neste notebook e saiba mais sobre os detalhes em Making LLMs even more accessible with bitsandbytes, 4-bit quantization and QLoRA.

Update on GitHub