Число, яке ще треба прочитати

Класифікатор ніколи не каже «шахрай». Він називає число — а перетворює його на вирок хтось інший. Найчастіше цим «кимось» виявляється рядок бібліотеки, написаний людиною, яка про твою задачу нічого не знала.

Та сама дошка оголошень про вживані телефони. Дешевий фільтр відбирає підозрілі оголошення й складає їх у чергу ручної перевірки — приблизно третина з них справді виявляється приманкою. Наша модель має розібрати цю чергу замість людини. Вона навчена, метрики поміряні, звіт красивий. Лишилось одне питання, на яке досі ніхто не відповів: що саме модель робить із конкретним оголошенням?

У темі про precision і recall ми вже казали: модель видає оцінку, а рішення ухвалює поріг. Тут ми доводимо цю думку до кінця. Спершу навчимось рахувати поріг замість того, щоб його вгадувати. Потім виявимо, що для цього розрахунку потрібне ще й число, яке не бреше, — і розберемось, як перевірити, чи воно не бреше, і що робити, коли бреше.

Мовчазне рішенняПоловина, взята зі стелі

Ось два рядки, які пише кожен, хто вперше навчив класифікатор:

predictions = model.predict(X_test)

Виглядає так, ніби модель повертає готові вироки: 0 або 1, чесний або шахрай. Насправді всередині цього виклику відбувається дві дії, і друга — не математика, а адміністративне рішення. Перевіримо це прямо: попросимо в моделі окремо числа й окремо вироки й порівняємо їх.

proba = model.predict_proba(X_test)[:, 1]
(proba >= 0.5) == model.predict(X_test)  →  True для всіх 2100 оголошень

Розбіжностей — рівно нуль. Тобто predict() — це не окремий розумний механізм, а predict_proba() плюс порівняння з числом 0.5. Модель нічого не вирішувала; вона назвала число, а половинку до нього приклала бібліотека.

І це не особливість саме нашої моделі. predict() у scikit-learn влаштований однаково для всіх класифікаторів: він бере той клас, у якого передбачена ймовірність найбільша. Для двох класів «найбільша з двох» — це те саме, що «більша за половину», просто записане інакше. Ніякого окремого порога для кожного обʼєкта, ніякого порівняння відстаней до центрів класів, ніякого голосування схожих сусідів усередині predict() немає: усе це — різні алгоритми, і кожен із них однаково закінчує тим самим порівнянням із 0.5.

Звідки взялась ця половина? З нічого. Точніше — з припущення, яке до нашої задачі не має жодного стосунку: помилитись в один бік так само погано, як помилитись в інший. На дошці оголошень це припущення просто хибне. Заблокувати чесного продавця — прикро. Пропустити шахрая — це гроші покупця, скарга, повернення коштів і поганий відгук про майданчик. Дві помилки різні, а поріг 0.5 вважає їх однаковими.

Де саме ховається рішення

Вісім оголошень із черги перевірки. Угорі — те, що модель справді порахувала. Унизу — те, що бібліотека з цього зробила.

Придивись до двох сусідів посередині. Оголошення з оцінкою 0.47 і 0.52 для моделі майже однакові — між ними пʼять сотих. Але вертикальна риска проходить між ними, і одне з них отримує блокування, а друге — ні. Уся різниця в долі цих двох оголошень створена не моделлю, а положенням риски.

Найнеприємніше в цій ситуації — не те, що 0.5 погане число. Іноді воно цілком годиться. Неприємне те, що воно обране мовчки: у коді немає рядка, який його призначає, тож немає й місця, де хтось міг би над ним замислитись. Перший крок теми — витягти це рішення на світло й ухвалити його свідомо.

Термінологія. Число на виході моделі ми називатимемо оцінкою або передбаченою ймовірністю — залежно від того, чи маємо право читати його буквально. Різниця між цими двома словами і є головною темою другої половини лекції. Поріг (threshold) — число, з яким оцінку порівнюють, щоб отримати рішення.

АрифметикаПоріг із ціни двох помилок

Якщо поріг не даний природою, звідки його брати? Відповідь на диво проста: із грошей. Не з інтуїції, не з традиції, а з двох чисел, які будь-який власник продукту назве за пʼять хвилин.

Порахуймо для нашої дошки. Заблокувати чесне оголошення (хибна тривога, FP) коштує майданчику приблизно 200 грн: втрачена комісія з угоди, робота підтримки, роздратований продавець. Пропустити шахрайське (пропуск, FN) коштує близько 1800 грн: повернення грошей покупцеві, розгляд скарги, репутаційна шкода. Точність цих оцінок не критична — важливе їхнє відношення, приблизно один до девʼяти.

Тепер найголовніше місце теми. Візьмемо одне оголошення, якому модель дала оцінку p, і чесно порахуємо, що вигідніше з ним зробити.

Крок 1 · що означає p

Припустімо, що число p можна читати буквально: це ймовірність того, що оголошення шахрайське. Тоді з ймовірністю p воно шахрайське і з ймовірністю 1 − p — чесне.

Крок 2 · скільки коштує заблокувати

Якщо ми блокуємо, ми помиляємось лише тоді, коли оголошення насправді чесне. Це трапляється з ймовірністю 1 − p, і коштує CFP. Середня втрата від рішення «блокувати»:

втрата(блокувати) = CFP · (1 − p)
Крок 3 · скільки коштує пропустити

Якщо пропускаємо, помиляємось тоді, коли воно шахрайське — з ймовірністю p, ціна CFN:

втрата(пропустити) = CFN · p
Крок 4 · порівнюємо

Блокувати варто тоді, коли це дешевше: CFP · (1 − p) < CFN · p. Розкриваємо дужки й переносимо все з p в один бік:

CFP < p · (CFN + CFP)   ⟹   p > CFP / (CFP + CFN)
Крок 5 · це і є поріг

Права частина не залежить від конкретного оголошення — тільки від двох цін. Отже, оптимальний поріг:

t* = CFP / (CFP + CFN) = 200 / (200 + 1800) = 0.10

Перевіримо руками на двох оголошеннях, щоб формула не лишалась значками.

Оголошення з оцінкою 0.15. Блокувати: 200 × 0.85 = 170 грн середніх втрат. Пропустити: 1800 × 0.15 = 270 грн. Блокувати дешевше — і справді, 0.15 більше за поріг 0.10.

Оголошення з оцінкою 0.05. Блокувати: 200 × 0.95 = 190 грн. Пропустити: 1800 × 0.05 = 90 грн. Тепер дешевше пропустити — і 0.05 справді менше за 0.10.

Зверни увагу, наскільки поріг 0.10 далекий від звичних 0.5. За замовчуванням система блокує оголошення, лише коли більш ніж наполовину впевнена у шахрайстві. Але при такому співвідношенні цін вигідно блокувати вже при одному шансі з десяти — бо девʼять зайвих блокувань дешевші за один пропуск.

Поріг і його ціна

1200 оголошень із перевірочної вибірки. Ліворуч — крива сумарних втрат від порогу, праворуч унизу — чотири клітинки матриці плутанини для поточного порогу.

втрати зараз—
мінімум можливий—
оптимум на даних—
формула дає—
Головне — рухай другий повзунок. Модель не змінюється взагалі: ті самі 1200 оцінок, та сама AUC. Змінюється лише ціна помилки — і разом із нею їде оптимальний поріг. При співвідношенні 1:1 мінімум стоїть біля 0.47, при 9:1 — біля 0.09, при 20:1 зʼїжджає до самого краю. Ціна помилки — це не деталь налаштування, це те, що взагалі визначає поріг. Рожевий хрестик — поріг за формулою, сірий — фактичний мінімум кривої.

Числа при відношенні 9:1 варто прочитати уважно. Поріг 0.5 дає 87 хибних тривог і 144 пропуски — це 276 600 грн втрат на 1200 оголошень. Поріг 0.088 дає 488 хибних тривог, але лише 18 пропусків — 130 000 грн. Та сама модель, той самий день, різниця в 146 600 грн — більш ніж удвічі — створена одним числом у конфігурації.

І формула не підвела: вона порадила 0.10, фактичний мінімум кривої стоїть на 0.088, а втрати в цих двох точках — 131 800 і 130 000 грн, різниця 1.4%. Це важливо саме тому, що формулу можна порахувати до того, як побачив дані.

Уся ця арифметика трималась на кроці 1. Ми припустили, що p можна читати буквально — що 0.15 означає «пʼятнадцять відсотків». Якщо це не так, кожен рядок виведення лишається правильним, а результат стає безглуздим: ми порівнюємо ціни, помножені на числа, які не є ймовірностями. Саме тому друга половина лекції — про перевірку цього припущення.

ПрактикаТри правила — три пороги

Ціни двох помилок відомі не завжди. Буває, що бізнес не готовий назвати вартість репутаційної шкоди, зате готовий назвати обмеження: «команда перевіряє щонайбільше сорок оголошень на день» або «ми маємо ловити девʼять шахраїв із десяти». Це теж повноцінні критерії, і кожен дає свій поріг.

Спосіб 1 — під задану повноту. Вимога звучить як «recall не нижче 0.90». Береш PR-криву з теми про ROC і PR, ідеш по ній до потрібного recall і читаєш поріг. У нас це t = 0.184: повнота рівно 0.900, але precision падає до 0.529 — половина заблокованих виявиться чесними.

Спосіб 2 — під обмеження ресурсу. Вимога звучить як «не більше сорока хибних тривог на 1200 оголошень». Тут поріг шукають з іншого боку: береш найнижчий поріг, за якого FP ще вкладається в квоту. У нас це t = 0.653 — і повнота падає до 0.445. Половина шахраїв проходить, зате модератори не потонули.

Спосіб 3 — максимум F-міри. Коли жодної зовнішньої вимоги немає, беруть поріг, у якому F1 найбільша. У нас це t = 0.436, F1 = 0.716, precision і recall майже рівні. Це чесний варіант «за замовчуванням», але саме варіант за замовчуванням: F1 однаково зважує обидві помилки, тобто мовчки повертає нас до припущення, від якого ми щойно відмовились.

Одні дані, пʼять вимог, пʼять порогів

Та сама модель на тих самих 1200 оголошеннях. Змінюється лише питання, яке ми ставимо.

вимогапорігrecallprecisionхибних тривогвтрати, 9:1
нічого не обирали0.5000.6420.74887276 600 грн
повнота ≥ 0.900.1840.9000.529322136 400 грн
не більше 40 тривог0.6530.4450.81740409 400 грн
максимум F10.4360.7160.715115228 200 грн
мінімум втрат0.0880.9550.440488130 000 грн
Розкид від 0.088 до 0.653 — у сім разів. Жоден із цих порогів не «правильніший» за інші: вони відповідають на різні питання. Правильна послідовність зворотна до звичної — спершу формулюєш вимогу словами, і лише потім дивишся, який поріг із неї випливає. Остання колонка показує ціну плутанини: якщо насправді твоя вимога економічна, то поріг під квоту модераторів коштує втричі дорожче за оптимум.

Останній рядок таблиці варто прочитати ще раз. Якби ми обирали поріг «за квотою модераторів», не спитавши про гроші, ми втратили б 409 400 грн замість 130 000. Обмеження на ресурс — законна вимога, але вона має бути усвідомленою, а не успадкованою від того, що модераторів найняли раніше, ніж поставили модель.

Поріг обирають на валідації, не на тесті. Це рівно те саме підглядання, про яке йшлось у темах перенавчання й підбору гіперпараметрів: щойно ти обрав по тестовій вибірці бодай одне число, вона перестала бути незалежною, і чесно назвати якість системи вже нема чим. Поріг — такий самий гіперпараметр, як C чи k, і місце йому в тому самому місці конвеєра.

Дві різні речіПорядок проти значення

Повернімось до кроку 1 виведення. Ми припустили, що оцінку моделі можна читати буквально. Перевірити це припущення важливіше, ніж здається, — і жодна з метрик попередніх тем цього не робить.

Візьмемо нашу модель і зробимо з її оцінками одну просту річ: стиснемо їх до середини. Кожне число замінимо на 0.5 + 0.42 · (p − 0.5). Оцінка 0.9 стане 0.668, оцінка 0.1 стане 0.332, оцінка 0.5 лишиться 0.5. Ніякої глибокої ідеї тут немає — це просто арифметика, яку ми робимо навмисно, щоб зіпсувати числа й подивитись, хто це помітить.

Результат: AUC не змінилась узагалі. Була 0.8600, стала 0.8600 — не в четвертому знаку, а взагалі, до останнього біта. Точність, precision, recall при відповідно зсунутому порозі — теж ті самі. А от Brier score, до якого ми дійдемо за хвилину, погіршився з 0.1378 до 0.1757.

AUC бачить порядок, калібрування бачить значення

Ті самі вісім оголошень. Угорі — чесні оцінки, унизу — вони ж, стиснуті до середини. Лінії ніде не перетинаються.

Ось чому так. AUC — це ймовірність того, що випадковий шахрай отримає вищу оцінку за випадкового чесного продавця. У цьому означенні є слово «вищу» і немає слова «наскільки». Будь-яке перетворення, що зберігає порядок, лишає AUC незмінною — можна стискати, розтягувати, підносити до квадрата чи брати корінь. Такі перетворення називають монотонними (monotone): що більше число на вході, то більше на виході, і жодного винятку. Далі в лекції це слово трапиться ще двічі — воно означає рівно це. Те саме стосується ROC, PR-кривої й усіх метрик, що рахуються після фіксації порога.

Звідси означення, яке варто запамʼятати дослівно. Модель калібрована (calibrated), якщо її числа можна читати буквально: серед оголошень, яким вона дала 0.7, приблизно 70% справді виявляються шахрайськими. Серед тих, кому дала 0.1, — приблизно 10%. І так у кожній точці шкали.

Калібрування й здатність розрізняти — це дві незалежні властивості, і плутати їх дорого. Модель може ідеально впорядковувати оголошення й при цьому називати безглузді числа: наш приклад зі стисканням саме такий. І навпаки — модель, яка всім підряд видає 0.33 (частку шахраїв у черзі), ідеально калібрована й абсолютно даремна: її AUC дорівнює 0.5.

Для тих, хто читав тему про ROC. Там ми казали, що AUC не бачить калібрування, одним реченням. Тепер видно, чому це не причіпка: увесь розрахунок порога з розділу 2 спирається на буквальне читання p. Модель із чудовою AUC і брехливими числами дасть тобі правильний рейтинг підозрілості й неправильний поріг — а рішення ухвалюється саме порогом.

ВимірюванняДіаграма надійності, Brier і ECE

Як перевірити калібрування на практиці? Означення каже: «серед оголошень з оцінкою 0.7 має бути 70% шахрайських». Проблема в тому, що оголошень із оцінкою рівно 0.7 у нас жодного — усі числа різні до восьмого знака. Розвʼязок простий і механічний: групуємо близькі оцінки в кошики (bins) і працюємо з кошиком як з однією точкою.

Порахуймо руками. Ріжемо відрізок від 0 до 1 на пʼять кошиків завширшки 0.2 і розкладаємо туди наші 1200 перевірочних оголошень. У кожному кошику рахуємо дві речі: середню оцінку, яку дала модель, і фактичну частку шахрайських.

кошикоголошеньсередня оцінкашахрайських насправдірозрив
0.0 – 0.25460.07948 / 546 = 0.0880.009
0.2 – 0.42200.28858 / 220 = 0.2640.024
0.4 – 0.61600.49579 / 160 = 0.4940.001
0.6 – 0.81600.688114 / 160 = 0.7130.025
0.8 – 1.01140.891103 / 114 = 0.9040.013

Читаємо третій рядок як приклад: модель сказала про 160 оголошень «десь половина з вас шахрайські», і серед них справді виявилось 79 шахрайських із 160 — це 0.494 проти обіцяних 0.495. Модель не вгадала кожне окреме оголошення, і не мусила: калібрування — це твердження про групу, а не про обʼєкт.

Якщо нанести пʼять пар «середня оцінка → фактична частка» на графік, вийде діаграма надійності (reliability diagram, вона ж калібрувальна крива). Ідеально калібрована модель лягає на діагональ: скільки пообіцяла, стільки й сталося. Точка нижче діагоналі означає надмірну впевненість (обіцяла більше, ніж сталося), вище — надмірну обережність.

Дві числові згортки цієї картинки нам знадобляться далі.

ECE (expected calibration error, очікувана похибка калібрування) — це середній розрив між обіцяним і фактичним, зважений за розміром кошика. Для таблиці вище: (546·0.009 + 220·0.024 + 160·0.001 + 160·0.025 + 114·0.013) / 1200 = 0.013. Читається буквально: у середньому модель помиляється у своїх обіцянках на 1.3 відсоткового пункту.

Brier score — середній квадрат різниці між оцінкою та фактом (0 або 1):

Brier = (1/n) · Σ (pi − yi)2

Значок Σ (грецька «сигма») означає «додай усе, що йде далі, по всіх обʼєктах»; n — кількість обʼєктів, p — оцінка моделі, y — факт: 1 для шахрайського оголошення й 0 для чесного. Що менше, то краще. Корисний орієнтир: модель, яка всім підряд називає частку шахраїв 0.335, дає Brier 0.2228 — усе, що гірше за це число, гірше за повну відмову від класифікації.

Чим ці два числа різняться. ECE міряє тільки калібрування й закриває очі на здатність розрізняти: модель-константа має ECE близький до нуля. Brier міряє обидві властивості одразу — його можна розкласти на доданок «наскільки добре розрізняє» й доданок «наскільки чесно називає числа». Тому Brier беруть як єдину оцінку якості ймовірностей, а ECE — коли хочуть подивитись саме на калібрування. Ціна ECE в тому, що він залежить від кількості кошиків: ті самі оцінки на пʼяти кошиках дають 0.013, а на десяти — 0.020, бо дрібніші кошики ловлять дрібніші розриви.

Діаграма надійності двох моделей

Десять кошиків, 1200 перевірочних оголошень. Розмір кружечка — скільки оголошень у кошику. Перемикач міняє модель.

AUC—
Brier—
ECE, 10 кошиків—
найбільший розрив—
Перемикай і дивись на перший рядок табло. AUC у обох моделей однакова до останнього знака — 0.860, бо модель B це модель A, стиснута до середини, а стискання не міняє порядку. Усе інше різне: точки моделі B не просто відхиляються від діагоналі, вони живуть у смузі від 0.29 до 0.71 і взагалі не заходять у крайні кошики. Модель B ніколи не скаже «це майже напевно шахрай», хоч і вміє їх упорядковувати не гірше за A.

ВинніХто бреше і як саме

Модель B ми зіпсували руками. Але справжні алгоритми псують свої ймовірності самі, і в кожного сімейства свій характерний почерк. Навчімо на нашій дошці чотири моделі й подивимось на їхні діаграми надійності поруч.

Чотири моделі, одні дані

6000 оголошень, з них 2100 перевірочних. Криві побудовані на десяти кошиках однакової ширини; порожні кошики просто не дають точки.

модельAUCBrierECEпочерк
логістична регресія0.8070.16570.027лягає на діагональ майже з коробки
випадковий ліс0.7850.17650.039трохи тягне до середини: обіцяв 0.95 — сталось 0.91
AdaBoost0.8130.20120.173усі оцінки затиснуті в 0.20–0.71, крива майже вертикальна
наївний Баєс0.7900.20420.151надто впевнений: обіцяв 0.94 — сталось 0.76
Перша колонка не корелює з третьою. AdaBoost має найкращу AUC із чотирьох — і найгірший ECE, ушестеро гірший за логістичну регресію. Як сортувальник він найкращий, як вимірювач — найгірший. Це і є те розділення, заради якого написано попередній розділ.

Механізми в кожного свої, і вони не випадкові.

Логістична регресія калібрована майже завжди, і це не везіння. Її навчають мінімізацією логістичних втрат, а ця функція влаштована так, що мінімум досягається саме на правдивих ймовірностях. Модель буквально оптимізує те, що ми потім міряємо. Умова одна: модель має бути достатньо гнучкою для задачі — сильно недонавчена лінійна модель на нелінійних даних теж поїде.

Випадковий ліс тягне до середини через усереднення. Щоб ліс видав рівно 1.0, усі 200 дерев мають одностайно проголосувати «шахрай»; досить одного незгодного — і крайнє значення втрачено. Тому оцінки лісу неохоче доходять до країв. Ефект тим сильніший, чим більше дерев і чим вони різноманітніші; на наших даних він помітний, але скромний.

AdaBoost — найяскравіший випадок. Він взагалі не оптимізує ймовірності: його мета — розсунути класи за межею, і число, яке він видає за ймовірність, є переробкою зваженої суми голосів слабких моделей. Результат видно в таблиці: усі 2100 оцінок влізли між 0.20 і 0.71, а 95% з них — між 0.3 і 0.7. Порядок при цьому чудовий — тому AUC найвища. Те саме роблять методи опорних векторів (SVM): їхня відстань до розділювальної межі не є й ніколи не була ймовірністю.

Наївний Баєс псує ймовірності протилежним чином — він надто впевнений. Причина в припущенні незалежності ознак, на якому він побудований. У нашій дошці ціна в гривнях, відносна ціна й відсоток знижки — це фактично три погляди на одну обставину. Наївний Баєс вважає їх трьома незалежними свідченнями й перемножує їх, тобто рахує один і той самий доказ тричі. Звідси оцінки на кшталт 0.94 там, де насправді 0.76.

Не заучуй напрямок, а міряй. У підручниках зазвичай пишуть, що бустинг і SVM тягнуть до середини, а наївний Баєс — до країв; на наших даних вийшло саме так. Але глибина дерев, кількість ітерацій і кількість даних усе це зсувають, а градієнтний бустинг із логістичною функцією втрат буває калібрований не гірше за лінійну модель. Правильна звичка — не пригадувати таблицю, а побудувати діаграму надійності для своєї моделі на своїх даних. Це десять рядків коду.

ЛікуванняПлатт та ізотонічна регресія

Погані ймовірності — не вирок. Якщо порядок правильний (а в AdaBoost він якраз чудовий), лишається виправити тільки шкалу. Ідея одна: навчити другу, крихітну модель, яка бере оцінку першої й перекладає її в чесну ймовірність. Ця друга модель одновимірна — на вході одне число, на виході одне число.

Калібрування Платта (Platt scaling) припускає, що виправлення має форму сигмоїди, і підбирає два числа: розтяг і зсув. Записується це так:

pчесна = 1 / (1 + e−(a·s + b))

Тут s — оцінка базової моделі, тобто те число, яке треба виправити; a і b — два параметри, які підбираються на калібрувальній вибірці; e — стала 2.718…; а вся права частина — це вже знайома з теми про логістичну регресію сигмоїда, яка бере будь-яке число й акуратно втискає його у відрізок від 0 до 1. Параметр a вирішує, наскільки круто крива йде вгору — тобто розтягує шкалу; b вирішує, де стоїть її середина — тобто зсуває. Отже, Платт — це та сама логістична регресія, тільки навчена на єдиній ознаці, оцінці базової моделі. Два параметри — значить, дуже стійка до шуму: їй вистачає кількох сотень обʼєктів. Ціна стійкості — жорсткість: якщо реальне викривлення не схоже на сигмоїду, Платт його не випрямить.

Ізотонічна регресія (isotonic regression) не припускає нічого, крім одного: виправлена ймовірність не має спадати, коли оцінка зростає. Серед усіх таких неспадних функцій вона шукає ту, що найкраще лягає на дані. Результат — сходинки: відрізки оцінок склеюються в блоки з однаковою виправленою ймовірністю.

Ось звідки береться її апетит до даних. У Платта параметрів рівно два, і жодні дані не змусять його намалювати щось, крім однієї плавної кривої. В ізотонічної «параметрів» стільки, скільки блоків вона вирішить утворити, а це вирішують самі дані — в інтерактиві нижче їх вийшов 21. Тепер уяви, що калібрувальних обʼєктів двісті: на блок припадає десяток, а частка позитивних у десятці буває тільки 0.0, 0.1, 0.2 і так далі, кроками по десятій. Добра половина цих значень — чиста випадковість того, як лягли мітки, і ізотонічна сумлінно запамʼятає її як «виправлену ймовірність». Платт таке згладить, бо йому просто нема чим це виразити. Звідси й орієнтир: Платту вистачає кількох сотень обʼєктів, ізотонічній варто мати від тисячі.

Лікування моделі B

Обидва методи навчені на калібрувальній половині (1200 оголошень) і показані на перевірочній (інші 1200). Сіра діагональ — ідеал.

Brier—
ECE, 10 кошиків—
AUC—
діапазон оцінок—
Дивись на два нижні числа табло. Brier падає з 0.1757 до 0.1385 (Платт) і 0.1395 (ізотонічна), ECE — з 0.182 до 0.033 і 0.029. А AUC у Платта не змінюється взагалі: сигмоїда строго зростає, тож порядок недоторканий. В ізотонічної AUC трохи просідає — 0.8574 замість 0.8600, — бо вона склеює сусідні оцінки в блоки з однаковим значенням, і частина порядку всередині блоків втрачається.

У scikit-learn усе це робить один клас:

CalibratedClassifierCV(estimator, method='sigmoid', cv=5)

Значення method='sigmoid' — це Платт, 'isotonic' — ізотонічна регресія. Параметр cv вирішує головну технічну проблему: калібрувальник не можна навчати на тих самих даних, на яких навчена базова модель. На навчальних даних модель надто впевнена, і калібрувальник вивчить не її справжнє викривлення, а сліди перенавчання. CalibratedClassifierCV робить це через крос-валідацію: у кожній згортці базова модель навчається на одній частині, а калібрувальник — на відкладеній.

Ось що вийшло на нашій дошці, коли ми пропустили три моделі через обидва методи з трьома згортками калібрування.

модельBrier як єПлаттізотонічнаAUC як є → Платт
логістична регресія0.16570.16570.16570.8071 → 0.8071
AdaBoost0.20120.16250.16260.8127 → 0.8158
наївний Баєс0.20420.17630.17340.7898 → 0.7899

Три висновки, і всі три варті уваги.

Калібрування не покращує здатність розрізняти. AUC до й після практично не рухається: 0.7898 проти 0.7899 у наївного Баєса, 0.8071 проти 0.8071 у логістичної регресії. Це не вада методу, а його визначення: монотонне перетворення не може переставити обʼєкти. Якщо тобі обіцяють, що калібрування «підвищить точність моделі», — обіцяють неможливе.

Звідки тоді взялись зайві три тисячних у AdaBoost. Його AUC піднялась із 0.8127 до 0.8158, і це не суперечить сказаному вище. CalibratedClassifierCV за замовчуванням не просто калібрує одну модель: він навчає по одній моделі на кожній згортці й усереднює їхні прогнози. Усереднення трьох моделей — це вже ансамбль, а ансамбль порядок міняти вміє. Саме калібрування тут ні до чого; якби ми калібрували одну заздалегідь навчену модель, AUC не зрушила б зовсім — як у Платта в інтерактиві вище.

Калібрувати калібровану модель безглуздо. У логістичної регресії Brier не зрушив із 0.1657 жодним із двох методів. Уся робота, уся крос-валідація, уся додаткова складність — заради нуля. Спершу міряй, потім лікуй.

Виграш там, де було зламано. AdaBoost відіграв 19% Brier і став найкращою моделлю в таблиці — при тому, що як сортувальник він був найкращим від початку. Калібрування не зробило його розумнішим, воно просто дозволило прочитати те, що він і так знав.

МежіКоли це справді важливо

Калібрування коштує зусиль, окремої вибірки й додаткової деталі в конвеєрі. Витрачати його треба не завжди. Правило одне й воно просте: дивись, куди йде число далі.

Калібрування критичне, коли оцінка входить у розрахунок. Порогове правило з розділу 2 — саме такий випадок: формула t* = C_FP / (C_FP + C_FN) перемножує гроші на ймовірності, і брехливі ймовірності дають брехливу відповідь. Перевіримо це на нашій зіпсованій моделі B. Правило каже блокувати все, що вище 0.10. Але найнижча оцінка моделі B дорівнює 0.29 — вона фізично не вміє видавати числа менші за 0.29. Отже, під поріг потрапляють усі 1200 оголошень: 798 хибних тривог, жодного пропуску, 159 600 грн замість 130 000. Формула не помилилась — їй згодували неправдиві числа.

Той самий механізм працює скрізь, де ймовірність множать на щось: очікуваний прибуток від показу оголошення, очікувані втрати від відмови в кредиті, ранжування черги за «ймовірність × сума угоди», оцінка ризику для регулятора, злиття прогнозів кількох моделей в один. У всіх цих випадках число читають буквально — і калібрування є обовʼязковим.

Калібрування байдуже, коли потрібен лише порядок. Якщо задача звучить як «дай сотню найпідозріліших оголошень на ранкову перевірку», то жодне монотонне викривлення шкали нічого не змінить: та сама сотня, у тому самому порядку. Так само байдуже, коли поріг ти підбираєш по даних, а не рахуєш формулою: підібраний поріг сам компенсує викривлення. Модель B при власному підібраному порозі 0.327 дає рівно ті самі 130 000 грн, що й модель A при 0.088, — бо це та сама модель, у якої лише переклеїли шкалу.

Проміжний випадок, який часто пропускають. Числа читає людина. Модератор бачить у панелі «ризик 0.85» і сприймає це як «майже напевно шахрай». Якщо модель насправді видає 0.85 там, де шахраїв 60%, то в модератора поступово формується недовіра до системи в цілому — він же бачить, що «майже напевно» помиляється кожного третього разу. Формально жоден розрахунок не постраждав. Практично система втратила користувача.

ПідсумокЩо варто винести

Ця тема ділить одну звичну дію — «модель класифікує оголошення» — на три окремі, і кожну з них хтось мусить виконати свідомо.

ідеясутьчому важливо
predict()це predict_proba() і порівняння з 0.5рішення вже ухвалене, просто не тобою
поріг з цінt* = CFP / (CFP + CFN)рахується до того, як побачив дані
інші правилапід повноту, під квоту, під максимум F1різні питання — різні пороги, розкид усемеро
де обиратина валідації, ніколи на тестіпоріг — такий самий гіперпараметр
калібруваннячисло можна читати буквальноінакше розрахунок із ним безглуздий
AUCбачить лише порядокчудова AUC не обіцяє чесних імовірностей
діаграма надійностікошики: обіцяне проти фактичногоєдиний спосіб побачити викривлення
Brier і ECEодне число замість картинкиBrier міряє все, ECE — лише калібрування
Платтсигмоїда, два параметристійкий, вистачає сотень обʼєктів
ізотонічнабудь-яка неспадна функціягнучкіша, треба від тисячі обʼєктів

І головна думка, якщо лишити одну. Модель віддає число, а не рішення. Перетворення числа на рішення — окрема інженерна задача з власною арифметикою, а перед нею стоїть ще одна: переконатися, що число взагалі означає те, що на ньому написано. Обидві ці задачі бібліотека розвʼязує за тебе мовчки, і обидві вона розвʼязує неправильно частіше, ніж хотілося б.

Наступна тема закриває блок про якість моделі — вона про діагностику: що робити, коли метрики розчарували. Там ми навчимось за поведінкою моделі відрізняти нестачу даних від нестачі ознак, а недонавчання — від перенавчання, і будувати з цього план дій замість випадкових спроб. Калібрування знадобиться там одразу: перш ніж лікувати модель, корисно перевірити, чи не бреше сам вимірювач.