Как оценивается качество разбиения в узле дерева решений?

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

Ответ

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

Ключевые критерии (метрики) для классификации:

  1. Критерий Джини (Gini Impurity):

    • Интуиция: Измеряет вероятность ошибки, если мы случайным образом присвоим метку объекту в узле согласно распределению классов в этом узле.
    • Формула для узла: G = 1 - Σ(p_i²), где p_i — доля образцов класса i в узле.
    • Чем меньше Джини (ближе к 0), тем однороднее узел (все образцы принадлежат одному классу).
    • Почему я его часто выбираю: Вычислительно эффективнее энтропии, так как не требует вычисления логарифмов. На практике разница в качестве моделей между Джини и энтропией обычно незначительна.
  2. Прирост информации (Information Gain) на основе энтропии:

    • Интуиция: Основан на понятии энтропии из теории информации. Энтропия измеряет степень неопределенности или беспорядка.
    • Формула энтропии узла: H = - Σ(p_i * log2(p_i)).
    • Прирост информации: IG = H(parent) - [weighted average of H(children)].
    • Алгоритм выбирает разбиение, которое максимизирует прирост информации (т.е. сильнее всего уменьшает энтропию).

Пример на Python с sklearn:

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier

X, y = load_iris(return_X_y=True)

# Дерево с критерием Джини (по умолчанию)
clf_gini = DecisionTreeClassifier(criterion='gini', max_depth=3)
clf_gini.fit(X, y)

# Дерево с критерием энтропии
clf_entropy = DecisionTreeClassifier(criterion='entropy', max_depth=3)
clf_entropy.fit(X, y)

# Можно посмотреть, какую неоднородность уменьшало каждое разбиение
print("Глубина дерева (Gini):", clf_gini.get_depth())
print("Глубина дерева (Entropy):", clf_entropy.get_depth())

Для регрессии используется другая метрика — среднеквадратичная ошибка (MSE) или среднее абсолютное отклонение (MAE). Алгоритм выбирает разбиение, которое минимизирует MSE в дочерних узлах.

Практический выбор:

  • В большинстве случаев я начинаю с критерия Джини из-за его скорости.
  • Если в данных есть небольшой шум, энтропия может быть чуть более чувствительной и создать немного более сбалансированное дерево.
  • Важно помнить, что сам критерий разбиения — лишь один из гиперпараметров. Гораздо большее влияние на итоговое качество модели оказывают ограничения на глубину дерева (max_depth), минимальное количество samples в листе (min_samples_leaf) и другие параметры, контролирующие переобучение.