Объяснение с нуля, шаг за шагом

Некоторое время назад мне пришлось объяснять древовидные алгоритмы человеку, разбиравшемуся в математике… но с нулевыми знаниями в науке о данных. Итак, я решил проигнорировать классические игрушечные наборы данных и начал полностью с нуля, с кучи 2-мерных точек.

Итак, после некоторого базового импорта

import pandas as pd
from sklearn import tree
import seaborn as sns

Я нарисовал на листе 6 точек: 4 синих и 2 оранжевых:

X = [[0, 0], [1, 1], [2,1], [1,2], [2,2], [0.5, 1.5]]
Y = [0, 1, 1, 1, 1, 0]

example = pd.DataFrame(X)
example["target"] = Y
display(example)

colors = example["target"].map({0:"orange", 1:"blue"})
sns.scatterplot(data=example, x=0, y=1, c=colors, s=200)

Это очень простой набор данных:

Вы можете увидеть эти несколько точек на графике:

Это видимые примеры явления. Каждая точка представляет собой элемент синего или оранжевого цвета с двумя функциями (по двум осям). Мы не знаем, сколько у нас других точек, но у каждого есть две черты и назначенный цвет. Явление можно описать площадью, и зная только видимые точки, мы не знаем, что это за явление. Мы могли бы предположить два примера:

Чтобы определить явление, т. е. чтобы нарисовать синие и оранжевые области, нам нужно определить модель, которая видит точки и предполагает, что области .

Что такое модель?

Модель – это математическое представление системы, которое можно использовать для разделения пространства на области, соответствующие разным классам, что позволяет классифицировать новые точки на основе их расположения в пределах космос. Модель учится видеть функции, содержащиеся в X (в данном случае две), и решать, какой из них является ее цветом (категорией).

После подгонки модель можно использовать для прогнозирования класса выборок:

clf = tree.DecisionTreeClassifier()
clf = clf.fit(X, Y)

Итак… модель «изучила» явление. С этого момента мы можем взять любую точку, которую захотим, и модель сможет назначить ей цвет. Будет ли это правильный цвет? Это зависит от разницы между тем, чему научилась модель, и реальностью. Предположим, например, что явление следующее:

Это был бы бардак!

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

Мы предполагаем, что явление определено лучше

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

clf.predict([[2., 2.]])

> array([1]) <== BLUE!!!

Давайте попробуем что-нибудь менее предсказуемое, проанализировав точку среди синих точек.

clf.predict([[1.5, 1.5]])

> array([1]) <== BLUE!!!

Легко, пока.

Теперь давайте попробуем с точкой посередине между синими и оранжевыми точками:

clf.predict([[0.5, 0.7]])

> array([0]) <== finally ORANGE!!!

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

clf.predict([[0.8, 1.5]])

> array([1]) <== BLUE!!!

Последний результат менее очевиден, чем предыдущие. Самое время спросить:

Как модель разделяет пространство?

Хорошая новость: можно посмотреть, как это работает.

tree.plot_tree(clf)

На предыдущем изображении описано, как модель будет назначать цвет каждой точке пространства. В нашем тренировочном наборе данных у нас есть 6 точек: 2 оранжевые и 2 синие. Рассмотрим функция 0. Модель автоматически определила пороговое значение 0,75.

  • Если мы рассмотрим элементы с X[0]≤0,75, мы найдем 2 синие точки и ни одной оранжевой точки.
  • Если мы рассмотрим элементы с X[0]>0,75, мы обнаружим отсутствие синих точек и 4 оранжевые точки.

Очень простым способом дерево способно идеально разделить две группы цветных точек (индекс Джини равен нулю!). Это можно увидеть графически:

import matplotlib.colors
from sklearn.inspection import DecisionBoundaryDisplay

# only for graphic reasons
cmap_yg_gr_lb = matplotlib.colors.ListedColormap(["gold", "lightblue"])

# Decision boundary of the model
DecisionBoundaryDisplay.from_estimator(
    clf,
    example.drop("target", axis=1),
    cmap=cmap_yg_gr_lb,
)

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

DecisionBoundaryDisplay.from_estimator(
    clf,
    example.drop("target", axis=1),
    cmap=cmap_yg_gr_lb,
    response_method="predict",
)

sns.scatterplot(data=example, x=0, y=1, c=colors, s=200)

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

Что произойдет, если тренировочный набор станет более сложным в управлении?! Например, имея:

X_two = [[0, 0], [1, 1], [2,1], [1,2], [2,2], [0.5, 1.5], [1.9,1.8]]
Y_two = [0, 1, 1, 1, 1, 0, 0]

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

example_two = pd.DataFrame(X_two)
example_two["target"] = Y_two

colors = example_two["target"].map({0:"orange", 1:"blue"})
sns.scatterplot(data=example_two, x=0, y=1, c=colors, s=200)

clf = tree.DecisionTreeClassifier()
clf = clf.fit(X_two, Y_two)

import matplotlib.colors
cmap_yg_gr_lb = matplotlib.colors.ListedColormap(["gold", "lightblue"])

DecisionBoundaryDisplay.from_estimator(
    clf,
    example_two.drop("target", axis=1),
    cmap = cmap_yg_gr_lb,  
    response_method = "predict",
)

sns.scatterplot(data=example_two, x=0, y=1, c=colors, s=200)

Что, если мы реплицируем тот же код для еще более сложного набора данных?

X_two = [[0  , 0  ] , [1  , 1  ] , [2  , 1  ] , [1  , 2  ] , [2  , 2  ],
         [0.5, 1.5] , [1.9, 1.8] , [2.1, 1.8] , [2.1, 2.1] , [2.5, 1.8],
         [2.1, 1.5] , [1.7, 1.7] , [-0.5, 0 ] , [0 , -0.5] , [-0.6, 0.5],
         [0.2, 0 ]]
Y_two = [0, 1, 1, 1, 1,
         0, 0, 1, 0, 0,
         0, 0, 1, 1, 1,
         1]

Итак, чем более сложными становятся данные и тем больше усложняется модель:

Это то, чего мы хотим? Модель, идеально разделяющая точки, которые она видит? Совсем нет, и мы поймем, почему…