Деревья решений и Random Forest — гайд для аналитика

Что такое дерево решений

Дерево решений (decision tree) — модель машинного обучения, которая последовательно разбивает данные на подгруппы по условиям на признаки. Визуально выглядит как перевёрнутое дерево: корень вверху, листья внизу. В каждом узле — вопрос («доход > 50K?»), в каждом листе — предсказание (класс или значение).

Почему аналитику важно это знать? Деревья — основа большинства моделей, которые используют в продуктовой аналитике: предсказание оттока, скоринг пользователей, сегментация. На собеседованиях спрашивают и про принципы работы, и про отличия от логистической регрессии.

Как дерево решает, где разбивать

На каждом шаге алгоритм перебирает все признаки и все пороги, выбирая разбиение, которое максимально уменьшает «неопределённость» в данных. Есть две основные метрики.

Gini impurity (индекс Джини) — вероятность ошибки при случайной классификации:

Gini = 1 - Σ pᵢ²

Где pᵢ — доля класса i в узле. Gini = 0 означает чистый узел (все объекты одного класса). Gini = 0.5 при двух равновероятных классах — максимальная неопределённость.

Entropy (энтропия) — мера информационной неопределённости:

Entropy = - Σ pᵢ · log₂(pᵢ)

Алгоритм выбирает разбиение с максимальным Information Gain = энтропия родителя - взвешенная энтропия потомков.

На практике Gini и энтропия дают почти одинаковые деревья. Gini быстрее вычислять, поэтому он стоит по умолчанию в scikit-learn.

Переобучение: главная проблема деревьев

Дерево без ограничений будет расти, пока каждый лист не станет чистым — то есть запомнит обучающую выборку целиком. На новых данных такая модель будет работать плохо. Это называется переобучение (overfitting).

Способы борьбы:

  • max_depth — максимальная глубина дерева (обычно 3–10)
  • min_samples_leaf — минимальное число объектов в листе
  • min_samples_split — минимальное число объектов для разбиения узла
  • Pruning (обрезка) — удаление ветвей, которые не улучшают качество на валидации

Но даже с ограничениями одно дерево нестабильно: небольшие изменения в данных могут радикально поменять структуру. Решение — ансамбли.

Random Forest: сила ансамбля

Random Forest (случайный лес) — ансамбль деревьев решений. Идея проста: строим много деревьев на разных подвыборках данных и усредняем их предсказания.

Два ключевых механизма:

Bagging (bootstrap aggregating): каждое дерево обучается на случайной подвыборке данных с возвращением (bootstrap-выборка). Примерно 63% уникальных наблюдений попадают в каждую выборку, остальные — out-of-bag (OOB), их можно использовать для оценки качества.

Random subspace: при каждом разбиении дерево выбирает лучший признак не из всех, а из случайного подмножества (обычно √n для классификации, n/3 для регрессии). Это декоррелирует деревья и улучшает ансамбль.

Результат — модель, которая:

  • Значительно устойчивее к переобучению, чем одно дерево
  • Не требует тщательной настройки гиперпараметров
  • Работает «из коробки» лучше большинства альтернатив
  • Даёт оценку важности признаков

Python: пример с scikit-learn

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
import pandas as pd

# Данные: предсказываем отток
df = pd.read_csv('users.csv')
features = ['days_active', 'sessions_last_week', 'purchases_total',
            'support_tickets', 'days_since_last_visit']

X = df[features]
y = df['churned']

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# Random Forest
model = RandomForestClassifier(
    n_estimators=200,       # число деревьев
    max_depth=8,            # ограничиваем глубину
    min_samples_leaf=20,    # минимум объектов в листе
    random_state=42,
    n_jobs=-1               # параллелизация
)
model.fit(X_train, y_train)
print(classification_report(y_test, model.predict(X_test)))

# Feature importance
importance = pd.Series(
    model.feature_importances_, index=features
).sort_values(ascending=False)
print(importance)

Feature importance показывает, какие признаки больше всего влияют на предсказание. Это полезно не только для модели, но и для продуктовых выводов: если days_since_last_visit — главный предиктор оттока, стоит фокусироваться на возвращении пользователей.

Деревья vs логистическая регрессия

Критерий Деревья / Random Forest Логистическая регрессия
Нелинейные зависимости Ловит автоматически Нужно добавлять вручную
Интерпретируемость Одно дерево — да, лес — частично Коэффициенты = влияние признака
Feature engineering Минимальный Критически важен
Мультиколлинеарность Не мешает Искажает коэффициенты
Малые данные (< 1000) Переобучается Работает стабильно
Категориальные признаки Работает нативно (в CatBoost) Нужен one-hot encoding

На собеседованиях часто спрашивают: «Когда вы выберете логистическую регрессию, а когда Random Forest?» Хороший ответ: логрег — когда важна интерпретируемость и мало данных, RF — когда данных достаточно и нужна максимальная точность без долгой подготовки фичей. Подробнее про логрег — в отдельной статье.

Если тема ML для аналитиков для вас новая, начните с общего обзора.

Вопросы с собеседований

Как дерево решений выбирает признак для разбиения? — Перебирает все признаки и пороги, выбирает тот, что максимально уменьшает Gini impurity (или максимизирует Information Gain при использовании энтропии). На каждом шаге выбирается жадно — лучшее разбиение прямо сейчас, без оглядки на будущие шаги.

В чём разница между Gini и энтропией? — Обе метрики измеряют «нечистоту» узла. Gini — вероятность ошибки при случайной классификации, энтропия — информационная неопределённость. На практике дают почти одинаковые деревья. Gini быстрее вычислять, поэтому чаще используется по умолчанию.

Что такое Random Forest и зачем он нужен? — Ансамбль деревьев решений. Каждое дерево обучается на случайной подвыборке данных (bagging) и на случайном подмножестве признаков (random subspace). Предсказания усредняются. RF устойчивее к переобучению, стабильнее и точнее одного дерева.

Как бороться с переобучением дерева решений? — Ограничить глубину (max_depth), установить минимальный размер листа (min_samples_leaf), использовать pruning. Радикальное решение — перейти к ансамблям: Random Forest или градиентный бустинг.

Как интерпретировать feature importance в Random Forest? — Feature importance показывает среднее уменьшение Gini impurity по всем деревьям при разбиении по данному признаку. Чем выше значение — тем важнее признак. Но стандартная importance смещена в пользу признаков с большим числом уникальных значений. Для точной оценки лучше использовать permutation importance.

FAQ

Сколько деревьев нужно в Random Forest?

Обычно 100–500 достаточно. После определённого числа качество выходит на плато, а время обучения продолжает расти. Начните с 200 и проверьте, растёт ли качество при увеличении. В большинстве случаев разница между 200 и 1000 деревьями минимальна.

Можно ли использовать Random Forest для регрессии?

Да. RandomForestRegressor работает так же, как классификатор, но в листьях вместо голосования по классам считается среднее значение целевой переменной. Используется для предсказания LTV, среднего чека, времени жизни пользователя.

В чём главный недостаток Random Forest по сравнению с градиентным бустингом?

Random Forest обычно уступает в точности градиентному бустингу (XGBoost, LightGBM) на табличных данных. Бустинг последовательно исправляет ошибки предыдущих деревьев, что даёт лучшую итоговую модель. Зато RF проще в настройке и менее склонен к переобучению.


Потренируйте вопросы по машинному обучению — откройте тренажёр. 1500+ вопросов для собеседования аналитика. Бесплатно.