Качество классификации и второй проект

Precision, recall и F1

Содержание курса

В прошлом уроке вы извлекли из матрицы ошибок четыре числа — TP, FP, TN, FN — и научились правильно раскладывать confusion_matrix по индексам. Теперь эти четыре числа перестают быть просто ячейками: из них собираются метрики, которые говорят о качестве модели на языке конкретных инженерных компромиссов.

TP, FP, FN как знаменатели precision и recall

Матрица ошибок хранит четыре числа, но accuracy сводит их к одному отношению: (TP + TN) / (TP + TN + FP + FN) — доля верных предсказаний среди всех. Precision и recall смотрят на более узкие срезы — и каждый срез отвечает ровно на один вопрос.

Precision спрашивает: «Из всего, что модель назвала положительным, сколько действительно положительных?» Множество «всего названного положительным» — это TP плюс FP. Отсюда:

Precision = TP / (TP + FP)

Знаменатель — вертикальный срез по предсказанным положительным (столбец 1 в матрице). Ложные тревоги (FP) тянут его вниз, потому что они увеличивают знаменатель без изменения числителя.

Recall спрашивает другое: «Из всех реальных положительных сколько модель нашла?» Теперь берём все реальные положительные — это TP плюс FN (те, кого модель пропустила):

Recall = TP / (TP + FN)

Знаменатель — горизонтальный срез по реальным положительным (строка 1 в матрице). Пропуски (FN) снижают recall: каждый пропущенный положительный объект увеличивает знаменатель, не трогая числитель.

Заметьте, что TN не входит ни в одну из этих формул. Это значит: если к данным добавить только новые истинно отрицательные объекты, не меняя TP и FP, ни precision, ни recall не изменятся — TN просто не участвует в расчёте. Однако это не означает устойчивости к любым изменениям состава данных: если вместе с новыми отрицательными объектами растёт и число FP (модель ошибочно относит часть из них к положительному классу), precision упадёт, несмотря на неизменный TP.

Чтобы связать формулы с конкретными ячейками матрицы: при вызове confusion_matrix(y_true, y_pred, labels=[0, 1]) строки соответствуют реальным классам, столбцы — предсказанным. Тогда:

  • cm[1, 1] = TP
  • cm[0, 1] = FP
  • cm[1, 0] = FN

Precision берёт столбец 1 (предсказано «1»): cm[1,1] / (cm[1,1] + cm[0,1]). Recall берёт строку 1 (реально «1»): cm[1,1] / (cm[1,1] + cm[1,0]).

Из формул напрямую следует, как менять поведение модели при прочих равных: если зафиксировать TP и снизить только FP — precision вырастет; если зафиксировать TP и снизить только FN — вырастет recall. Это и есть инженерный компромисс между двумя метриками: FP «стоит» precision, FN «стоит» recall.

Однако на практике прочие равные не сохраняются: при сдвиге порога классификации вместе с FP меняется и TP, поэтому precision может как вырасти, так и упасть. Предсказать направление изменений без пересчёта нельзя — нужно смотреть на конкретные числа. Взаимозависимость precision и recall при изменении порога разбирается подробнее в следующем уроке.

Если модель не предсказала ни одного положительного объекта

При TP + FP = 0 обычная формула precision делит ноль на ноль. Это не «идеальная точность»: модель вообще не выдала положительных ответов. В scikit-learn можно явно выбрать поведение через zero_division:

from sklearn.metrics import precision_score, recall_score, f1_score

y_true = [0, 1, 1, 0]
y_pred = [0, 0, 0, 0]
for metric in (precision_score, recall_score, f1_score):
    print(metric(y_true, y_pred, pos_label=1, zero_division=0))

Все три строки выведут 0.0. Для precision ноль выбран параметром вместо неопределённого отношения; recall равен нулю потому, что оба реальных положительных объекта пропущены. В отчёте рядом с метриками сохраняйте число предсказанных и реальных положительных объектов: одинаковый ноль может возникать по разным причинам.

Начать заново?

Помощник начнёт новый диалог по этой задаче. Текущая переписка останется в истории до конца срока хранения.

О переписке

Можно приложить до трёх фото PNG, JPEG или WebP по 5 МБ.

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

Проверка решения остаётся отдельным действием.