Sobes.tech
Назад к вопросам
Middle
12

Какие есть методы выбора threshold по ROC кривой?

Компании, где спрашивали
ГазпромбанкГазпромбанк

Ответ от нейросети

sobes.tech AI

Что хотят услышать интервьюеры:

Нужно показать, что threshold на ROC-кривой выбирают не «по максимуму accuracy», а исходя из бизнес-цели и баланса между false positive и false negative. Обычно смотрят на точки, которые дают лучший компромисс между TPR и FPR, либо минимизируют заданную функцию потерь. Важно уметь назвать несколько практических критериев и объяснить, когда каждый из них уместен.

Определение:

Threshold — это порог, по которому вероятностный выход модели переводится в класс 0/1. На ROC-кривой каждой точке соответствует конкретный threshold, а выбор порога означает выбор компромисса между чувствительностью (TPR) и долей ложных срабатываний (FPR).

Основные способы выбора threshold по ROC:

  • Максимум Youden’s J: выбрать точку с максимумом TPR - FPR.
  • Ближайшая к левому верхнему углу: минимизировать расстояние до точки (0, 1).
  • По заданному ограничению: выбрать порог, который обеспечивает нужный FPR, TPR, recall или precision.
  • По стоимости ошибок: минимизировать ожидаемые потери, если false positive и false negative стоят по-разному.
  • По business-kpi: выбрать threshold так, чтобы выполнялось требование продукта, например не более 1% ложных срабатываний.

Пример использования:

Допустим, модель определяет мошеннические транзакции. Ложный пропуск мошенничества дорого стоит, но слишком много ложных блокировок тоже плохо. Поэтому threshold выбирают не по точности, а по ROC-кривой: например, берут порог, который дает высокий TPR при допустимом FPR.

from sklearn.metrics import roc_curve
import numpy as np

y_true = [0, 0, 1, 1, 0, 1, 0, 1]
y_score = [0.1, 0.4, 0.35, 0.8, 0.2, 0.7, 0.05, 0.9]

fpr, tpr, thresholds = roc_curve(y_true, y_score)

# 1) Youden's J
j = tpr - fpr
best_idx_j = np.argmax(j)
best_threshold_j = thresholds[best_idx_j]

# 2) Ближайшая к (0,1)
dist = np.sqrt(fpr**2 + (1 - tpr)**2)
best_idx_dist = np.argmin(dist)
best_threshold_dist = thresholds[best_idx_dist]

print(best_threshold_j, best_threshold_dist)

Пояснение кода:

Код строит ROC-кривую по истинным меткам и скору модели. Затем:

  • roc_curve возвращает массивы fpr, tpr и thresholds.
  • Для метода Youden считается разность tpr - fpr, и выбирается максимальное значение.
  • Для метода ближайшей точки к левому верхнему углу считается евклидово расстояние до (0, 1), и выбирается минимум.

На практике после выбора порога его дополнительно проверяют на отложенной выборке, чтобы не переобучиться на метрику выбора threshold.

Ключевые моменты:

  • Threshold выбирают не «вообще лучший», а под конкретную цель и стоимость ошибок.
  • Популярный критерий — Youden’s J = TPR - FPR.
  • Часто используют минимум расстояния до точки (0,1) на ROC.
  • В реальных задачах важнее ограничение по FPR/TPR или стоимость ошибок, чем абстрактный максимум ROC.
  • Threshold нужно подбирать на валидации, а не на тесте.
  • Если классы сильно несбалансированы, ROC полезна, но threshold часто лучше оценивать вместе с precision-recall метриками.