сеньорчикОткрыть в Telegram
← вся теориятеория к собесу · Классический ML

Калибровка и выбор порога

Зачем это спрашивают

«Твой скор 0.9 - это вероятность 90 процентов?» - вопрос, который довольно чисто отделяет мидла от джуна. Большинство читает скор как вероятность и ошибается. Тема всплывает везде, где скор превращается в деньги: скоринг, риск, ожидаемая ценность, пороги.

Типовые формулировки: «что такое калиброванная модель?», «как проверишь калибровку?», «почему после калибровки AUC не изменился?».

// Держи в голове одну связку - ранжирование и калибровка это независимые свойства. На ней стоит вся тема, и почти каждый вопрос ею закрывается.

Что значит «модель откалибрована»

Проверка делается руками и без формул. Собери все объекты, которым модель дала скор около 0.7 - пусть их набралась тысяча. Посчитай, сколько из них на самом деле оказались позитивными. Если примерно 700 - в этой точке модель откалибрована: обещала 70 процентов, столько и вышло. Если 400 - она переуверена, обещает больше, чем случается.

Проделай это по всем корзинам скоров и нарисуй график «что обещали» против «что случилось» - это калибровочная кривая (reliability diagram). Идеал - диагональ. Кривая, провисающая под диагональю, означает системную переуверенность.

Числовые сводки той же картинки: Brier score - средний квадрат разницы между предсказанной вероятностью и фактом 0 или 1; log loss - то же самое, но с жёстким штрафом за уверенную ошибку; ECE (expected calibration error) - средний зазор между обещанным и случившимся по корзинам.

// «Позитивных 70 процентов» проверяется только на данных, где известен ответ. Поэтому калибровку смотрят на отложенной выборке, а в проде - на подтянувшихся метках.

Ранжирование и калибровка - разные вещи

Возьми готовую модель и возведи все её скоры в квадрат: 0.9 станет 0.81, 0.5 станет 0.25, 0.2 станет 0.04. Порядок объектов не изменился ни на одну позицию - значит AUC (area under the curve) остался ровно тем же, до последнего знака. А калибровка изменилась полностью: то, что обещало 50 процентов, теперь обещает 25.

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

// Проверить это на своей модели - пять минут: посчитай AUC до и после калибровки и посмотри на калибровочную кривую до и после. Первое совпадёт, второе изменится до неузнаваемости.

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

Кто врёт и чем чинят

Некалиброваны почти все сильные модели, и врут они в разные стороны. Градиентный бустинг и нейросети обычно переуверены: их гоняют разделять классы как можно резче, и скоры стягиваются к краям, к нулю и единице. Случайный лес врёт наоборот - он усредняет голоса деревьев, а среднее редко бывает крайним, поэтому его скоры жмутся к середине. SVM (support vector machine) выдаёт расстояние до разделяющей границы, которое вообще не вероятность. Логистическая регрессия чаще всего калибрована из коробки: её и обучают на log loss, который штрафует именно за неверную вероятность.

Чинят поверх готовой модели, не трогая её саму. Platt scaling - логистическая регрессия, у которой единственный вход это скор модели: всего два параметра, поэтому она устойчива на малых данных, но и форму кривой поправить может только плавно. Isotonic regression подгоняет произвольную неубывающую ступенчатую функцию: гибче, вытянет любую кривую, зато на паре сотен примеров радостно переобучится на шум.

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

log loss
штраф за уверенную ошибку: сказать «0.99» и промахнуться дороже, чем сказать «0.6» и промахнуться

Порог считают, а не назначают

Порог - это граница, за которой скор превращается в действие: заблокировать транзакцию, позвонить клиенту, отправить письмо в спам. Дефолтные 0.5 не выбирал никто, они просто стоят в библиотеке.

Взрослый способ: назови цену. Ложная тревога стоит 50 рублей работы оператора, пропуск стоит 5000 рублей списанных денег. Прогони все пороги от 0 до 1, на каждом посчитай 50·FP (false positive) + 5000·FN (false negative) по валидации, возьми минимум. Порог оказался посчитанным из бизнеса, а не назначенным из воздуха, и его можно защитить перед продактом.

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

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

базовая ставка
доля позитивов в реальном потоке данных. Прореживание негативов её меняет, и модель об этом не знает

Как отвечать: «Скор модели 0.9 - можно читать как вероятность 90 процентов?»

Только если модель откалибрована, а по умолчанию это не так: бустинги и сети обычно переуверены. Проверяю калибровочной кривой - беру объекты со скором около 0.9 и смотрю, правда ли позитивных среди них около 90 процентов. Если нет, калибрую поверх модели на отложенной выборке: Platt при малых данных, isotonic когда данных хватает. Отдельно держу в голове даунсэмплинг - после него вероятности смещены и нужна поправка на базовую ставку. И сразу оговорюсь, что AUC от калибровки не изменится: это монотонное преобразование, ранжирование и калибровка - независимые свойства.

Диагностика, починка и два классических нюанса. Последняя фраза снимает встречный вопрос про неизменившийся AUC до того, как его успели задать.

На чём валят

  • Читать скор бустинга как вероятность без проверки - «0.9» там может означать что угодно.
  • «AUC не изменился после калибровки, значит она бесполезна» - AUC и не должен был меняться.
  • Ставить isotonic на сотне примеров: ступени переобучатся на шум, там нужен Platt.
  • Калибровать на трейне модели и получить ту же переуверенность, только оформленную аккуратнее.
  • Забыть поправку после обучения с прореженными негативами.
  • Оставить порог 0.5, когда цены ошибок отличаются в сто раз.

Проверьте себя

Пять вопросов из банка по этой подтеме. Всего их 8, остальные разбираются в тренажёре.

  1. #calibration_thresholds1 / 5
    Что показывает precision-recall кривая при переборе порога?
    A)Зависимость точности модели от числа пройденных обучающих эпох на кривой обучения
    B)Как по порогу размениваются precision и recall: ниже порог — выше recall, ниже precision
    C)Долю верных вероятностей по бинам
    D)Скорость обучения при разных learning rate
    показать ответ и разбор
    +B)Как по порогу размениваются precision и recall: ниже порог — выше recall, ниже precision

    // разбор: PR-кривая рисует пары (recall, precision) по всем порогам. Снижая порог, мы объявляем позитивами больше примеров — recall растёт, но precision обычно падает (больше ложных срабатываний). Кривая наглядно показывает достижимые компромиссы и рабочую точку под требование бизнеса; площадь под ней (PR-AUC) особенно информативна на дисбалансе, где ROC оптимистичен.

  2. #calibration_thresholds2 / 5
    Цена ложного пропуска и ложной тревоги сильно различаются. Как это встроить в выбор порога?
    A)Игнорировать цены ошибок и просто максимизировать общую accuracy по всем классам сразу
    B)Взять порог, дающий поровну FP и FN
    C)Минимизировать ожидаемую стоимость: порог взвешивает FP и FN их ценами
    D)Оставить 0.5 и компенсировать ценами уже после классификации
    показать ответ и разбор
    +C)Минимизировать ожидаемую стоимость: порог взвешивает FP и FN их ценами

    // разбор: Оптимальный порог зависит от матрицы стоимостей. Если пропуск (FN) дороже ложной тревоги (FP), выгодно понизить порог: ловим больше позитивов ценой лишних FP, потому что каждый пропуск дорог. Формально минимизируют ожидаемую стоимость = стоимость_FP·FP + стоимость_FN·FN по валидации; при калиброванных вероятностях оптимальный порог выражается через отношение цен. Accuracy и «поровну FP/FN» цены не учитывают.

  3. #calibration_thresholds3 / 5
    Почему высокая точность классификации не гарантирует, что модель даёт хорошие вероятности?
    A)Разделение классов и достоверность вероятностей — разные свойства модели
    B)Точность и калибровка — это одно и то же
    C)Высокая точность классификации автоматически делает вероятности модели калиброванными
    D)Вероятности вообще не связаны с качеством модели
    показать ответ и разбор
    +A)Разделение классов и достоверность вероятностей — разные свойства модели

    // разбор: Классификатор может отлично разделять классы (высокая accuracy/AUC) и при этом выдавать вероятности, не соответствующие частотам: например, всем позитивам ставить 0.99, а негативам 0.5 — порог сработает, но p не отражает риск. Многие модели (SVM, бустинги, нейросети с определёнными лоссами) склонны к пере-/недоуверенности. Если решения принимаются по величине вероятности (ожидаемая стоимость, ставки), нужна отдельная калибровка.

  4. #calibration_thresholds4 / 5
    Бинарный классификатор выдал для клиента 0.83. Что это за число и как получить из него ответ «да/нет»?
    A)Доля признаков за позитивный класс; ответ даёт их голосование
    B)Точность модели на этом объекте; сравнить с точностью на трейне
    C)Оценка вероятности позитива; сравнить с выбранным порогом
    D)Расстояние до разделяющей границы; взять его знак
    показать ответ и разбор
    +C)Оценка вероятности позитива; сравнить с выбранным порогом

    // разбор: Модель отдаёт скор — оценку вероятности того, что объект относится к позитивному классу. Метка появляется, когда скор сравнивают с порогом: по умолчанию 0.5, но это соглашение, а не закон. Порог выбирают под цену ошибок: дорог пропуск — опускаем, дорога ложная тревога — поднимаем.

  5. #calibration_thresholds5 / 5
    Порог выбрали на валидации, где позитивов 30%. В проде позитивов 3%. Что с порогом?
    A)Ничего: порог — свойство модели, а не данных
    B)Он останется корректным: доля позитивов на скоры модели не влияет
    C)Он поплывёт: при редком позитиве precision на нём рухнет
    D)Его надо умножить на отношение долей позитивов
    показать ответ и разбор
    +C)Он поплывёт: при редком позитиве precision на нём рухнет

    // разбор: Порог — точка на кривой компромисса, а положение самой кривой зависит от базовой доли позитивов. Скоры, откалиброванные на 30% позитивов, в проде с 3% систематически завышены: та же уверенность даёт куда меньше настоящих срабатываний на каждое ложное, и precision падает. Порог перевыбирают на выборке с боевой пропорцией, а вероятности перекалибровывают под новый prior.

дальше

Теорию прочитали. Навык ставится повторением

В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, лимит только на количество вопросов в день.