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

Como criar um ensemble Stacking em Machine Learning: passo a passo

João Barros 23 de October de 2026 6 min de leitura

Este tutorial mostra como criar um ensemble Stacking em Machine Learning para combinar vários modelos e melhorar o desempenho de classificação. Stacking é particularmente útil quando modelos individuais têm pontos fortes diferentes (por exemplo, um capta bem relações lineares, outro capta interacções não lineares) e queremos obter um desempenho global mais robusto e frequentemente com menor erro do que cada modelo isolado.

Pré-requisitos

  • Python 3.8+
  • scikit-learn instalado (pip install scikit-learn)
  • pandas e numpy para manipulação de dados
  • noções básicas de classificação e validação cruzada

Ter um ambiente com CPU razoável ajuda (Stacking com cv=5 e vários estimadores pode consumir tempo). Para conjuntos de dados maiores, considere usar n_jobs=-1 para paralelizar. Exemplos abaixo usam o conjunto Iris, pequeno e didáctico.

Passo 1: Entender o que é Stacking e quando usar

Stacking é um ensemble que treina vários modelos base (base models) e depois um modelo final (meta-modelo) que aprende a combinar as previsões desses base models. Em vez de simplesmente votar ou fazer average, o meta-modelo observa as previsões dos base models (normalmente as previsões out-of-fold) e aprende pesos/combinações, reduzindo viés e/ou variância.

Quando usar:

  • Se tens modelos com comportamentos complementares (ex.: RandomForest captura interacções, LogisticRegression é estável para relações lineares).
  • Se queres melhorar a generalização sem recorrer apenas a hiperparametrização intensa.
  • Quando tens dados suficientes para criar meta-features sem sobreajustar — por exemplo, para Iris (150 amostras) funciona bem como demonstração; em problemas reais tens tipicamente centenas ou milhares de amostras.

Técnica chave: usar validação cruzada (cv) para gerar previsões out-of-fold dos base models, evitando fugas de informação do treino directo para o meta-modelo.

Passo 2: Preparar os dados

Carrega um conjunto simples (ex.: Iris) e divide em treino/teste. Garantir limpeza e codificação de variáveis categóricas se existirem. Importante: para classificadores sensíveis à escala (KNN, SVM, LogisticRegression) aplicar StandardScaler dentro de um pipeline.

import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

data = load_iris()
X = pd.DataFrame(data.data, columns=data.feature_names)
y = pd.Series(data.target)

# Com test_size=0.2 e 150 amostras -> 120 treino / 30 teste
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)

Stratify mantém proporções das classes no treino/teste. Para conjuntos maiores, considerar validação adicional com cross_val_score para medir robustez.

Passo 3: Escolher modelos base e meta-modelo

Escolhe modelos diversos para captar diferentes tipos de padrões. Exemplo prático: LogisticRegression (linear), RandomForestClassifier (ensemble de árvores) e KNeighborsClassifier (método baseado em distância). O meta-modelo costuma ser simples — LogisticRegression é uma boa escolha inicial para evitar sobreajuste.

from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import StackingClassifier

estimators = [
    ('rf', RandomForestClassifier(n_estimators=50, random_state=42)),
    ('knn', KNeighborsClassifier(n_neighbors=5)),
    ('lr', LogisticRegression(max_iter=200))
]

meta_clf = LogisticRegression()

Notas: n_estimators=50 é escolhido por rapidez; em produção usar 100-500 conforme orçamento. KNN com k=5 é típico; experimentar k entre 3 e 15. meta_clf simples evita que o ensemble se torne demasiado complexo.

Passo 4: Construir e treinar o Stacking

Usa StackingClassifier do scikit-learn: define estimators e final_estimator. O parâmetro cv determina como os meta-features são gerados (por defeito, cada base model faz previsões out-of-fold num cv de 5 folds, produzindo um conjunto de previsões usados para treinar o meta-modelo).

stack = StackingClassifier(estimators=estimators, final_estimator=meta_clf, cv=5, n_jobs=-1)
stack.fit(X_train, y_train)

Explicação prática: com cv=5, cada base model faz 5 treinos em 80% dos dados e prevê os 20% restantes; as previsões concatenadas formam as features para o meta-modelo. Para classificações múltiplas podes usar predict_proba (gera mais colunas) ou predict (uma coluna por modelo), consoante o parâmetro do StackingClassifier.

Passo 5: Avaliar o ensemble e comparar com modelos individuais

Avalia com métricas: accuracy, precision, recall, f1 e matriz de confusão. Compara o Stacking com cada modelo base para confirmar melhoria. Exemplos típicos com Iris: Stacking accuracy pode subir para 0.96-0.98 enquanto modelos individuais andam entre 0.90 e 0.96 — ganhos modestos mas consistentes.

from sklearn.metrics import accuracy_score, classification_report

# Previsões
y_pred_stack = stack.predict(X_test)
print('Stacking accuracy:', accuracy_score(y_test, y_pred_stack))
print(classification_report(y_test, y_pred_stack))

# Avaliar modelos individuais
for name, est in estimators:
    est.fit(X_train, y_train)
    y_pred = est.predict(X_test)
    print(f"{name} accuracy:", accuracy_score(y_test, y_pred))

Interpreta resultados: se o Stacking não melhora, verifica se os modelos base são demasiado semelhantes ou se o meta-modelo está a sobreajustar.

Passo 6: Evitar overfitting e erros comuns

Erros comuns: usar o mesmo fold de treino para gerar meta-features sem validação adequada, não normalizar features quando necessário, e usar um meta-modelo demasiado complexo (p.ex., uma árvore muito profunda) que aprenda ruído. Boas práticas:

  • Usar pipelines com StandardScaler para KNN e LogisticRegression.
  • Validar o ensemble com cross_val_score para estimar robustez (ex.: mean cross-val accuracy com cv=5).
  • Experimentar com predict_proba no StackingClassifier para oferecer mais informação ao meta-modelo.
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import cross_val_score

# Exemplo com pipeline para KNN
estimators_pipe = [
    ('rf', RandomForestClassifier(n_estimators=50, random_state=42)),
    ('knn', make_pipeline(StandardScaler(), KNeighborsClassifier(n_neighbors=5))),
    ('lr', make_pipeline(StandardScaler(), LogisticRegression(max_iter=200)))
]
stack_pipe = StackingClassifier(estimators=estimators_pipe, final_estimator=LogisticRegression(), cv=5, n_jobs=-1)
print('Cross-val accuracy (stack):', np.mean(cross_val_score(stack_pipe, X_train, y_train, cv=5)))

Verificar o resultado

Confirma que o Stacking tem accuracy igual ou superior aos modelos individuais e que a matriz de confusão distribui erros de forma aceitável. Usa cross_val_score para validar robustez e verifica se o meta-modelo acrescenta valor — por exemplo, olhando para os coeficientes se for LogisticRegression (valores maiores correspondem a maior peso nas previsões de certos base models).

Conclusão

Stacking permite combinar forças de vários modelos para melhorar previsões; o próximo passo é testar com conjuntos maiores ou com modelos diferentes (p.ex., XGBoost, LightGBM) e experimentar meta-modelos alternativos. Dica prática: começa com modelos simples e cv=5, mede ganhos percentuais (p.ex., +1-3% de accuracy) e só depois aumenta a complexidade para não introduzir overfitting. Que combinação vais experimentar a seguir?