Аналитика27 августа 2026 г.

Порог классификатора: как сравнить число пропусков и ложных тревог

Автор
Ненашев А.
На чтение
6 мин
Дата обновления
27.08.2026
Старт:В любой момент
Срок обучения:40 часов
Машинное обучение. Базовый уровень
Сформируйте устойчивые практические навыки подготовки данных, обучения и оценки базовых моделей машинного обучения в Python, а также навыки сборки воспроизводимого решения на базе scikit-learn.
Подробнее
1 690 ₽95 000 ₽
#COURSE##INNER#

Порог классификатора: как сравнить число пропусков и ложных тревог

У бинарного классификатора есть два разных слоя решения. Сначала модель оценивает вероятность или скор для положительного класса. Потом вы превращаете этот скор в действие: считать объект положительным или нет. Именно второй шаг задается порогом. Поэтому вопрос «какой порог поставить?» нельзя сводить к автоматическому 0,5: это лишь стандартное правило по умолчанию, а не универсально правильный выбор.

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

Что именно меняется, когда вы двигаете порог

При одном и том же обученном классификаторе набор вероятностей не меняется только потому, что вы сдвинули порог. Меняется лишь финальная разметка: какие объекты попадут в положительный класс. Поэтому спор о пороге — это не спор о «лучшем алгоритме», а о правиле принятия решения поверх уже полученных оценок модели.

В scikit-learn метод predict для бинарной классификации использует фиксированное отсечение по умолчанию: положительный класс ставится при вероятности выше 0,5, а для decision_function — при скоре выше 0. Это удобно как стартовая точка, но документация прямо разделяет статистическую задачу предсказания вероятности и прикладную задачу действия по этой вероятности. Из этого и следует главный вывод статьи: порог выбирают под последствия ошибок, а не по привычке.

Еще один важный момент: если вы подбираете порог на тех же данных, на которых обучали модель, легко получить слишком оптимистичную картину. Корректнее использовать валидационную выборку или кросс-валидацию. Иначе вы оптимизируете решение под уже увиденные примеры, а не под будущие.

Учебный пример: три порога на одной и той же модели

Учебный пример. Представим модель, которая оценивает, нужно ли отправить входящий тикет в срочную эскалацию. Положительный класс — эскалировать. Пропуск означает, что срочный тикет остался в обычной очереди. Ложная тревога означает, что обычный тикет зря ушел дежурной команде. Ниже условные данные по 12 тикетам: скор модели и фактический исход, где 1 — действительно нужен срочный разбор, 0 — не нужен.

ТикетСкор моделиФакт
10.921
20.811
30.760
40.681
50.610
60.561
70.490
80.441
90.370
100.291
110.180
120.120

Проверим три порога: 0,3, 0,5 и 0,7. Для простоты считаем, что объект относится к положительному классу, если скор >= порогу. Это условность примера, но она удобна для ручной проверки. Один и тот же набор скоринговых оценок даст нам три разных набора решений.

Если хотите воспроизвести расчет, вот минимальный код для среды Python 3.11 без дополнительных библиотек:

scores = [0.92, 0.81, 0.76, 0.68, 0.61, 0.56, 0.49, 0.44, 0.37, 0.29, 0.18, 0.12]
y_true = [1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0]

def calc(threshold):
    pred = [1 if s >= threshold else 0 for s in scores]
    tp = sum(p == 1 and y == 1 for p, y in zip(pred, y_true))
    fp = sum(p == 1 and y == 0 for p, y in zip(pred, y_true))
    fn = sum(p == 0 and y == 1 for p, y in zip(pred, y_true))
    tn = sum(p == 0 and y == 0 for p, y in zip(pred, y_true))
    precision = tp / (tp + fp) if (tp + fp) else 0
    recall = tp / (tp + fn) if (tp + fn) else 0
    accuracy = (tp + tn) / len(y_true)
    return threshold, tp, fp, fn, tn, round(precision, 3), round(recall, 3), round(accuracy, 3)

for t in [0.3, 0.5, 0.7]:
    print(calc(t))

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

Таблица ошибок: что происходит на порогах 0,3, 0,5 и 0,7

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

ПорогTPFPFNTNPrecisionRecallAccuracy
0.354120.5560.8330.583
0.542240.6670.6670.667
0.721450.6670.3330.583

Здесь хорошо видно, как движется баланс. Порог 0,3 почти не пропускает срочные случаи: FN = 1. Но за это приходится платить большим числом лишних срабатываний: FP = 4. Порог 0,7 делает систему осторожной: ложных тревог всего одна, зато срочных пропусков уже четыре. Порог 0,5 оказался серединой и дал лучшую accuracy на этой маленькой выборке, но это не делает его автоматически лучшим по смыслу задачи.

Отдельно полезно заметить, что precision у порогов 0,5 и 0,7 одинаковая — 0,667, а recall сильно отличается: 0,667 против 0,333. Значит, одна только precision не объясняет качество решения. Если команда смотрит только на одну метрику, она легко выберет порог, который «красиво смотрится» в отчете, но плохо подходит процессу.

Как выбрать порог по условиям задачи, а не по привычке

Теперь превратим таблицу ошибок в прикладное решение. Допустим, для вашей службы пропуск срочного тикета условно в 5 раз неприятнее ложной тревоги. Тогда можно посчитать простую учебную функцию потерь: потери = 5 × FN + 1 × FP. Получаем: для порога 0,3 потери равны 9, для 0,5 — 12, для 0,7 — 21. В такой постановке низкий порог выглядит разумнее, потому что он защищает от пропусков.

Но бывает и обратная картина. Если дежурная команда маленькая, а каждый лишний вызов очень дорог по времени, можно условно считать потери = 1 × FN + 3 × FP. Тогда получаем: 13 для порога 0,3, 8 для 0,5 и 7 для 0,7. На тех же самых предсказаниях уже выигрывает высокий порог. Модель не изменилась ни на шаг, изменились только последствия ошибок.

Из этого следует практический порядок действий. Сначала сформулируйте, что для вас хуже: пропуск или ложная тревога. Потом переведите это в метрику или хотя бы в простое правило сравнения ошибок. После этого смотрите на таблицу по нескольким порогам, а не на одну точку. Если данных достаточно, подбирайте порог на отдельной валидации или через кросс-валидацию, а не на обучающей выборке.

Если вы работаете в scikit-learn, полезно помнить и еще одну вещь: порог можно подбирать уже после обучения модели. Это удобно, когда сама модель неплохо ранжирует объекты, но прикладное решение требует другой точки отсечения. Тогда задача не в том, чтобы срочно менять алгоритм, а в том, чтобы честно сравнить последствия разных порогов.

Чек-лист проверки и что изучать дальше

Перед тем как закреплять порог, проверьте четыре пункта. Первый: на каких данных он выбран — не пересекаются ли они с обучением. Второй: какая метрика или функция потерь отражает задачу, а не просто удобна по умолчанию. Третий: как меняются FN и FP при соседних порогах, например 0,45, 0,50 и 0,55. Четвертый: что произойдет на краях, когда положительных предсказаний очень мало или слишком много.

Практический результат такого подхода прост: вместо совета «ставьте 0,5» вы получаете таблицу, по которой можно осознанно объяснить выбор. В нашем учебном примере 0,5 дало лучшую accuracy, 0,3 — меньше пропусков, 0,7 — меньше ложных тревог. Значит, правильный порог — это не магическое число, а оформленное решение о компромиссе.

Если хотите разобрать тему системно, во внутренней карточке каталога есть курс «Машинное обучение. Базовый уровень». По официальной странице школы и сохраненной программе подтверждены темы модуля по классификации: логистическая регрессия, вероятности и пороги решений, матрица ошибок, метрики accuracy, precision, recall, F1 и выбор порога.

Курсы

112752
0,0
0 отзывов
Машинное обучение. Базовый уровень
  • В любой момент
  • 40 часов
  • с преподавателем
  • удостоверение
1 690 ₽95 000 ₽
-98%
Перейти на сайт