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

Как обучается модель случайного леса?

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

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

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

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

Как обучается модель случайного леса?

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

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

Вместо одного большого дерева, которое может переобучиться, Random Forest строит несколько деревьев на случайных подвыборках данных. Каждое дерево делает своё предсказание, и финальный результат — среднее (регрессия) или голос большинства (классификация).

Процесс обучения Random Forest пошагово

Шаг 1: Bootstrap (Bootstrap Aggregating / Bagging)

Для каждого из N деревьев (обычно 100-1000):

  • Случайно выбираем n образцов из тренировочного набора с возвращением (допускаются дубликаты)
  • Получается подвыборка примерно такого же размера как исходный набор
  • ~37% данных (1 - (1-1/n)^n) не попадают в выборку (OOB — Out-of-Bag данные)
from sklearn.ensemble import RandomForestClassifier
import numpy as np

# Симуляция bootstrap
data = np.arange(10)  # [0, 1, 2, ..., 9]
bootstrap_sample = np.random.choice(data, size=len(data), replace=True)
print(f"Исходные данные: {data}")
print(f"Bootstrap выборка: {bootstrap_sample}")
# Пример выхода: [2, 7, 5, 5, 9, 1, 2, 7, 3, 6]
# Видим, что 5 и 7 повторяются, а 0, 4, 8 не попали

Шаг 2: Построение дерева решений

Для каждой bootstrap выборки строим полное дерево решений без pruning:

from sklearn.tree import DecisionTreeClassifier

def build_tree_on_bootstrap_sample(X, y, n_features=None):
    # Индексы для bootstrap
    bootstrap_indices = np.random.choice(len(X), size=len(X), replace=True)
    
    X_boot = X[bootstrap_indices]
    y_boot = y[bootstrap_indices]
    
    # Случайное подмножество признаков для каждого расщепления
    # Обычно sqrt(n_features) для классификации, n_features/3 для регрессии
    tree = DecisionTreeClassifier(
        max_features=n_features,
        max_depth=None,  # дерево растёт до полной глубины
        min_samples_split=1
    )
    tree.fit(X_boot, y_boot)
    return tree

Шаг 3: Случайное выбор признаков на каждом расщеплении

Ключевая идея: при поиске лучшего расщепления в каждом узле дерева используем только случайное подмножество признаков:

# Вместо того, чтобы проверить все признаки
if use_all_features:  # ❌ Плохо - соседние деревья будут очень похожи
    best_split_features = range(n_features)

# Используем только sqrt(n_features) признаков
if use_random_features:  # ✅ Хорошо - декорелирует деревья
    best_split_features = np.random.choice(
        n_features,
        size=int(np.sqrt(n_features)),  # для классификации
        replace=False
    )

Это очень важно для уменьшения корреляции между деревьями!

Математическое описание алгоритма

Алгоритм Random Forest
─────────────────────────────────────────

По i от 1 до n_trees:
  1. Создать bootstrap выборку B_i из обучающего набора
  2. Построить дерево T_i на B_i:
     - На каждом узле:
       a) Выбрать случайное подмножество m признаков
       b) Найти лучший признак и threshold из m признаков
       c) Расщепить узел
     - Растить дерево до максимальной глубины (без pruning)

Для предсказания нового образца x:
  Классификация: класс = argmax (количество голосов за класс k)
  Регрессия: значение = среднее из всех T_i(x)

Пример обучения на Python

from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split

# Создаём данные
X, y = make_classification(n_samples=1000, n_features=20, n_informative=10)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

# Создаём и обучаем модель
rf = RandomForestClassifier(
    n_estimators=100,           # количество деревьев
    max_features='sqrt',        # sqrt(n_features) для классификации
    max_depth=None,             # дерево растёт без ограничений
    min_samples_split=2,        # минимум образцов для расщепления узла
    min_samples_leaf=1,         # минимум в листе
    bootstrap=True,             # использовать bootstrap
    random_state=42,
    n_jobs=-1,                  # использовать все CPU cores
    oob_score=True              # вычислить score на OOB данных
)

rf.fit(X_train, y_train)

# Оценка качества
from sklearn.metrics import accuracy_score, classification_report

y_pred = rf.predict(X_test)
print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")
print(f"OOB Score: {rf.oob_score_:.3f}")  # Estimate качества без тестового сета

Важные параметры

RandomForestClassifier(
    n_estimators=100,          # больше деревьев = лучше (но медленнее)
                               # обычно 100-1000
    
    max_features='sqrt',       # количество признаков для расщепления
                               # 'sqrt' для классификации
                               # 'log2' для регрессии
    
    max_depth=None,            # глубина дерева (None = без ограничений)
                               # для борьбы с переобучением уменьшить
    
    min_samples_split=2,       # мин. образцов для расщепления узла
                               # увеличить чтобы упростить дерево
    
    min_samples_leaf=1,        # мин. образцов в листе
                               # увеличить чтобы упростить дерево
    
    random_state=42,           # reproducibility
    
    n_jobs=-1,                 # распараллеливание (-1 = все ядра)
    
    class_weight='balanced',   # для дисбалансированных классов
)

Преимущества Random Forest

  1. Высокое качество — часто лучше одного дерева
  2. Устойчивость к переобучению — bootstrap и случайные признаки
  3. Параллелизация — деревья строятся независимо
  4. Handling missing data — может работать с пропусками
  5. Feature importance — можно оценить важность каждого признака
  6. Не требует нормализации — работает с сырыми признаками
  7. OOB estimate — оценка качества без отдельного тестового сета

Feature Importance в Random Forest

# Посмотреть важность признаков
importances = rf.feature_importances_
feature_names = [f"Feature {i}" for i in range(X.shape[1])]

for name, importance in sorted(zip(feature_names, importances), 
                               key=lambda x: x[1], reverse=True)[:10]:
    print(f"{name}: {importance:.4f}")

# Визуализировать
import matplotlib.pyplot as plt
plt.barh(feature_names, importances)
plt.xlabel('Importance')
plt.show()

Out-of-Bag (OOB) оценка

Красивое свойство Random Forest:

# Примерно 37% данных не попали в каждую bootstrap выборку
# Можем использовать их как тестовый сет без отдельного split!

rf = RandomForestClassifier(oob_score=True)
rf.fit(X_train, y_train)

print(f"OOB Score: {rf.oob_score_:.3f}")  # Качество на OOB данных
# Обычно близко к тестовому качеству

Когда использовать Random Forest?

  • Классификация и регрессия — универсален
  • Много признаков — работает хорошо
  • Нелинейные зависимости — ловит сложные паттерны
  • Дисбалансированные классы — параметр class_weight
  • Быстрое решение — быстрее настройки Deep Learning

Когда использовать другие методы?

  • Очень большой набор данных — XGBoost часто быстрее
  • Нужна максимальная точность — Gradient Boosting (XGBoost, LightGBM)
  • Нужна интерпретируемость — одно дерево вместо леса
  • Много категориальных признаков — обработать кодированием лучше

Итог

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

Как обучается модель случайного леса? | PrepBro