Уяви студента, який готується до іспиту за збіркою задач із відповідями. Він розвʼязав усі сто задач, звірив кожну з відповіддю, вивчив розвʼязки напамʼять і тепер розвʼязує ці сто задач на 100%. Питання: що це число каже про його оцінку на іспиті? Абсолютно нічого. Бо на іспиті будуть інші задачі.
Модель у машинному навчанні — той самий студент. Вона теж бачила відповіді, теж може вивчити їх напамʼять, і теж покаже блискучий результат на тому, що вже бачила. Уся дисципліна чесного вимірювання якості зводиться до однієї ідеї: щоб дізнатись, чи навчилась модель, треба перевірити її на задачах, яких вона не бачила. Далі — як саме це робиться, чому вибірок потрібно три, а не дві, і які помилки непомітно перетворюють усю перевірку на самообман.
01 / МотиваціяНавчальна помилка завжди бреше
Почнемо з демонстрації, а не з теорії. Візьмемо просту модель — метод k найближчих сусідів. Він не має жодних формул: щоб класифікувати новий обʼєкт, модель шукає k найсхожіших обʼєктів серед тих, які їй показали, і повертає відповідь більшості з них.
Параметр k керує гнучкістю. При k = 1 модель відповідає
за єдиним найближчим сусідом — і на навчальних даних це означає, що вона просто знаходить
сама себе. Точність на навчальній вибірці буде рівно 100%, завжди, на будь-яких даних,
навіть на чистому шумі. Це не досягнення, це визначення.
Інтерактив 1 · Чому не можна вірити точності на навчальних даних
Ліворуч — межа рішень методу k сусідів. Праворуч — дві криві точності залежно від k.
Різниця між двома кривими — це і є ціна самообману. Навчальна точність вимірює запамʼятовування. Тестова вимірює узагальнення — здатність працювати на нових даних. Нас цікавить винятково друга, і отримати її можна лише одним способом: відкласти частину даних убік і не давати моделі їх бачити.
02 / РозбиттяТри конверти, три ролі
Стандартна практика — розділити наявні дані на три незалежні частини. Слово «незалежні» тут ключове: жоден обʼєкт не має потрапити у дві частини одночасно.
| вибірка | хто її бачить | для чого потрібна | як часто торкаємось |
|---|---|---|---|
| train | алгоритм навчання | підбір параметрів моделі: ваг, порогів, розбиттів дерева | щоразу під час навчання |
| validation | ти, дослідник | вибір між моделями і гіперпараметрами: яке k, який степінь, яка архітектура | десятки й сотні разів |
| test | ніхто до самого кінця | одна незміщена оцінка якості моделі, яку ти вже обрав | рівно один раз |
Формально різниця між train і validation у тому, хто підганяється під дані. На навчальній вибірці підганяється алгоритм: він крутить ваги, поки помилка не перестане падати. На валідаційній підганяєшся ти: дивишся на число, змінюєш гіперпараметр, запускаєш ще раз. Це той самий процес оптимізації — просто цикл проходить через людину. І він так само здатен перенавчитись.
scikit-learn) «validation» і «test» називають навпаки або зливають в одне.
Не сперечайся про слова — важлива лише роль: одна відкладена вибірка потрібна для
вибору, друга для звіту. І це мають бути різні вибірки.03 / Прокляття переможцяЧому двох вибірок замало
Найпоширеніше заперечення звучить так: «навіщо три? Навчив на train, поміряв на test, обрав найкращу модель — хіба цього мало?» Мало. І щоб зрозуміти чому, треба побачити ефект, який в економіці називають прокляттям переможця (winner's curse).
Уяви, що ти виміряв точність двадцяти однаково хороших моделей на вибірці зі ста обʼєктів. Справжня точність кожної — рівно 80%, але виміряна коливається: комусь пощастило на кілька легких прикладів і вийшло 85%, комусь не пощастило і вийшло 74%. Тепер ти обираєш ту, що показала найбільше число, і звітуєш про 85%.
Проблема в тому, що ця модель виграла не тому, що вона краща, а тому, що їй більше пощастило на цій конкретній вибірці. Максимум із двадцяти шумних вимірювань систематично більший за справжнє значення. Ти обрав не найкращу модель — ти обрав найвдалішу похибку вимірювання.
Ця нерівність — вся суть у двох рядках. Математичне сподівання максимуму більше за максимум сподівань, і різниця тим більша, чим більше моделей ти порівнюєш і чим менша вибірка. Покрути обидва повзунки й подивись, як росте розрив:
Інтерактив 2 · Що станеться, якщо обирати модель по тесту
Кожна сіра точка — модель-кандидат. По горизонталі її справжня якість, по вертикалі — виміряна на тестовій вибірці.
Звідси й потреба у третій вибірці. Валідаційна вибірка бере на себе увесь бруд: її оцінка після сотні експериментів справді стає завищеною, і це нормально — ми і не збиралися їй вірити. Її робота інша: ранжувати моделі між собою. А тестова лишається недоторканою, тому її число можна показувати людям.
04 / ДисциплінаТесту торкаємось рівно один раз
Правило звучить майже релігійно, але має цілком технічне обґрунтування. Кожен погляд на тестову вибірку — це біт інформації, який просочується у твої рішення. Побачив, що модель дала 82%, вирішив «спробую ще один варіант ознак» — і ти вже оптимізуєш під тест. Формально ти нічого не робив із даними, але процес вибору тепер залежить від них.
На практиці це дає таку послідовність:
- Розділив дані на три частини до того, як почав щось робити.
- Тестову частину поклав окремо і не відкривав.
- Навчав десятки моделей на train, порівнював їх на validation.
- Обрав переможця, зафіксував усі гіперпараметри, більше нічого не змінюєш.
- Тепер, і тільки тепер, порахував метрику на test. Це число — у звіт.
05 / ВитікЩо таке витік даних
Витік даних (data leakage) — це ситуація, коли інформація з тестової вибірки якимось шляхом дісталася до моделі під час навчання. Оцінка після цього стає завищеною, іноді до абсурду: 99% на тесті і повний провал у продакшені.
Найнеприємніша властивість витоку — він не виглядає як помилка. Код працює, метрика чудова, тести проходять. Єдиний симптом — «підозріло добре». Тому головна навичка тут не діагностична, а профілактична: знати чотири типові сценарії й перевіряти їх щоразу.
06 / СценаріїЧотири способи отруїти собі оцінку
Сценарій 1 · Препроцесинг до розбиття
Класика. Ти завантажив дані, нормалізував ознаки, заповнив пропуски середнім, відібрав найкорисніші ознаки — і лише потім розділив на train і test. Здається невинним: жодних міток, самі числа. Але кожна з цих операцій рахувалась по всіх даних, включно з тестовими. Середнє, яким ти заповнив пропуски, знає про тестові обʼєкти. Ознаки, які ти відібрав, відібрані з урахуванням тестових міток.
Правило: будь-яке перетворення, що має параметри (середнє, стандартне відхилення,
мінімум, максимум, список обраних ознак, словник токенів), налаштовується
на train і лише застосовується до val і test. У scikit-learn це
буквально різниця між fit_transform на навчальній частині і
transform на решті — і саме тому існує Pipeline.
Сценарій 2 · Дублікати й групи
Один пацієнт зробив три знімки. Один користувач залишив пʼятдесят відгуків. Один товар зʼявляється в каталозі під двома артикулами. Якщо розбивати випадково по рядках, копії того самого обʼєкта опиняться і в train, і в test — і модель просто впізнає їх, а не узагальнює.
Лікується груповим розбиттям: спочатку ділиш групи (пацієнтів, користувачів, товари), потім усі рядки групи їдуть в одну вибірку цілком.
Сценарій 3 · Витік із майбутнього
Якщо дані мають час, випадкове розбиття вбиває задачу. Модель, навчена на подіях за весь рік, передбачає події березня, «знаючи» вересень. У житті такої розкоші не буде: завтрашній день прогнозують, маючи лише вчорашній. Розбиття для часових рядів завжди хронологічне: минуле у train, майбутнє у test.
Сценарій 4 · Ознака, що містить відповідь
Найковарніший випадок. У таблиці є колонка, яка потрапила туди після того, як відповідь стала відома. Прогнозуєш відтік клієнтів — а серед ознак є «дата закриття рахунку». Прогнозуєш дефолт — а є «сума списаного боргу». Модель знаходить цю ознаку миттєво і дає майже ідеальну якість.
Симптом: одна ознака дає підозріло високу якість сама по собі. Лікування: для кожної ознаки поставити питання «чи буде вона відома на момент прогнозу?» — і безжально викидати ті, для яких відповідь «ні».
Інтерактив нижче міряє реальний масштаб трьох із цих сценаріїв. Порівняй, наскільки різні за силою витоки бувають:
Інтерактив 3 · Скільки коштує кожен вид витоку
Дві гістограми: рожева — оцінка з витоком, бірюзова — чесна. Пунктир — справжня якість моделі.
07 / БалансСтратифікація
Випадкове розбиття справедливе в середньому, але кожне конкретне розбиття — це випадкова величина. Якщо класи збалансовані, все гаразд. Якщо мінорний клас складає 2% — а це типово для шахрайства, рідкісних хвороб, відмов обладнання — випадковість починає шкодити.
Порахуємо. Тестова вибірка на 100 обʼєктів, мінорний клас 2%. Очікувано в ній буде
2 позитивні приклади. Стандартне відхилення цієї кількості — √(100·0,02·0,98) ≈ 1,4.
Тобто цілком буденний випадок — нуль позитивних прикладів у тесті. А це означає, що
recall не визначений, а вся оцінка перетворюється на лотерею.
Стратифікація прибирає саме цю дисперсію: замість того щоб тасувати все разом, ми тасуємо кожен клас окремо і беремо з нього рівно ту частку, яка потрібна. Пропорція класів у кожній вибірці тоді збігається з пропорцією в усіх даних майже точно.
Інтерактив 4 · Стратифікація при дисбалансі класів
600 випадкових розбиттів і 600 стратифікованих. По горизонталі — яка частка мінорного класу опинилась у тесті.
scikit-learn це один аргумент —
train_test_split(..., stratify=y). Коштує нічого, а прибирає цілий клас
проблем. Для регресії стратифікують за квантилями цільової величини.08 / ПропорціїЯк обирати розміри вибірок
Універсальної відповіді немає, бо ти ділиш обмежений ресурс між двома суперечливими цілями. Кожен обʼєкт, відданий у test, — це обʼєкт, якого недоотримала модель. Кожен обʼєкт, залишений у train, — це втрачена точність вимірювання.
| обсяг даних | типове розбиття | чому саме так |
|---|---|---|
| < 1 000 | крос-валідація | окрема валідаційна вибірка вийде надто малою, щоб щось міряти |
| 1 000 — 100 000 | 60 / 20 / 20 | класика: і вчитись є на чому, і міряти є на чому |
| > 1 000 000 | 98 / 1 / 1 | 1% від мільйона — це 10 000 обʼєктів, а такої вибірки для оцінки вже вистачає |
Логіка останнього рядка важлива: розмір відкладених вибірок визначається не часткою, а абсолютною кількістю. Питання завжди одне — скільки обʼєктів потрібно, щоб похибка вимірювання стала прийнятною. Якщо відповідь «десять тисяч», то на мільйоні це один відсоток, а на десяти тисячах — усі сто.
Інтерактив 5 · Розбиття та розкид оцінки
Смуга зверху — пропорції. Гістограма знизу — точність на тесті по 300 різних випадкових розбиттях тих самих даних.
09 / ПохибкаСкільки коштує мала тестова вибірка
Розкид із попереднього інтерактиву не містить нічого таємничого — його можна порахувати
олівцем. Точність на тесті — це частка правильних відповідей серед n
незалежних спроб. Кількість успіхів має біноміальний розподіл, а отже стандартна похибка
самої частки дорівнює:
Тут p — справжня точність моделі, n — розмір тестової вибірки.
Виведення на два рядки: дисперсія однієї спроби (успіх/невдача) дорівнює p(1−p),
дисперсія середнього з n незалежних спроб у n разів менша,
корінь дає стандартне відхилення.
Величина «модель вгадала» приймає 1 з імовірністю p і 0 з імовірністю 1−p:
Дисперсія середнього незалежних величин ділиться на n:
При достатньому n розподіл близький до нормального, тож 95% інтервал:
Ключовий наслідок — корінь у знаменнику. Щоб зменшити похибку вдвічі, вибірку треба збільшити вчетверо. Тому інтуїція «додам ще трохи даних у тест» працює погано: від 100 до 200 обʼєктів похибка падає лише на 30%.
Інтерактив 6 · Стандартна похибка й довірчий інтервал
Крива SE(n) у логарифмічному масштабі. Праворуч — як виглядає 95% інтервал навколо виміряної точності.
10 / АльтернативаКоли даних мало: крос-валідація
На маленькому датасеті одна валідаційна вибірка нічого не варта: 15% від 400 обʼєктів — це 60 обʼєктів, і за формулою вище похибка оцінки складе близько 5 пп. Порівнювати на цьому моделі безглуздо.
Розвʼязок — k-кратна крос-валідація. Дані (без тесту!) ділять на k рівних частин. Далі k разів навчають модель на k−1 частинах і міряють на тій, що лишилась. Кожен обʼєкт рівно один раз побував у ролі перевірочного, і жодного разу модель не міряли на тому, на чому вчили. Підсумкова оцінка — середнє з k чисел, а їхній розкид одразу показує, наскільки вона надійна.
11 / ПідсумокЧекліст перед тим, як довіритись числу
- Розбиття зроблено першим. До будь-якого аналізу, нормалізації чи відбору ознак.
- Перетворення навчені лише на train. Усе інше — тільки
transform. Найпростіше гарантувати це черезPipeline. - Перевірено дублікати й групи. Один реальний обʼєкт не має зустрічатися у двох вибірках.
- Якщо є час — розбиття хронологічне. Майбутнє не тече в минуле.
- Кожна ознака доступна на момент прогнозу. Ознака, що зʼявляється після події, — не ознака, а відповідь.
- Класи стратифіковано. Особливо при дисбалансі.
- Порахована SE. Різниця, менша за похибку, не є різницею.
- Тест відкрито один раз. І це сталося після того, як усі рішення вже прийняті.
І остання думка, задля якої все це робиться. Розбиття даних — це не бюрократія і не ритуал. Це єдиний доступний нам спосіб змоделювати майбутнє: тестова вибірка вдає із себе дані, яких ще не існує. Наскільки чесно ми зіграємо цю виставу, настільки достовірним буде число, з яким модель піде в реальний світ. Зіпсувати виставу легко — і зазвичай це роблять не зі злого умислу, а через один рядок коду, поставлений на два рядки вище, ніж треба.
practice.ipynb ти реалізуєш
розбиття вручну через numpy, порівняєш його зі стратифікованим,
відтвориш витік через препроцесинг до розбиття й побачиш його ціну в числах,
а потім складеш коректний Pipeline із крос-валідацією.Далі в темі
Теорію прочитано. Тепер закріпи її на практиці.