Pular para o conteúdo principal

Capítulo 1: Abordagem Tradicional de Fine-Tuning

Atualizando Todos os Parâmetros do Modelo​

O fine-tuning tradicional envolve a atualização de todos os parâmetros treináveis do modelo durante o treinamento. Isso proporciona a máxima flexibilidade para adaptar modelos a novas tarefas.


Como Funciona o Fine-Tuning Completo​

O Loop de Treinamento​

  1. Forward Pass: Os dados passam por todo o modelo
  2. Cálculo da Loss: Compara a previsão com o alvo
  3. Backward Pass: Calcula os gradientes para todos os parâmetros
  4. Atualização dos Pesos: Aplica os gradientes para atualizar todos os pesos
  5. Repetir: Continua até a convergência

Exemplo Completo de Treinamento​

import torch
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
TrainingArguments,
Trainer,
DataCollatorForLanguageModeling,
)
from datasets import load_dataset

# Load model and tokenizer
model_name = "meta-llama/Llama-3.1-8B"
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token

# Load model - all parameters trainable by default
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.bfloat16, # Use bf16 for memory efficiency
device_map="auto",
)

# Verify all parameters are trainable
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
total_params = sum(p.numel() for p in model.parameters())
print(f"Trainable: {trainable_params:,} / {total_params:,} = 100%")

# Prepare dataset
dataset = load_dataset("databricks/dolly-15k", split="train[:1000]")

def format_instruction(example):
return {
"text": f"### Instruction:\n{example['instruction']}\n\n### Response:\n{example['response']}"
}

dataset = dataset.map(format_instruction)

def tokenize(example):
return tokenizer(
example["text"],
truncation=True,
max_length=512,
padding="max_length",
)

tokenized_dataset = dataset.map(tokenize, remove_columns=dataset.column_names)

# Training configuration
training_args = TrainingArguments(
output_dir="./llama-full-ft",
num_train_epochs=3,
per_device_train_batch_size=1, # Limited by memory
gradient_accumulation_steps=16, # Simulate batch size of 16
learning_rate=2e-5,
weight_decay=0.01,
warmup_ratio=0.03,
logging_steps=10,
save_strategy="epoch",
bf16=True, # Use bfloat16
gradient_checkpointing=True, # Save memory
optim="adamw_torch_fused", # Efficient optimizer
)

# Create trainer
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_dataset,
data_collator=DataCollatorForLanguageModeling(tokenizer, mlm=False),
)

# Train
trainer.train()

# Save
model.save_pretrained("./llama-full-ft-final")
tokenizer.save_pretrained("./llama-full-ft-final")

Componentes-Chave Explicados​

Taxa de Aprendizado (Learning Rate)​

learning_rate = 2e-5 # Common range: 1e-5 to 5e-5

Para fine-tuning completo, utilize taxas de aprendizado menores do que em PEFT:

  • Muito alta: O modelo diverge ou esquece o pré-treinamento
  • Muito baixa: O treinamento é lento, pode não se adaptar o suficiente

Decaimento de Peso (Weight Decay)​

weight_decay = 0.01 # Regularization to prevent overfitting

O weight decay previne overfitting penalizando pesos muito altos.

Warmup​

warmup_ratio = 0.03 # 3% of training steps

Aumenta gradualmente a taxa de aprendizado no início para um treinamento mais estável.

Gradient Checkpointing​

gradient_checkpointing = True # Trade compute for memory

Recalcula ativações durante o backward pass ao invés de armazená-las—economiza cerca de 30% de memória.


Opções de Otimizador​

OtimizadorMemóriaVelocidadeQualidade
AdamWAltaRápidoMelhor
Adam 8-bitMédiaMédiaBoa
SGDBaixaLentoRequer ajuste
AdafactorBaixaMédiaBoa
# Standard AdamW
optim = "adamw_torch"

# Fused AdamW (faster)
optim = "adamw_torch_fused"

# 8-bit Adam (less memory)
optim = "adamw_8bit"

# Adafactor (no momentum states)
optim = "adafactor"

Dinâmica do Treinamento​

Curva de Loss​

Epoch 1: Training loss decreasing rapidly
(Model adapting to new data)

Epoch 2: Training loss stabilizing
(Watch validation loss for overfitting)

Epoch 3: Possible overfitting
(Training loss still drops, validation may increase)

Monitorando o Treinamento​

# Using Weights & Biases
training_args = TrainingArguments(
# ... other args ...
report_to="wandb",
run_name="llama-full-ft-experiment-1",
)

Principais métricas para acompanhar:

  • Training Loss: Deve diminuir
  • Validation Loss: Deve diminuir, mas observe divergência em relação ao training loss
  • Gradient Norm: Picos podem indicar instabilidade
  • Learning Rate: Verifique se warmup e decaimento estão funcionando

Treinamento com Precisão Mista​

Por Que Usar Precisão Mista?​

# Half the memory, often faster training
bf16 = True # Preferred for newer GPUs (Ampere+)
# OR
fp16 = True # For older GPUs
PrecisãoMemóriaAlcanceEstabilidade
float324 bytesCompletoMáxima
bfloat162 bytesCompletoAlta
float162 bytesLimitadoMédia
Float16 Stability

Float16 tem um alcance numérico mais estreito e pode causar overflow/underflow. BFloat16 mantém o alcance do float32 com menor precisão, tornando-o mais estável.


Salvando e Carregando​

Durante o Treinamento (Checkpoints)​

training_args = TrainingArguments(
save_strategy="steps",
save_steps=500,
save_total_limit=3, # Keep only last 3 checkpoints
)

Após o Treinamento​

# Save the full model
model.save_pretrained("./final-model")
tokenizer.save_pretrained("./final-model")

# Later, load it
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("./final-model")

Vantagens do Fine-Tuning Completo​

Máxima Personalização​

Todos os parâmetros podem ser ajustados para sua tarefa.

Potencialmente Maior Qualidade​

Sem restrições de pesos congelados.

Simplicidade​

Não é necessário configurar adapters.

Saída Unificada​

Arquivo único de modelo, sem overhead de adapter na inferência.


Desvantagens​

Alta Demanda de Memória​

É necessário armazenar modelo, gradientes e estados do otimizador.

Risco de Esquecimento Catastrófico​

Pode perder conhecimento pré-treinado.

Custo Elevado​

Requer recursos significativos de GPU.

Treinamento Lento​

Todos os parâmetros precisam ser atualizados.


Quando Usar Fine-Tuning Completo​

Caso de UsoRecomendação
Máxima qualidade necessária✅ Full FT
Restrição de recursos❌ Use PEFT
Experimentação rápida❌ Use PEFT
Produção em escala⚠️ Considere trade-offs
Pesquisa/benchmark✅ Full FT

Principais Pontos​

✅ Fine-tuning completo atualiza todos os parâmetros do modelo

✅ Requer muita memória de GPU (modelo + gradientes + otimizador)

✅ Use precisão mista e gradient checkpointing para reduzir memória

✅ Taxas de aprendizado menores que PEFT (1e-5 a 5e-5)

✅ Monitore overfitting com validation loss

✅ Melhor opção para máxima personalização quando há recursos disponíveis


Próximos Passos​

Continue para Capítulo 2: Requisitos Computacionais para entender exatamente as necessidades de memória e processamento.


Verificação Rápida​

Antes de avançar, certifique-se de que você consegue responder:

  1. Quais são os quatro principais componentes armazenados na memória da GPU durante o treinamento?
  2. Por que o bfloat16 é frequentemente preferido ao float16?
  3. Qual a faixa típica de taxa de aprendizado para fine-tuning completo?