Дерево решений — это контролируемый алгоритм машинного обучения, который работает на основе рекурсивных ответов на некоторые вопросы (условия «если-или-или»). Алгоритм используется как для регрессии, так и для классификации. Однако в основном для решения задач классификации.
Вопросы в ящиках называются внутренними узлами, ответы на которые разделяют их на ветви. Узлы, которые больше не разделяются, называются листьями, которые представляют собой решение/вывод модели.
Это дерево, конечно, намного больше и сложнее для больших наборов данных по сравнению с нашим простым примером выше. Дерево растет и формируется в зависимости от данных, которые мы ему предоставляем (обучение модели). Однако эта простая диаграмма также показывает, насколько просто работает алгоритм. Вы уже можете представить, что для правильного разделения данных необходимо задать правильные вопросы, начиная с верхнего узла. Это означает, что то, какие функции и какие условия использовать, имеет решающее значение для построения хорошо работающего дерева решений. Как это возможно?
Во-первых, признак корневого узла выбирается на основе результатов измерения отбора атрибутов (ASM). После этого ASM применяется ко всем возникающим узлам рекурсивно до тех пор, пока не будет невозможно больше разделение (когда мы достигаем листа).
Мера выбора подмножества атрибутов (ASM)
Мера выбора подмножества атрибутов — это метод, используемый для сокращения данных. Сокращение данных необходимо для лучшего анализа и прогнозирования целевой переменной. Таким образом, дерево решений выбирает узлы для наилучшего разбиения данных.
Два основных метода ASM:
- индекс Джини
- Прирост информации (ID3)
Индекс Джини
Индекс Джини или примесь Джини — это мера примеси (степень вероятности того, что признак будет классифицирован неверно), используемая для создания дерева решений. Признак с низким значением индекса Джини должен быть предпочтительным для решения узлов при создании дерева решений. Индекс Джини используется для создания только бинарных разбиений в дереве.
Информационное усиление (ID3)
Информационный прирост показывает, насколько информативен признак, измеряя изменения энтропии после разбиения данных по этому признаку. Алгоритм дерева решений всегда пытается максимизировать информационный выигрыш, при этом узел с наибольшим информационным выигрышем выбирается в качестве первого узла (первое разбиение). Поэтому дерево сначала разбивается по признаку с наибольшей энтропией, уменьшая энтропию по всем листьям.
Формула энтропии такова:
Мы можем использовать модель DecisionTreeClassifier из библиотеки scikit learn:
Используем набор данных по раку из библиотеки scikit-learn и применим модель Decision Tree:
# Import train_test_split function and the dataset
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer
from sklearn.tree import DecisionTreeClassifier
cancer = load_breast_cancer()
y = cancer.target
X = cancer.data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
clf = DecisionTreeClassifier(criterion='entropy', random_state=0)
clf.fit(X_train, y_train)
print("Training accuracy {:.2f}".format(clf.score(X_train,y_train)))
print("Test accuracy: {:.2f}".format(clf.score(X_test,y_test)))
Точность обучения выше, чем точность тестирования, что говорит о том, что наша модель слишком хорошо подходит к данным. Давайте построим график нашего дерева решений и проверим его сложность.
from sklearn import tree
import matplotlib.pyplot as plt
fig, axes = plt.subplots(nrows = 1,ncols = 1,figsize = (16,8), dpi=100)
tree.plot_tree(clf, feature_names = cancer.feature_names, class_names=cancer.target_names, filled = True, fontsize = 5);
Изменение критерия asm с gine на энтропию:
clf = DecisionTreeClassifier(criterion='entropy', random_state=0)
clf.fit(X_train, y_train)
print("Training accuracy:{:.2f}".format(clf.score(X_train,y_train)))
print("Test accuracy: {:.2f}".format(clf.score(X_test,y_test)))
Точность нашего теста повысилась при использовании меры выбора атрибутов энтропии в качестве критерия разбиения. Мы можем снова взглянуть на дерево, чтобы увидеть, есть ли какие-либо изменения в выполненных разбиениях.
fig, axes = plt.subplots(nrows = 1,ncols = 1,figsize = (16,8), dpi=100)
tree.plot_tree(clf, feature_names = cancer.feature_names, class_names=cancer.target_names, filled = True, fontsize = 5);
Как мы видим, наше дерево довольно сложное, что приводит к чрезмерной подгонке данных. Мы можем уменьшить сложность дерева, задав максимальную глубину (max_depth), и предотвратить перебор.
clf = DecisionTreeClassifier(max_depth=3)
clf.fit(X_train, y_train)
print("Training accuracy:{:.2f}".format(clf.score(X_train,y_train)))
print("Test accuracy: {:.2f}".format(clf.score(X_test,y_test)))
Уменьшив максимальную глубину нашего дерева решений до трех, мы смогли уменьшить перебор и немного повысить точность теста. Если теперь мы рассмотрим диаграмму нашего дерева, то увидим гораздо более простое дерево…
Установив max_depth равным 3, мы уменьшили сложность дерева решений путем его обрезки. Эта обрезанная модель менее сложна и немного проще для понимания по сравнению с предыдущей моделью, где дерево продолжало расщепляться, пока все листья не стали чистыми (gini impurtiy = 0).
Регрессия дерева решений
Давайте посмотрим, как дерево решений работает для задачи регрессии. Для этого мы можем снова сгенерировать случайный набор данных:
import numpy as np
np.random.seed(5)
X = np.sort(5 * np.random.rand(40, 1), axis=0)
y = np.sin(X).ravel()
# Add noise to targets
y[::5] += 1 * (0.5 - np.random.rand(8))
Либарий scikit-learn предоставляет нам модель дерева решений для регрессии под названием DecisionTreeRegressor:
from sklearn.tree import DecisionTreeRegressor
dt_reg = DecisionTreeRegressor(criterion="squared_error", random_state=0)
dt_reg.fit(X, y)
fig, axes = plt.subplots(nrows = 1, ncols = 1, figsize=(16,8), dpi=100)
tree.plot_tree(dt_reg, feature_names='X', filled=True, fontsize=5);
#generate a random Test data
T = np.linspace(0, 5, 100)[:, np.newaxis]
#creating two regression trees with different depths
dt_reg_1 = DecisionTreeRegressor(max_depth = 10, random_state=0)
dt_reg_2 = DecisionTreeRegressor(max_depth = 3, random_state=0)
#training the models
dt_reg_1.fit(X, y)
dt_reg_2.fit(X, y)
#making predictions for the random test data we generated above
y_pred_1 = dt_reg_1.predict(T)
y_pred_2 = dt_reg_2.predict(T)
#comparison plot to see the effect of tree depth
plt.figure()
plt.scatter(X, y, s=40, c="orange", label="actual")
plt.plot(T, y_pred_1, color="b", label="max_depth=10", linewidth=2)
plt.plot(T, y_pred_2, color="g", label="max_depth=3", linewidth=2)
plt.xlabel("X")
plt.ylabel("y")
plt.title("Decision Tree Regression")
plt.legend()
plt.show()
Глядя на рисунок, мы видим, что модель регрессора дерева решений с максимальной глубиной, установленной на десять, слишком хорошо подходит к данным, улавливая весь шум в данных. Более того, дерево с максимальной глубиной, установленной на три, гораздо лучше обобщает и создает лучшее соответствие данным, не захватывая весь шум.
Преимущества
Легко понять, интерпретировать и визуализировать
Обычно не требуется масштабирование или нормализация признаков и их отбор
Хорошо работает с несколькими типами данных (категориальными, числовыми, двоичными) в наборе данных (облегчает предварительную обработку данных).
Он также подходит для решения задач с несколькими выводами
Недостатки
Деревья решений имеют тенденцию к чрезмерной подгонке и не очень хорошо обобщают.
Для лучшего обобщения в основном требуется ансамбль деревьев других моделей
Деревья решений склонны формировать смещенные деревья, если есть дисбаланс данных. Наборы данных с доминирующими классами должны быть сбалансированы.
Если вам понравилось это, не стесняйтесь следовать за мной для получения новых уроков и курсов по машинному обучению!