← Назад к вопросам

Что такое bagging?

1.7 Middle🔥 161 комментариев
#Машинное обучение

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое bagging?

Bagging (Bootstrap Aggregating) — это метод ансамбля, который создаёт несколько подвыборок из исходного датасета с повторениями (bootstrap), обучает на каждой отдельную модель, а затем усредняет предсказания. Цель — снизить дисперсию и улучшить обобщаемость.

Основная идея

1. Берём исходный датасет (n примеров)
2. Создаём k подвыборок размером n с повторениями (sampling with replacement)
3. На каждой подвыборке обучаем модель (обычно одного типа)
4. Предсказания усредняются или комбинируются

Математическое объяснение

Исходная дисперсия модели:

Var(y) = σ²

Дисперсия ансамбля из k независимых моделей:

Var(ансамбль) = σ²/k  (если модели идеально некоррелированы)

На практике:

Var(ансамбль) ≈ σ² × (ρ + (1-ρ)/k)

где:
- ρ — средняя корреляция между моделями
- k — количество моделей в ансамбле

When k → ∞, дисперсия стремится к σ² × ρ (остаётся корреляция ошибок)

Практическая реализация (с нуля)

import numpy as np
from sklearn.datasets import make_classification
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

def bagging_manual(X, y, n_models=10, sample_size=None):
    """Простой bagging с нуля"""
    if sample_size is None:
        sample_size = len(X)
    
    n_samples = len(X)
    models = []
    
    for _ in range(n_models):
        # Bootstrap: случайная выборка с повторениями
        indices = np.random.choice(n_samples, size=sample_size, replace=True)
        X_bootstrap = X[indices]
        y_bootstrap = y[indices]
        
        # Обучаем модель на bootstrap выборке
        model = DecisionTreeClassifier(max_depth=5, random_state=None)
        model.fit(X_bootstrap, y_bootstrap)
        models.append(model)
    
    return models

def bagging_predict(models, X):
    """Усреднение предсказаний"""
    predictions = np.array([model.predict(X) for model in models])
    # Voting классификатор — берём режим (самый частый класс)
    y_pred = np.apply_along_axis(lambda x: np.bincount(x).argmax(), 0, predictions)
    return y_pred

def bagging_predict_proba(models, X):
    """Усреднение вероятностей"""
    predictions = np.array([model.predict_proba(X) for model in models])
    # Усреднение вероятностей по моделям
    return np.mean(predictions, axis=0)

# Использование
X, y = make_classification(n_samples=200, n_features=20, n_classes=2, random_state=42)
models = bagging_manual(X, y, n_models=10)
y_pred = bagging_predict(models, X)
accuracy = accuracy_score(y, y_pred)
print(f"Accuracy (Bagging): {accuracy:.4f}")

Встроенная реализация (scikit-learn)

from sklearn.ensemble import BaggingClassifier, BaggingRegressor
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LinearRegression

# Классификация
bagging_clf = BaggingClassifier(
    estimator=DecisionTreeClassifier(max_depth=5),
    n_estimators=100,        # Количество базовых моделей
    max_samples=0.8,         # 80% примеров в каждой выборке
    max_features=0.8,        # 80% признаков в каждой выборке
    bootstrap=True,          # С повторениями
    random_state=42
)
bagging_clf.fit(X_train, y_train)
y_pred = bagging_clf.predict(X_test)
y_pred_proba = bagging_clf.predict_proba(X_test)

# Регрессия
bagging_reg = BaggingRegressor(
    estimator=LinearRegression(),
    n_estimators=50,
    max_samples=1.0,
    max_features=1.0,
    random_state=42
)
bagging_reg.fit(X_train, y_train)
y_pred = bagging_reg.predict(X_test)

Сравнение: Баггинг vs Бустинг

from sklearn.ensemble import (
    BaggingClassifier,
    AdaBoostClassifier,
    GradientBoostingClassifier
)
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score

X, y = make_classification(n_samples=300, n_features=20, random_state=42)

# Bagging (параллельное обучение)
bagging = BaggingClassifier(
    DecisionTreeClassifier(max_depth=5),
    n_estimators=50
)

# Boosting (последовательное обучение)
adaboost = AdaBoostClassifier(
    DecisionTreeClassifier(max_depth=3),
    n_estimators=50
)

gradboost = GradientBoostingClassifier(
    n_estimators=50,
    learning_rate=0.1
)

# Сравнение
for name, model in [("Bagging", bagging), ("AdaBoost", adaboost), ("GradBoost", gradboost)]:
    scores = cross_val_score(model, X, y, cv=5)
    print(f"{name}: {scores.mean():.4f} (+/- {scores.std():.4f})")

# Output обычно показывает:
# Bagging: 0.85 (+/- 0.03)
# AdaBoost: 0.88 (+/- 0.02)        — лучше (фокусируется на ошибках)
# GradBoost: 0.92 (+/- 0.01)       — лучше всех (более сложный)

Случайные леса (Random Forest) — это специальный случай Bagging

from sklearn.ensemble import RandomForestClassifier

# Random Forest = Bagging + Random Feature Selection
rf = RandomForestClassifier(
    n_estimators=100,
    max_features='sqrt',        # √k случайных признаков
    max_samples=1.0,            # 100% примеров (bootstrap по умолчанию)
    max_depth=None,
    random_state=42
)

rf.fit(X_train, y_train)
feature_importance = rf.feature_importances_

print(f"Важность признаков: {feature_importance}")
print(f"Топ-5 признаков: {np.argsort(feature_importance)[-5:]}")

Когда использовать Bagging

Плюсы:

  • Снижает дисперсию (уменьшает overfitting)
  • Параллельное обучение (быстро)
  • Простая реализация
  • Работает со сложными моделями (деревья, нейросети)
  • Позволяет оценить важность признаков

Минусы:

  • Не снижает смещение (bias), только дисперсию
  • Может быть медленнее чем одна большая модель
  • Требует больше памяти (k моделей вместо одной)

Bagging vs Pojedental моделей

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score

# Одно дерево (high variance, low bias)
tree = DecisionTreeClassifier(max_depth=5)
scores_tree = cross_val_score(tree, X, y, cv=5)

# Bagging из 50 деревьев (low variance)
bagging = BaggingClassifier(DecisionTreeClassifier(max_depth=5), n_estimators=50)
scores_bagging = cross_val_score(bagging, X, y, cv=5)

print(f"Одно дерево: {scores_tree.mean():.4f} (дисперсия: {scores_tree.std():.4f})")
print(f"Bagging: {scores_bagging.mean():.4f} (дисперсия: {scores_bagging.std():.4f})")
# Bagging обычно имеет МЕНЬШУЮ дисперсию (std)

Оценка неопределённости (Out-Of-Bag, OOB)

# Для каждого примера в bootstrap есть примеры, которые НЕ вошли в выборку
# Это называется Out-Of-Bag (OOB)
# Можем использовать их для оценки ошибок на валидации БЕЗ отдельного hold-out

bagging = BaggingClassifier(
    DecisionTreeClassifier(max_depth=5),
    n_estimators=100,
    oob_score=True  # Включить OOB оценку
)

bagging.fit(X_train, y_train)
print(f"OOB Score: {bagging.oob_score_:.4f}")
# OOB Score часто близка к cross-validation score

Bagging — простой и эффективный способ улучшить модели за счёт уменьшения дисперсии!

Что такое bagging? | PrepBro