Матрица ошибок: precision, recall и ловушка accuracy
У классификатора четыре возможных исхода, и сворачивать их в одну «долю верных ответов» опасно. Чтобы честно измерить качество, исходы раскладывают в матрицу ошибок, а из неё считают метрики под конкретную задачу. Двигайте порог и разделимость классов — все числа пересчитываются.
Двигайте порог — Precision и Recall обмениваются. Хуже разделимость (классы перекрыты) — обе метрики падают. Accuracy обманчива на дисбалансе: если спама мало, «всё не спам» даёт высокую accuracy, но Recall = 0.
Любое предсказание попадает в одну из четырёх клеток. TP (true positive) — поймали спам. TN (true negative) — правильно пропустили обычное письмо. FP (false positive) — зря пометили нужное письмо спамом. FN (false negative) — проворонили спам в инбоксе. Эти четыре числа и есть матрица ошибок.
Первое, что делают с готовой моделью, — строят матрицу ошибок и смотрят precision/recall, а не одну accuracy. Особенно если интересующий класс редкий: мошенничество, болезнь, отток. Там высокая accuracy почти ничего не значит.
Когда нужно одно число для сравнения моделей, берут F1 — гармоническое среднее precision и recall: оно высоко, только если обе метрики высоки. Но и его подбирают осознанно, помня, что precision и recall отвечают на разные вопросы.
Медицинский скрининг настроен на высокий recall: лучше лишний раз перепроверить здорового, чем пропустить больного. Поэтому за чувствительным первым тестом идёт точный подтверждающий — он добирает precision.
Спам-фильтр, наоборот, бережёт precision: пользователю важнее не потерять нужное письмо, чем изредка увидеть спам в инбоксе. Одна и та же матрица ошибок, но приоритеты противоположные — и порог стоит в разных местах.
Определения
Матрица считается при конкретном пороге: сдвиньте его — и precision с recall поменяются. Сравнивать модели «при пороге 0.5 по умолчанию» некорректно, особенно на несбалансированных классах.
Precision зависит от доли позитивного класса в потоке: перенесите модель туда, где мошенничество вдвое реже, — precision упадёт сам по себе, без деградации модели. Recall от базовой ставки не зависит.