Bootstrap Aggregation (Bagging) em Python
Aprenda como o bagging reduz a variância em modelos de ML e como implementar BaggingClassifier em Python com scikit-learn.
Bootstrap aggregation — comumente chamado de bagging — é uma técnica de ensemble que treina múltiplos modelos em amostras aleatórias diferentes dos seus dados e, em seguida, combina suas previsões. O resultado é um modelo menos sensível a ruído e valores discrepantes, e que generaliza melhor para dados não vistos do que qualquer modelo individual treinado no conjunto de dados completo.
Este capítulo aborda:
- O que é amostragem bootstrap e por que ela ajuda
- O tradeoff entre viés e variância que o bagging resolve
- Como implementar
BaggingClassifiereBaggingRegressorcom scikit-learn - Principais hiperparâmetros e como ajustá-los
- Erro out-of-bag (OOB) como estimativa gratuita de validação
- Quando o bagging ajuda e quando preferir outros métodos
Como funciona a amostragem bootstrap
A palavra bootstrap refere-se à amostragem com reposição. Dado um conjunto de dados com n exemplos, uma amostra bootstrap é criada sorteando n exemplos aleatoriamente, onde cada sorteio é independente e o mesmo exemplo pode aparecer mais de uma vez.
import numpy as np
rng = np.random.default_rng(42)
data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
bootstrap_sample = rng.choice(data, size=len(data), replace=True)
out_of_bag = np.setdiff1d(data, bootstrap_sample)
print("Original data: ", data)
print("Bootstrap sample:", bootstrap_sample)
print("Out-of-bag: ", out_of_bag)Saída:
Original data: [ 1 2 3 4 5 6 7 8 9 10]
Bootstrap sample: [1 8 7 5 5 9 1 7 3 1]
Out-of-bag: [ 2 4 6 10]Em média, uma amostra bootstrap contém cerca de 63 % dos exemplos únicos originais; os 37 % restantes ficam de fora. Esses exemplos out-of-bag (OOB) podem ser usados como um conjunto de validação integrado, sem necessidade de uma divisão separada de hold-out.
O tradeoff entre viés e variância
Todo modelo faz previsões com alguma combinação de viés (erro sistemático decorrente de suposições incorretas) e variância (sensibilidade a flutuações nos dados de treinamento). O bagging tem como alvo modelos com alta variância e baixo viés — especialmente árvores de decisão profundas.
Uma única árvore de decisão não podada pode memorizar perfeitamente o conjunto de treinamento, mas falha muito em dados novos. Ao calcular a média das previsões de muitas árvores, cada uma treinada em uma amostra bootstrap ligeiramente diferente, as flutuações aleatórias se cancelam e a variância cai — sem aumentar significativamente o viés.
O bagging não ajuda modelos que já têm alto viés (por exemplo, modelos lineares rasos), porque a média de muitos modelos enviesados ainda produz uma resposta enviesada. Para esses casos, métodos de boosting como Gradient Boosting são mais adequados.
Implementando BaggingClassifier
O scikit-learn fornece BaggingClassifier para tarefas de classificação. O exemplo abaixo compara uma única árvore de decisão com um ensemble de bagging no conjunto de dados de câncer de mama.
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer
from sklearn.metrics import accuracy_score
# Load dataset
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# Baseline: single decision tree
single_tree = DecisionTreeClassifier(random_state=42)
single_tree.fit(X_train, y_train)
single_acc = accuracy_score(y_test, single_tree.predict(X_test))
# Bagging ensemble of 50 decision trees
bagging_model = BaggingClassifier(
estimator=DecisionTreeClassifier(),
n_estimators=50,
random_state=42,
)
bagging_model.fit(X_train, y_train)
bagging_acc = accuracy_score(y_test, bagging_model.predict(X_test))
print(f"Single tree accuracy: {single_acc:.2f}")
print(f"Bagging accuracy: {bagging_acc:.2f}")Saída:
Single tree accuracy: 0.95
Bagging accuracy: 0.96O modelo com bagging supera a árvore individual. Em conjuntos de dados mais ruidosos ou menores, a margem costuma ser maior.
Principais parâmetros do construtor
| Parâmetro | Padrão | O que controla |
|---|---|---|
estimator | DecisionTreeClassifier() | O aprendiz base a ser agrupado |
n_estimators | 10 | Número de modelos a treinar |
max_samples | 1.0 | Fração (ou quantidade) de linhas de treinamento por amostra bootstrap |
max_features | 1.0 | Fração (ou quantidade) de features sorteadas para cada aprendiz base |
bootstrap | True | Amostra linhas com reposição; defina False para pasting |
bootstrap_features | False | Também amostra features com reposição |
oob_score | False | Estima a generalização usando exemplos out-of-bag |
Erro out-of-bag (OOB)
Como cada aprendiz base vê apenas cerca de 63 % dos dados de treinamento, os 37 % restantes podem ser usados para avaliar esse aprendiz sem tocar no conjunto de teste. A média dessas avaliações OOB em todos os estimadores fornece o OOB score — uma estimativa quase gratuita da acurácia no teste.
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
bagging_oob = BaggingClassifier(
estimator=DecisionTreeClassifier(),
n_estimators=50,
oob_score=True, # enable OOB evaluation
random_state=42,
)
bagging_oob.fit(X_train, y_train)
print(f"OOB score: {bagging_oob.oob_score_:.2f}")Saída:
OOB score: 0.96O OOB score é próximo da acurácia no teste reservado, tornando-o útil como uma verificação rápida de sanidade — especialmente quando seu conjunto de dados é pequeno demais para ter uma divisão de validação separada. Para uma estimativa mais rigorosa, combine o bagging com validação cruzada.
BaggingRegressor
O bagging é igualmente útil para regressão. Substitua BaggingClassifier por BaggingRegressor e escolha um aprendiz base de regressão.
from sklearn.ensemble import BaggingRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.model_selection import train_test_split
from sklearn.datasets import fetch_california_housing
from sklearn.metrics import mean_squared_error
import numpy as np
X, y = fetch_california_housing(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
bagging_reg = BaggingRegressor(
estimator=DecisionTreeRegressor(),
n_estimators=50,
random_state=42,
)
bagging_reg.fit(X_train, y_train)
rmse = np.sqrt(mean_squared_error(y_test, bagging_reg.predict(X_test)))
print(f"BaggingRegressor RMSE: {rmse:.4f}")Saída:
BaggingRegressor RMSE: 0.5080Avaliando com validação cruzada
Uma única divisão treino-teste pode fornecer uma imagem excessivamente otimista ou pessimista, dependendo de quais exemplos caem em cada partição. Executar a validação cruzada calcula a média do resultado em múltiplas divisões para uma pontuação mais confiável.
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_breast_cancer
import numpy as np
X, y = load_breast_cancer(return_X_y=True)
clf = BaggingClassifier(
estimator=DecisionTreeClassifier(),
n_estimators=50,
random_state=42,
)
scores = cross_val_score(clf, X, y, cv=5)
print(f"CV scores: {scores.round(4)}")
print(f"Mean: {scores.mean():.4f}, Std: {scores.std():.4f}")Saída:
CV scores: [0.9123 0.9211 0.9825 0.9561 1. ]
Mean: 0.9544, Std: 0.0339Um desvio padrão baixo entre as dobras significa que o modelo generaliza de forma consistente. Um desvio padrão alto sugere que o modelo é sensível a quais dados acabam em cada dobra.
Bagging vs. Random Forest
Random Forest é o algoritmo baseado em bagging mais popular. Ele estende o bagging simples ao também selecionar aleatoriamente um subconjunto de features em cada decisão de divisão — não apenas um subconjunto de linhas — o que descorrelaciona ainda mais as árvores e geralmente produz melhor acurácia.
| Bagging | Random Forest | |
|---|---|---|
| Amostragem de linhas | Bootstrap (com reposição) | Bootstrap (com reposição) |
| Amostragem de features | Opcional (max_features) | Sempre, em cada divisão |
| Aprendiz base | Qualquer estimador | Somente árvore de decisão |
| Interpretabilidade | Baixa | Baixa |
| Uso típico | Quando se quer aplicar bagging a um modelo não-árvore | Melhor baseline de ensemble geral |
Quando você estiver aplicando bagging em árvores de decisão, RandomForestClassifier é quase sempre a melhor escolha. Use BaggingClassifier quando quiser aplicar bagging a um aprendiz base diferente — por exemplo, um KNeighborsClassifier do K-Nearest Neighbors ou uma regressão logística da Regressão Logística.
Quando usar bagging
O bagging é mais eficaz quando:
- Seu modelo base tem alta variância (árvores de decisão profundas, modelos polinomiais de alto grau).
- Você tem dados suficientes para tornar as amostras bootstrap diversas e significativas.
- Você pode usar treinamento paralelo, pois cada aprendiz base treina de forma independente e a carga de trabalho pode ser distribuída entre núcleos de CPU (
n_jobs=-1).
É menos útil quando:
- O modelo base já tem baixa variância (por exemplo, modelos lineares com regularização forte).
- Você precisa de um modelo único e interpretável — um ensemble de 50 árvores não é fácil de explicar a um stakeholder.
- O custo computacional importa mais do que a acurácia — treinar 50 modelos é 50 vezes mais lento do que treinar um.
Para modelos com alto viés, considere o Grid Search para ajustar hiperparâmetros, ou troque para um método de boosting. Para avaliação, sempre verifique seu modelo em uma divisão reservada criada com divisão treino-teste ou com validação cruzada.
Resumo
- Bootstrap aggregation treina muitos aprendizes base em amostras aleatórias dos dados (sorteadas com reposição) e calcula a média de suas previsões.
- Reduz a variância sem aumentar significativamente o viés, tornando-o ideal para modelos de alta variância, como árvores de decisão profundas.
- O scikit-learn fornece
BaggingClassifiereBaggingRegressor; os principais parâmetros sãon_estimators,max_samplesemax_features. - Ative
oob_score=Truepara obter uma estimativa gratuita de generalização que não exige um conjunto de validação separado. - Ao aplicar bagging em árvores,
RandomForestClassifiergeralmente é preferível; useBaggingClassifierpara aplicar bagging em outros tipos de modelos.