Регрессор дерева решений — визуальное руководство с помощью Scikit Learn

Понимание деревьев решений без математики

В этой статье мы реализуем DecisionTreeRegressor из scikit-learn в python, чтобы визуализировать, как работает эта модель. Мы не будем использовать никаких математических терминов, но воспользуемся визуализацией, чтобы продемонстрировать, как работает регрессор дерева решений, и влияние некоторых гиперпараметров.

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

В основном мы будем изучать влияние двух гиперпараметров, которые могут быть интуитивно понятны: max depth и min_samples_leaf. Другие гиперпараметры аналогичны, основная идея — ограничить размер правил.

Одна нелинейная переменная

Давайте использовать некоторые простые данные только с переменной функции x.

# Import the required libraries
from sklearn.tree import DecisionTreeRegressor
import numpy as np
# Define the dataset
X = np.array([[1], [3], [4], [7], [9], [10], [11], [13], [14], [16]])
y = np.array([3, 4, 3, 15, 17, 15, 18, 7, 3, 4])

И мы можем визуализировать данные в виде графика (x, y).

import matplotlib.pyplot as plt

# Plot the dataset with the decision tree splits
plt.figure(figsize=(10,6))
plt.scatter(X, y, color='blue')
plt.show()

И на следующем изображении для первого разреза мы можем визуально угадать два возможных разделения, как показано ниже:

Теперь модель регрессора дерева решений точно определяет, какое разделение лучше. Укажем аргумент max_depth=1, чтобы получить только одно разделение:

from sklearn.tree import DecisionTreeRegressor

# Fit the decision tree model
model = DecisionTreeRegressor(max_depth=1)
model.fit(X, y)

# Generate predictions for a sequence of x values
x_seq = np.arange(0, 17, 0.1).reshape(-1, 1)
y_pred = model.predict(x_seq)

Если мы решили получить 4 региона, мы можем попробовать max_depth=2, и мы получим:

Затем мы можем визуализировать, как гиперпараметр max_depth влияет на окончательную модель, с помощью изображения ниже:

Мы также можем построить то же самое с другим гиперпараметром min_samples_leaf, который представляет собой минимальное количество наблюдений, которые должны быть в конечных областях (которые мы называем листьями, потому что в конце ветвления дерева мы находим листья!)

Одна «линейная» функция

Регрессор дерева решений является нелинейным регрессором. Мы можем видеть, как он ведет себя/моделирует данные из предыдущих примеров. Что происходит с «линейными» данными?

Давайте возьмем этот простой пример идеально линейных данных:

import numpy as np

X=np.arange(1,13,1).reshape(-1,1)
y=np.concatenate((np.arange(1,12,1),12), axis=None)

plt.scatter(X,y)

Вы видите, что соотношение очень простое: y = x!

Если мы используем классическую визуализацию дерева решений, вы можете сразу увидеть, как ведет себя модель.

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

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

Теперь правда в том, что вы не можете заранее знать поведение набора данных. И это то, о чем говорит теория отсутствия бесплатных обедов.

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

Две непрерывные функции

Для двух непрерывных переменных мы должны создать трехмерный график.

Во-первых, давайте сгенерируем некоторые данные.

import numpy as np
from sklearn.tree import DecisionTreeRegressor
import plotly.graph_objs as go
from plotly.subplots import make_subplots

# Define the data
X = np.array([[1, 2], [3, 4], [4, 5], [7, 2], [9, 5], [10, 4], [11, 3], [13, 5], [14, 3], [16, 1],
              [10, 10], [16, 10], [12, 10]])
y = np.array([3, 4, 3, 15, 17, 15, 18, 7, 3, 4,8,10,13])

Затем можно создать модель:

# Fit the decision tree model
model = DecisionTreeRegressor(max_depth=3)
model.fit(X, y)

Наконец, мы можем создать 3D-график с помощью plotly.

# Create an interactive 3D plot with Plotly
fig = make_subplots(rows=1, cols=1, specs=[[{'type': 'surface'}]])

fig.add_trace(go.Surface(x=x_seq, y=y_seq, z=z_seq, colorscale='Viridis', showscale=True,opacity = 0.5),
              row=1, col=1)

fig.add_trace(go.Scatter3d(x=X[:, 0], y=X[:, 1], z=y, mode='markers', marker=dict(size=5, color='red')),
              row=1, col=1)

fig.update_layout(title='Decision Tree with Max Depth = {}'.format(max_depth),
                  scene=dict(xaxis_title='x1', yaxis_title='x2', zaxis_title='Predicted Y'))

fig.show()

Мы можем сравнить разные значения глубины, как показано на изображении ниже:

Если вы создаете график с помощью Python, вы можете манипулировать им, чтобы увидеть визуализацию под разными углами.

Заключение

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

В случае деревьев решений они уже достаточно интуитивно понятны для понимания с визуализацией правил в виде дерева. Классическая визуализация с x, y (и z) может быть дополнительной.

Мы также можем ВИДИТЬ, что модель сильно нелинейна. И набор данных не нуждается ни в каком масштабировании.

Я пишу о машинном обучении и науке о данных и понятно объясняю сложные концепции. Пожалуйста, следуйте за мной по ссылке ниже и получите полный доступ к моим статьям: https://medium.com/@angela.shi/membership