Pular para o conteúdo principal

Capítulo 2: Quantização 4-bit com bitsandbytes

Entendendo e Implementando Quantização Eficiente​

A biblioteca bitsandbytes permite quantização em 4-bit e 8-bit para carregamento e treinamento eficiente de modelos.


Fundamentos da Quantização​

O que é Quantização?​

Converter valores de alta precisão para precisão mais baixa:

Float16: 2 bytes por parâmetro
Int8: 1 byte por parâmetro
Int4: 0,5 bytes por parâmetro

Economia de Memória​

# Memória do modelo 7B
fp32 = 7e9 * 4 / 1e9 # 28 GB
fp16 = 7e9 * 2 / 1e9 # 14 GB
int8 = 7e9 * 1 / 1e9 # 7 GB
int4 = 7e9 * 0.5 / 1e9 # 3,5 GB

BitsAndBytesConfig​

Configuração Completa​

from transformers import BitsAndBytesConfig
import torch

bnb_config = BitsAndBytesConfig(
# Usar quantização 4-bit
load_in_4bit=True,

# Tipo de quantização NF4 (recomendado)
bnb_4bit_quant_type="nf4",

# Computar em bfloat16 para maior estabilidade
bnb_4bit_compute_dtype=torch.bfloat16,

# Quantização dupla para economia extra
bnb_4bit_use_double_quant=True,
)

Explicação dos Parâmetros​

ParâmetroOpçõesRecomendação
load_in_4bitTrue/FalseTrue para QLoRA
bnb_4bit_quant_type"nf4", "fp4""nf4" (melhor qualidade)
bnb_4bit_compute_dtypetorch.bfloat16, torch.float16bfloat16 (mais estável)
bnb_4bit_use_double_quantTrue/FalseTrue (mais economia)

NF4 vs FP4​

NF4 (NormalFloat4)​

  • Projetado para pesos com distribuição normal
  • Valores iguais em cada intervalo de quantização
  • Melhor qualidade para redes neurais

FP4 (Float4)​

  • Quantização uniforme
  • Mais simples, porém menos ideal para pesos
# NF4 recomendado
bnb_4bit_quant_type="nf4"

Carregando um Modelo Quantizado​

from transformers import AutoModelForCausalLM, AutoTokenizer

model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3.1-8B",
quantization_config=bnb_config,
device_map="auto",
torch_dtype=torch.bfloat16,
)

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.1-8B")

# Verificar memória
print(f"Memória: {torch.cuda.memory_allocated() / 1e9:.2f} GB")

Preparando para o Treinamento​

from peft import prepare_model_for_kbit_training

# Etapas necessárias de preparação:
# 1. Ativar gradient checkpointing
# 2. Converter layer norms para float32
# 3. Habilitar gradientes de entrada

model = prepare_model_for_kbit_training(model)

O que o prepare_model_for_kbit_training Faz​

  1. Ativa gradient checkpointing para eficiência de memória
  2. Converte layer norms para float32 para maior estabilidade
  3. Define requires_grad de forma apropriada
  4. Gerencia embeddings para gradientes de entrada

Configuração Completa do QLoRA​

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training

# 1. Configuração de quantização
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_use_double_quant=True,
)

# 2. Carregar modelo quantizado
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3.1-8B",
quantization_config=bnb_config,
device_map="auto",
)

# 3. Preparar para treinamento
model = prepare_model_for_kbit_training(model)

# 4. Adicionar LoRA
lora_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
lora_dropout=0.05,
task_type="CAUSAL_LM",
)

model = get_peft_model(model, lora_config)
model.print_trainable_parameters()

Principais Pontos​

✅ bitsandbytes permite quantização 4-bit/8-bit
✅ NF4 é ideal para pesos de redes neurais
✅ Quantização dupla adiciona ~11% de economia extra
✅ Use prepare_model_for_kbit_training antes de adicionar LoRA
✅ O dtype de computação deve ser bfloat16 para maior estabilidade


Continue para o Capítulo 3: Treinamento Eficiente em Memória →