Метрики классификации: accuracy, precision, recall, F1
Почему «точность» (accuracy) обманчива и какие метрики показывают правду.
Метрика — число, которым измеряют качество модели на тестовых данных.
Матрица ошибок
Для бинарной классификации все предсказания делятся на четыре типа. Пусть «1» — это положительный класс (например, «болен»):
- TP (true positive) — верно предсказали «1» (болен и определили как больного).
- FP (false positive) — ложная тревога: предсказали «1», а на деле «0» (здорового назвали больным).
- TN (true negative) — верно предсказали «0».
- FN (false negative) — пропуск: предсказали «0», а на деле «1» (больного назвали здоровым).
Эти четыре числа и есть матрица ошибок. Из них считают все метрики.
Четыре метрики и их смысл
- Accuracy (точность общая) = доля верных ответов =
(TP+TN) / всего. Проста, но обманчива при перекосе классов. - Precision (точность положительных) =
TP / (TP+FP). Из тех, кого назвали «1», сколько действительно «1». Высокая precision — мало ложных тревог. - Recall (полнота) =
TP / (TP+FN). Из всех реальных «1» сколько поймали. Высокий recall — мало пропусков. - F1 — баланс precision и recall (их гармоническое среднее). Хорош, когда важны обе.
Почему accuracy обманывает
Пусть болен 1 человек из 100. Модель, которая всем говорит «здоров», даёт accuracy 99% — и при этом бесполезна: ни одного больного не нашла. Recall у неё 0. Вот почему при редком классе смотрят на precision и recall, а не на одну accuracy.
Precision vs recall: компромисс
| Что дороже ошибиться | Важнее метрика | Пример |
| Пропустить положительный | Recall | Диагностика болезни |
| Поднять ложную тревогу | Precision | Блокировка письма как спама |
Поднимая порог классификатора, обычно растёт precision, но падает recall, и наоборот. Идеала «и то, и другое по максимуму» не бывает — выбирают под задачу.
Считаем все метрики на Python
Без библиотек, на двух списках. Код запускается:
# 1 = положительный класс
y_true = [1, 0, 1, 1, 0, 1, 0, 0, 1, 0]
y_pred = [1, 0, 1, 0, 0, 1, 1, 0, 1, 0]
tp = fp = tn = fn = 0
for t, p in zip(y_true, y_pred):
if t == 1 and p == 1: tp += 1
elif t == 0 and p == 1: fp += 1
elif t == 0 and p == 0: tn += 1
elif t == 1 and p == 0: fn += 1
print("TP =", tp, "FP =", fp, "TN =", tn, "FN =", fn)
accuracy = (tp + tn) / len(y_true)
precision = tp / (tp + fp)
recall = tp / (tp + fn)
f1 = 2 * precision * recall / (precision + recall)
print("Accuracy =", round(accuracy, 2))
print("Precision =", round(precision, 2))
print("Recall =", round(recall, 2))
print("F1 =", round(f1, 2))
Вывод:
TP = 4 FP = 1 TN = 4 FN = 1 Accuracy = 0.8 Precision = 0.8 Recall = 0.8 F1 = 0.8
Поменяйте предсказания в y_pred и проследите, как смещаются precision и recall, — это лучший способ прочувствовать метрики.
Итог
- Матрица ошибок (TP, FP, TN, FN) — основа всех метрик классификации.
- Accuracy обманчива при редком классе; смотрите precision и recall.
- Precision — мало ложных тревог; recall — мало пропусков; F1 — их баланс.
- Выбор метрики зависит от того, какая ошибка дороже в вашей задаче.