(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Como fazer validação cruzada em Machine Learning

João Barros 05 de July de 2026 5 min de leitura

A validação cruzada é uma das formas mais fiáveis de avaliar um modelo de Machine Learning. Em vez de confiar numa única divisão entre treino e teste, o modelo é avaliado várias vezes em partes diferentes dos dados, o que produz uma estimativa muito mais estável do desempenho real. Esta técnica é especialmente valiosa quando tens poucos dados, porque aproveita todos os exemplos tanto para treinar como para testar. A seguir vês como fazer validação cruzada em Machine Learning com scikit-learn, com exemplos simples e prontos a correr.

Pré-requisitos

  • Python 3 instalado no teu computador.
  • As bibliotecas scikit-learn e NumPy instaladas (pip install scikit-learn).
  • Saber o que é um modelo e a diferença entre dados de treino e de teste.
  • Um editor de código ou o Jupyter Notebook para correr os exemplos.

Passo 1: Preparar os dados

Para este exemplo usamos o conjunto de dados iris, que já vem incluído no scikit-learn e não precisa de qualquer descarga. Separamos as características (X) da classe que queremos prever (y). As características são as colunas que descrevem cada flor — comprimento e largura das pétalas e das sépalas — e a classe é a espécie que queremos identificar.

from sklearn.datasets import load_iris

data = load_iris()
X = data.data
y = data.target
print(X.shape)

O resultado (150, 4) indica 150 exemplos e 4 características. É um conjunto pequeno e equilibrado, perfeito para aprender.

Passo 2: Escolher o modelo

A validação cruzada funciona com qualquer modelo do scikit-learn. Vamos usar uma regressão logística como exemplo. O parâmetro max_iter garante que o treino tem iterações suficientes para convergir.

from sklearn.linear_model import LogisticRegression

model = LogisticRegression(max_iter=200)

Repara que ainda não treinámos nada: a função de validação cruzada vai tratar disso por nós. Se preferires outro algoritmo, basta substituir esta linha — o resto do código mantém-se igual.

Passo 3: Aplicar a validação cruzada

A função cross_val_score faz todo o trabalho. Com cv=5 divide os dados em 5 partes (chamadas folds), treina o modelo 5 vezes e, em cada uma, usa uma parte diferente para teste e as restantes para treino. É daqui que vem o nome k-fold. Ao repetir a avaliação em várias divisões, reduz-se o risco de um resultado enganador causado por uma divisão particularmente fácil ou difícil.

from sklearn.model_selection import cross_val_score

scores = cross_val_score(model, X, y, cv=5)
print(scores)

O resultado é uma lista com 5 valores de exatidão, um por cada fold. Cada valor está entre 0 e 1. Usar 5 ou 10 folds é a escolha mais comum.

Passo 4: Interpretar os resultados

Um único número não chega: interessa saber a média e a variação entre os folds. A média é a melhor estimativa do desempenho do modelo; o desvio padrão mostra se esse desempenho é consistente.

print("Mean accuracy:", scores.mean().round(3))
print("Std deviation:", scores.std().round(3))

Um desvio padrão baixo significa que o modelo se comporta de forma parecida em todas as partes dos dados — sinal de um resultado fiável. Um desvio alto sugere que o modelo é instável ou que há poucos dados. Por exemplo, uma média de 0.97 com um desvio de 0.02 indica que o modelo acerta cerca de 97% das vezes de forma consistente.

Passo 5: Ter mais controlo com StratifiedKFold

Em problemas de classificação convém que cada fold mantenha a mesma proporção de classes que o conjunto completo. O StratifiedKFold faz exatamente isso, e com shuffle=True e random_state os resultados ficam reproduzíveis. Sem estratificação, um fold poderia ficar com demasiados exemplos de uma só espécie, distorcendo a avaliação.

from sklearn.model_selection import StratifiedKFold

kfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, X, y, cv=kfold)
print(scores.mean().round(3))
Dica: usa sempre o mesmo random_state para conseguires comparar experiências de forma justa.

Verificar o resultado

Se tudo correu bem, o print(scores) mostra um array com 5 números entre 0 e 1, e a média aparece como um único valor (por exemplo, à volta de 0.97 no conjunto iris). Confirma que a média está próxima dos valores individuais dos folds. Se surgir um aviso de convergência, aumenta o max_iter; se os valores variarem muito, pode faltar dados ou o modelo não ser o mais adequado.

Conclusão

Já consegues avaliar um modelo de forma robusta, sem depender da sorte de uma única divisão dos dados. O passo seguinte natural é combinar a validação cruzada com o GridSearchCV para escolher os melhores hiperparâmetros, ou usar cross_val_predict para inspecionar as previsões fold a fold. Experimenta trocar a LogisticRegression por um RandomForestClassifier: será que a exatidão média sobe?