Случайный лес и бэггинг: зачем объединять деревья

Случайный лес обучает много различающихся деревьев и объединяет их прогнозы. Отдельное дерево нестабильно: небольшая замена строк способна перестроить верхние ветви. Усреднение снижает эту вариативность и обычно даёт более надёжное качество без тонкой настройки каждого дерева.

Идея bootstrap и бэггинга

Для каждого базового алгоритма создаётся bootstrap-выборка: строки случайно выбираются из train с возвращением. Некоторые объекты повторяются, другие не попадают в конкретный набор. Деревья видят разные данные и совершают не полностью одинаковые ошибки.

В общем бэггинге классификаторы можно объединять голосованием или оценками классов. Конкретно RandomForestClassifier в scikit-learn усредняет вероятности деревьев и выбирает класс с максимальной средней вероятностью; в регрессии используется средний прогноз. Усреднение уменьшает вариативность, когда ошибки деревьев не идеально коррелированы, но не устраняет общий систематический bias.

Что добавляет случайный лес

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

Цена — больше памяти, времени и менее компактное объяснение. Лес нельзя свести к одному небольшому набору правил без потери поведения ансамбля.

Обучение классификатора

from sklearn.datasets import load_wine
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report
from sklearn.model_selection import train_test_split

X, y = load_wine(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42, stratify=y
)

forest = RandomForestClassifier(
    n_estimators=300,
    min_samples_leaf=3,
    max_features='sqrt',
    n_jobs=-1,
    random_state=42,
)
forest.fit(X_train, y_train)

predictions = forest.predict(X_test)
print(classification_report(y_test, predictions))

n_estimators задаёт число деревьев. После некоторого значения добавление деревьев обычно стабилизирует результат, но не исправляет систематическую ошибку постановки. min_samples_leaf и max_depth по-прежнему управляют сложностью базовых моделей.

Out-of-bag оценка

У каждого дерева остаются строки, не попавшие в его bootstrap-набор. Их можно использовать для out-of-bag оценки, включив oob_score=True. Это полезная внутренняя диагностика, но она не заменяет test при временной зависимости, группах или сдвиге данных.

Случайная bootstrap-схема предполагает подходящую независимость объектов. Если события одного пользователя размешаны, OOB столкнётся с той же утечкой связей, что и обычный случайный split.

Важность признаков

Impurity-based importance леса быстро вычисляется, но наследует смещения деревьев. Permutation importance измеряет падение качества после перемешивания столбца на независимых данных. При сильно коррелирующих признаках оба могут делить важность между заменяемыми сигналами.

Интерпретацию начинайте с проверки качества по срезам и здравого смысла. Высокая важность технического идентификатора — повод искать утечку, а не рассказывать красивую историю.

Практика: лес против одного дерева

Обучите одно дерево и random forest на пяти вариантах train-test split. Запишите среднюю метрику и её разброс. Сравните время обучения, размер модели и стабильность. Затем ограничьте max_depth леса и проверьте, всегда ли более сложные деревья улучшают независимый результат.

Что важно запомнить

Источники