Собесов

Хабр ML — Precision vs Recall: что выбрать в задаче антифрода

ML / Data ScienceМетрикиСредняяMiddle

Условие

Модель определяет, является ли транзакция мошеннической. Аналитик может настраивать порог threshold. Какую метрику оптимизировать: precision, recall, F1? Обоснуйте на бизнес-аргументах.

Решение

Определения через confusion matrix

Pred = 1 Pred = 0
True = 1 TP FN
True = 0 FP TN
  • Precision = TP / (TP + FP) — «среди тех, кого назвали fraud, какая доля реально fraud». Цена FP высока.
  • Recall = TP / (TP + FN) — «какую долю реальных fraud мы поймали». Цена FN высока.
  • F1 = 2 · P · R / (P + R) — гармоническое среднее. Балансирует, штрафует за дисбаланс.
  • F-beta = (1 + β²) · P · R / (β² · P + R). β > 1 — приоритет recall; β < 1 — приоритет precision.

Антифрод-кейс

В классическом антифроде структура такая:

  • FN (пропустили fraud) — банк теряет деньги (от тысяч до миллионов рублей).
  • FP (ложно заблокировали хорошую транзакцию) — расстроенный клиент, support-call, репутационные потери, иногда отток.

В бизнес-логике: 1 FN стоит, скажем, ₽5000 в среднем; 1 FP — ₽500 (стоимость call + risk оттока). Тогда:

Cost = 5000 · FN + 500 · FP

Это expected cost — её и нужно минимизировать. Это часто не F1, не «balanced» порог, а специфический threshold под бизнес.

Как выбирать порог

import numpy as np
 
scores  = model.predict_proba(X_val)[:, 1]
y_true  = y_val.values
 
thresholds = np.linspace(0.01, 0.99, 99)
costs = []
for t in thresholds:
    pred = scores > t
    tp = ((pred == 1) & (y_true == 1)).sum()
    fp = ((pred == 1) & (y_true == 0)).sum()
    fn = ((pred == 0) & (y_true == 1)).sum()
    cost = 5000 * fn + 500 * fp
    costs.append(cost)
 
best_t = thresholds[np.argmin(costs)]

Не только threshold

  1. Каскад моделей. «Очень уверенно fraud → блок; средне уверенно → ручная проверка; иначе → пропускаем».
  2. Сегментация. Разные пороги для разных сумм/каналов/новых клиентов.
  3. Тестирование операционных метрик. «Сколько call-center’ов выдерживает текущий FP-объём?»

Когда F1 уместен

  • Когда относительная цена FP и FN сопоставима (обычно никогда в реальном бизнесе);
  • Для отчётности в академических работах;
  • В fast-iteration: F1 — простой single-number summary.

В реальном антифроде чаще оптимизируют Recall at fixed Precision (например, «при precision ≥ 80% максимизировать recall») или непосредственно expected cost.

Подводные камни

  1. Оптимизировать accuracy в задаче с 0.1% fraud — модель «всё нормально» даёт 99.9% accuracy и нулевую пользу.
  2. F1 не учитывает реальные стоимости ошибок. Используйте F-beta или expected cost.
  3. Threshold выбирается на test set, отчётность — на нём же. Это утечка. Делите данные: train / val (для threshold) / test (для окончательной отчётности).
  4. Calibration важна. Threshold = 0.5 на некалиброванной модели бессмыслен.
  5. Drift операционной среды. Доля мошенников и поведение non-fraud меняются — пороги нужно переоценивать.

Эталонный ответ

В антифроде оптимизируйте expected cost (5000·FN + 500·FP в примере), а не F1. F1 уместен, когда FP и FN equally costly — это редкий случай в проде. Практически: ищите argmin_t Cost(t) на валидационной выборке, фиксируйте threshold, валидируйте на test.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти