Transformers documentation
Bitsandbytes
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
Linear8bitLteLinear4bitque 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:
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.
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.
| Recurso | Requisito Mínimo de Hardware |
|---|---|
| Otimizadores de 8 bits | GPUs 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/FP4 | GPUs 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.
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.dtypeUma 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")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
)Por padrão, todos os outros módulos, como torch.nn.LayerNorm, são convertidos para torch.float16. 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_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.dtypeCertifique-se de ter a versão mais recente do bitsandbytes para que você possa serializar modelos de 4 bits e enviá-los ao Hub com push_to_hub(). Use save_pretrained() para salvar o modelo de 4 bits localmente.
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")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