W3docs

Машинное обучение: понимание матрицы ошибок

Узнайте, что такое матрица ошибок, как построить её в Python с scikit-learn, визуализировать с seaborn и вычислить precision, recall и F1-score.

Матрица ошибок — это таблица, которая обобщает результаты предсказаний классификационной модели, сравнивая фактические метки с предсказанными. Она является отправной точкой для вычисления precision, recall, F1-score и большинства других метрик классификации.

В этой главе рассматривается:

  • Что означают четыре ячейки (TP, FP, TN, FN) и почему каждая из них важна
  • Как вычислять стандартные метрики из этих ячеек
  • Построение и визуализация матрицы ошибок в Python с помощью scikit-learn и seaborn
  • Многоклассовые матрицы ошибок
  • Типичные ошибки — особенно при работе с несбалансированными наборами данных

Что такое матрица ошибок?

Для бинарного классификатора (два возможных класса: положительный и отрицательный) матрица ошибок представляет собой таблицу 2×2:

Предсказан положительныйПредсказан отрицательный
Фактически положительныйTrue Positive (TP)False Negative (FN)
Фактически отрицательныйFalse Positive (FP)True Negative (TN)

Каждая ячейка считает определённый тип результата:

ТерминАббревиатураЗначение
True PositiveTPМодель предсказала положительный; реальность — положительный ✓
True NegativeTNМодель предсказала отрицательный; реальность — отрицательный ✓
False PositiveFPМодель предсказала положительный; реальность — отрицательный ✗ (ошибка I рода)
False NegativeFNМодель предсказала отрицательный; реальность — положительный ✗ (ошибка II рода)

Простой способ запомнить: первое слово (True / False) говорит о том, было ли предсказание верным; второе слово (Positive / Negative) — что именно предсказала модель.

Метрики, вычисляемые из матрицы

Четыре счётчика лежат в основе всех стандартных метрик классификации:

МетрикаФормулаЧто измеряет
Accuracy(TP + TN) / (TP + TN + FP + FN)Общая доля верных предсказаний
PrecisionTP / (TP + FP)Из всех положительных предсказаний, сколько оказались верными
Recall (Sensitivity)TP / (TP + FN)Из всех фактически положительных, сколько было найдено
SpecificityTN / (TN + FP)Из всех фактически отрицательных, сколько было корректно исключено
F1-Score2 × Precision × Recall / (Precision + Recall)Гармоническое среднее precision и recall

Когда отдавать приоритет precision или recall

  • Приоритет recall актуален, когда пропуск положительного случая обходится дорого — медицинский скрининг, обнаружение мошенничества, спам-фильтры, которые должны поймать каждое нежелательное письмо.
  • Приоритет precision актуален, когда ложные срабатывания обходятся дорого — рекомендации к операции, маркировка юридических документов, системы push-уведомлений.
  • F1-score балансирует оба показателя и является метрикой по умолчанию при несбалансированных данных.

Численный пример с расчётами

Предположим, модель проверяет 100 пациентов на наличие заболевания:

  • TP = 50 (больные пациенты, выявленные верно)
  • FP = 5 (здоровые пациенты, ошибочно отмеченные как больные)
  • FN = 10 (больные пациенты, пропущенные моделью)
  • TN = 35 (здоровые пациенты, верно признанные здоровыми)

Пошаговые вычисления:

Accuracy  = (50 + 35) / 100 = 0.85  (85 %)
Precision = 50 / (50 + 5)  ≈ 0.909 (90.9 %)
Recall    = 50 / (50 + 10) ≈ 0.833 (83.3 %)
F1-Score  = 2 × 0.909 × 0.833 / (0.909 + 0.833) ≈ 0.869 (86.9 %)

Обратите внимание: accuracy (85 %) выглядит неплохо, однако recall составляет лишь 83 % — то есть 10 из 60 больных пациентов были пропущены. В медицинском контексте это несоответствие важнее, чем само значение accuracy.

Построение матрицы ошибок в Python

Использование scikit-learn

sklearn.metrics предоставляет confusion_matrix() и готовый текстовый отчёт через classification_report().

from sklearn.metrics import confusion_matrix, classification_report

# Ground-truth labels and model predictions
y_true = [1, 1, 0, 0, 1, 0, 1, 0, 1, 0]
y_pred = [1, 0, 0, 1, 1, 0, 1, 0, 1, 1]

cm = confusion_matrix(y_true, y_pred)
print("Confusion Matrix:")
print(cm)
print()
print(classification_report(y_true, y_pred, target_names=["Negative", "Positive"]))

confusion_matrix() возвращает массив NumPy. По умолчанию строки — фактические классы, а столбцы — предсказанные (соответствует показанной выше таблице). Расположение элементов массива:

[[TN  FP]
 [FN  TP]]

Ручное вычисление метрик

Можно извлечь четыре ячейки и вычислить метрики самостоятельно для проверки:

from sklearn.metrics import confusion_matrix

y_true = [1, 1, 0, 0, 1, 0, 1, 0, 1, 0]
y_pred = [1, 0, 0, 1, 1, 0, 1, 0, 1, 1]

tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()

accuracy  = (tp + tn) / (tp + tn + fp + fn)
precision = tp / (tp + fp)
recall    = tp / (tp + fn)
f1        = 2 * precision * recall / (precision + recall)

print(f"TP={tp}, FP={fp}, FN={fn}, TN={tn}")

print(f"Accuracy : {accuracy:.3f}")
print(f"Precision: {precision:.3f}")
print(f"Recall   : {recall:.3f}")
print(f"F1-Score : {f1:.3f}")

Ожидаемый вывод:

TP=4, FP=2, FN=1, TN=3
Accuracy : 0.700
Precision: 0.667
Recall   : 0.800
F1-Score : 0.727

Визуализация с помощью seaborn

Тепловая карта делает матрицу ошибок более наглядной, особенно при многоклассовых задачах:

import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import confusion_matrix

y_true = [1, 1, 0, 0, 1, 0, 1, 0, 1, 0]
y_pred = [1, 0, 0, 1, 1, 0, 1, 0, 1, 1]

cm = confusion_matrix(y_true, y_pred)

sns.heatmap(
    cm,
    annot=True,
    fmt="d",
    cmap="Blues",
    xticklabels=["Negative", "Positive"],
    yticklabels=["Negative", "Positive"],
)
plt.xlabel("Predicted label")
plt.ylabel("True label")
plt.title("Confusion Matrix")
plt.tight_layout()
plt.savefig("confusion_matrix.png", dpi=150)
plt.show()

annot=True печатает количество внутри каждой ячейки; fmt="d" форматирует их как целые числа.

Многоклассовые матрицы ошибок

При наличии более двух классов матрица ошибок расширяется до сетки N×N. Каждая строка по-прежнему представляет фактические классы; каждый столбец — предсказанные. Диагональные ячейки — верные предсказания; внедиагональные — ошибки.

from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
import matplotlib.pyplot as plt

# Three classes: cat, dog, rabbit
y_true = ["cat", "dog", "rabbit", "cat", "dog", "rabbit",
          "cat", "dog", "cat", "rabbit"]
y_pred = ["cat", "dog", "rabbit", "dog", "dog", "cat",
          "cat", "rabbit", "cat", "rabbit"]

labels = ["cat", "dog", "rabbit"]
cm = confusion_matrix(y_true, y_pred, labels=labels)
print(cm)

disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=labels)
disp.plot(cmap="Blues")
plt.title("Multi-Class Confusion Matrix")
plt.tight_layout()
plt.savefig("cm_multiclass.png", dpi=150)
plt.show()

ConfusionMatrixDisplay (добавлен в scikit-learn 0.24) — удобная однострочная альтернатива тепловой карте seaborn, не требующая зависимости от seaborn.

Для многоклассовых задач precision и recall вычисляются для каждого класса и затем усредняются. classification_report() предоставляет три стратегии усреднения:

  • macro — невзвешенное среднее по классам (все классы равнозначны).
  • weighted — среднее, взвешенное по поддержке (количеству истинных экземпляров каждого класса).
  • micro — агрегирование TP/FP/FN по всем классам перед делением (даёт общую accuracy для сбалансированных наборов).

Типичные ошибки

Accuracy вводит в заблуждение на несбалансированных данных

Рассмотрим набор данных, где 95 % образцов относятся к отрицательному классу. Модель, всегда предсказывающая отрицательный класс, достигает 95 % accuracy, но имеет нулевой recall — она никогда не обнаруживает положительные случаи. Матрица ошибок сразу это показывает: вся первая строка (фактически положительные) будет состоять исключительно из FN.

Всегда дополняйте accuracy метриками precision, recall или F1-score при несбалансированных данных. Смотрите главу Train/Test Split о том, как создать репрезентативную выборку, и главу AUC-ROC Curve о метрике оценки, независимой от порога.

Неправильный выбор стратегии усреднения

Использование усреднения macro при сильном дисбалансе классов завышает оценку редких классов. Используйте weighted для реалистичного представления общего качества модели на всём наборе данных.

Отсутствие нормализации

Абсолютные значения зависят от размера набора данных. При сравнении моделей, обученных на наборах разного размера, нормализуйте матрицу, разделив каждую строку на её сумму (передайте normalize='true' в confusion_matrix()):

cm_normalized = confusion_matrix(y_true, y_pred, normalize="true")
print(cm_normalized.round(2))

Теперь каждая строка суммируется до 1.0 и показывает долю каждого фактического класса, предсказанного верно.

Матрица ошибок и другие инструменты оценки

ИнструментЛучше всего подходит для
Матрица ошибокПонимания конкретных типов ошибок модели
AUC-ROC CurveСравнения классификаторов при всех порогах принятия решений
Cross-ValidationОценки того, насколько хорошо матрица обобщается на новых данных
Grid SearchНастройки гиперпараметров с использованием выбранной метрики (например, F1-score)

Ключевые выводы

  • Матрица ошибок разбивает предсказания на TP, FP, TN и FN — четыре значения, раскрывающие какие ошибки допускает модель, а не просто сколько.
  • Accuracy в одиночку недостаточна; всегда проверяйте precision, recall и F1-score, особенно при несбалансированных данных.
  • Используйте sklearn.metrics.confusion_matrix() для вычислений и seaborn или ConfusionMatrixDisplay для визуализации.
  • Многоклассовые матрицы следуют тому же соглашению: строка = фактический класс, столбец = предсказанный, и масштабируются до N×N.
  • Выбирайте стратегию усреднения (macro, weighted, micro) в соответствии с распределением классов в вашем наборе данных.
Was this page helpful?