Какие деревья предпочтительнее для Random Forest?
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Какие деревья предпочтительнее для Random Forest
Random Forest использует множество деревьев решений для создания мощного ensemble модели. Вопрос о том, какие деревья лучше всего работают в контексте Random Forest, имеет четкий ответ.
Основной принцип Random Forest
Random Forest базируется на двух ключевых идеях:
- Разнообразие (Diversity) — каждое дерево должно быть разным
- Относительная слабость отдельных деревьев — это превращается в силу ensemble
Предпочтительные деревья: ГЛУБОКИЕ и БЕЗ РЕГУЛЯРИЗАЦИИ
Почему именно глубокие деревья?
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
import numpy as np
X, y = make_classification(n_samples=1000, n_features=20, random_state=42)
# Random Forest с глубокими деревьями (по умолчанию)
rf_deep = RandomForestClassifier(
n_estimators=100,
max_depth=None, # Без ограничения глубины
min_samples_split=2, # Минимум 2 образца
min_samples_leaf=1, # По одному в листе
random_state=42
)
# Random Forest с мелкими деревьями
rf_shallow = RandomForestClassifier(
n_estimators=100,
max_depth=5, # Ограничиваем глубину
min_samples_split=20,
min_samples_leaf=10,
random_state=42
)
# Сравнение
print(f"Deep trees CV score: {cross_val_score(rf_deep, X, y, cv=5).mean():.3f}")
print(f"Shallow trees CV score: {cross_val_score(rf_shallow, X, y, cv=5).mean():.3f}")
# Deep trees обычно дают лучший результат
Почему глубокие деревья работают лучше в Random Forest
1. Разнообразие через случайность
Каждое дерево в Random Forest обучается:
- На случайной подвыборке данных (bootstrap)
- С использованием случайного подмножества признаков
Глубокие деревья усиливают этот эффект:
from sklearn.ensemble import RandomForestClassifier
import matplotlib.pyplot as plt
# Деревья получают разные выборки и признаки
rf = RandomForestClassifier(
n_estimators=100,
max_features='sqrt', # sqrt(n_features) при каждом разделении
bootstrap=True, # Случайная выборка с повторениями
random_state=42
)
# Каждое дерево переобучается на своей подвыборке
# Но разнообразие + усреднение исправляют переобучение
2. Комплементарность деревьев
# Если деревья идентичны (мелкие):
# Они делают одинаковые ошибки
# Усреднение не помогает
# Если деревья разные (глубокие):
# Они делают разные ошибки
# Усреднение сильно помогает
Практический пример: влияние глубины на точность
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import numpy as np
X, y = make_classification(n_samples=1000, n_features=20, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
depths = [2, 5, 10, 20, None] # None = без ограничения
train_scores = []
test_scores = []
for depth in depths:
rf = RandomForestClassifier(
n_estimators=100,
max_depth=depth,
random_state=42
)
rf.fit(X_train, y_train)
train_scores.append(rf.score(X_train, y_train))
test_scores.append(rf.score(X_test, y_test))
# Результаты показывают, что без ограничения (None) дает лучший результат
for d, train, test in zip(depths, train_scores, test_scores):
print(f"Depth={d}: Train={train:.3f}, Test={test:.3f}")
Гиперпараметры Random Forest
1. max_depth: лучше None (без ограничения)
# Плохо — ограничиваем глубину
rf = RandomForestClassifier(max_depth=5)
# Хорошо — даем деревьям расти глубоко
rf = RandomForestClassifier(max_depth=None) # По умолчанию
2. min_samples_split: лучше низкое значение
# Плохо — требуем больше образцов для разделения
rf = RandomForestClassifier(min_samples_split=50)
# Хорошо — позволяем деревьям глубже разделяться
rf = RandomForestClassifier(min_samples_split=2) # По умолчанию
3. min_samples_leaf: лучше низкое значение
# Плохо
rf = RandomForestClassifier(min_samples_leaf=20)
# Хорошо
rf = RandomForestClassifier(min_samples_leaf=1) # По умолчанию
Анализ ошибок деревьев
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X_train, y_train)
# Получаем ошибки отдельных деревьев
predictions = np.array([
tree.predict(X_test) for tree in rf.estimators_
])
print(f"Shape: {predictions.shape}") # (100, samples)
# Дисперсия предсказаний разных деревьев
variance = predictions.var(axis=0).mean()
print(f"Average variance: {variance:.3f}")
# Глубокие деревья имеют ВЫСОКУЮ дисперсию (разные ошибки)
# Усреднение эту дисперсию снижает
Регуляризация в Random Forest
Вместо ограничения глубины деревьев, Random Forest управляет переобучением через:
rf = RandomForestClassifier(
n_estimators=100, # Больше деревьев = лучше
max_features='sqrt', # Случайность в признаках
bootstrap=True, # Случайные подвыборки
oob_score=True, # Out-of-bag оценка
random_state=42
)
rf.fit(X_train, y_train)
print(f"OOB Score: {rf.oob_score_:.3f}") # Оценка на неиспользованных данных
Когда ограничивать глубину в Random Forest?
# Если очень мало памяти:
rf_small = RandomForestClassifier(
n_estimators=50,
max_depth=20, # Ограничиваем немного
random_state=42
)
# Если нужна интерпретируемость:
rf_interpretable = RandomForestClassifier(
n_estimators=100,
max_depth=10, # Мелкие деревья понятнее
random_state=42
)
# Но для максимальной точности:
rf_optimal = RandomForestClassifier(
n_estimators=200,
max_depth=None, # Деревья растут свободно
random_state=42
)
Сравнение с отдельным деревом
from sklearn.tree import DecisionTreeClassifier
X, y = make_classification(n_samples=1000, n_features=20, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Одно глубокое дерево
tree = DecisionTreeClassifier(max_depth=None, random_state=42)
tree.fit(X_train, y_train)
print(f"Tree: Train={tree.score(X_train, y_train):.3f}, Test={tree.score(X_test, y_test):.3f}")
# Output: Train=0.99, Test=0.75 (переобучение)
# Random Forest из глубоких деревьев
rf = RandomForestClassifier(n_estimators=100, max_depth=None, random_state=42)
rf.fit(X_train, y_train)
print(f"RF: Train={rf.score(X_train, y_train):.3f}, Test={rf.score(X_test, y_test):.3f}")
# Output: Train=0.95, Test=0.83 (лучше баланс)
Главный вывод
Для Random Forest лучше всего подходят ГЛУБОКИЕ, СЛАБО РЕГУЛЯРИЗОВАННЫЕ деревья
Это потому что:
- Разнообразие — каждое дерево разное благодаря bootstrap и случайным признакам
- Комплементарность — разные деревья делают разные ошибки
- Усреднение — комбинирование множества слегка переобученных моделей дает отличный результат
- Слабые ученики — философия ensemble: много слабых + комбинирование = сильный
Параметры по умолчанию в scikit-learn оптимальны именно поэтому.