Ir para o conteúdo

Data Leakage

Vazamento de Dados

O vazamento de dados é o destruidor silencioso de modelos. Ocorre quando informações de fora do conjunto de treinamento são inadvertidamente usadas para criar o modelo, fazendo-o parecer muito melhor do que realmente é. Modelos com vazamento podem alcançar acurácia de validação quase perfeita, passar em todos os testes e falhar completamente em produção.

O Vazamento de Dados é a principal causa de resultados de AM irreproduziveis

O vazamento pode ser sutil o suficiente para que praticantes experientes o ignorem. É responsável por uma parcela significativa de artigos de aprendizado de máquina retratados e implantações em produção que falharam.


Tipos de Vazamento de Dados

1. Vazamento de Alvo

Usar features que são causalmente causadas pelo alvo, não causas dele.

Exemplo: Prever se um paciente receberá prescrição do antibiótico X.

Feature Vazamento? Motivo
Idade, pressão arterial ✅ Não Existem antes do diagnóstico
Flag tomou_antibiotico_x SIM Causada pela prescrição
data_visita_farmacia SIM Acontece após a prescrição
pontuacao_recomendacao_medico SIM Faz parte da decisão

O modelo aprende "se tomou_antibiotico_x = True, então prescrição = True" — uma regra circular e inútil.

Prevenção: Para cada feature, pergunte: "Este valor existe no momento da previsão?" Se a resposta for "às vezes" ou "depende", trate com suspeição.


2. Contaminação Treino-Teste

Permitir que informações do conjunto de teste influenciem o processo de treinamento.

A forma mais comum: ajustar um pré-processador (scaler, imputer, encoder) em todo o dataset antes da divisão.

Código errado:

# ❌ VAZAMENTO — scaler vê os dados de teste
scaler = StandardScaler()
X_all_scaled = scaler.fit_transform(X_all)          # usa TODOS os dados
X_train, X_test = train_test_split(X_all_scaled)

Código correto:

# ✅ CORRETO — scaler vê apenas os dados de treino
X_train, X_test = train_test_split(X_all)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)             # fit + transform apenas no treino
X_test  = scaler.transform(X_test)                  # apenas transform no teste

Usando Pipelines (recomendado):

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression

pipe = Pipeline([
    ('scaler', StandardScaler()),
    ('model', LogisticRegression())
])
pipe.fit(X_train, y_train)     # scaler.fit é chamado apenas em X_train
pipe.score(X_test, y_test)     # scaler.transform é chamado em X_test

Pipelines do Scikit-learn são a forma idiomática de prevenir contaminação treino-teste.


3. Vazamento Temporal

Em problemas de séries temporais, usar informações futuras para prever o passado.

         Passado                  Futuro
── [x₁, x₂, x₃] ──prever──► [x₄] ──────────►
                    NÃO deve ver x₄ durante treino para x₃!

Errado: Divisão aleatória em um dataset de série temporal.

Correto: Sempre use uma divisão temporal — todos os dados de treino vêm estritamente antes do período de validação/teste.

# ❌ Errado para séries temporais
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# ✅ Correto para séries temporais
split_idx = int(len(X) * 0.8)
X_train, X_test = X[:split_idx], X[split_idx:]
y_train, y_test = y[:split_idx], y[split_idx:]

4. Vazamento na Engenharia de Features

Calcular features que agregam informações do dataset completo — incluindo as linhas de teste.

# ❌ VAZAMENTO: estatísticas de grupo calculadas em todo o dataset
df['media_gasto_usuario'] = df.groupby('user_id')['gasto'].transform('mean')

# ✅ CORRETO: calcular no conjunto de treino, mesclar no teste
medias_treino = X_train.groupby('user_id')['gasto'].mean().rename('media_gasto_usuario')
X_train = X_train.merge(medias_treino, on='user_id', how='left')
X_test  = X_test.merge(medias_treino, on='user_id', how='left')   # usa stats do treino

Checklist para Detecção de Vazamento

**🔍 Desempenho suspeitamente alto?** Se seu modelo atinge >95% de acurácia em um problema difícil, suspeite de vazamento antes de comemorar. **Checklist:** - [ ] Cada feature existe no **momento da previsão** em produção? - [ ] O **scaler/imputer é ajustado apenas nos dados de treino**? - [ ] Para séries temporais: a divisão é **estritamente temporal**? - [ ] Alguma feature **correlaciona perfeitamente** (>0,99) com o alvo? - [ ] Há **timestamps futuros** em features "passadas"? - [ ] Você calculou **agregações de grupo** em todo o dataset? - [ ] O desempenho é **bom demais** na validação, mas ruim quando implantado?

Um Exemplo Real Famoso: o Heritage Health Prize

O Heritage Health Prize de 2011 (competição de $3M) teve várias equipes top desqualificadas por vazamento. Uma equipe atingiu AUC=0,98 na validação — muito acima do baseline humano — ao usar acidentalmente uma feature derivada da variável alvo. Quando o erro foi descoberto e a feature removida, o desempenho caiu para AUC=0,76.

A lição: resultados extraordinários exigem escrutínio extraordinário dos dados.