Используйте matplotlib для визуализации границ решений для алгоритмов классификации в Python

Введение

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

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

Содержание учебного пособия

В этом руководстве я начну со встроенного пакета набора данных в библиотеке Sklearn, чтобы сосредоточиться на этапах реализации. После этого я буду использовать предварительно обработанные данные (без пропущенных данных или выбросов) для построения поверхности принятия решений после применения стандартного средства масштабирования.

  • Поверхность принятия решения
  • Импорт важных библиотек
  • Генерация набора данных
  • Создание поверхности принятия решений
  • Подача заявки на получение реальных данных

Поверхность принятия решения

Классификация в машинном обучении означает обучение ваших данных назначению меток для примеров ввода.

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

Конечная цель классификации - разделить пространство объектов так, чтобы метки назначались точкам в пространстве объектов как можно точнее.

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

Импорт важных библиотек

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn import datasets
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.model_selection import train_test_split

Создать набор данных

Я буду использовать функцию make_blobs() в классе наборов данных из библиотеки Sklearn для создания настраиваемого набора данных. Это позволит сосредоточиться на реализации, а не на очистке данных. Однако шаги те же и представляют собой типичный шаблон.
Для простоты давайте начнем с определения переменных набора данных с 1000 выборками и только двумя функциями и стандартным отклонением 3.

X, y = datasets.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 = np.where(y == class_value)
    # create scatter of these samples
    plt.scatter(X[row_ix, 0], X[row_ix, 1])
# show the plot
plt.show()

Здесь мы перебрали набор данных и нанесли точки между каждым X и y , окрашенные меткой класса. На следующем этапе нам нужно построить модель прогнозной классификации, чтобы предсказать класс невидимых точек. В этом случае можно использовать логистическую регрессию, поскольку у нас есть только две категории.

Разработайте модель логистической регрессии

regressor = LogisticRegression()
# fit the regressor into X and y
regressor.fit(X, y)
# apply the predict method 
y_pred = regressor.predict(X)

Все y_pred можно оценить с помощью accuracy_scoreclass из библиотекиsklearn.

accuracy = accuracy_score(y, y_pred)
print('Accuracy: %.3f' % accuracy)
## Accuracy: 0.972

Создание поверхности принятия решений

matplotlib предоставляет удобную функцию contour(), которая может вставлять цвета между точками. Однако, как предлагается в документации, нам необходимо определить сетку точек X из y в пространстве функций. Отправной точкой было бы найти максимальное значение и минимальное значение каждой функции, а затем увеличить их на единицу, чтобы убедиться, что все пространство покрыто.

min1, max1 = X[:, 0].min() - 1, X[:, 0].max() + 1 #1st feature
min2, max2 = X[:, 1].min() - 1, X[:, 1].max() + 1 #2nd feature

Затем мы можем определить масштаб координат, используя функцию arange() из библиотеки numpy с разрешением0.01, чтобы получить диапазон масштаба.

x1_scale = np.arange(min1, max1, 0.1)
x2_scale = np.arange(min2, max2, 0.1)

Следующим шагом будет преобразование x1_scale и x2_scale в сетку. Функция meshgrid() из библиотеки numpy - это то, что нам нужно.

x_grid, y_grid = np.meshgrid(x1_scale, x2_scale)

Сгенерированный x_grid представляет собой двумерный массив. Чтобы использовать его, нам нужно уменьшить размер до одномерного массива, используя метод flatten() из библиотекиnumpy.

# flatten each grid to a vector
x_g, y_g = x_grid.flatten(), y_grid.flatten()
x_g, y_g = x_g.reshape((len(x_g), 1)), y_g.reshape((len(y_g), 1))

Наконец, складываем векторы бок о бок в виде столбцов во входном наборе данных, как в исходном наборе данных, но с гораздо более высоким разрешением.

grid = np.hstack((x_g, y_g))

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

# make predictions for the grid
y_pred_2 = model.predict(grid)
#predict the probability
p_pred = model.predict_proba(grid)
# keep just the probabilities for class 0
p_pred = p_pred[:, 0]
# reshaping the results
p_pred.shape
pp_grid = p_pred.reshape(x_grid.shape)

Теперь сгенерирована сетка значений и метка прогнозируемого класса по пространству функций.

Впоследствии мы построим эти сетки как контурный график, используя contourf().
Для функции contourf() требуются отдельные сетки для каждой оси. Для этого мы можем использовать x_grid и y_grid и изменить форму прогнозов (y_pred), чтобы они имели ту же форму.

# plot the grid of x, y and z values as a surface
surface = plt.contourf(x_grid, y_grid, pp_grid, cmap='Pastel1')
plt.colorbar(surface)
# create scatter plot for samples from each class
for class_value in range(2):
# get row indexes for samples with this class
    row_ix = np.where(y == class_value)
    # create scatter of these samples
    plt.scatter(X[row_ix, 0], X[row_ix, 1], cmap='Pastel1')
# show the plot
plt.show()

Применить к реальным данным

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

dataset = pd.read_csv('../input/logistic-reg-visual/Social_Network_Ads.csv')
dataset.head()

В наборе данных есть две функции Age и EstimatedSalary и одна зависимая переменная, приобретенная как двоичный столбец. Значение 0 представляет человека с таким же возрастом и зарплатой, который не покупал машину. Однако одно означает, что человек действительно купил машину. Следующим шагом будет отделение зависимой переменной от таких функций, как X и y.

X = dataset.iloc[:, :-1].values
y = dataset.iloc[:, -1].values
# splitting the dataset
X_train, X_test, y_train, y_test = train_test_split(
                                               X, y, 
                                               test_size = 0.25,
                                               random_state = 0)

Масштабирование функций

Нам нужен этот шаг, потому что Age и salary не в одном масштабе

sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

Построение логистической модели и соответствие обучающим данным

classifier = LogisticRegression(random_state = 0)
# fit the classifier into train data
classifier.fit(X_train, y_train)
# predicting the value of y 
y_pred = classifier.predict(X_test)

Постройте поверхность решения - результаты обучения

#1. reverse the standard scaler on the X_train
X_set, y_set = sc.inverse_transform(X_train), y_train
#2. Generate decision surface boundaries
min1, max1 = X_set[:, 0].min() - 10, X_set[:, 0].max() + 10 # for Age
min2, max2 = X_set[:, 1].min() - 1000, X_set[:, 1].max() + 1000 # for salary
#3. Set coordinates scale accuracy
x_scale ,y_scale = np.arange(min1, max1, 0.25), np.arange(min2, max2, 0.25)
#4. Convert into vector 
X1, X2 = np.meshgrid(x_scale, y_scale)
#5. Flatten X1 and X2 and return the output as a numpy array
X_flatten = np.array([X1.ravel(), X2.ravel()])
#6. Transfor the results into it's original form before scaling
X_transformed = sc.transform(X_flatten.T)
#7. Generate the prediction and reshape it to the X to have the same shape
Z_pred = classifier.predict(X_transformed).reshape(X1.shape)
#8. set the plot size
plt.figure(figsize=(20,10))
#9. plot the contour function
plt.contourf(X1, X2, Z_pred,
                     alpha = 0.75, 
                     cmap = ListedColormap(('#386cb0', '#f0027f')))
#10. setting the axes limit
plt.xlim(X1.min(), X1.max())
plt.ylim(X2.min(), X2.max())
#11. plot the points scatter plot ( [salary, age] vs. predicted classification based on training set)
for i, j in enumerate(np.unique(y_set)):
    plt.scatter(X_set[y_set == j, 0], 
                X_set[y_set == j, 1], 
                c = ListedColormap(('red', 'green'))(i), 
                label = j)
    
#12. plot labels and adjustments
plt.title('Logistic Regression (Training set)')
plt.xlabel('Age')
plt.ylabel('Estimated Salary')
plt.legend()
plt.show()

График решения для тестового набора

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

Вывод

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

использованная литература

  1. ИП Sklearn.datasets A
  2. Использование панд для преобразования данных
  3. matplotlib.c ontour () A PI
  4. Numpy.meshgrid () A PI
  5. Постройте поверхность решения дерева решений на наборе данных радужной оболочки глаза - пример sklearn
  6. Полнофункциональный блокнот Kaggle
  7. Репозиторий GitHub