Постройте поверхность принятия решений для алгоритмов машинного обучения в Python
Алгоритмы классификации учатся назначать метки классов примерам, хотя их решения могут показаться непрозрачными.
Популярной диагностикой для понимания решений, принимаемых алгоритмом классификации, является поверхность решений. Это график, показывающий, как алгоритм подходящего машинного обучения прогнозирует грубую сетку во входном пространстве объектов.
График поверхности решений — это мощный инструмент для понимания того, как данная модель «видит» задачу прогнозирования и как она решила разделить входное пространство объектов по меткам классов.
В этом уроке вы узнаете, как построить поверхность принятия решений для алгоритма машинного обучения классификации.
После завершения этого урока вы будете знать:
- Поверхность принятия решений — это диагностический инструмент, позволяющий понять, как алгоритм классификации делит пространство признаков.
- Как построить поверхность принятия решений для использования четких меток классов для алгоритма машинного обучения.
- Как построить и интерпретировать поверхность решений, используя прогнозируемые вероятности.
Начните свой проект с моей новой книги «Освоение машинного обучения с помощью Python», включающей пошаговые руководства и файлы исходного кода Python для все примеры.
Давайте начнем.
Обзор руководства
Этот урок разделен на три части; они есть:
- Поверхность принятия решения
- Набор данных и модель
- Постройте поверхность решения
Поверхность принятия решения
Алгоритмы машинного обучения классификации учатся назначать метки входным примерам.
Рассмотрим числовые входные объекты для задачи классификации, определяющие непрерывное входное пространство объектов.
Мы можем думать о каждом входном объекте, определяющем ось или измерение в пространстве объектов. Два входных объекта будут определять пространство объектов, которое представляет собой плоскость с точками, обозначающими входные координаты во входном пространстве. Если бы входных переменных было три, пространство признаков было бы трехмерным объемом.
Каждой точке пространства можно присвоить метку класса. С точки зрения двумерного пространства признаков мы можем думать, что каждая точка на плоскости имеет разный цвет в соответствии с присвоенным ей классом.
Цель алгоритма классификации — научиться разделять пространство признаков так, чтобы метки правильно назначались точкам в пространстве признаков или, по крайней мере, настолько правильно, насколько это возможно.
Это полезное геометрическое понимание классификационного прогнозного моделирования. Мы можем сделать еще один шаг вперед.
После того, как алгоритм машинного обучения классификации разделяет пространство признаков, мы можем классифицировать каждую точку в пространстве признаков на некоторой произвольной сетке, чтобы получить представление о том, как именно алгоритм решил разделить пространство признаков.
Это называется поверхностью принятия решения или границей решения и представляет собой диагностический инструмент для понимания модели в задаче классификационного прогнозного моделирования.
Хотя понятие «поверхность» предполагает двумерное пространство объектов, этот метод можно использовать с пространствами объектов с более чем двумя измерениями, где поверхность создается для каждой пары входных объектов.
Теперь, когда мы знакомы с тем, что такое поверхность решений, давайте определим набор данных и модель, для которых мы позже исследуем поверхность решений.
Набор данных и модель
В этом разделе мы определим задачу классификации и прогнозирующую модель для изучения этой задачи.
Набор данных синтетической классификации
Мы можем использовать функцию scikit-learn make_blobs() для определения задачи классификации с двумерным числовым пространством классов, и каждой точке присваивается одна из двух меток класса, например. задача бинарной классификации.
...
# generate dataset
X, y = make_blobs(n_samples=1000, centers=2, n_features=2, random_state=1, cluster_std=3)
После определения мы можем затем создать точечную диаграмму пространства объектов, где первый объект определяет ось X, второй объект определяет ось Y, а каждый образец представлен как точка в пространстве объектов.
Затем мы можем раскрасить точки на диаграмме рассеяния в соответствии с их меткой класса как 0 или 1.
...
# create scatter plot for samples from each class
for class_value in range(2):
# get row indexes for samples with this class
row_ix = where(y == class_value)
# create scatter of these samples
pyplot.scatter(X[row_ix, 0], X[row_ix, 1])
# show the plot
pyplot.show()
Ниже приведен полный пример определения и построения набора данных синтетической классификации.
# generate binary classification dataset and plot
from numpy import where
from matplotlib import pyplot
from sklearn.datasets import make_blobs
# generate dataset
X, y = make_blobs(n_samples=1000, centers=2, n_features=2, random_state=1, cluster_std=3)
# create scatter plot for samples from each class
for class_value in range(2):
# get row indexes for samples with this class
row_ix = where(y == class_value)
# create scatter of these samples
pyplot.scatter(X[row_ix, 0], X[row_ix, 1])
# show the plot
pyplot.show()
При выполнении примера создается набор данных, а затем он отображается в виде точечной диаграммы с точками, окрашенными в соответствии с меткой класса.
Мы можем видеть четкое разделение между примерами из двух классов и можем представить, как модель машинного обучения может провести линию, разделяющую два класса, например. возможно, диагональная линия проходит прямо посередине двух групп.
Прогнозирующая модель классификации соответствия
Теперь мы можем подогнать модель к нашему набору данных.
В этом случае нам подойдет алгоритм логистической регрессии, поскольку мы можем прогнозировать как четкие метки классов, так и вероятности, которые мы можем использовать в нашей поверхности принятия решений.
Мы можем определить модель, а затем подогнать ее к набору обучающих данных.
...
# define the model
model = LogisticRegression()
# fit the model
model.fit(X, y)
После определения мы можем использовать модель для прогнозирования набора обучающих данных, чтобы получить представление о том, насколько хорошо он научился делить пространство признаков набора обучающих данных и назначать метки.
...
# make predictions
yhat = model.predict(X)
Прогнозы можно оценить, используя точность классификации.
...
# evaluate the predictions
acc = accuracy_score(y, yhat)
print('Accuracy: %.3f' % acc)
Ниже приведен полный пример подбора и оценки модели на основе набора данных синтетической бинарной классификации.
# example of fitting and evaluating a model on the classification dataset
from sklearn.datasets import make_blobs
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
# generate dataset
X, y = make_blobs(n_samples=1000, centers=2, n_features=2, random_state=1, cluster_std=3)
# define the model
model = LogisticRegression()
# fit the model
model.fit(X, y)
# make predictions
yhat = model.predict(X)
# evaluate the predictions
acc = accuracy_score(y, yhat)
print('Accuracy: %.3f' % acc)
Выполнение примера соответствует модели и делает прогноз для каждого примера.
Примечание. Ваши результаты могут отличаться в зависимости от стохастической природы алгоритма или процедуры оценки или различий в числовой точности. Попробуйте запустить пример несколько раз и сравнить средний результат.
В этом случае мы видим, что модель достигла производительности около 97,2 процента.
Accuracy: 0.972
Теперь, когда у нас есть набор данных и модель, давайте рассмотрим, как мы можем разработать поверхность принятия решений.
Постройте поверхность решения
Мы можем создать поверхность принятия решений, подобрав модель к набору обучающих данных, а затем используя ее для прогнозирования сетки значений во входной области.
Получив сетку прогнозов, мы можем построить значения и метки их классов.
Диаграмму рассеяния можно было бы использовать, если бы была взята достаточно мелкая сетка. Лучшим подходом является использование контурного графика, который может интерполировать цвета между точками.
Можно использовать функцию contextf() Matplotlib.
Для этого необходимо выполнить несколько шагов.
Во-первых, нам нужно определить сетку точек в пространстве объектов.
Для этого мы можем найти минимальные и максимальные значения для каждого объекта и расширить сетку на один шаг дальше, чтобы охватить все пространство объектов.
...
# define bounds of the domain
min1, max1 = X[:, 0].min()-1, X[:, 0].max()+1
min2, max2 = X[:, 1].min()-1, X[:, 1].max()+1
Затем мы можем создать однородную выборку по каждому измерению, используя функцию arange() с выбранным разрешением. В этом случае мы будем использовать разрешение 0,1.
...
# define the x and y scale
x1grid = arange(min1, max1, 0.1)
x2grid = arange(min2, max2, 0.1)
Теперь нам нужно превратить это в сетку.
Мы можем использовать функцию meshgrid() NumPy для создания сетки из этих двух векторов.
Если первый признак x1 — это наша ось X пространства признаков, то нам нужна одна строка значений x1 сетки для каждой точки на оси Y.
Аналогично, если мы возьмем x2 в качестве оси Y пространства признаков, тогда нам понадобится один столбец значений x2 сетки для каждой точки на оси X.
Функция meshgrid() сделает это за нас, дублируя строки и столбцы по мере необходимости. Он возвращает две сетки для двух входных векторов. Первая сетка значений x и вторая — значений y, организованная в сетку строк и столбцов соответствующего размера в пространстве объектов.
...
# create all of the lines and rows of the grid
xx, yy = meshgrid(x1grid, x2grid)
Затем нам нужно выровнять сетку, чтобы создать образцы, которые мы можем ввести в модель и сделать прогноз.
Для этого сначала мы сглаживаем каждую сетку в вектор.
...
# flatten each grid to a vector
r1, r2 = xx.flatten(), yy.flatten()
r1, r2 = r1.reshape((len(r1), 1)), r2.reshape((len(r2), 1))
Затем мы складываем векторы рядом как столбцы во входном наборе данных, например. как наш исходный набор обучающих данных, но с гораздо более высоким разрешением.
...
# horizontal stack vectors to create x1,x2 input for the model
grid = hstack((r1,r2))
Затем мы можем ввести это в нашу модель и получить прогноз для каждой точки сетки.
...
# make predictions for the grid
yhat = model.predict(grid)
# reshape the predictions back into a grid
Все идет нормально.
У нас есть сетка значений в пространстве признаков и метках классов, как это предсказывает наша модель.
Далее нам нужно построить сетку значений в виде контурного графика.
Функция контурф() принимает отдельные сетки для каждой оси, точно так же, как то, что было возвращено нашим предыдущим вызовом meshgrid(). Большой!
Таким образом, мы можем использовать xx и yy, которые мы подготовили ранее, и просто изменить форму прогнозов (yhat) из модели, чтобы они имели ту же форму.
...
# reshape the predictions back into a grid
zz = yhat.reshape(xx.shape)
Затем мы рисуем поверхность решения с помощью двухцветной карты цветов.
...
# plot the grid of x, y and z values as a surface
pyplot.contourf(xx, yy, zz, cmap='Paired')
Затем мы можем нанести на график фактические точки набора данных сверху, чтобы увидеть, насколько хорошо они были разделены поверхностью принятия решений логистической регрессии.
Полный пример построения поверхности решения для модели логистической регрессии в нашем наборе данных синтетической бинарной классификации приведен ниже.
# decision surface for logistic regression on a binary classification dataset
from numpy import where
from numpy import meshgrid
from numpy import arange
from numpy import hstack
from sklearn.datasets import make_blobs
from sklearn.linear_model import LogisticRegression
from matplotlib import pyplot
# generate dataset
X, y = make_blobs(n_samples=1000, centers=2, n_features=2, random_state=1, cluster_std=3)
# define bounds of the domain
min1, max1 = X[:, 0].min()-1, X[:, 0].max()+1
min2, max2 = X[:, 1].min()-1, X[:, 1].max()+1
# define the x and y scale
x1grid = arange(min1, max1, 0.1)
x2grid = arange(min2, max2, 0.1)
# create all of the lines and rows of the grid
xx, yy = meshgrid(x1grid, x2grid)
# flatten each grid to a vector
r1, r2 = xx.flatten(), yy.flatten()
r1, r2 = r1.reshape((len(r1), 1)), r2.reshape((len(r2), 1))
# horizontal stack vectors to create x1,x2 input for the model
grid = hstack((r1,r2))
# define the model
model = LogisticRegression()
# fit the model
model.fit(X, y)
# make predictions for the grid
yhat = model.predict(grid)
# reshape the predictions back into a grid
zz = yhat.reshape(xx.shape)
# plot the grid of x, y and z values as a surface
pyplot.contourf(xx, yy, zz, cmap='Paired')
# create scatter plot for samples from each class
for class_value in range(2):
# get row indexes for samples with this class
row_ix = where(y == class_value)
# create scatter of these samples
pyplot.scatter(X[row_ix, 0], X[row_ix, 1], cmap='Paired')
# show the plot
pyplot.show()
Выполнение примера соответствует модели и использует ее для прогнозирования результатов для сетки значений в пространстве признаков и отображает результат в виде контурного графика.
Мы видим, как и могли предположить, что логистическая регрессия делит пространство признаков прямой линией. В конце концов, это линейная модель; это все, что он может сделать.
Создание поверхности принятия решений почти похоже на волшебство. Это дает немедленное и значимое представление о том, как модель освоила задачу.
Попробуйте использовать разные алгоритмы, например SVM или дерево решений.
Опубликуйте полученные карты в виде ссылок в комментариях ниже!
Мы можем добавить больше глубины поверхности решений, используя модель для прогнозирования вероятностей вместо меток классов.
...
# make predictions for the grid
yhat = model.predict_proba(grid)
# keep just the probabilities for class 0
yhat = yhat[:, 0]
На графике мы можем увидеть, насколько уверенно или вероятно то, что каждая точка в пространстве признаков принадлежит каждой из меток классов, как видно из модели.
Мы можем использовать другую карту цветов с градациями и показать легенду, чтобы можно было интерпретировать цвета.
...
# plot the grid of x, y and z values as a surface
c = pyplot.contourf(xx, yy, zz, cmap='RdBu')
# add a legend, called a color bar
pyplot.colorbar(c)
Полный пример создания поверхности принятия решений с использованием вероятностей приведен ниже.
# probability decision surface for logistic regression on a binary classification dataset
from numpy import where
from numpy import meshgrid
from numpy import arange
from numpy import hstack
from sklearn.datasets import make_blobs
from sklearn.linear_model import LogisticRegression
from matplotlib import pyplot
# generate dataset
X, y = make_blobs(n_samples=1000, centers=2, n_features=2, random_state=1, cluster_std=3)
# define bounds of the domain
min1, max1 = X[:, 0].min()-1, X[:, 0].max()+1
min2, max2 = X[:, 1].min()-1, X[:, 1].max()+1
# define the x and y scale
x1grid = arange(min1, max1, 0.1)
x2grid = arange(min2, max2, 0.1)
# create all of the lines and rows of the grid
xx, yy = meshgrid(x1grid, x2grid)
# flatten each grid to a vector
r1, r2 = xx.flatten(), yy.flatten()
r1, r2 = r1.reshape((len(r1), 1)), r2.reshape((len(r2), 1))
# horizontal stack vectors to create x1,x2 input for the model
grid = hstack((r1,r2))
# define the model
model = LogisticRegression()
# fit the model
model.fit(X, y)
# make predictions for the grid
yhat = model.predict_proba(grid)
# keep just the probabilities for class 0
yhat = yhat[:, 0]
# reshape the predictions back into a grid
zz = yhat.reshape(xx.shape)
# plot the grid of x, y and z values as a surface
c = pyplot.contourf(xx, yy, zz, cmap='RdBu')
# add a legend, called a color bar
pyplot.colorbar(c)
# create scatter plot for samples from each class
for class_value in range(2):
# get row indexes for samples with this class
row_ix = where(y == class_value)
# create scatter of these samples
pyplot.scatter(X[row_ix, 0], X[row_ix, 1], cmap='Paired')
# show the plot
pyplot.show()
Выполнение примера прогнозирует вероятность членства в классе для каждой точки сетки в пространстве объектов и отображает результат.
Здесь мы видим, что модель неопределенна (более светлые цвета) в середине области, учитывая шум выборки в этой области пространства признаков. Мы также видим, что модель очень уверена (полноцветная) в нижней левой и верхней правой половинах области.
Вместе четкие классы и поверхности вероятностных решений представляют собой мощные диагностические инструменты для понимания вашей модели и того, как она делит пространство признаков для вашей задачи прогнозного моделирования.
Дальнейшее чтение
В этом разделе представлены дополнительные ресурсы по этой теме, если вы хотите углубиться в нее.
- API matplotlib.pyplot.contourf.
- Цветовые карты Matplotlib
- API numpy.meshgrid.
- Постройте поверхность решений дерева решений на наборе данных радужной оболочки глаза, пример sklearn.
Краткое содержание
В этом уроке вы узнали, как построить поверхность принятия решений для алгоритма машинного обучения классификации.
В частности, вы узнали:
- Поверхность принятия решений — это диагностический инструмент, позволяющий понять, как алгоритм классификации делит пространство признаков.
- Как построить поверхность принятия решений для использования четких меток классов для алгоритма машинного обучения.
- Как построить и интерпретировать поверхность решений, используя прогнозируемые вероятности.
У вас есть вопросы?
Задавайте свои вопросы в комментариях ниже, и я постараюсь ответить.