W3docs

Bootstrap Aggregation (Bagging) в Python

Узнайте, как бэггинг снижает дисперсию ML-моделей и как реализовать BaggingClassifier в Python.

Bootstrap aggregation — широко известный как бэггинг — это ансамблевый метод, при котором несколько моделей обучаются на разных случайных выборках ваших данных, а затем их предсказания объединяются. В результате получается модель, менее чувствительная к шуму и выбросам, которая лучше обобщается на новых данных, чем любая отдельная модель, обученная на всём датасете.

В этой главе рассматривается:

  • Что такое бутстрэп-выборка и почему она помогает
  • Компромисс между смещением и дисперсией, который решает бэггинг
  • Как реализовать BaggingClassifier и BaggingRegressor с помощью scikit-learn
  • Ключевые гиперпараметры и способы их настройки
  • Ошибка out-of-bag (OOB) как бесплатная оценка на валидационной выборке
  • Когда бэггинг помогает, а когда лучше выбрать другие методы

Как работает бутстрэп-выборка

Слово bootstrap означает выборку с возвращением. Для датасета из n примеров одна бутстрэп-выборка создаётся путём случайного извлечения n примеров, где каждое извлечение независимо и один и тот же пример может встречаться более одного раза.

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)

Вывод:

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]

В среднем бутстрэп-выборка содержит около 63 % уникальных оригинальных примеров; оставшиеся 37 % не попадают в неё. Эти примеры out-of-bag (OOB) можно использовать как встроенную валидационную выборку без необходимости делать отдельный отложенный раздел.

Компромисс между смещением и дисперсией

Каждая модель делает предсказания с некоторым сочетанием смещения (систематической ошибки из-за неверных допущений) и дисперсии (чувствительности к флуктуациям в обучающих данных). Бэггинг нацелен на модели с высокой дисперсией и низким смещением — в особенности на глубокие деревья решений.

Одно необрезанное дерево решений может идеально запомнить обучающую выборку, но плохо справляется с новыми данными. Усредняя предсказания множества деревьев, каждое из которых обучено на немного другой бутстрэп-выборке, случайные флуктуации компенсируют друг друга и дисперсия снижается — без существенного увеличения смещения.

Бэггинг не помогает моделям с высоким смещением (например, неглубоким линейным моделям), поскольку усреднение многих смещённых моделей всё равно даёт смещённый результат. В таких случаях более подходящими являются методы бустинга, такие как Gradient Boosting.

Реализация BaggingClassifier

scikit-learn предоставляет BaggingClassifier для задач классификации. В примере ниже сравнивается одиночное дерево решений с ансамблем на основе бэггинга на датасете рака молочной железы.

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

Вывод:

Single tree accuracy:  0.95
Bagging accuracy:      0.96

Модель с бэггингом превосходит одиночное дерево. На более зашумлённых или небольших датасетах разрыв обычно больше.

Ключевые параметры конструктора

ПараметрПо умолчаниюЧто контролирует
estimatorDecisionTreeClassifier()Базовый алгоритм для бэггинга
n_estimators10Количество моделей для обучения
max_samples1.0Доля (или количество) строк обучающей выборки на бутстрэп-выборку
max_features1.0Доля (или количество) признаков для каждого базового алгоритма
bootstrapTrueВыборка строк с возвращением; установите False для вставки без возвращения
bootstrap_featuresFalseТакже выбирать признаки с возвращением
oob_scoreFalseОценка обобщающей способности с помощью out-of-bag примеров

Ошибка out-of-bag (OOB)

Поскольку каждый базовый алгоритм видит лишь около 63 % обучающих данных, оставшиеся 37 % можно использовать для его оценки, не затрагивая тестовую выборку. Усреднение этих OOB-оценок по всем оценщикам даёт OOB-оценку — практически бесплатную оценку точности на тестовой выборке.

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

Вывод:

OOB score: 0.96

OOB-оценка близка к точности на отложенной тестовой выборке, что делает её полезной для быстрой проверки — особенно когда датасет слишком мал для выделения отдельного раздела для валидации. Для более строгой оценки сочетайте бэггинг с кросс-валидацией.

BaggingRegressor

Бэггинг одинаково полезен для задач регрессии. Замените BaggingClassifier на BaggingRegressor и выберите базовый алгоритм регрессии.

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

Вывод:

BaggingRegressor RMSE: 0.5080

Оценка с помощью кросс-валидации

Единственное разбиение на обучающую и тестовую выборки может давать чрезмерно оптимистичный или пессимистичный результат в зависимости от того, какие примеры попадут в каждый раздел. Использование кросс-валидации усредняет результат по нескольким разбиениям для получения более надёжной оценки.

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

Вывод:

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

Низкое стандартное отклонение по фолдам означает, что модель обобщается стабильно. Высокое стандартное отклонение свидетельствует о том, что модель чувствительна к тому, какие данные попадают в каждый фолд.

Бэггинг против Random Forest

Random Forest — наиболее популярный алгоритм на основе бэггинга. Он расширяет обычный бэггинг, также случайным образом выбирая подмножество признаков при каждом разбиении узла — не только подмножество строк — что дополнительно декоррелирует деревья и зачастую даёт более высокую точность.

БэггингRandom Forest
Выборка строкBootstrap (с возвращением)Bootstrap (с возвращением)
Выборка признаковОпционально (max_features)Всегда, при каждом разбиении
Базовый алгоритмЛюбой оценщикТолько дерево решений
ИнтерпретируемостьНизкаяНизкая
Типичное применениеКогда нужно применить бэггинг к модели не на основе дереваЛучшая базовая ансамблевая модель на все случаи

Если вы применяете бэггинг к деревьям решений, RandomForestClassifier почти всегда является лучшим выбором. Используйте BaggingClassifier, когда хотите применить бэггинг к другому базовому алгоритму — например, к KNeighborsClassifier из раздела K-Nearest Neighbors или к логистической регрессии из раздела Logistic Regression.

Когда использовать бэггинг

Бэггинг наиболее эффективен, когда:

  • Ваша базовая модель имеет высокую дисперсию (глубокие деревья решений, полиномиальные модели высокой степени).
  • У вас достаточно данных для создания разнообразных бутстрэп-выборок.
  • Вы можете позволить себе параллельное обучение, поскольку каждый базовый алгоритм обучается независимо и нагрузка может распределяться по ядрам CPU (n_jobs=-1).

Бэггинг менее полезен, когда:

  • Базовая модель уже имеет низкую дисперсию (например, линейные модели с сильной регуляризацией).
  • Вам нужна единственная интерпретируемая модель — ансамбль из 50 деревьев сложно объяснить заинтересованному лицу.
  • Вычислительные затраты важнее точности — обучение 50 моделей в 50 раз медленнее, чем обучение одной.

Для моделей с высоким смещением рассмотрите Grid Search для настройки гиперпараметров или переключитесь на метод бустинга. Для оценки всегда проверяйте модель на отложенной выборке, созданной с помощью train-test split или кросс-валидации.

Итоги

  • Bootstrap aggregation обучает множество базовых алгоритмов на случайных выборках данных (с возвращением) и усредняет их предсказания.
  • Метод снижает дисперсию без существенного увеличения смещения, что делает его идеальным для моделей с высокой дисперсией, таких как глубокие деревья решений.
  • scikit-learn предоставляет BaggingClassifier и BaggingRegressor; ключевые параметры: n_estimators, max_samples и max_features.
  • Включите oob_score=True для бесплатной оценки обобщающей способности без необходимости использовать отдельную валидационную выборку.
  • При бэггинге деревьев обычно предпочтителен RandomForestClassifier; используйте BaggingClassifier для бэггинга других типов моделей.
Was this page helpful?