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

Ответ

Плюсы:

  • Интерпретируемость и визуализация: Логику принятия решений одиночного дерева можно проследить от корня до листа и легко объяснить бизнесу. Дерево можно визуализировать (например, с помощью 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()

Ответ 18+ 🔞

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

Что в них хорошего, ёпта:

  • Прозрачность, как у алкаша после запоя: Ты можешь проследить всю цепочку решений от начала и до конца. Почему клиенту отказали? А потому что, блядь, возраст меньше 25, доход ниже среднего, и он ещё и в прошлый раз просрочку допустил. Всё наглядно, можно даже картинку нарисовать. Бизнес-дядьки это обожают.
  • Масштабирование? Да похуй! Им всё равно, в рублях у тебя доход или в йенах. Они режут данные по порогам, так что можешь не париться с StandardScaler.
  • Жрут что дают: Категориальные признаки, пропуски — в теории им по барабану. На практике в 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"Переобученное дерево — Обучающая: {dtree_overfit.score(X_train, y_train):.3f}, Тестовая: {dtree_overfit.score(X_test, y_test):.3f}")
print(f"Урезанное дерево — Обучающая: {dtree_regularized.score(X_train, y_train):.3f}, Тестовая: {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()

Увидишь разницу в цифрах сразу. Первое дерево натренируется почти на 100%, а на новых данных накроется медным тазом. Второе, хоть и не так идеально на обучающих, зато на реальных данных не опозорится. Вот и вся мораль, чувак.