Найти тему
Властелин машин

Визуализация матрицы расхождений - ключ к пониманию ошибок классификации

Оглавление

«Ошибки — это наука, помогающая нам двигаться вперёд», — говорил Уильям Ченнинг. Визуализация - отличный инструмент, который помогает анализировать данные и выявлять закономерности.

Рассмотрим удобный способ отображения в Python одной из метрик классификации под названием confusion matrix (на русский переводят по-разному - матрица ошибок, неточностей, расхождений или несоответствий).

Сначала загрузим демонстрационный датасет.

import numpy as np
import pandas as pd

from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression

df = load_iris(as_frame=True)['frame']
d = {k:v for k, v in enumerate(load_iris().target_names)}
df['target'] = df['target'].map(d)
df = df.sample(frac=1, random_state=0)

df.head()

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

model = LogisticRegression(random_state=0, max_iter=1000).fit(df.drop(columns='target'), df.target)

y_p = model.predict(df.drop(columns='target'))

Теперь получим значения ошибок, воспользовавшись функцией confusion_matrix из модуля sklearn.metrics:

from sklearn.metrics import confusion_matrix

labels = np.sort(df['target'].unique())
cm = confusion_matrix(y_true = df['target'], y_pred = y_p,
labels=labels,
normalize=None)
cm

-2

В строке i и колонке j матрицы располагаются значения, соответствующие количеству объектов класса i, которые предсказаны как j. Значения классов берутся, как метки встретившиеся хотя бы раз в y_true или y_pred упорядоченные по возрастанию. Я намеренно передаю метки явно в параметре labels для демонстрации этого поведения (этим же параметром, можно поменять порядок вывода или указать подмножество/список меток для вывода).

matshow

Визуализацию начнем с низкоуровневых способов matplotlib закончим более быстрыми. Первым кандидатом будет matshow модуля matplotlib.pyplot, которая предоставляет полотно, а элементы потребуется добавлять самостоятельно. Ниже показано, как задать размеры картинки, метки классов, а также дополнить ячейки значениями матрицы через текстовые элементы (большинство настроек разбирались ранее здесь и здесь):

import matplotlib.pyplot as plt
fig = plt.figure(figsize=(5, 5))

plt.matshow(cm, alpha=1, cmap='coolwarm', fignum=fig.number)

plt.xticks(range(len(labels)), labels, rotation='vertical')
plt.yticks(range(len(labels)), labels)
plt.gca().xaxis.set_ticks_position('bottom')

for i in range(cm.shape[0]):
for j in range(cm.shape[1]):
plt.gca().text(x=j, y=i, s=cm[i][j], ha='center', va='center')

plt.xlabel('Predicted label')
plt.ylabel('True label')

-3
-4

imshow

Функция imshow работает аналогично, только для управления размером не надо явно передавать номер фигуры (как делали выше используя fignum, так как по умолчанию matshow сама создает фигуру):

fig = plt.figure(figsize=(5, 5))

plt.imshow(cm, cmap='viridis')

plt.xticks(range(len(labels)), labels, rotation='vertical')
plt.yticks(range(len(labels)), labels)
plt.gca().xaxis.set_ticks_position('bottom')

for i in range(cm.shape[0]):
for j in range(cm.shape[1]):
plt.gca().text(x=j, y=i, s=cm[i][j], ha='center', va='center', color="white")

plt.xlabel('Predicted label')
plt.ylabel('True label')

-5
-6

heatmap

Для отображения с помощью функции heatmap из библиотеки seaborn надо будет внести минимальные правки (закомментировал строки, которые помогут добавить подписи):

import seaborn as sns
plt.figure(figsize=(5,5))

# fmt='.1f'
sns.heatmap(pd.DataFrame(cm, index=labels, columns=labels), annot=True,
fmt='d', cmap='inferno', cbar=False)

# plt.xticks(range(len(labels)), list(labels), rotation='vertical')
# plt.yticks(range(len(labels)), labels)

# plt.xlabel('Predicted label')
# plt.ylabel('True label')

-7
-8

ConfusionMatrixDisplay

Об удобстве вывода задумались и разработчики scikit-learn, написав класс ConfusionMatrixDisplay. С помощью его методов, например, from_predictions можно сразу нарисовать картинку:

from sklearn.metrics import ConfusionMatrixDisplay

ConfusionMatrixDisplay.from_predictions(y_true=df['target'], y_pred=y_p,
labels=labels, colorbar=False,
xticks_rotation='vertical', im_kw={'cmap':'viridis'});

-9

Однако для более гибкой настройки лучше создать класс с помощью конструктора, инициализировав параметр confusion_matrix нашей матрицей ошибок, а затем вызвать метод plot объекта с настройками отображения:

cmp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=labels)

fig, ax = plt.subplots(figsize=(5,5))
cmp.plot(ax=ax, xticks_rotation='vertical', colorbar=False, im_kw={'cmap':'coolwarm'},
text_kw={'color':"white"})

-10
-11

#vis#draw#ml#evaluation

-12

Наука
7 млн интересуются