ML

Дерево решений. Задачи к собеседованию.

Объяснить, как работает дерево решений. Какие критерии используются при разбиении данных в узлах?

Дерево решений рекурсивно перебирает все признаки и находит значения, разбивающие данные на две группы с максимальным приростом метрики.

В задачах классификации используются критерий Джини или энтропия Шэннона. В задачах регрессии – MSE, MAE.

Что такое переобучение в деревьях решений и как с ним бороться?

Переобучение – это слишком сильная подстройка модели под обучающие данные. При этом на обучающих данных метрики качества высокие, а на тестовых – заметно ниже.

Для борьбы с переобучением дерева решений применяется регуляризация с настройкой таких гиперпараметров, как: max_depth, min_samples_split, min_samples_leaf. Они настраиваются до начала обучения модели.

Реализовать дерево решений из Sklearn и настроить его гиперпараметры с помощью кроссвалидации.

Пример решения для задачи классификации:

# Подбор гиперпараметров дерева решений с помощью кроссвалидации

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split, GridSearchCV, StratifiedKFold
from sklearn.metrics import accuracy_score
import pandas as pd


# Задаем гиперпараметры для перебора вариантов
params = {
    'max_depth': [3, 5, 10],
    'min_samples_split': [3, 5, 10],
    'min_samples_leaf': [3, 5, 10],
    'max_features': [3, 5, 10],
    'criterion': ['gini', 'entropy']
}

# Загрузка данных
X, y = load_iris(return_X_y=True)

# Разбиение данных на обучающие и тестовые
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

# Инициализация модели и её обучение
model = DecisionTreeClassifier(random_state=1)

# Используем стратифицированную кроссвалидацию из 5 фолдов с перемешиванием
cv = StratifiedKFold(n_splits=5, shuffle=True)

# Выполняем перебор гиперпараметров с оценкой полученных моделей
gscv = GridSearchCV(model, params, cv=cv, scoring='accuracy')
gscv.fit(X_train, y_train)

# Прогноз лучшей модели
best_model = gscv.best_estimator_
y_pred = best_model.predict(X_test)

# Оценка качества прогноза лучшей модели
acc = accuracy_score(y_test, y_pred)
print(f"Accuracy: {acc:.2f}")

# Просмотр лучших параметров и лучшей модели
print(f"Best params: {gscv.best_params_}")
print(f"Best estimator: {gscv.best_estimator_}")

# Вывод всех полученных комбинаций гиперпараметров с оценками моделей
results = pd.DataFrame(gscv.cv_results_)
print(results[['params', 'mean_test_score', 'rank_test_score']].sort_values(by='rank_test_score'))

Какие признаки важны в построенном дереве?

Для выявления важнейших признаков можно воспользоваться атрибутом .feature_importances_ и визуализацией дерева .plot_tree().

Вот наиболее точный способ оценки важности признаков:

print(f"Feature importances: {best_model.feature_importances_}")

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

from sklearn.tree import plot_tree

# Здесь код загрузки данных и построения модели

plot_tree(model)

Как дерево решений обрабатывает категориальные признаки?

В реализации Scikit Learn – категориальные признаки необходимо кодировать (One Hot Encoding, Ordinal Encoding).

В Catboost и подобных алгоритмах бустинга категориальные признаки обрабатываются нативно.

Как прочитать и понять визуализированное дерево решений?

Пример визуализации.

Каждый прямоугольник — это узел дерева. Он содержит:

  • feature_name <= threshold — условие разбиения (если это не лист),
  • gini или entropy — значение функции потерь в этом узле (оно всегда стремится к минимизации),
  • samples — сколько объектов дошло до этого узла,
  • value = [n1, n2, n3] — количество объектов каждого класса в этом узле,
  • class = ... — к какому классу относится узел (наиболее частый класс).

Как дерево ведет себя на несбалансированных классах?

Дисбаланс классов может привести к некорректным результатам в задачах классификации. Особенно, если число данных одного класса значительно выше данных другого класса.

Для количественной балансировки классов в дереве решений можно применить аргумент class_weight.

model = DecisionTreeClassifier(class_weight="balanced")    # Возможны и другие варианты аргумента

Также для балансировки классов можно применить другие техники:

  • SMOTE – искусственное увеличение данных для минорного класса с целью создать баланс с мажорным классом.
  • undersampling – обрезка количества наблюдений для мажорного класса с целью создать баланс с минорным.

Вставить формулу как
Блок
Строка
Дополнительные настройки
Цвет формулы
Цвет текста
#333333
Используйте LaTeX для набора формулы
Предпросмотр
\({}\)
Формула не набрана
Вставить