У попередній темі ми довели детектор шахрайських оголошень до кінця: постановка, чесний поділ, базова лінія, ітерації, один-єдиний замір на тесті й обґрунтоване рішення запускати. Остання її фраза була про те, що модель у продакшні деградує. Ця тема — про те, як саме, як швидко і що з цим робити.
Дошка та сама: оголошення про вживані телефони, модель відповідає на питання, чи є оголошення шахрайським у мить публікації. Тільки тепер вона працює в бою. На день запуску ми поміряли її на 500 відкладених оголошеннях і отримали F1 = 0.843 (precision 0.854, recall 0.833). Це число ми записали у звіт. Далі буде видно, скільки воно проживе.
ПерехідНавчання закінчилось — робота почалась
Модель у зошиті й модель у бою — це два різні інженерні обʼєкти, які випадково мають однакові ваги. У зошиті в тебе є таблиця: усі рядки одразу, усі колонки заповнені, усі правильні відповіді відомі, а часу порахувати — скільки завгодно. У бою немає жодної з цих чотирьох речей.
Дані приходять по одному. Не таблиця на тисячу рядків, а одне оголошення, яке щойно натиснули «Опублікувати». Усе, що ти рахував «по колонці» — медіану, середнє, квантилі для масштабування — у цю мить порахувати ні з чого. Значить, воно має бути вже пораховане й покладене поруч із моделлю. Ця думка проста, і саме на ній ламається більшість перших запусків.
Відповідь потрібна швидко. Людина натиснула кнопку й дивиться на екран. Якщо модель думає секунду, це вже помітно; якщо три — оголошення публікують без перевірки, бо ніхто не тримає користувача в очікуванні. Тобто в бою в тебе зʼявляється бюджет часу, якого в зошиті не існувало взагалі.
Ніхто не скаже, чи вона вгадала. Оце найважче. У зошиті колонка з правильними відповідями лежала поруч. У бою правильна відповідь на питання «чи це був шахрай» приходить тоді, коли покупець втратив передоплату й написав скаргу, — тобто через тижні. А для більшості оголошень не приходить ніколи: вони просто зникають із дошки, і ніхто не знає, чим вони були.
І світ не стоїть. Таблиця в зошиті — фотографія одного дня, продакшн — відео. Ціни падають, зʼявляються нові моделі телефонів, а шахраї змінюють поведінку саме тому, що їх почали ловити.
Життєвий цикл моделі
Тема 30 доводить до четвертого блоку й зупиняється. Усе, що після нього, — це кільце, яке крутиться, поки система жива.
У темі 29 ми міряли моделі не лише якістю, а й вартістю підтримки. Тепер видно, звідки та вартість береться: модель, яка щомісяця вимагає перенавчання, розбору скарг і звірки довідників, коштує стільки, скільки коштує людина, яка це робить, — і платять цю ціну щомісяця.
РежимиПакетно чи на запит
Перше архітектурне рішення після запуску — коли рахувати. Тут є дві незалежні осі, і їх постійно плутають в одну.
Вісь перша: коли навчається модель. Статичне навчання — навчили один раз, поклали файл із вагами в сервіс, він там і живе. Динамічне — модель перенавчається за розкладом чи за подією, і в бою щоразу опиняється нова.
Вісь друга: коли рахується відповідь. Статичний висновок (його ще звуть пакетним, batch) — раз на добу проганяємо всі активні оголошення й складаємо відповіді в таблицю; сервіс потім просто дістає готове. Динамічний висновок (онлайновий) — відповідь рахується в мить запиту.
Дві осі дають чотири комбінації, і в кожної своя ціна. Покрути перемикачі й подивись, що змінюється для нашої дошки.
Чотири способи запустити ту саму модель
Перемикай обидві осі. Змінюються не слова, а чотири числа: затримка відповіді, свіжість прогнозу, вік моделі й те, що зламається першим.
Практичне правило просте. Починай із лівої верхньої клітинки — статичне навчання, пакетний висновок: її найдешевше налагодити й найлегше переробити, бо пачку можна порахувати ще раз. Праворуч рухайся, лише коли затримка справді заважає задачі, а вниз — лише коли вже вмієш міряти якість у бою. Динамічне навчання без моніторингу — це автомат, який щоночі викочує модель, якої ніхто не бачив.
SkewTraining/serving skew
А тепер головна пастка теми, і вона трапляється до будь-якого дрейфу — у перший же день роботи.
Training/serving skew (розбіжність між навчанням і бойовим застосуванням) — це коли одна й та сама ознака рахується двома різними способами: одним у зошиті, іншим у сервісі. Модель при цьому в бою бачить не ті числа, на яких її навчали, — і робить не ті висновки.
Це той самий механізм, що й витік через передобробку з теми 09, де медіана для заповнення пропусків рахувалась по всій таблиці. Різниця лише в тому, де це виявляється: витік підробляє число у звіті, а skew підробляє роботу системи. Перше коштує ніяковості на презентації, друге — грошей.
Наша ознака — price_deviation. Рахується вона так:
Словами: у скільки разів ціна цього оголошення відрізняється від типової — байдуже, в який бік. Розберемо знаки. Типова ціна — медіана цін усередині групи «модель телефона + рік випуску»; ці медіани заздалегідь порахували й склали в довідник. ln — натуральний логарифм: він перетворює «у скільки разів» на число, яке зручно порівнювати, і дає нуль там, де відношення дорівнює одиниці — ln(1) = 0, ln(2) ≈ 0.69, ln(0.5) ≈ −0.69. Дві вертикальні риски — модуль, тобто знак мінус ми відкидаємо.
Логарифм тут не прикраса. Без нього «удвічі дешевше за типову» дало б 0.5, а «удвічі дорожче» — 2.0, і однакові за силою відхилення в різні боки модель бачила б як різні за силою. З логарифмом обидва дають 0.69. А модуль потрібен тому, що підозріле і те, і те. Уся ознака тримається на одному числі ззовні — типовій ціні з довідника. І ось де починається різниця.
У зошиті ти сидиш із таблицею за дванадцять місяців і міряєш якість помісячно. Довідник ти щоразу будуєш із того самого місяця, який зараз оцінюєш, — він у тебе під рукою, і це виглядає природним. У бою в мить публікації оголошення сервіс має рівно один довідник: той, що поїхав разом із моделлю в день запуску. Оголошень цього місяця ще просто не існує.
Ось одне оголошення з десятого місяця: Beta 12, 2021 рік, ціна 2 790 грн,
чесне.
Обидва числа рахуються тією самою формулою, тож перевіримо їх руками.
Медіана групи «Beta 12, 2021» у десятому місяці — 3 325 грн.
Та сама група, але медіана на десять місяців старша — 4 990 грн. Тоді ці телефони справді стільки коштували.
Одне оголошення, одна формула, один рядок коду — і число відрізняється в 3.3 раза. Для моделі 0.175 означає «звичайна ціна», а 0.581 — «підозріло дешево». Той самий чесний продавець у зошиті проходить, а в бою потрапляє в чергу до модератора.
Та сама ознака, порахована двома способами
Перемкни спосіб. Угорі — медіанне відхилення по місяцях, унизу — F1. Числа праворуч — за весь рік, усі 18 000 оголошень.
За рік зошит обіцяє F1 0.725, а система дає 0.614. Розрив 0.111 — і це не помилка вимірювання й не невдача моделі, а різниця між двома способами порахувати одне число.
Одну річ на цій фігурі легко прочитати неправильно. Падають обидві криві: навіть зі свіжим довідником F1 зʼїжджає з 0.889 у четвертому місяці до 0.434 у дванадцятому. Skew — це не падіння, а відстань між кривими. Падають вони з іншої причини, і саме про неї наступний розділ.
Найцікавіше — третій варіант. Довідник можна будувати з минулого місяця: ці оголошення в бою вже існують, правильні відповіді для них не потрібні, тож заборони немає жодної. Так система дає 0.730. Тобто зошит не брехав про досяжну якість — він брехав про ту конкретну систему, яку ми запустили.
Порівняй три числа між собою. Чесний, але недосяжний замір — 0.725. Досяжний і чесний — 0.730: різниця 0.005, тобто ніяка. А запущена система — 0.614, на 0.116 нижче за досяжне. Отже втрата взялась не з того, що ознака погана, і не з того, що свіжий довідник чимось кращий, а з того, що сервіс отримав інший довідник, ніж той, на якому міряли.
Звідси три речі, які це лікують, у порядку важливості. Перша — одна функція на обидва боки, і про неї нижче окремо. Друга — міряти так, як рахуватиме сервіс: якщо в бою довідник буде місячної давності, то й у зошиті будуй його з минулого місяця. Тоді число у звіті стає обіцянкою про систему, а не про формулу. Третя — записувати в журнал значення ознак у мить прогнозу: без цього skew неможливо ні знайти, ні довести, бо в бою не лишиться слідів того, що модель насправді бачила (про журнал — у розділі 6).
ДрейфТри різні дрейфи
Спершу розведімо дрейф зі skew, бо на нашій дошці вони зрослись: довідник стоїть, ринок їде — і розрив між зошитом і боєм із місяцями росте, наче він теж дрейф. Розводить їх одне питання: чи потрібен для цього час? Skew видно на одному оголошенні в один день: береш рядок, рахуєш ознаку двома шляхами й порівнюєш два числа, як ми щойно зробили. Дрейф на одному рядку не видно взагалі — він існує лише як різниця між двома моментами в часі. Skew — це вада системи, вона є в день запуску; дрейф — це властивість світу, він приходить сам.
Тепер про сам дрейф. Це слово в розмовах означає щонайменше три різні речі, і від того, яка саме трапилась, залежить, що робити. Розберемо їх на нашій дошці.
Дрейф даних (data drift) — поїхав розподіл ознак, а звʼязок із відповіддю лишився. Телефони дешевшають: за рік медіанна ціна на дошці впала з 3 980 до 2 250 грн, тобто на 43 %. Правило «ціна набагато нижча за типову — підозріло» при цьому не змінилось ні на йоту. Зламався не звʼязок, а довідник, яким ми рахуємо «типову».
Дрейф концепції (concept drift) — розподіл ознак може лишитись тим самим, але змінилось те, що ознака означає. Шахраї, яких почали ловити за дешевою приманкою, переходять на ціну біля типової: телефон коштує рівно скільки треба, а грошей покупець усе одно не побачить. Ознака та сама, значення те саме, відповідь інша. Цей дрейф найгірший, бо жоден нагляд за даними не зобовʼязаний його побачити.
Дрейф міток (label drift) — змінилась частка самих відповідей. Наприклад, шахраїв стало вдвічі більше через свято чи через дірку в реєстрації. Це найпростіший випадок: він видно одним числом, щойно зʼявляються мітки.
Три дрейфи й що саме в них рухається
Однакове слово, три різні поломки. Ліворуч рухається розподіл, посередині — межа рішення, праворуч — частка класів.
Практична різниця в реакції. Дрейф даних лікується оновленням довідників і перерахунком ознак — часто без жодного перенавчання. Дрейф концепції лікується тільки свіжою розміткою: нову схему шахрайства модель не вигадає, її треба показати. Дрейф міток вимагає передусім перевірити, чи це не поламане джерело даних, — різкий стрибок частки класу набагато частіше означає баг, ніж подію в реальному світі.
ЗатримкаКоли ти дізнаєшся
Тепер зберемо все разом. Ми взяли модель дня запуску, заморозили її разом із довідником — так, як це реально роблять — і прогнали через дванадцять місяців дошки, на якій ринок дешевшає, а шахраї з пʼятого місяця починають міняти схему.
Проблема в тому, що метрику якості в бою не видно. Щоб порахувати F1, потрібні правильні відповіді, а вони приходять тоді, коли шахрая викрили. Візьмімо затримку два місяці — це оптимістично. Отже, у сьомому місяці ти тримаєш у руках якість пʼятого.
А от розподіл ознак доступний одразу: щоб подивитись, як виглядає
price_deviation у сьогоднішніх оголошеннях, мітки не потрібні взагалі.
Найпоширеніша міра такого зсуву — PSI (population stability index,
індекс стабільності популяції). Робить вона просту річ.
Візьми стару вибірку — ту, на якій навчались, — і поділи її на десять кошиків так, щоб у кожен потрапило рівно 10 % значень. Тепер розкидай по тих самих кошиках нові значення. Якщо нічого не змінилось, у кожному знову буде близько 10 %. Якщо розподіл поїхав, десь стане густо, десь порожньо. PSI підсумовує цю різницю по всіх кошиках:
Розберемо кожен знак. Σ (грецька «сигма») означає «склади все, що написано далі, по всіх десяти кошиках». si — частка старих значень у кошику номер i; за побудовою вона дорівнює 0.1. ni — частка нових. Різниця n − s каже, наскільки кошик змінився; ln — натуральний логарифм, він відповідає на питання «у скільки разів», а не «на скільки»: ln(1) = 0, ln(1.2) ≈ 0.18, ln(0.8) ≈ −0.22.
Порахуймо руками на двох кошиках замість десяти. Було порівну: 50 % і 50 %. Стало 60 % і 40 %.
Частка виросла з 0.50 до 0.60. Різниця +0.10, відношення 0.60 ÷ 0.50 = 1.2.
Частка впала з 0.50 до 0.40. Різниця −0.10, відношення 0.40 ÷ 0.50 = 0.8. Логарифм числа, меншого за одиницю, відʼємний — і мінус на мінус дає плюс.
PSI = 0.0182 + 0.0223 = 0.041. Обидва доданки додатні — так і має бути: PSI не буває відʼємним, бо будь-яка зміна є зміною.
Якщо замість 60/40 стало 80/20, той самий рахунок дає 0.30 × ln(1.6) + (−0.30) × ln(0.4) = 0.141 + 0.275 = 0.416. Кошик поїхав утричі далі (0.30 замість 0.10), а PSI виріс уже вдесятеро: 0.416 проти 0.041. Так і має бути — PSI росте приблизно як квадрат зсуву, тож він навмисне мовчить на дрібних коливаннях і різко кричить на справжніх.
Усталені пороги: 0.1 — варто подивитись, 0.25 — зсув значний. Вони не закон природи, а звичка галузі; для конкретної системи їх підбирають на історії.
Поруч із PSI майже завжди рахують KS-тест (критерій Колмогорова–Смирнова). Він міряє те саме зміщення, але інакше: не по кошиках, а по накопичених частках.
Розберемо знаки. F(x) — накопичена частка: яка доля значень не перевищує x. Наприклад, якщо половина оголошень має відхилення до 0.2, то F(0.2) = 0.5. Fстар рахується на старій вибірці, Fнов — на новій, а max означає «пройди всю шкалу й візьми найбільшу різницю». Словами: знайди точку, у якій два розподіли розходяться найсильніше, і назви величину цього розходження.
Порахуймо на тих самих двох кошиках. Було 50 % і 50 %, тож накопичені частки старого розподілу — 0.50 на межі кошиків і 1.00 у кінці. Стало 60 % і 40 %: 0.60 і 1.00. Різниці — 0.10 і 0.00, найбільша з них 0.10. Це і є KS. Для 80/20 так само вийде 0.30. KS завжди між 0 і 1, і читається прямо: 0.30 означає, що в найгіршій точці шкали розподіли розходяться на 30 % вибірки.
Дві міри йдуть поруч, але поводяться по-різному, і це видно на нашому році: у пʼятому місяці PSI 0.108 і KS 0.113 — майже те саме, а в дванадцятому PSI 1.668 проти KS 0.495. Причина в тому, що KS упирається в одиницю, а PSI верхньої межі не має й на сильних зсувах росте набагато швидше. Тому пороги для них різні, і «0.1 і 0.25» — це пороги PSI, не KS.
А тепер — центральна картинка теми. Веди повзунок від першого місяця до дванадцятого.
Розрив між «зіпсувалась» і «дізнався»
Угорі — розподіл ознаки: сірий контур це день запуску, заливка це поточний місяць. Нижче — правда про якість і те, що ти реально бачиш. Внизу — PSI, який мітки не потребує.
Ось що показує цей повзунок, якщо провести його цілком.
Модель фактично зіпсувалась у пʼятому місяці: F1 упав до 0.777, нижче домовлених 0.80. У той самий пʼятий місяць PSI вперше перетнув 0.1 — і це видно було того ж дня, без жодної мітки. А метрика якості за пʼятий місяць доїхала до тебе аж у сьомому. Два місяці детектор працював гірше, ніж обіцяв, а у звіті світилось зелене: у пʼятому місяці на екрані стояв F1 за третій — 0.879.
Цей розрив і є суттю теми. Не «модель погана» і не «дрейф існує», а те, що між поломкою і її виявленням лежить рівно стільки часу, скільки їде розмітка. Скоротити його можна двома способами: швидше отримувати мітки (кнопка «поскаржитись» на оголошенні дає розмітку за години, а не за місяці) або дивитись на те, що видно без міток.
- дрейф концепції вони не бачать узагалі. Якщо шахраї перейшли на ціну біля типової, розподіл ознаки може лишитись тим самим, PSI — близьким до нуля, а модель уже помиляється;
- вони не кажуть, чи зсув шкідливий. Ознака могла поїхати там, де модель на неї майже не спирається: PSI великий, а якість ціла;
- вони рахуються по одній ознаці. Кожна колонка окремо може лишитись на місці, а звʼязок між ними — змінитись, і жодна з двох мір цього не покаже.
НаглядЩо моніторити
Найпоширеніша помилка — моніторити тільки якість. Її, як ми щойно бачили, часто не видно місяцями. Робочий набір сигналів вибудовується за іншим принципом: від того, що приходить швидко, до того, що приходить пізно. Метрика якості — остання в цьому списку, а не перша.
Що міряти, як часто й що робити при відхиленні
Порядок рядків — це порядок, у якому сигнали доходять до тебе. Верхні приходять за хвилини, нижні — за місяці.
| що міряємо | як часто | межа | що робити при відхиленні |
|---|---|---|---|
| Помилки сервісу | щохвилини | понад 0.1 % запитів | будити чергового: це не модель, це сервіс |
| Затримка відповіді | щохвилини | понад 100 мс у 95 % запитів | шукати повільний крок конвеєра, не міняти модель |
| Пропуски й типи в колонках | щогодини | +5 пунктів до звичного | перевірити джерело: майже завжди зламався постачальник даних |
| Частка оголошень, які модель позначила тривогою | щодня | ±20 % від стартових 16 % | шукати причину; у нас за рік стало 33 % — удвічі більше, хоча самих шахраїв не побільшало |
| Розподіли ознак (PSI, KS) | щотижня | PSI 0.10 — дивитись, 0.25 — тривога | звірити довідники, порівняти з попереднім тижнем |
| Скарги від людей | щодня | зростання два тижні поспіль | читати самі скарги: це найдешевша нова розмітка |
| Метрика якості на свіжій розмітці | щомісяця, із затримкою | F1 нижче 0.80 | перенавчати, а відкочувати лише якщо перед падінням міняли модель (розділ 10) |
Дві поради з практики. По-перше, записуй те, з чим модель насправді працювала: не лише відповідь, а й значення ознак у мить прогнозу. Без цього skew із розділу 3 неможливо ні знайти, ні довести. По-друге, сигнал без порога — це не моніторинг: графік, на який ніхто не дивиться, дає лише відчуття контролю.
ТермінСкільки живе модель
Чесна відповідь: залежно від того, як швидко змінюється предметна область, і дізнатись це можна тільки заміром. Прогноз погоди старіє за години, розпізнавання рукописних цифр — за роки. Наш детектор шахрайства зістарився за пʼять місяців, бо в нього є противник, який навмисне змінює поведінку.
Ліки від старіння одні: навчити модель наново на свіжих даних. Далі це зветься перенавчанням — і не плутай його з перенавчанням у сенсі теми 17, де тим самим словом називають модель, яка завчила навчальну вибірку. Тут ідеться про повторне навчання: ті самі кроки, що й у день запуску, тільки на новішій таблиці.
Перенавчати можна двома способами, і вибір між ними — це вибір, хто ухвалює рішення.
За розкладом. Щомісяця, щотижня, щоночі — байдуже коли, головне завжди. Плюс у передбачуваності: команда знає, коли це станеться, і встигає підготуватись. Мінус у тому, що розклад не знає про світ: він перенавчить модель тоді, коли нічого не змінилось, і не перенавчить у тиждень, коли зламалось усе.
За тригером. Перенавчаємо, коли спрацював сигнал: PSI перейшов поріг, частка тривог виїхала за коридор, якість на свіжій розмітці впала. Плюс — реакція на подію, а не на календар. Мінус — тригер треба налаштувати, і хибне спрацювання коштує викату нової моделі, якої ніхто не просив.
«Налаштувати» тут означає одне число, і воно вирішує все. Візьми PSI нашого року з Інтерактиву 3: 0.019, 0.053, 0.041, 0.073, 0.108, 0.182, 0.344 — далі тільки більше. Поріг 0.25 уперше спрацював би аж у сьомому місяці, тобто рівно тоді, коли й так приїхала метрика за пʼятий: виграшу нуль, тригер спізнився разом із розміткою. Поріг 0.10 спрацював би в пʼятому — за два місяці до метрики, у той самий місяць, коли якість насправді провалилась. І за перші чотири місяці він не дав би жодної хибної тривоги: PSI там не піднімався вище 0.073.
Це і є ціна питання. Високий поріг перетворює тригер на дорогий спосіб дізнатись те саме й тоді ж; низький дає ті самі два місяці фори, але на спокійнішому році перетнувся б і без поломки, і команда викочувала б моделі, яких ніхто не просив. Тому поріг беруть не з таблиці, а зі своєї історії: такий, щоб на минулих даних він спрацьовував раніше за метрику й мовчав у місяці, коли все було гаразд. А поки такої історії немає — розклад чесніший за тригер, бо в нього немає числа, яке можна вгадати неправильно.
Порівняймо обидві дисципліни на нашій дошці. «Запустили й забули» — це модель дня запуску, яка працює весь рік без жодної зміни: її помісячна якість намальована на Інтерактиві 3. «Перенавчаємо щомісяця» — це щоразу нова модель, навчена на трьох останніх розмічених місяцях. Слово «розмічених» тут головне: мітки їдуть два місяці, тож на початку дванадцятого місяця остання повна розмітка — за десятий, і вчитись доводиться на місяцях 8-10.
Перше число можна перевірити просто на Інтерактиві 3: це середнє восьми помісячних значень із пʼятого місяця до дванадцятого — 0.777, 0.700, 0.608, 0.528, 0.463, 0.432, 0.297 і 0.334. Друге — те саме середнє, тільки щомісяця з новою моделлю.
Перенавчання працює: різниця між «детектор гальмує» і «детектор здався». Але подивись уважно на друге число. 0.647 — це теж далеко не 0.843 із дня запуску, і до дванадцятого місяця навіть свіжа модель дає близько 0.5. Причина не в алгоритмі: модель, навчена на місяцях 8-10, ловить шахраїв, які працювали у місяцях 8-10, а в дванадцятому схема вже інша. Поки мітки їдуть два місяці, модель приречена бігти позаду на два місяці.
Чому навіть свіжа модель відстає на два місяці
Початок дванадцятого місяця роботи. Зеленим — усе, на чому модель, яка працює просто зараз, узагалі могла навчитись.
ВерсіїВерсія всього
Питання, яке рано чи пізно ставлять усім: «Учора система пропустила ось це оголошення. Чому?» Відповісти на нього можна лише тоді, коли ти здатен відтворити вчорашній стан. А для цього версію мають мати три речі, а не одна.
Модель. Не «остання», а конкретний файл із конкретним номером, який лежить незмінним. Разом із ним — усе, що модель тягне за собою: довідник типових цін, список категорій, межі масштабування. Це один артефакт, а не файл із вагами плюс кілька змінних у чиємусь коді.
Дані. Не «таблиця оголошень», а зріз, на якому ця модель навчалась: які рядки, за який період, із якою розміткою. Таблиця в базі змінюється щодня; без зафіксованого зрізу навчання не відтворити навіть за тиждень.
Код. Той самий комміт, що готував ознаки й навчав. Разом із версіями
бібліотек: результат OneHotEncoder чи порядок колонок можуть відрізнятись
між версіями, і модель, навчена на одній, тихо помиляється на іншій.
Мінімальна форма, яка вже рятує: кожен прогноз у журналі має нести номер версії моделі. Одне поле — і питання «що змінилось між вівторком і середою» перетворюється з розслідування на запит.
Інструментів для цього багато — трекери експериментів, реєстри моделей, планувальники конвеєрів, сховища ознак. Називати конкретні тут немає сенсу: вони змінюються швидше за курс. Принцип же не змінюється: усе, що впливає на результат, має версію, а результат має посилання на неї.
ВикатЯк випускати нову
Нова модель краща за стару на крос-валідації. Це ще не привід міняти її в бою одним рухом: «краще на історії» і «краще на живих людях» — різні твердження, і друге перевіряють окремо.
Чотири щаблі викату
Стара модель лишається в бою, поки нова не довела своє. Червона стрілка знизу працює з будь-якого щабля.
Тіньовий запуск (shadow mode). Нова модель отримує ті самі запити, що й стара, рахує відповідь і записує її в журнал — але рішення ухвалює стара. Ризику для людей нуль. Що це дає: ти бачиш реальну затримку, реальні збої на реальних даних і відсоток розбіжностей із чинною моделлю. Якщо нова модель позначає втричі більше оголошень, ти дізнаєшся про це до того, як черга модератора вибухне, а не після.
Канарковий викат (canary). Нова модель ухвалює рішення, але для маленької частки — скажімо, 5 % оголошень. Мета не поміряти якість (на 5 % за день її й не поміряєш), а спіймати грубу поломку на малій крові.
A/B. Дві моделі працюють паралельно на порівнянних частках трафіку, і ми міряємо не тільки метрику моделі, а й те, що важить для дошки: скільки скарг, скільки часу витратили модератори. У статистику тут не занурюємось; достатньо трьох правил. Ділити випадково й на рівні того, кого це стосується (у нас — оголошення). Дивитись результат один раз наприкінці домовленого періоду: щоденне підглядання рано чи пізно покаже «перемогу» на чистому шумі. Період — не коротший за тиждень, бо понеділок не схожий на суботу.
ВідкатПлан відкату
Найпрактичніша річ у всій темі, і вона вміщається в одне речення: план відкату має існувати до запуску, а не після поломки.
Причина проста. У момент, коли щось зламалось, у тебе немає ні часу, ні спокою на те, щоб придумати процедуру: рішення ухвалюватимуться поспіхом і з неповними даними. Усе, що можна вирішити заздалегідь, має бути вирішене заздалегідь.
Мінімальний план — чотири пункти, і кожен має бути записаний до викату:
- За якою умовою відкочуємо. Не «якщо стане погано», а число: частка позначених вийшла за коридор, помилки сервісу понад 0.5 %, скарги за добу зросли втричі.
- Куди відкочуємо. Конкретна версія моделі, яка лежить незмінна й готова прийняти трафік. Разом із її довідником — інакше відкат поверне ваги, але лишить нові ознаки, і вийде третя система, якої ніхто не бачив.
- Хто натискає. Одна людина з правом ухвалити це рішення без наради. Якщо потрібна нарада, відкат займе день.
- Скільки це триває. Якщо відкат займає годину, умова спрацювання має бути значно суворішою, ніж якщо він займає хвилину.
Тепер межа, яку варто провести до того, як припече: відкат лікує поганий викат, а не дрейф. Якщо якість упала одразу після того, як у бій пішла нова модель, — відкочуйся не роздумуючи: стара щойно працювала, і працюватиме знову. Якщо ж якість повзе вниз місяцями, а моделі ніхто не міняв, відкочуватись просто нікуди: попередня версія ще старша, тобто ще далі від сьогоднішнього світу. Тоді ліки інші — новий довідник, свіжа розмітка, перенавчання з розділу 7. Питання, яке розводить ці два випадки, одне: що змінилось останнім — наша система чи світ?
І одна порада, яку зазвичай ігнорують: відкат треба спробувати до того, як він знадобиться. Процедура, записана в документі й ніколи не виконана, — це не процедура, а намір.
РеальністьЩо ламається насправді
Уся ця тема була про модель. Тепер чесна поправка: у продакшні ламається переважно не модель, а конвеєр навколо неї. Сама модель якраз стабільна — та сама матриця ваг щодня дає ті самі числа. Псується те, що подає їй дані.
Типовий список, і в ньому немає нічого про машинне навчання:
- колонку
памʼять_гбперейменували наstorage— модель отримала пропуск замість числа й тихо працює на медіані; - джерело почало віддавати ціну рядком «12 000 грн» замість числа — і вся ознака перетворилась на пропуски;
- відвалилась вивантажка довідника, і сервіс тиждень працює з місячної давності типовими цінами;
- зʼявилась нова модель телефона, якої немає в жодній категорії — і кодувальник категорій ставить нулі в усі стовпці;
- хтось поміняв часовий пояс, і «вік акаунта» став відʼємним у частини рядків;
- оновили бібліотеку, порядок колонок після кодування змінився — модель перемножує ваги не з тими ознаками.
Спільне в усіх шести: жодна не викидає помилку. Сервіс відповідає, графіки малюються, метрика мовчить, бо міток немає. Саме тому в таблиці моніторингу перші три рядки — не про модель, а про дані: частка пропусків у колонці й типи значень ловлять таку поломку за години, тоді як якість покаже її за місяці.
ДаліЩо далі
На цьому таблична частина курсу закінчується. Озирнись: ти почав із питання «що таке машинне навчання», пройшов сім моделей і десяток метрик, зібрав наскрізний проєкт — а закінчуєш темою, у якій найважливіше число не F1, а кількість місяців між поломкою й виявленням.
Звідси варто забрати одну звичку. Число на тесті — це не властивість моделі, а обіцянка, дійсна доти, доки світ схожий на ту таблицю. Тому питання «яка в неї точність» неповне; повне звучить так: «яка в неї точність, як довго вона такою лишиться і як я дізнаюсь, що вже ні».
Далі — нейронні мережі. Вони починаються
там, де таблиця закінчується: текст, звук, зображення. Усе, що ти щойно прочитав, там
не скасовується, а дорожчає. Модель більша, навчання довше, відкат складніший, а ознаки
модель робить собі сама — і це означає, що подивитись на них очима, як ми дивились на
price_deviation, стане важче. Дисципліна з цієї теми там потрібніша, а не
менш потрібна.