Какие плюсы и минусы у древовидных моделей?

«Какие плюсы и минусы у древовидных моделей?» — вопрос из категории Деревья и ансамбли, который задают на 26% собеседований Data Scientist / ML Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Плюсы:

  • Интерпретируемость и визуализация: Логику принятия решений одиночного дерева можно проследить от корня до листа и легко объяснить бизнесу. Дерево можно визуализировать (например, с помощью plot_tree из sklearn).
  • Не требуют масштабирования признаков: Поскольку алгоритм разделяет данные по пороговым значениям, масштабирование числовых признаков не влияет на результат.
  • Работа с данными «как есть»: Могут напрямую обрабатывать категориальные признаки (хотя реализации в sklearn требуют их числового кодирования) и пропущенные значения (в некоторых алгоритмах).
  • Устойчивость к нелинейностям и выбросам: Деревья хорошо улавливают сложные нелинейные зависимости, а разбиение по медиане делает их устойчивыми к выбросам в признаках.

Минусы:

  • Высокая дисперсия и переобучение: Одиночное дерево без ограничений (например, max_depth=None) почти наверняка переобучится, идеально разделив обучающую выборку. Небольшое изменение данных может радикально изменить структуру дерева.
  • Жадный алгоритм: Разбиения выбираются локально оптимально на каждом шаге, что не гарантирует глобального оптимума всей структуры дерева.
  • Плохая экстраполяция: Деревья не могут предсказывать за пределами диапазона значений, увиденных при обучении. Они предсказывают среднее значение таргета в листе, поэтому не способны на прогнозы вне обучающего распределения.
  • Проблемы с границами: Создают кусочно-постоянные предсказания и перпендикулярные границы решений, что может быть неэффективно для некоторых задач.

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

from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

X, y = make_moons(n_samples=300, noise=0.25, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# Переобученное дерево
dtree_overfit = DecisionTreeClassifier(random_state=42)
dtree_overfit.fit(X_train, y_train)

# Регуляризованное дерево
dtree_regularized = DecisionTreeClassifier(max_depth=4, min_samples_leaf=5, random_state=42)
dtree_regularized.fit(X_train, y_train)

print(f"Overfit tree - Train: {dtree_overfit.score(X_train, y_train):.3f}, Test: {dtree_overfit.score(X_test, y_test):.3f}")
print(f"Regularized tree - Train: {dtree_regularized.score(X_train, y_train):.3f}, Test: {dtree_regularized.score(X_test, y_test):.3f}")

# Визуализация регуляризованного дерева
plt.figure(figsize=(12, 8))
plot_tree(dtree_regularized, filled=True, feature_names=["x1", "x2"], class_names=["0", "1"])
plt.show()