Imagine ter um modelo de IA que conhece exatamente seu negócio!
Fine-tuning é o processo de pegar um modelo pré-treinado e especializar ele nos seus dados específicos.
Nesta aula, você vai aprender a criar modelos únicos que falam a linguagem do seu negócio e resolvem problemas específicos!
Fine-tuning é como dar aulas particulares para um modelo de IA que já é inteligente. Em vez de treinar do zero, você pega um modelo que já sabe muito e ensina ele coisas específicas do seu domínio.
Imagine que você contrata um médico formado (modelo pré-treinado) e ele faz uma especialização em cardiologia (fine-tuning com dados cardíacos). Ele já sabia medicina, mas agora é expert no seu caso específico!
O que é: Ajusta todos os parâmetros do modelo
Quando usar: Muitos dados disponíveis
Recursos: GPU potente necessária
Resultado: Máxima personalização
O que é: Ajusta apenas uma pequena parte
Quando usar: Poucos dados, recursos limitados
Recursos: GPU doméstica suficiente
Resultado: 90% da qualidade, 10% do custo
O que é: Congela camadas e treina só o final
Quando usar: Classificação simples
Recursos: Muito baixo
Resultado: Rápido e básico
Para a maioria dos casos, use LoRA (Parameter-Efficient). É o melhor custo-benefício: qualidade alta com recursos baixos!
Problema: ChatGPT genérico para consultas médicas
Solução: Fine-tune com literatura médica
Resultado: Respostas precisas e confiáveis
Problema: IA não entende termos legais
Solução: Treino com documentos jurídicos
Resultado: Assistente legal especializado
Problema: Descrições genéricas de produtos
Solução: Fine-tune com catálogo da empresa
Resultado: Descrições no tom da marca
Problema: Explicações não adaptadas ao nível
Solução: Treino com material pedagógico
Resultado: Tutor personalizado
Vamos criar um modelo personalizado para analisar sentimentos de reviews de produtos brasileiros!
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from transformers import (
AutoTokenizer,
AutoModelForSequenceClassification,
TrainingArguments,
Trainer,
DataCollatorWithPadding
)
import torch
from datasets import Dataset
import json
from datetime import datetime
import os
class BrazilianSentimentAnalyzer:
def __init__(self, model_name="neuralmind/bert-base-portuguese-cased"):
"""Inicializa o sistema de fine-tuning"""
print("🤖 Inicializando Sistema de Fine-tuning...")
self.model_name = model_name
self.tokenizer = AutoTokenizer.from_pretrained(model_name)
self.model = None
self.trainer = None
# Configuração de labels
self.id2label = {0: "NEGATIVO", 1: "NEUTRO", 2: "POSITIVO"}
self.label2id = {"NEGATIVO": 0, "NEUTRO": 1, "POSITIVO": 2}
print(f"✅ Modelo base carregado: {model_name}")
def create_sample_dataset(self):
"""Cria um dataset de exemplo com reviews brasileiros"""
sample_data = [
# Reviews Positivos
("Produto incrível, superou todas as expectativas! Recomendo muito!", "POSITIVO"),
("Excelente qualidade, chegou rápido e bem embalado. Nota 10!", "POSITIVO"),
("Adorei a compra! Produto exatamente como descrito, muito satisfeito.", "POSITIVO"),
("Melhor investimento que fiz este ano! Funciona perfeitamente.", "POSITIVO"),
("Atendimento espetacular e produto de primeira linha. Parabéns!", "POSITIVO"),
("Chegou antes do prazo e com qualidade excepcional. Voltarei a comprar!", "POSITIVO"),
("Produto maravilhoso, minha família toda adorou! Super recomendo.", "POSITIVO"),
("Qualidade premium pelo preço justo. Estou muito feliz com a compra!", "POSITIVO"),
("Funciona exatamente como prometido. Produto de excelente qualidade!", "POSITIVO"),
("Superou minhas expectativas! Produto top, entrega rápida.", "POSITIVO"),
# Reviews Neutros
("Produto ok, nada excepcional mas cumpre o que promete.", "NEUTRO"),
("Chegou no prazo, qualidade razoável. Atende às necessidades básicas.", "NEUTRO"),
("Produto mediano, tem pontos positivos e negativos. Regular.", "NEUTRO"),
("Funciona bem, mas poderia ter mais funcionalidades pelo preço.", "NEUTRO"),
("Qualidade aceitável, sem grandes surpresas positivas ou negativas.", "NEUTRO"),
("Produto comum, nada demais. Serve para o básico.", "NEUTRO"),
("Entrega foi ok, produto dentro do esperado. Nem bom nem ruim.", "NEUTRO"),
("Cumpre sua função básica, mas não impressiona. Mediano.", "NEUTRO"),
("Produto regular, tem prós e contras. Aceitável pelo preço.", "NEUTRO"),
("Funciona como deveria, sem grandes emoções. Produto padrão.", "NEUTRO"),
# Reviews Negativos
("Produto horrível, não funcionou nem um dia! Não recomendo!", "NEGATIVO"),
("Pior compra que já fiz! Qualidade péssima e atendimento terrível.", "NEGATIVO"),
("Chegou com defeito e o suporte não resolve. Muito frustrado!", "NEGATIVO"),
("Produto completamente diferente do anunciado. Me senti enganado!", "NEGATIVO"),
("Péssima qualidade, quebrou logo no primeiro uso. Dinheiro jogado fora!", "NEGATIVO"),
("Atendimento ao cliente pessimo! Produto veio errado e não trocam.", "NEGATIVO"),
("Não funcionou como prometido. Muito decepcionado com a compra.", "NEGATIVO"),
("Produto de qualidade duvidosa, não vale o dinheiro investido.", "NEGATIVO"),
("Chegou danificado e demorou semanas para entregar. Experiência ruim!", "NEGATIVO"),
("Propaganda enganosa! Produto não tem metade das funcionalidades prometidas.", "NEGATIVO"),
# Mais variações...
("Este produto mudou minha vida! Qualidade incomparável!", "POSITIVO"),
("Bom produto, mas nada extraordinário. Cumpre sua função.", "NEUTRO"),
("Total perda de dinheiro! Produto não funciona direito.", "NEGATIVO"),
("Estou impressionado com a qualidade! Superou expectativas!", "POSITIVO"),
("Produto mediano, serve para emergência mas não é o ideal.", "NEUTRO"),
("Péssimo! Não comprem este produto, é uma enganação!", "NEGATIVO"),
("Incrível! Melhor compra que já fiz online! 5 estrelas!", "POSITIVO"),
("Produto ok para o preço. Nada de especial mas funciona.", "NEUTRO"),
("Qualidade muito abaixo do esperado. Não recomendo!", "NEGATIVO"),
("Fantástico! Produto chegou perfeito e funciona maravilhosamente!", "POSITIVO")
]
# Converter para DataFrame
df = pd.DataFrame(sample_data, columns=['texto', 'sentimento'])
# Adicionar label numérico
df['label'] = df['sentimento'].map(self.label2id)
print(f"📊 Dataset criado com {len(df)} exemplos:")
print(df['sentimento'].value_counts())
return df
def load_custom_dataset(self, csv_path):
"""Carrega dataset personalizado de um CSV"""
try:
df = pd.read_csv(csv_path)
# Verificar se as colunas necessárias existem
required_cols = ['texto', 'sentimento']
if not all(col in df.columns for col in required_cols):
raise ValueError(f"CSV deve conter as colunas: {required_cols}")
# Converter sentimentos para labels numéricos
df['label'] = df['sentimento'].map(self.label2id)
# Remover linhas com labels inválidos
df = df.dropna(subset=['label'])
df['label'] = df['label'].astype(int)
print(f"📁 Dataset carregado de {csv_path}")
print(f"📊 {len(df)} exemplos encontrados:")
print(df['sentimento'].value_counts())
return df
except Exception as e:
print(f"❌ Erro ao carregar dataset: {e}")
print("📊 Usando dataset de exemplo...")
return self.create_sample_dataset()
def prepare_dataset(self, df):
"""Prepara o dataset para treinamento"""
print("🔄 Preparando dataset...")
# Dividir em treino e validação
train_df, val_df = train_test_split(
df,
test_size=0.2,
random_state=42,
stratify=df['label']
)
# Converter para datasets do Hugging Face
train_dataset = Dataset.from_pandas(train_df)
val_dataset = Dataset.from_pandas(val_df)
# Tokenizar
def tokenize_function(examples):
return self.tokenizer(
examples['texto'],
truncation=True,
padding=True,
max_length=512
)
train_dataset = train_dataset.map(tokenize_function, batched=True)
val_dataset = val_dataset.map(tokenize_function, batched=True)
print(f"✅ Dataset preparado:")
print(f" 📚 Treino: {len(train_dataset)} exemplos")
print(f" 🧪 Validação: {len(val_dataset)} exemplos")
return train_dataset, val_dataset
def setup_model_for_training(self):
"""Configura o modelo para fine-tuning"""
print("🎯 Configurando modelo para treinamento...")
self.model = AutoModelForSequenceClassification.from_pretrained(
self.model_name,
num_labels=3, # NEGATIVO, NEUTRO, POSITIVO
id2label=self.id2label,
label2id=self.label2id
)
print("✅ Modelo configurado para 3 classes de sentimento")
def train_model(self, train_dataset, val_dataset, output_dir="./fine_tuned_model"):
"""Executa o fine-tuning"""
print("🚀 Iniciando Fine-tuning...")
# Configurações de treinamento
training_args = TrainingArguments(
output_dir=output_dir,
learning_rate=2e-5,
per_device_train_batch_size=8,
per_device_eval_batch_size=8,
num_train_epochs=3,
weight_decay=0.01,
logging_dir=f'{output_dir}/logs',
logging_steps=10,
evaluation_strategy="epoch",
save_strategy="epoch",
load_best_model_at_end=True,
metric_for_best_model="eval_loss",
greater_is_better=False,
report_to=None, # Desabilita wandb
save_total_limit=2
)
# Data collator
data_collator = DataCollatorWithPadding(tokenizer=self.tokenizer)
# Configurar trainer
self.trainer = Trainer(
model=self.model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=val_dataset,
tokenizer=self.tokenizer,
data_collator=data_collator,
)
# Treinar!
print("⚡ Iniciando treinamento...")
start_time = datetime.now()
self.trainer.train()
end_time = datetime.now()
duration = end_time - start_time
print(f"🎉 Treinamento concluído!")
print(f"⏱️ Tempo total: {duration}")
# Salvar modelo
self.trainer.save_model()
self.tokenizer.save_pretrained(output_dir)
print(f"💾 Modelo salvo em: {output_dir}")
return self.trainer.evaluate()
def test_model(self, texts):
"""Testa o modelo fine-tuned com novos textos"""
print("🧪 Testando modelo personalizado...")
if not self.model or not self.trainer:
print("❌ Modelo não foi treinado ainda!")
return
# Tokenizar textos
inputs = self.tokenizer(texts, truncation=True, padding=True, return_tensors="pt")
# Fazer predições
with torch.no_grad():
outputs = self.model(**inputs)
predictions = torch.nn.functional.softmax(outputs.logits, dim=-1)
# Processar resultados
results = []
for i, text in enumerate(texts):
pred_probs = predictions[i].numpy()
pred_class = np.argmax(pred_probs)
pred_label = self.id2label[pred_class]
confidence = pred_probs[pred_class]
results.append({
'texto': text,
'sentimento_predito': pred_label,
'confianca': float(confidence),
'probabilidades': {
'NEGATIVO': float(pred_probs[0]),
'NEUTRO': float(pred_probs[1]),
'POSITIVO': float(pred_probs[2])
}
})
return results
def compare_with_generic_model(self, texts):
"""Compara modelo personalizado com genérico"""
print("🆚 Comparando modelos...")
# Modelo genérico
from transformers import pipeline
generic_classifier = pipeline(
"sentiment-analysis",
model="cardiffnlp/twitter-roberta-base-sentiment-latest"
)
# Modelo personalizado
custom_results = self.test_model(texts)
print("\n" + "="*80)
print("📊 COMPARAÇÃO: MODELO GENÉRICO vs PERSONALIZADO")
print("="*80)
for i, text in enumerate(texts):
print(f"\n📝 Texto: '{text}'")
# Resultado genérico
generic_result = generic_classifier(text)[0]
print(f"🤖 Genérico: {generic_result['label']} ({generic_result['score']:.3f})")
# Resultado personalizado
custom_result = custom_results[i]
print(f"🎯 Personalizado: {custom_result['sentimento_predito']} ({custom_result['confianca']:.3f})")
print("-" * 40)
def save_training_report(self, eval_results, output_dir):
"""Salva relatório do treinamento"""
report = {
'model_name': self.model_name,
'training_completed_at': datetime.now().isoformat(),
'evaluation_results': eval_results,
'label_mapping': self.id2label,
'training_config': {
'epochs': 3,
'learning_rate': 2e-5,
'batch_size': 8
}
}
report_path = os.path.join(output_dir, 'training_report.json')
with open(report_path, 'w', encoding='utf-8') as f:
json.dump(report, f, indent=2, ensure_ascii=False)
print(f"📋 Relatório salvo: {report_path}")
# Exemplo de uso completo
if __name__ == "__main__":
print("🎯 INICIANDO FINE-TUNING DE ANÁLISE DE SENTIMENTOS")
print("="*60)
# Inicializar sistema
analyzer = BrazilianSentimentAnalyzer()
# Carregar dados (use seu CSV ou dataset de exemplo)
# df = analyzer.load_custom_dataset("meus_reviews.csv") # Seu CSV
df = analyzer.create_sample_dataset() # Dataset de exemplo
# Preparar dataset
train_dataset, val_dataset = analyzer.prepare_dataset(df)
# Configurar modelo
analyzer.setup_model_for_training()
# Treinar modelo
eval_results = analyzer.train_model(train_dataset, val_dataset)
# Salvar relatório
analyzer.save_training_report(eval_results, "./fine_tuned_model")
# Testar com novos exemplos
test_texts = [
"Este produto é simplesmente fantástico! Melhor compra do ano!",
"Produto chegou quebrado e o atendimento é péssimo. Não recomendo!",
"Produto ok, nada demais mas funciona. Preço justo.",
"Adorei! Superou todas as minhas expectativas. 5 estrelas!",
"Muito decepcionado com a qualidade. Não vale o dinheiro."
]
print("\n" + "="*60)
print("🧪 TESTANDO MODELO PERSONALIZADO")
print("="*60)
results = analyzer.test_model(test_texts)
for result in results:
print(f"\n📝 '{result['texto']}'")
print(f"🎯 Sentimento: {result['sentimento_predito']} ({result['confianca']:.3f})")
print(f"📊 Probabilidades:")
for sentiment, prob in result['probabilidades'].items():
print(f" {sentiment}: {prob:.3f}")
# Comparar com modelo genérico
print("\n" + "="*60)
print("🆚 COMPARAÇÃO COM MODELO GENÉRICO")
print("="*60)
analyzer.compare_with_generic_model(test_texts)
print(f"\n🎉 FINE-TUNING CONCLUÍDO COM SUCESSO!")
print(f"💾 Modelo salvo em: ./fine_tuned_model")
print(f"🚀 Agora você tem um modelo personalizado para análise de sentimentos!")
O que é: Velocidade de aprendizado
Dica: Comece com 2e-5, aumente se for lento, diminua se instável
O que é: Quantas vezes ver todos os dados
Dica: Monitore a validação, pare se começar a piorar
O que é: Quantos exemplos por vez
Dica: Maior = mais estável, mas usa mais memória
O que é: Previne overfitting
Dica: Aumente se modelo decorar os dados
Percentual de acertos geral
Acertos / Total × 100
Bom: > 85%
Dos que disse que era X, quantos eram realmente X
Verdadeiros Positivos / (VP + Falsos Positivos)
Bom: > 80%
Dos que eram X, quantos conseguiu identificar
Verdadeiros Positivos / (VP + Falsos Negativos)
Bom: > 80%
Média harmônica entre Precision e Recall
2 × (Precision × Recall) / (Precision + Recall)
Bom: > 80%
Aplicação: Análise de prontuários médicos
Valor: R$ 50.000 - R$ 200.000 por projeto
Exemplo: Classificar gravidade de casos
Aplicação: Chatbots especializados
Valor: R$ 20.000 - R$ 100.000 por projeto
Exemplo: Atendimento específico do setor
Aplicação: Análise de sentimentos de marca
Valor: R$ 10.000 - R$ 50.000 mensais
Exemplo: Monitor de reputação online
Aplicação: Tutores IA personalizados
Valor: R$ 30.000 - R$ 150.000 por instituição
Exemplo: Assistente pedagógico especializado
Você acabou de aprender uma das habilidades mais valiosas em IA: personalizar modelos para problemas específicos!
Na próxima aula, vamos aprender a processar e analisar documentos com IA, extraindo insights valiosos de PDFs, contratos e relatórios!
"Com Fine-tuning, você não usa IA - você cria IA personalizada"
- Isaque Victor