Порог классификации: минимизация стоимости ошибок

Ложная тревога и пропуск события могут стоить по-разному. Переберите пороги, посчитайте FP и FN и выберите решение с наименьшей стоимостью ошибок. Для реального подбора используют валидацию, а финальный тест оставляют для оценки.

Программа курса «Классическое машинное обучение: алгоритмы и практика на Python».

Оптимизация порога бинарной классификации по матрице потерь

Что уже дано

Проверяющая система выполняет решение в среде Python 3.12 с доступной библиотекой numpy. Никаких вспомогательных глобальных переменных, файлов или предопределённых датасетов перед запуском не создаётся. Проверяющие тесты напрямую импортируют и вызывают функцию optimize_decision_threshold.

Что нужно сделать

Реализуйте функцию optimize_decision_threshold(y_true, probas, thresholds, cost_fp, cost_fn).

Функция принимает:

  • y_true: одномерный массив или последовательность бинарных истинных меток (значения 0 или 1) длины ;
  • probas: одномерный массив или последовательность вероятностей положительного класса из диапазона той же длины ;
  • thresholds: непустой список или массив вещественных чисел — кандидатов на порог классификации, каждый ;
  • cost_fp: неотрицательное число (int или float) — стоимость одной ошибки ложной тревоги (False Positive);
  • cost_fn: неотрицательное число (int или float) — стоимость одной ошибки пропуска целевого события (False Negative).

Правила принятия решения и оценки стоимости:

  1. Для каждого порога объект относится к классу 1, если , и к классу 0, если . При точном равенстве решение строго относится к классу 1.
  2. Правильные ответы (TP и TN) оцениваются в 0 потерь. Суммарная стоимость ошибок для порога вычисляется по формуле:
  3. Порог считается лучшим, если он минимизирует величину . Если несколько кандидатов дают строго одинаковую минимальную стоимость, ничья разрешается в пользу большего значения порога (более консервативное принятие решения).

Функция должна вернуть словарь dict с двумя ключами:

  • "best_threshold": выбранный лучший порог (число типа float);
  • "threshold_reports": список словарей для каждого кандидата из thresholds в исходном порядке. Каждый словарь содержит ровно 4 ключа: "threshold" (float), "fp" (int), "fn" (int), "cost" (float или int).

Ввод и вывод

stdin не используется. Печатать через print в stdout ничего не нужно.

Проверяющая система вызывает функцию optimize_decision_threshold(y_true, probas, thresholds, cost_fp, cost_fn) с аргументами в виде списков или массивов NumPy и проверяет возвращённый словарь.

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

y_val = [0, 0, 1, 1]
p_val = [0.1, 0.4, 0.35, 0.8]
candidates = [0.1, 0.35, 0.5]
result = optimize_decision_threshold(y_val, p_val, candidates, cost_fp=2, cost_fn=10)
print(result["best_threshold"])
print(result["threshold_reports"])

Результат:

0.35
[{'threshold': 0.1, 'fp': 2, 'fn': 0, 'cost': 4}, {'threshold': 0.35, 'fp': 1, 'fn': 0, 'cost': 2}, {'threshold': 0.5, 'fp': 0, 'fn': 1, 'cost': 10}]
РешениеPython

Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.

Отправьте решение, чтобы увидеть результаты тестов.

Связанные задачи