Python: как нормализовать матрицу путаницы?

Я вычислил матрицу путаницы для моего классификатора, используя метод confusion_matrix() из пакета sklearn. Диагональные элементы матрицы путаницы представляют собой число точек, для которых предсказанная метка равна истинной метке, в то время как недиагональные элементы - это те, которые неверно маркированы классификатором.

Я хотел бы нормализовать свою матрицу путаницы, чтобы она содержала только числа от 0 до 1. Я хотел бы прочитать процент правильно классифицированных образцов из матрицы.

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

Ответ 1

Я предполагаю, что M[i,j] означает Element of real class i was classified as j. Если это будет наоборот, вам нужно будет транспонировать все, что я говорю. Я также собираюсь использовать следующую матрицу для конкретных примеров:

1 2 3
4 5 6
7 8 9

Есть две вещи, которые вы можете сделать:

Поиск того, как классифицирован каждый класс

Первое, что вы можете задать, это то, что процент элементов реального класса i здесь классифицируется как каждый класс. Для этого возьмем строку, фиксирующую i, и разделим каждый элемент на сумму элементов в строке. В нашем примере объекты класса 2 классифицируются как класс 1 4 раза, классифицируются как класс 2 5 раз и классифицируются как класс 3 6 раз. Чтобы найти проценты, мы просто делим все на сумму 4 + 5 + 6 = 15

4/15 of the class 2 objects are classified as class 1
5/15 of the class 2 objects are classified as class 2
6/15 of the class 2 objects are classified as class 3

Поиск классов, ответственных за каждую классификацию

Второе, что вы можете сделать, это посмотреть на каждый результат из вашего классификатора и спросить, сколько из этих результатов происходит из каждого реального класса. Это будет похоже на другой случай, но с столбцами вместо строк. В нашем примере наш классификатор возвращает "1" 1 раз, когда исходный класс равен 1, 4 раза, когда исходный класс равен 2 и 7 раз, когда исходный класс равен 3. Чтобы найти проценты, мы делим на сумму 1 + 4 + 7 = 12

1/12 of the objects classified as class 1 were from class 1
4/12 of the objects classified as class 1 were from class 2
7/12 of the objects classified as class 1 were from class 3

-

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

Ответ 2

Предположим, что

>>> y_true = [0, 0, 1, 1, 2, 0, 1]
>>> y_pred = [0, 1, 0, 1, 2, 2, 1]
>>> C = confusion_matrix(y_true, y_pred)
>>> C
array([[1, 1, 1],
       [1, 2, 0],
       [0, 0, 1]])

Затем, чтобы узнать, сколько образцов в классе получили их правильную метку, вам нужно

>>> C / C.astype(np.float).sum(axis=1)
array([[ 0.33333333,  0.33333333,  1.        ],
       [ 0.33333333,  0.66666667,  0.        ],
       [ 0.        ,  0.        ,  1.        ]])

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

>>> from sklearn.metrics import precision_recall_fscore_support
>>> _, recall, _, _ = precision_recall_fscore_support(y_true, y_pred)
>>> recall
array([ 0.33333333,  0.66666667,  1.        ])

Аналогично, если вы разделите сумму на axis=0, вы получите точность (доля предсказаний класса k с меткой истины истины k):

>>> C / C.astype(np.float).sum(axis=0)
array([[ 0.5       ,  0.33333333,  0.5       ],
       [ 0.5       ,  0.66666667,  0.        ],
       [ 0.        ,  0.        ,  0.5       ]])
>>> prec, _, _, _ = precision_recall_fscore_support(y_true, y_pred)
>>> prec
array([ 0.5       ,  0.66666667,  0.5       ])

Ответ 3

Матричный вывод с помощью sklearn confusion_matrix() равен таким образом, что

C_ {i, j} равно числу наблюдений, которые, как известно, находятся в группе я но предсказано, что он находится в группе j

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

Обратите внимание, что у sklearn есть сводная функция, которая вычисляет метрики из матрицы путаницы: class_report. Он выводит точность и отзыв, а не специфичность и чувствительность, но они часто рассматриваются как более информативные в целом (особенно для несбалансированной многоклассовой классификации).

Ответ 4

Из документации по sklearn (пример графика)

cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]

где см - матрица путаницы, предоставленная sklearn.

Ответ 5

Есть библиотека, предоставленная самим scikit-learn для построения графиков. Он основан на matplotlib и должен быть уже установлен, чтобы продолжить.

pip install scikit-plot

Теперь просто установите параметр нормализации на true:

import scikitplot as skplt 
skplt.metrics.plot_confusion_matrix(Y_TRUE, Y_PRED, normalize=True)

Ответ 6

Используя Seaborn, вы можете легко распечатать нормализованную и довольно запутанную матрицу с картой пустотности:

enter image description here

from sklearn.metrics import confusion_matrix
import seaborn as sns

cm = confusion_matrix(y_test, y_pred)
# Normalise
cmn = cm.astype('float') / 
cm.sum(axis=1)[:, np.newaxis]
fig, ax = plt.subplots(figsize=(10,10))
sns.heatmap(cmn, annot=True, fmt='.2f', xticklabels=target_names, yticklabels=target_names)
plt.ylabel('Actual')
plt.xlabel('Predicted')
plt.show(block=False)

Ответ 7

Я думаю, что самый простой способ сделать это, сделав:

c = sklearn.metrics.confusion_matrix(y, y_pred)
normed_c = (c.T / c.astype(np.float).sum(axis=1)).T