W3docs

Bootstrap Aggregation (Bagging) in Python

Lerne, wie Bagging die Varianz in ML-Modellen reduziert und wie du BaggingClassifier in Python implementierst.

Bootstrap Aggregation — häufig als Bagging bezeichnet — ist eine Ensemble-Technik, die mehrere Modelle auf verschiedenen zufälligen Stichproben deiner Daten trainiert und anschließend deren Vorhersagen kombiniert. Das Ergebnis ist ein Modell, das weniger empfindlich gegenüber Rauschen und Ausreißern ist und besser auf unbekannte Daten verallgemeinert als ein einzelnes Modell, das auf dem gesamten Datensatz trainiert wurde.

Dieses Kapitel behandelt:

  • Was Bootstrap-Sampling ist und warum es hilft
  • Den Bias-Varianz-Kompromiss, den Bagging adressiert
  • Wie man BaggingClassifier und BaggingRegressor mit scikit-learn implementiert
  • Wichtige Hyperparameter und wie man sie abstimmt
  • Out-of-Bag (OOB)-Fehler als kostenlosen Validierungsschätzer
  • Wann Bagging hilft und wann andere Methoden vorzuziehen sind

Wie Bootstrap-Sampling funktioniert

Das Wort Bootstrap bezieht sich auf Sampling mit Zurücklegen. Gegeben ein Datensatz mit n Beispielen wird eine Bootstrap-Stichprobe erstellt, indem n Beispiele zufällig gezogen werden, wobei jeder Zug unabhängig ist und dasselbe Beispiel mehr als einmal erscheinen kann.

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)

Ausgabe:

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]

Im Durchschnitt enthält eine Bootstrap-Stichprobe etwa 63 % der einzigartigen Originalbeispiele; die verbleibenden 37 % werden ausgelassen. Diese Out-of-Bag-(OOB-)Beispiele können als integriertes Validierungsset verwendet werden, ohne dass eine separate Hold-out-Aufteilung benötigt wird.

Der Bias-Varianz-Kompromiss

Jedes Modell macht Vorhersagen mit einer Kombination aus Bias (systematischer Fehler durch falsche Annahmen) und Varianz (Empfindlichkeit gegenüber Schwankungen in den Trainingsdaten). Bagging zielt auf Modelle mit hoher Varianz und niedrigem Bias ab — insbesondere tiefe Entscheidungsbäume.

Ein einzelner unbeschnittener Entscheidungsbaum kann den Trainingsdatensatz perfekt auswendig lernen, versagt jedoch auf neuen Daten. Indem die Vorhersagen vieler Bäume gemittelt werden, die jeweils auf einer leicht unterschiedlichen Bootstrap-Stichprobe trainiert wurden, heben sich die zufälligen Schwankungen auf und die Varianz sinkt — ohne den Bias wesentlich zu erhöhen.

Bagging hilft nicht bei Modellen, die bereits einen hohen Bias haben (zum Beispiel flache lineare Modelle), da das Mitteln vieler verzerrter Modelle immer noch ein verzerrtes Ergebnis liefert. Für diese Fälle sind Boosting-Methoden wie Gradient Boosting besser geeignet.

BaggingClassifier implementieren

scikit-learn stellt BaggingClassifier für Klassifikationsaufgaben bereit. Das folgende Beispiel vergleicht einen einzelnen Entscheidungsbaum mit einem gebaggerten Ensemble auf dem Brustkrebs-Datensatz.

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}")

Ausgabe:

Single tree accuracy:  0.95
Bagging accuracy:      0.96

Das gebaggerte Modell übertrifft den einzelnen Baum. Bei verrauschteren oder kleineren Datensätzen ist der Unterschied in der Regel größer.

Wichtige Konstruktorparameter

ParameterStandardWas er steuert
estimatorDecisionTreeClassifier()Der zu baggernde Basis-Lerner
n_estimators10Anzahl der zu trainierenden Modelle
max_samples1.0Anteil (oder Anzahl) der Trainingszeilen pro Bootstrap-Stichprobe
max_features1.0Anteil (oder Anzahl) der für jeden Basis-Lerner gezogenen Merkmale
bootstrapTrueZeilen mit Zurücklegen sampeln; auf False setzen für Pasting
bootstrap_featuresFalseMerkmale ebenfalls mit Zurücklegen sampeln
oob_scoreFalseGeneralisierung mithilfe von Out-of-Bag-Beispielen schätzen

Out-of-Bag (OOB)-Fehler

Da jeder Basis-Lerner nur etwa 63 % der Trainingsdaten sieht, können die verbleibenden 37 % zur Auswertung dieses Lerners verwendet werden, ohne das Testset zu berühren. Das Mitteln dieser OOB-Auswertungen über alle Schätzer hinweg ergibt den OOB-Score — einen nahezu kostenlosen Schätzer der Testgenauigkeit.

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}")

Ausgabe:

OOB score: 0.96

Der OOB-Score liegt nahe an der gehaltenen Testgenauigkeit und ist daher als schnelle Plausibilitätsprüfung nützlich — besonders wenn dein Datensatz zu klein ist, um eine separate Validierungsaufteilung zu erlauben. Für eine genauere Schätzung kombiniere Bagging mit Kreuzvalidierung.

BaggingRegressor

Bagging ist auch für Regression nützlich. Ersetze BaggingClassifier durch BaggingRegressor und wähle einen Regressions-Basis-Lerner.

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}")

Ausgabe:

BaggingRegressor RMSE: 0.5080

Auswertung mit Kreuzvalidierung

Eine einzelne Train-Test-Aufteilung kann je nachdem, welche Beispiele in welche Partition fallen, ein übermäßig optimistisches oder pessimistisches Bild ergeben. Die Ausführung von Kreuzvalidierung mittelt das Ergebnis über mehrere Aufteilungen hinweg für einen zuverlässigeren Score.

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}")

Ausgabe:

CV scores: [0.9123 0.9211 0.9825 0.9561 1.    ]
Mean: 0.9544, Std: 0.0339

Eine niedrige Standardabweichung über die Faltungen hinweg bedeutet, dass das Modell konsistent generalisiert. Eine hohe Standardabweichung deutet darauf hin, dass das Modell empfindlich darauf reagiert, welche Daten in welche Faltung gelangen.

Bagging vs. Random Forest

Random Forest ist der beliebteste Bagging-basierte Algorithmus. Er erweitert einfaches Bagging, indem bei jeder Teilungsentscheidung zusätzlich eine zufällige Teilmenge von Merkmalen ausgewählt wird — nicht nur eine Teilmenge von Zeilen —, was die Bäume weiter dekorreliert und häufig eine bessere Genauigkeit erzielt.

BaggingRandom Forest
Zeilen-SamplingBootstrap (mit Zurücklegen)Bootstrap (mit Zurücklegen)
Merkmal-SamplingOptional (max_features)Immer, bei jeder Teilung
Basis-LernerBeliebiger SchätzerNur Entscheidungsbaum
InterpretierbarkeitNiedrigNiedrig
Typischer EinsatzWenn ein Nicht-Baum-Modell gebaggert werden sollBester allgemeiner Ensemble-Ausgangspunkt

Wenn Entscheidungsbäume gebaggert werden, ist RandomForestClassifier fast immer die bessere Wahl. Verwende BaggingClassifier, wenn du einen anderen Basis-Lerner baggern möchtest — zum Beispiel einen KNeighborsClassifier aus K-Nearest Neighbors oder eine logistische Regression aus Logistic Regression.

Wann Bagging eingesetzt werden sollte

Bagging ist am effektivsten, wenn:

  • Dein Basismodell eine hohe Varianz hat (tiefe Entscheidungsbäume, Polynommodelle hohen Grades).
  • Du genug Daten hast, um diverse Bootstrap-Stichproben sinnvoll zu machen.
  • Du dir paralleles Training leisten kannst, da jeder Basis-Lerner unabhängig trainiert und die Arbeitslast auf CPU-Kerne verteilt werden kann (n_jobs=-1).

Es ist weniger hilfreich, wenn:

  • Das Basismodell bereits eine niedrige Varianz hat (z. B. lineare Modelle mit starker Regularisierung).
  • Du ein einzelnes, interpretierbares Modell benötigst — ein Ensemble aus 50 Bäumen lässt sich einem Stakeholder nicht leicht erklären.
  • Rechenkosten wichtiger sind als Genauigkeit — das Training von 50 Modellen ist 50-mal langsamer als das Training eines einzelnen.

Für Modelle mit hohem Bias solltest du Grid Search zur Hyperparameter-Abstimmung in Betracht ziehen oder zu einer Boosting-Methode wechseln. Zur Auswertung überprüfe dein Modell immer auf einer Hold-out-Aufteilung, die mit Train-Test-Split oder Kreuzvalidierung erstellt wurde.

Zusammenfassung

  • Bootstrap Aggregation trainiert viele Basis-Lerner auf zufälligen Stichproben der Daten (mit Zurücklegen gezogen) und mittelt deren Vorhersagen.
  • Es reduziert die Varianz, ohne den Bias wesentlich zu erhöhen, und ist damit ideal für Modelle mit hoher Varianz wie tiefe Entscheidungsbäume.
  • scikit-learn stellt BaggingClassifier und BaggingRegressor bereit; wichtige Parameter sind n_estimators, max_samples und max_features.
  • Aktiviere oob_score=True für einen kostenlosen Generalisierungsschätzer, der kein separates Validierungsset erfordert.
  • Beim Baggern von Bäumen ist RandomForestClassifier in der Regel vorzuziehen; verwende BaggingClassifier, um andere Modelltypen zu baggern.
Was this page helpful?