Validação Cruzada K-Fold Estratificada (Stratified K-Fold Cross-Validation)
Visão geral
Validação cruzada em k dobras estratificada (stratified k-fold cross-validation) é uma estratégia de divisão para validação cruzada (CV, cross-validation) em classificação (classification) que busca tornar a avaliação do modelo mais confiável — especialmente quando o conjunto de dados tem desbalanceamento de classes (class imbalance).
Assim como na validação cruzada em k dobras padrão, ela divide o conjunto de dados em k dobras (folds) de tamanhos aproximadamente iguais. A diferença-chave é a estratificação (stratification): cada dobra é construída de modo que as proporções de classes na dobra correspondam de perto às proporções globais de classes no conjunto de dados completo.
Isso é importante porque, sob desbalanceamento, divisões ingênuas podem acidentalmente criar dobras com exemplos demais poucos (ou até zero) de uma classe minoritária. Isso pode levar a:
- métricas instáveis (alta variância entre dobras),
- conclusões enganosas durante a seleção de modelos (model selection)/ajuste de hiperparâmetros (hyperparameter tuning),
- falhas no treinamento ou na pontuação (por exemplo, métricas que exigem ambas as classes presentes).
A validação cruzada em k dobras estratificada é uma das estratégias de avaliação mais usadas na prática em fluxos de trabalho de aprendizado supervisionado (supervised learning) e é uma ferramenta padrão abordada em Validação e Validação Cruzada (Validation & Cross-Validation) e Desbalanceamento de Classes (Class Imbalance).
Como a validação cruzada em *k* dobras estratificada funciona
Assuma um conjunto de dados de classificação com entradas (X) e rótulos (y), e que você escolha um número de dobras (k) (comumente 5 ou 10).
Em alto nível, a validação cruzada em k dobras estratificada:
- Agrupa exemplos por rótulo de classe.
- Divide os exemplos de cada classe em k partes (da forma mais uniforme possível).
- Constrói cada dobra combinando uma parte de cada classe, para que cada dobra tenha aproximadamente a mesma distribuição de classes do conjunto de dados como um todo.
- Repete o treinamento e a avaliação k vezes:
- Treina em (k-1) dobras
- Valida na dobra restante
- Agrega as métricas entre dobras (média, desvio padrão e, às vezes, intervalos de confiança).
Exemplo: por que a estratificação ajuda
Suponha que você tenha 1.000 exemplos com uma divisão 95/5:
- 950 negativos
- 50 positivos
Com validação cruzada em k dobras padrão (sem estratificação), é possível (especialmente com poucos dados) que uma dobra termine com pouquíssimos positivos — ou até nenhum. Com validação cruzada em k dobras estratificada e (k=5), cada dobra terá aproximadamente:
- 190 negativos
- 10 positivos
Isso torna a avaliação por dobra mais significativa e comparável.
Comportamento multiclasse
Para classificação multiclasse, a estratificação tenta preservar a proporção de cada classe em toda dobra. Isso geralmente é bem suportado em bibliotecas amplamente usadas.
Ressalva em multirrótulo
Em classificação multirrótulo (multilabel) (cada exemplo pode ter vários rótulos), “proporções de classe” são mais complicadas (os rótulos não são mutuamente exclusivos). Implementações padrão de validação cruzada em k dobras estratificada tipicamente não resolvem perfeitamente esse cenário; métodos especializados (por exemplo, estratificação iterativa) são frequentemente usados no lugar.
Quando usar validação cruzada em *k* dobras estratificada
Use validação cruzada em k dobras estratificada quando:
- Você está fazendo classificação e as classes são desbalanceadas, mesmo que moderadamente.
- Seu conjunto de dados é pequeno a médio, onde a variação aleatória nas divisões pode afetar fortemente as métricas.
- Você está fazendo ajuste de hiperparâmetros e quer dobras de validação estáveis e representativas.
- Você quer comparar modelos de forma justa usando métricas sensíveis à prevalência (por exemplo, acurácia, F1).
Ela é especialmente comum em fluxos de trabalho que avaliam usando:
- métricas derivadas de Matriz de Confusão (Confusion Matrix) (precisão (precision), revocação (recall), F1)
- AUC ROC (ROC AUC) ou AUC PR (PR AUC) (veja Característica de Operação do Receptor (ROC) (Receiver Operating Characteristic (ROC)) e Métricas (Metrics))
- medidas de qualidade probabilística e ajuste de limiar (veja Calibração (Calibration))
Quando você talvez não precise:
- Se você tem conjuntos de dados muito grandes com exemplos minoritários em quantidade suficiente, a diferença entre divisões estratificadas e não estratificadas frequentemente se torna desprezível (embora a estratificação raramente prejudique).
- Se seus dados têm dependências de grupo ou tempo (veja armadilhas abaixo). Nesses casos, você pode precisar de outras estratégias de divisão.
Validação cruzada em *k* dobras estratificada vs validação cruzada em *k* dobras padrão
Validação cruzada em *k* dobras padrão
- Divide o conjunto de dados em k dobras sem considerar os rótulos.
- Funciona bem para muitos problemas de classificação balanceada e muitos problemas de regressão (quando as suposições i.i.d. (i.i.d. assumptions) se mantêm).
- Sob desbalanceamento, pode criar dobras com distribuições de classe distorcidas.
Validação cruzada em *k* dobras estratificada
- Restringe a divisão para que cada dobra aproxime a distribuição de rótulos do conjunto de dados completo.
- Tipicamente reduz a variância (variance) das estimativas de desempenho em classificação desbalanceada.
- Não corrige vazamento de dados ou problemas de estrutura de dependência.
Nota sobre regressão: “estratificação” via binning
A validação cruzada em k dobras estratificada é, fundamentalmente, um conceito de classificação. Para regressão, profissionais às vezes aproximam a estratificação por meio de discretização em bins (binning) do alvo contínuo (por exemplo, quantis) e estratificando pelos bins. Isso pode estabilizar a avaliação quando a distribuição do alvo é altamente assimétrica — mas é uma aproximação, e as escolhas de bins podem afetar os resultados.
Intuição teórica: por que a estratificação melhora a confiabilidade
A validação cruzada busca estimar o desempenho de generalização (generalization performance) de um modelo. Com classes desbalanceadas, a métrica de avaliação pode ser altamente sensível a quais exemplos minoritários caem no conjunto de validação.
A estratificação ajuda garantindo que cada dobra de validação seja mais representativa da distribuição global de rótulos. Isso tipicamente:
- reduz flutuações de dobra para dobra (menor variância),
- torna comparações de modelos mais estáveis,
- evita dobras degeneradas (por exemplo, sem amostras positivas).
Porém:
- A estratificação não garante uma estimativa não viesada do desempenho no mundo real se a distribuição do seu conjunto de dados diferir das condições de implantação (deployment).
- A estratificação não corrige vazamento de dados (uma fonte muito maior de resultados excessivamente otimistas).
Implementação prática (exemplos em scikit-learn)
Uso básico: `StratifiedKFold`
import numpy as np
from sklearn.model_selection import StratifiedKFold
from sklearn.datasets import make_classification
X, y = make_classification(
n_samples=1000,
n_features=20,
weights=[0.95, 0.05],
random_state=0
)
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
for fold, (train_idx, val_idx) in enumerate(skf.split(X, y), start=1):
y_val = y[val_idx]
counts = np.bincount(y_val)
print(f"Fold {fold}: negatives={counts[0]}, positives={counts[1]}")
Parâmetros-chave:
n_splits: número de dobras (k)shuffle=True: recomendado em muitos cenários que não dependem de tempo para aleatorizar a atribuiçãorandom_state: para reprodutibilidade ao embaralhar
Pré-processamento correto com pipelines (Pipelines) (evite vazamento)
Um erro comum é ajustar pré-processadores (scalers, imputers, seletores de atributos) no conjunto de dados completo antes da validação cruzada. Isso causa vazamento de dados (data leakage) das dobras de validação para o treinamento.
Use um Pipeline para que o pré-processamento seja ajustado dentro de cada dobra de treinamento:
from sklearn.model_selection import cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
pipe = Pipeline([
("imputer", SimpleImputer(strategy="median")),
("scaler", StandardScaler()),
("clf", LogisticRegression(max_iter=1000))
])
scores = cross_val_score(
pipe, X, y,
cv=skf,
scoring="f1" # choose metrics appropriate for imbalance
)
print(scores.mean(), scores.std())
A escolha de métrica é muito importante sob desbalanceamento; veja Métricas e Desbalanceamento de Classes.
Ajuste de hiperparâmetros: `GridSearchCV` com validação cruzada estratificada
No scikit-learn, muitos estimadores de classificação usam, por padrão, validação cruzada estratificada quando você passa um inteiro cv=5 e a tarefa é classificação, mas é melhor ser explícito:
from sklearn.model_selection import GridSearchCV
param_grid = {
"clf__C": [0.1, 1.0, 10.0],
"clf__class_weight": [None, "balanced"],
}
search = GridSearchCV(
estimator=pipe,
param_grid=param_grid,
scoring="average_precision", # PR-AUC is often informative under imbalance
cv=skf,
n_jobs=-1
)
search.fit(X, y)
print(search.best_params_, search.best_score_)
Validação cruzada em *k* dobras estratificada repetida para estimativas mais estáveis
Uma única execução de validação cruzada em k dobras ainda pode ser um pouco ruidosa para conjuntos de dados pequenos. Repetir a validação cruzada estratificada com diferentes embaralhamentos pode estabilizar as estimativas:
from sklearn.model_selection import RepeatedStratifiedKFold, cross_val_score
rskf = RepeatedStratifiedKFold(n_splits=5, n_repeats=10, random_state=42)
scores = cross_val_score(pipe, X, y, cv=rskf, scoring="f1")
print(scores.mean(), scores.std())
Armadilhas comuns (e como evitá-las)
1) Vazamento de dados por pré-processamento e engenharia de atributos
Problema: Ajustar etapas de pré-processamento em todos os dados antes da divisão (por exemplo, escalonamento, imputação, PCA, seleção de atributos) vaza informação da validação.
Correção: Coloque todo o pré-processamento dentro de um Pipeline e faça validação cruzada no pipeline.
Também fique atento a vazamento via:
- codificação do alvo (target encoding) ou codificação pela média (mean encoding) calculadas globalmente,
- seleção de atributos baseada em correlação com o alvo calculada em todos os dados,
- vetorizadores de texto (text vectorizers) ajustados em todos os documentos (use pipeline para que sejam ajustados por dobra).
Este é um tema central em Validação e Validação Cruzada.
2) Vazamento por reamostragem (resampling) (SMOTE/sobreamostragem (oversampling)) feita globalmente
Com dados desbalanceados, as pessoas frequentemente fazem sobreamostragem de exemplos minoritários. Se você fizer sobreamostragem antes da validação cruzada, duplicatas/pontos sintéticos podem vazar para as dobras de validação.
Correção: Faça sobreamostragem dentro de cada dobra de treinamento apenas (por exemplo, com um pipeline do imbalanced-learn). Conceitualmente:
- divida em treino/val para a dobra,
- reamostre apenas o treino,
- ajuste no treino reamostrado,
- avalie no val intacto.
3) Dados agrupados: a estratificação pode quebrar a independência
Se múltiplas linhas vierem da mesma entidade (usuário, paciente, dispositivo, sessão), a estratificação aleatória pode colocar a mesma entidade tanto em treino quanto em validação, causando resultados excessivamente otimistas.
Exemplos:
- múltiplas imagens médicas por paciente,
- muitas transações por cliente,
- medições repetidas por máquina.
Correção: Use divisão consciente de grupos (por exemplo, GroupKFold) ou variantes estratificadas por grupo (por exemplo, StratifiedGroupKFold, se disponível no seu stack). O objetivo passa a ser:
- manter todas as amostras de um grupo em uma única dobra,
- e preservar as proporções de classes tanto quanto possível.
Frequentemente há um trade-off: estratificação perfeita pode ser impossível quando grupos são grandes ou rótulos são distribuídos de forma desigual entre grupos.
4) Dependências temporais: a estratificação pode causar vazamento temporal
Para séries temporais (time series) ou qualquer processo temporal, embaralhar e estratificar pode treinar com dados do “futuro” e validar com dados do “passado”, inflando o desempenho.
Correção: Use estratégias de divisão conscientes do tempo, como janelas deslizantes/expansivas; veja Validação Cruzada para Séries Temporais (Time Series Cross-Validation).
Mesmo que o balanceamento global de classes seja preservado, violar a ordem temporal pode tornar a avaliação inválida.
5) Dobras demais para classes raras
A validação cruzada em k dobras estratificada precisa de exemplos suficientes de cada classe para distribuir entre as dobras.
Regra prática:
- Se a classe mais rara tem (m) exemplos, em geral você precisa de (k \le m).
- Com classes extremamente raras, até (k=5) pode ser alto demais.
Correções:
- reduzir
n_splits, - usar validação cruzada estratificada repetida com menos dobras,
- considerar outros desenhos de avaliação (por exemplo, uma única Divisão Treino-Teste (Train-Test Split) com estratificação cuidadosa mais estimativas de incerteza).
6) “Estratificação” não resolve mudança de distribuição
Se a distribuição em implantação diferir da distribuição do conjunto de dados (por exemplo, prevalência diferente, população diferente), a validação cruzada estratificada ainda pode ser enganosa.
Correção: Considere uma avaliação que corresponda às condições de implantação (divisões temporais, por local, geográficas etc.) e complemente com métricas robustas e análise de incerteza (veja Estimativa de Incerteza (Uncertainty Estimation) / Quantificação de Incerteza (Uncertainty Quantification)).
Notas práticas: métricas, reporte e interpretabilidade
Escolha métricas que reflitam o problema sob desbalanceamento
A acurácia pode parecer excelente enquanto vai mal na classe minoritária. Prefira métricas alinhadas aos seus objetivos:
- Precisão/revocação/F1 (a partir da Matriz de Confusão)
- Acurácia balanceada
- AUC PR (precisão média) frequentemente é mais informativa do que AUC ROC quando positivos são raros
- métricas ponderadas por custo quando erros têm custos diferentes (veja Aprendizado Sensível a Custo (Cost-Sensitive Learning))
Veja Métricas para orientações e trade-offs.
Reporte a variabilidade, não apenas um único número
A validação cruzada fornece k pontuações (ou mais, se repetida). Reporte:
- média e desvio padrão,
- opcionalmente intervalos de confiança (com cuidado — as dobras da validação cruzada não são totalmente independentes),
- e pontuações por dobra ao depurar.
Para uma comparação mais rigorosa de modelos/hiperparâmetros, veja Desenho de Experimentos e Poder (Experiment Design & Power).
Validação cruzada aninhada para estimativas não viesadas na seleção de modelo
Se você ajusta hiperparâmetros e reporta a melhor pontuação a partir da mesma validação cruzada, pode obter estimativas otimistas. Uma correção comum é a validação cruzada aninhada (nested cross-validation):
- uma validação cruzada interna seleciona hiperparâmetros,
- uma validação cruzada externa estima o desempenho.
A estratificação tipicamente é usada em ambos os loops para classificação desbalanceada.
Exemplo trabalhado: dobras padrão vs estratificadas sob forte desbalanceamento
Considere 200 amostras com apenas 10 positivas (5%). Com dobras não estratificadas, você pode facilmente obter uma dobra com 0 positivas, tornando métricas como revocação indefinidas e tornando o treinamento instável para alguns modelos.
Um padrão rápido de inspeção:
import numpy as np
from sklearn.model_selection import KFold, StratifiedKFold
# Simulate labels: 190 zeros, 10 ones
y = np.array([0]*190 + [1]*10)
kf = KFold(n_splits=5, shuffle=True, random_state=0)
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=0)
def fold_counts(splitter, y):
out = []
for _, val_idx in splitter.split(np.zeros_like(y), y):
counts = np.bincount(y[val_idx], minlength=2)
out.append(tuple(counts))
return out
print("KFold:", fold_counts(kf, y))
print("StratifiedKFold:", fold_counts(skf, y))
Resultado típico:
KFoldpode produzir dobras como(40, 0),(39, 1), etc.StratifiedKFoldtende a(38, 2)de forma consistente
Essa consistência é exatamente o que torna a avaliação estratificada mais confiável sob desbalanceamento.
Resumo
A validação cruzada em k dobras estratificada é uma prática recomendada padrão para classificação desbalanceada, porque mantém proporções de classes consistentes entre as dobras, reduzindo a variância e prevenindo divisões patológicas.
Ela não é uma solução para tudo. As formas mais comuns pelas quais a validação cruzada estratificada ainda dá errado são:
- vazamento (pré-processamento ou reamostragem feitos fora do loop de validação cruzada),
- estruturas de dependência (grupos/usuários/pacientes vazando entre dobras),
- ordenação temporal (treinar no futuro).
Quando usada corretamente — tipicamente via pipelines, métricas apropriadas e divisores conscientes de dependências — a validação cruzada em k dobras estratificada é uma base prática e confiável para avaliação e seleção de modelos dentro de um fluxo de trabalho mais amplo descrito em Validação e Validação Cruzada.