Cross-validation e métricas honestas
- ⬜🌳 Árvores: RF, XGBoost, LightGBM(Machine Learning Clássico)
Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.
Validação é onde modelos morrem ou sobrevivem
Cross-validation não é formalidade — é como você descobre se o modelo generaliza. A escolha do esquema de split codifica premissas sobre o problema: se você errar aqui, vai reportar AUC 0.95 em slide e ver 0.72 em produção.
Esquemas de split
| Esquema | Premissa que ele assume | Usar quando | O erro de usar o errado |
|---|---|---|---|
| Aleatório estratificado | Exemplos independentes | Tabular sem tempo nem agrupamento | Nenhum, se a premissa vale |
| Por grupo | Exemplos do mesmo grupo se parecem | Vários registros por cliente, paciente ou dispositivo | O modelo decora o grupo e a nota infla |
| Temporal, avançando a janela | O futuro depende do passado | Qualquer série com ordem | Treinar com dado posterior ao que se prediz — nota excelente, produção péssima |
| Reservado intocado | Você vai iterar muito | Sempre, além da validação cruzada | Depois de cinquenta experimentos, a validação já foi consumida pelas suas escolhas |
from sklearn.model_selection import (
KFold, StratifiedKFold, TimeSeriesSplit, GroupKFold
)
# Tabular iid, classificação -> StratifiedKFold
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
# Time series -> walk-forward
tss = TimeSeriesSplit(n_splits=5, gap=1) # gap evita vazamento de vizinhos
for train_idx, val_idx in tss.split(X):
pass # train sempre antes de val no tempo
# Dados agrupados (mesmo usuário em várias linhas) -> GroupKFold
gkf = GroupKFold(n_splits=5)
for train_idx, val_idx in gkf.split(X, y, groups=user_ids):
passSe você não sabe qual esquema usar, comece desenhando como a predição será feita em produção: dado timestamp T, com que dados você treina e em que você prediz? Sua CV deve simular isso.
Métricas de classificação
from sklearn.metrics import (
precision_score, recall_score, f1_score,
roc_auc_score, average_precision_score,
balanced_accuracy_score, confusion_matrix, classification_report,
)
y_pred = model.predict(X_val)
y_proba = model.predict_proba(X_val)[:, 1]
print(classification_report(y_val, y_pred))
print(f'ROC-AUC: {roc_auc_score(y_val, y_proba):.4f}')
print(f'PR-AUC: {average_precision_score(y_val, y_proba):.4f}')
print(f'Balanced acc: {balanced_accuracy_score(y_val, y_pred):.4f}')
print(confusion_matrix(y_val, y_pred))Em classes desbalanceadas, PR-AUC é mais sensível que ROC-AUC. ROC pode parecer alto (0.9+) enquanto precision na classe positiva é 0.1 — PR-AUC expõe isso.
O módulo diz que o esquema de divisão codifica premissas sobre o problema. Qual é a pergunta que orienta a escolha?
Métricas de regressão
from sklearn.metrics import (
mean_absolute_error, mean_squared_error,
mean_absolute_percentage_error, r2_score,
)
import numpy as np
mae = mean_absolute_error(y_val, y_pred)
rmse = np.sqrt(mean_squared_error(y_val, y_pred))
mape = mean_absolute_percentage_error(y_val, y_pred)
r2 = r2_score(y_val, y_pred)
# MAE é robusto a outliers; RMSE pune outliers quadraticamente
# MAPE é interpretável em % mas explode perto de y=0
# R² responde "quanto da variância expliquei?"Intervalos de confiança
from sklearn.utils import resample
import numpy as np
def bootstrap_ci(y_true, y_pred, metric, n=1000, alpha=0.05):
scores = []
rng = np.random.default_rng(42)
for _ in range(n):
idx = rng.integers(0, len(y_true), len(y_true))
scores.append(metric(y_true[idx], y_pred[idx]))
lo, hi = np.quantile(scores, [alpha/2, 1 - alpha/2])
return np.mean(scores), lo, hi
mean_auc, lo, hi = bootstrap_ci(y_val, y_proba, roc_auc_score)
print(f'AUC: {mean_auc:.3f} [{lo:.3f}, {hi:.3f}]')Reportar intervalo de confiança 95% (bootstrap) é o mínimo para decidir entre modelos. Diferença de 0.02 em AUC pode não ser estatisticamente significante. Hoje isso separa produto que acerta de produto que vive em loop de refactor.
Perguntas frequentes
❓ Por que validação cruzada em vez de uma divisão só?
❓ Como validar modelo de série temporal?
❓ Qual métrica escolher?
Fixando
Com classes fortemente desbalanceadas, por que a área sob a curva de precisão e revocação revela o que a curva de característica de operação esconde?
Por que reportar intervalo de confiança por reamostragem em vez de um número único?
Terminou de ler?
Marcar como concluído registra o XP, mantém sua sequência e coloca 3 cartas deste módulo na fila de revisão espaçada.
Próximos passos sugeridos
Temas deste módulo
Discussão
Carregando comentários…