🔄 MÓDULO 5: "Validação Cruzada e Sobreajuste: Construindo Modelos que Generalizam"

Objetivo:

Entender por que um modelo que tem bom desempenho em dados de treinamento pode falhar no mundo real. Aprender a detectar, prevenir e medir o sobreajuste usando técnicas de validação robustas.


5.1 O que é Sobreajuste?

Sobreajuste ocorre quando um modelo aprende os dados de treinamento muito bem—incluindo ruído e padrões aleatórios—em vez de padrões gerais. Resultado:

  • ✅ Excelente desempenho em dados de treinamento.
  • ❌ Péssimo desempenho em novos dados (teste ou produção).

Imagine um aluno que memoriza respostas de exame em vez de entender conceitos. No exame real, ele reprova.


5.2 Como Detectar Sobreajuste?

Método mais simples: comparar desempenho em treinamento vs. validação/teste.

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

modelo = LogisticRegression()
modelo.fit(X_train, y_train)

# Desempenho em treinamento
y_train_pred = modelo.predict(X_train)
train_acc = accuracy_score(y_train, y_train_pred)

# Desempenho em teste
y_test_pred = modelo.predict(X_test)
test_acc = accuracy_score(y_test, y_test_pred)

print(f"Acurácia de Treinamento: {train_acc:.4f}")
print(f"Acurácia de Teste:     {test_acc:.4f}")

# Se train_acc >> test_acc → Sobreajuste!

⚠️ Exemplo típico:

  • Acurácia de Treinamento: 0.998
  • Acurácia de Teste: 0.821
    → Modelo está sobreajustado.

5.3 O que Causa Sobreajuste?

  • Modelo muito complexo (ex., árvore de decisão com profundidade 20 em um conjunto de dados pequeno).
  • Poucos dados de treinamento.
  • Muitas características (maldição da dimensionalidade).
  • Ruído nos dados (rótulos incorretos, outliers não tratados).

5.4 Soluções para Evitar Sobreajuste

➤ Regularização

Adiciona uma penalidade à função de perda para evitar que os coeficientes fiquem muito grandes.

# Regressão logística com regularização L2 (Ridge)
modelo_l2 = LogisticRegression(penalty='l2', C=1.0)  # C menor = mais regularização

# Com L1 (Lasso) para seleção automática de características
modelo_l1 = LogisticRegression(penalty='l1', solver='liblinear', C=0.1)

L1 (Lasso): Pode zerar coeficientes → seleção de características.
L2 (Ridge): Reduz coeficientes mas não os zera → mais estável.


➤ Simplificar o Modelo

  • Reduzir profundidade da árvore.
  • Reduzir camadas/neurônios em redes.
  • Usar menos características (seleção de características).

➤ Mais Dados

Simples mas poderoso. Mais dados representativos ajudam o modelo a aprender padrões mais gerais.


➤ Validação Cruzada

A melhor ferramenta para avaliar a capacidade de generalização de um modelo antes de ver dados de teste.


5.5 Validação Cruzada: Seu Escudo contra o Otimismo

Validação simples (divisão treino/teste) pode ser enganosa se a divisão for sorte ou azar.

Validação cruzada (CV) divide os dados em K dobras, treina K vezes, cada vez usando uma dobra diferente como validação.

Resultado: uma estimativa de desempenho mais robusta e confiável.

from sklearn.model_selection import cross_val_score

modelo = LogisticRegression()

# Validação cruzada de 5 dobras
scores = cross_val_score(modelo, X_train, y_train, cv=5, scoring='roc_auc')

print(f"AUC-ROC por dobra: {scores}")
print(f"AUC-ROC médio: {scores.mean():.4f} (+/- {scores.std() * 2:.4f})")

Vantagens:

  • Usa todos os dados para treinamento e validação.
  • Reduz variância na estimativa de desempenho.
  • Ideal para comparar modelos ou ajustar hiperparâmetros.

5.6 Tipos de Validação Cruzada

➤ K-Fold CV (padrão)

Divide em K partes iguais. Cada dobra é usada uma vez como validação.

from sklearn.model_selection import KFold

kf = KFold(n_splits=5, shuffle=True, random_state=42)

➤ K-Fold Estratificado CV

Mantém proporções de classes em cada dobra. ESPECIALMENTE IMPORTANTE PARA CONJUNTOS DE DADOS DESBALANCEADOS.

from sklearn.model_selection import StratifiedKFold

skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(modelo, X_train, y_train, cv=skf, scoring='roc_auc')

➤ Leave-One-Out CV (LOO)

Cada dobra é uma única observação. Muito caro computacionalmente; apenas para conjuntos de dados muito pequenos.


📈 Visualização: Comparando Treino/Teste vs CV

import numpy as np

# Treinar e avaliar com treino/teste simples
modelo.fit(X_train, y_train)
test_score = roc_auc_score(y_test, modelo.predict_proba(X_test)[:,1])

# Avaliar com CV no conjunto de treinamento
cv_scores = cross_val_score(modelo, X_train, y_train, cv=5, scoring='roc_auc')

plt.figure(figsize=(8,5))
plt.axhline(y=test_score, color='red', linestyle='--', label=f'Pontuação Teste: {test_score:.4f}')
plt.plot(range(1,6), cv_scores, 'bo-', label='Pontuações CV por Dobra')
plt.axhline(y=cv_scores.mean(), color='blue', linestyle='-', label=f'Média CV: {cv_scores.mean():.4f}')
plt.title("Comparação: Validação Cruzada vs Teste Final")
plt.xlabel("Dobra")
plt.ylabel("AUC-ROC")
plt.legend()
plt.grid()
plt.show()

📝 Exercício 5.1: Diagnóstico e Prevenção de Sobreajuste

Conjunto de dados: caracteristicas_fraude.csv (pré-processado com características selecionadas)

Tarefas:

  1. Treinar um modelo Random Forest com profundidade máxima = 20.
  2. Calcular acurácia e AUC-ROC nos conjuntos de treinamento e teste. Há sobreajuste?
  3. Aplicar validação cruzada estratificada de 5 dobras no conjunto de treinamento. Comparar AUC-ROC médio com pontuação de teste.
  4. Agora treinar um Random Forest com profundidade máxima = 5. Repetir passos 2 e 3.
  5. Comparar ambos os modelos: qual generaliza melhor? Por quê?
  6. (Opcional) Tentar Regressão Logística com regularização (C=0.01) e comparar.

💡 Notas Adicionais:

  • Sempre use StratifiedKFold para problemas de classificação desbalanceados.
  • Validação cruzada NÃO DEVE incluir o conjunto de teste final. Conjunto de teste é sagrado—usado apenas uma vez, no final.
  • Sobreajuste não é inerentemente ruim. Às vezes é inevitável. O que importa é detectar e controlar.
  • Em competições do Kaggle, vencedores usam validação cruzada estratificada com múltiplas sementes para garantir estabilidade.

Course Info

Course: AI-course1

Language: PT

Lesson: Module5