Ліс замість дерева

Одне дерево нестабільне, і виправити це всередині дерева неможливо. Зате можна побудувати сотню поганих дерев і змусити їх голосувати.

Наприкінці 1906 року статистик Френсіс Гальтон опинився на сільському ярмарку, де відвідувачі за монету вгадували вагу бика. Гальтон зібрав 787 записок і, готуючись посміятися з натовпу, порахував медіану здогадок. Вона відрізнялась від справжньої ваги менш ніж на один відсоток — точніше за будь-якого окремого фермера й точніше за експертів.

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

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

ІдеяМудрість натовпу

Ансамбль (ensemble) — це набір моделей, чиї прогнози обʼєднують в один. Слово нічого не каже про те, які саме моделі всередині й чим вони відрізняються: ансамбль — це спосіб складати відповіді, а не окремий алгоритм навчання.

Складати можна двома способами, і різницю між ними варто закріпити відразу, бо далі вона спливе ще двічі.

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

Щоб ансамбль виграв у окремої моделі, потрібні дві умови, і обидві однаково важливі:

Друга умова — і є весь фокус. Подивімось на неї на пʼятьох деревах і одному клієнті, якого треба класифікувати. Правильна відповідь — «лишиться». Дерева дають:

випадокголоси пʼятьох дереввердикт більшості
дерева однаковіпіде · піде · піде · піде · підепіде — помилка
дерева різнілишиться · піде · лишиться · піде · лишитьсялишиться — правильно

У другому рядку двоє дерев із пʼятьох помилились — рівно стільки ж помилок, скільки буває в поганому дереві. Але помилки припали на різні дерева, тому в сумі їх переголосували. У першому рядку помилок теж могло бути дві на пʼять — за умови, що дерева різні. Вони не різні, тому всі пʼять помилок сіли на того самого клієнта.

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

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

ТеоріяТеорема Кондорсе

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

P(M, p) = Σk > M/2 C(M, k) · pk · (1 − p)M−k

Словами: перебери всі варіанти, у яких правильно проголосувала більшість, порахуй ймовірність кожного — і склади їх.

Розбір по символах — усі, а не «очевидні».

Порахуймо руками. Візьмімо три дерева з точністю 0.6 кожне. Більшість — це двоє або троє правих.

  1. Рівно двоє праві (k = 2). Один конкретний розклад «права пара + один хибний» має ймовірність 0.6 · 0.6 · 0.4 = 0.144. Таких розкладів C(3, 2) = 3 штуки, отже 3 · 0.144 = 0.432.
  2. Усі троє праві (k = 3). Один розклад, ймовірність 0.6 · 0.6 · 0.6 = 0.216.
  3. Складаємо: 0.432 + 0.216 = 0.648. Три дерева по 0.6 дали 0.648 — майже пʼять відсоткових пунктів задарма, без єдиної нової ознаки й без жодного гіперпараметра.

Те, що ми щойно порахували, — хвіст біноміального розподілу: сума ймовірностей «k або більше успіхів із M спроб». Висновок із формули відомий як теорема присяжних, і в ній три випадки, які треба знати напамʼять:

  1. Якщо p > 0.5, то P зростає з M і прямує до одиниці. Достатньо взяти більше голосів — і колективна помилка стане як завгодно малою.
  2. Якщо p = 0.5, то P дорівнює 0.5 за будь-якого M. Натовп монеток — це монетка.
  3. Якщо p < 0.5, ефект обертається: P спадає з M і прямує до нуля. Натовп поганих моделей упевнено помиляється — і що більший натовп, то впевненіше.

Третій випадок найлегше проґавити, тому підставмо в ту саму формулу p = 0.45 — модель, гіршу за монетку лише на пʼять сотих:

дерев Mбільшість права, точність дерева 0.45точність дерева 0.60
10.45000.6000
110.36690.7535
510.23590.9265
2010.07740.9979

Двісті одне дерево, кожне з яких вгадує майже в половині випадків, разом дають 7.74% — гірше, ніж кидати монетку. Це не збій алгоритму, а та сама сума з формули: хвіст біноміального розподілу з p нижче половини сповзає до нуля рівно так само рішуче, як із p вище половини він піднімається до одиниці. Голосування не створює знання — воно лише підсилює те, що вже є в кожному голосі, у який бік воно б не показувало.

Крива Кондорсе

Скільки моделей потрібно, щоб більшість була права. Сірі криві — орієнтири для p = 0.4, 0.5, 0.6, 0.7.

P більшості—
виграш, в.п.—
при 11 деревах—
при 51 дереві—
Спробуй p = 0.45. Крива піде вниз: кожне додане дерево робить ансамбль гіршим. Це не парадокс, а та сама математика з іншим знаком — більшість надійно відтворює те, у чому окремі моделі систематично помиляються.

Дрібний шрифтЗастереження про незалежність

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

Незалежні тут означає буквально: результат одного голосу нічого не каже про результат іншого. Якщо перший присяжний помилився, це не змінює ймовірності, що помилиться другий. Саме на цьому припущенні тримається C(M, k) у формулі: коефіцієнт рахує кількість способів отримати k правильних голосів із M, вважаючи, що кожен голос кидається окремо, як окрема монетка.

У житті присяжні перемовляються, а моделі вчаться на одних і тих самих даних. Якщо всі дерева побудовані на однаковій вибірці однаковим детермінованим алгоритмом, вони будуть ідентичними. Ефективна кількість голосів у такому ансамблі дорівнює одиниці, скільки б дерев ми не додали.

Ліс не виконує обіцянки Кондорсе — і не може її виконати

Це треба сказати прямо, бо інакше два попередні розділи разом складаються в неправду. Теорема обіцяє: 201 дерево по 0.6 дає 0.998. Реальний ліс із 201 дерева на реальних даних дає, скажімо, 0.85 — і не тому, що ми щось зробили не так, а тому, що умова теореми не виконується й ніколи не виконуватиметься.

Причина проста й вимірювана. Дві бутстреп-вибірки (розділ 04) — це два жереби з того самого мішка з 200 клієнтів. Порахуймо, наскільки вони перетинаються: у середньому 63% обʼєктів однієї бутстреп-вибірки лежать і в другій (замір на наших даних, 2000 пар жеребів; те саме число 1 − 1/e, яке ми виведемо в наступному розділі). Два дерева, що вчились на майже однакових даних, і помиляються майже однаково. Незалежності немає — є лише послаблена залежність.

Тому правильне читання теореми Кондорсе таке: у формулу треба підставляти не кількість дерев M, а ефективну кількість голосів — набагато меншу. Скільки саме — теорема не каже, а ось наскільки дорого обходиться залежність, ми порахуємо точно в розділі 11: там залишкова кореляція ρ перетвориться на стелю, нижче якої дисперсію лісу не опустити жодною кількістю дерев.

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

І ось тут стає видно, чому трюків саме два, а не один. Бутстреп (розділ 04) міняє дані під деревом — але, як ми щойно порахували, лишає між вибірками 63% спільного, а на однакових даних жадібний алгоритм часто обирає ту саму ознаку в корінь. Знизити кореляцію ще нижче можна тільки втрутившись у сам алгоритм: заборонити деревам дивитись на всі ознаки одразу. Це другий трюк — випадкові підмножини ознак, розділ 06. Один трюк без другого дає ансамбль, який працює, але недопрацьовує.

Трюк першийБеггінг і бутстреп

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

Лео Брейман 1996 року запропонував підробку, яка виявилась напрочуд робочою: бутстреп (bootstrap) — витягування n обʼєктів із наявних n з поверненням. Ідея не його: сам прийом придумав статистик Бредлі Ефрон 1979 року як спосіб оцінити похибку будь-якої статистики, коли повторити експеримент неможливо. Брейман приніс цей прийом у машинне навчання.

Мішок із поверненням — на пʼятьох клієнтах

Уяви мішок із пʼятьма картками: А Б В Г Д. Тягнемо картку, записуємо ім'я, кладемо картку назад і перемішуємо. І так пʼять разів — рівно стільки, скільки карток у мішку. Ось один такий жереб:

витягування12345
випалоБГБДГ

Нова вибірка — це Б Б Г Г Д: пʼять записів, як і було. Але Б і Г потрапили двічі, а А і В не потрапили взагалі. Дерево, навчене на цій вибірці, про клієнтів А і В нічого не знатиме, зате Б і Г вважатиме вдвічі важливішими, ніж вони є. Наступний жереб дасть інший перекіс — і інше дерево.

Чому саме з поверненням? Питання не риторичне, і відповідей три.

  1. Без повернення нічого не вийде взагалі. Витягнути n обʼєктів із n без повернення — це просто взяти всю вибірку, перемішавши порядок. Ті самі 200 клієнтів, те саме дерево. Жодної різноманітності.
  2. Розмір лишається n. Можна було б брати підвибірки меншого розміру без повернення — такий варіант існує й зветься pasting. Але тоді кожне дерево вчиться на меншій вибірці, ніж могло б, і стає слабшим. Повернення дає різноманітність, не забираючи обсягу.
  3. Повторення — це і є перекіс. Різні дерева бачать не просто різні набори клієнтів, а різні ваги тих самих клієнтів. Саме цей перекіс і зсуває пороги розрізів, роблячи дерева несхожими.

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

Беггінг — це бутстреп плюс усереднення

Метод «навчи модель на кожній бутстреп-вибірці й усередни прогнози» називається беггінгом. Назва — склеєне bootstrap aggregating: перше слово про те, звідки беруться вибірки, друге (aggregating — «зведення докупи») про те, що робиться з прогнозами. Алгоритм цілком уміщується в три рядки:

  1. Зроби T бутстреп-вибірок розміру n.
  2. Навчи на кожній свою копію моделі — незалежно від інших.
  3. Для прогнозу спитай усі T копій і візьми більшість (класифікація) або середнє (регресія).

Зверни увагу, чого в цьому описі немає: слова «дерево». Беггінг — обгортка над будь-якою моделлю, і в scikit-learn це окремий клас BaggingClassifier(estimator=…), куди можна покласти хоч дерево, хоч kNN, хоч логістичну регресію.

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

Випадковий ліс = беггінг над деревами плюс другий трюк із розділу 06. Якщо другий трюк вимкнути (дозволити вузлу дивитись на всі ознаки), лишиться чистий беггінг — рядок mtry = p у таблиці розділу 06 саме про це.

АрифметикаЗвідки береться 63%

Скільки різних обʼєктів потрапляє в одну бутстреп-вибірку? Порахуймо це до кінця — виведення коротке й дуже показове.

крок 1 · одне витягування

Візьмімо конкретного клієнта. За одне витягування ймовірність, що дістали саме його, дорівнює 1/n. Отже, ймовірність, що дістали не його:

1 − 1/n
крок 2 · усі n витягувань

Витягування незалежні, тому ймовірність, що його не взяли жодного разу за n спроб, — це добуток n однакових множників:

P(не потрапив) = (1 − 1/n)n
крок 3 · границя

Тепер найцікавіше. Вираз (1 − 1/n)n має дві частини, які тягнуть у різні боки: множник 1 − 1/n із ростом n наближається до одиниці (одиниця в будь-якому степені — одиниця), а степінь n росте (число, менше за одиницю, у великому степені прямує до нуля). Хто переможе — з формули не видно. Тому просто підставмо числа й подивімось:

n(1 − 1/n)nяк це рахується
20.250000.5 · 0.5
50.327680.8 помножене саме на себе 5 разів
100.348680.9 у степені 10
200.358490.95 у степені 20
1000.366030.99 у степені 100
10000.367700.999 у степені 1000

Стовпчик не розбігається й не спадає до нуля — він упирається в число 0.3678… Ніяка з двох частин не перемогла, вони врівноважились. Математики записують цей факт так:

limn→∞ (1 − 1/n)n = e−1 ≈ 0.368

Причому збіжність швидка: вже при n = 20 значення дорівнює 0.358, при n = 100 — 0.366.

крок 4 · висновок

Отже, приблизно 36.8% обʼєктів у кожну конкретну вибірку не потрапляють, а 63.2% потрапляють хоча б раз:

частка унікальних ≈ 1 − e−1 ≈ 0.632
Що таке lim і що таке e — якщо ці значки бачиш уперше.

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

Що відбувається при бутстрепі

Кожна клітинка — один обʼєкт вибірки. Колір показує, скільки разів його витягнули.

унікальних—
теорія—
поза вибіркою—
max повторів—
Що читати: сірі клітинки — обʼєкти, які в цю вибірку не потрапили, тобто out-of-bag. Їхня частка коливається навколо 36.8% і майже не залежить від n — у цьому і краса границі.

Трюк другийВипадкові ознаки й декореляція

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

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

Як цей параметр зветься в коді. Скорочення mtry прийшло з реалізації випадкового лісу мовою R і стало загальновживаним у статтях — саме тому ми користуємось ним у тексті. Але в scikit-learn цей самий параметр зветься max_features, і шукати mtry в документації Python марно. Значення за замовчуванням для класифікації — рядок max_features="sqrt", тобто корінь квадратний із кількості ознак, округлений угору; для регресії RandomForestRegressor за замовчуванням бере 1.0, тобто всі ознаки. Число, частку або рядок "log2" можна задати вручну.

Стандартні рекомендації такі:

задачаmtry за замовчуваннямміркування
класифікація√pсильна декореляція, дерева слабші, але різні
регресіяp/3у регресії дерева чутливіші, потрібно більше ознак
mtry = pце вже просто беггінгдерева найсильніші, але найсхожіші

Тут працює компроміс сили й кореляції, який Брейман сформулював прямо: якість лісу зростає, коли окремі дерева сильніші, і коли вони менш корельовані. Але ці дві вимоги тягнуть у різні боки. Малий mtry робить дерева різними — і водночас слабшими, бо найкорисніша ознака часто буває недоступною. Великий mtry робить кожне дерево сильним — і всі їх схожими. Оптимум зазвичай десь посередині, і √p — непогане перше наближення.

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

Скільки ознак дозволити вузлу

Шість ознак, ліс із 24 дерев. Три криві: сила окремого дерева, схожість дерев і точність ансамблю.

точність лісу—
середнє дерево—
згода дерев—
найкращий mtry—
Що читати: «згода дерев» — частка тестових обʼєктів, на яких два випадково взяті дерева дають однакову відповідь. Це практична міра кореляції: 100% означало б, що ансамбль вироджений і складається фактично з однієї моделі.

ЗбіркаАлгоритм цілком

Тепер можна записати весь випадковий ліс у пʼять рядків. Нехай задано кількість дерев T, розмір підмножини ознак mtry й обмеження на дерево:

  1. Для кожного дерева t = 1…T витягни бутстреп-вибірку розміру n з поверненням.
  2. Вирости на ній дерево звичайним жадібним алгоритмом, але в кожному вузлі перебирай лише mtry випадково обраних ознак.
  3. Дерево не обрізай. Так, у попередній лекції ми казали, що глибокі дерева перенавчаються — тут це навмисне.
  4. Для прогнозу пропусти обʼєкт крізь усі T дерев і візьми більшість голосів (або середнє від часток класу, якщо потрібні ймовірності).
  5. Обʼєкти, що не потрапили в бутстреп конкретного дерева, використай для OOB-оцінки.

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

Скільки дерев треба

Повертаємось до двох ознак. Насиченість кольору — наскільки одностайно голосує ліс у цій точці.

точність лісу—
одне дерево—
приріст—
межа 36 дерев—
Що видно: при одному дереві межа — рвані прямокутники з різкими краями. З десятком дерев зʼявляються півтони: там, де дерева не згодні, ліс не впевнений. Крива внизу усереднена за чотирма незалежними лісами, щоб не показувати випадкові коливання одного запуску.
Скільки дерев брати. Точність виходить на плато, і додаткові дерева її вже не псують — на відміну від глибини одного дерева, більше ніколи не означає гірше. Тому n_estimators обирають не якістю, а бюджетом часу: 100–500 у типовій задачі, більше — коли потрібні стабільні оцінки ймовірностей.

ПеревіркаДерево проти лісу

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

Натисни кнопку кілька разів і дивись на числа праворуч. Нас цікавить не так точність, як стабільність: наскільки сильно змінюється відповідь моделі, коли дані змінились ледь-ледь.

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

Саме це число, а не точність, і є предметом розділу. Ось чому.

Чому обидві моделі впираються десь у 85%, а не в 99%. У наших даних 10% міток навмисне перевернуто — клієнт поводиться всупереч своєму стажу й витратам. Це невиправний шум: жодна модель, хоч дерево, хоч ліс, хоч ідеальна формула, не може вгадати перевернуту мітку, бо в ознаках про неї нічого немає. Стеля тут близько 90%, і ліс на 85% сидить біля неї, а не «недобирає до сотні». Дивись на відстань до стелі й на розкид між запусками, а не на абсолютну цифру.

Наскільки ліс стабільніший

Ліворуч — одне дерево, праворуч — ліс із 25 дерев. Обидва вчаться на одній і тій самій новій підвибірці.

зсув межі · дерево—
зсув межі · ліс—
test · дерево
test · ліс—
у середньому за всі запуски · дерево / ліс—
«Зсув межі» — частка площини, де модель класифікує інакше, ніж на попередньому запуску. Для дерева це зазвичай 10–20%, для лісу — одиниці відсотків. Дисперсія не зникла: вона поділилась на кількість дерев.

БонусOOB — безкоштовна валідація

Повернімось до тих 36.8%, що лишились поза кожною бутстреп-вибіркою. Для конкретного клієнта приблизно третина дерев його не бачила під час навчання. Зберімо голоси тільки цих дерев — вийде чесний прогноз для клієнта, зроблений моделлю, яка з ним не знайома.

Повторивши це для всіх n клієнтів, отримаємо out-of-bag оцінку якості:

OOB-точність = ⅟n Σi [ ŷiOOB = yi ]
Розбір по символах. n — скільки всього клієнтів; i — номер клієнта, і Σi означає «пройди по всіх клієнтах і склади». yi — справжня відповідь для клієнта i, ŷi (читається «ігрек з дашком») — прогноз; надпис OOB нагадує, що прогноз зроблено лише тими деревами, які цього клієнта не бачили. Квадратні дужки [ … ] — не множення й не масив, а скорочення для «1, якщо написане всередині правда, і 0, якщо неправда». Отже вся формула словами: порахуй, скільки клієнтів вгадано, і поділи на кількість клієнтів. Це звичайна частка правильних відповідей — просто записана так, щоб було видно, які саме відповіді беруться.

Це майже те саме, що крос-валідація, тільки безкоштовно: ніякого повторного навчання, ніякої відкладеної вибірки. У scikit-learn вона вмикається одним аргументом oob_score=True, і результат читається з rf.oob_score_.

Чому це справді безкоштовно

Порівняймо витрати. Щоб отримати чесну оцінку відкладеною вибіркою, треба забрати з навчання, скажімо, 20% даних — модель вчиться на 160 клієнтах замість 200 і виходить гіршою. Пʼятикратна крос-валідація повертає ці дані, але коштує пʼять повних навчань замість одного. OOB не забирає жодного обʼєкта й не додає жодного навчання: розподіл на «бачив» і «не бачив» уже відбувся сам, усередині бутстрепу, і залишилось тільки не викинути прапорці, які й так лежать у памʼяті. Це рідкісний випадок, коли безкоштовність не має підступу — але має межі.

Коли OOB не можна вірити

  1. Дерев мало. Про кожного клієнта голосує лише та третина дерев, яка його не бачила. У нашому лісі з 36 дерев це в середньому 13.1 дерева на клієнта — подивись на табло «дерев на голос» в інтерактиві нижче. При десятьох деревах на голос припадає близько трьох, і OOB оцінює вже не той ансамбль, який ти збираєшся використовувати. Нижче сотні дерев до OOB варто ставитись як до орієнтира.
  2. OOB систематично трохи занижує. Причина — та сама третина: ансамбль із 13 дерев гірший за ансамбль із 36, а міряємо ми саме менший. Тому очікуваний напрямок похибки — песимістичний, і це найкращий із можливих напрямків: краще недооцінити модель, ніж переоцінити.
  3. Але власний шум OOB зазвичай більший за це заниження. Наша OOB рахується на 200 обʼєктах, а частка на 200 обʼєктах має стандартну похибку близько ±0.03, тобто ±3 в. п. Це помітно більше за систематичний перекіс, тому знак різниці може вийти будь-який: в інтерактиві нижче при 36 деревах OOB дає 87.5% проти 85.3% на тесті — вийшла вища, попри теоретичний песимізм. Висновок практичний: різниці в 2-3 в. п. між OOB і тестом ні про що не свідчать, і шукати в них сенс не треба.
  4. Без бутстрепу OOB не існує. Якщо поставити bootstrap=False, кожне дерево бачить усі дані, обʼєктів «поза мішком» немає взагалі, і oob_score=True просто впаде помилкою.

OOB проти тестової вибірки

Рожева крива рахується всередині навчальних даних, бірюзова — на 1200 клієнтах, яких модель не бачила.

OOB—
test—
розбіжність—
дерев на голос—
Чому на початку крива стрибає: при пʼяти деревах кожен клієнт отримує голоси лише від двох-трьох дерев, які його не бачили, та ще й рахується все на 200 обʼєктах. Це оцінка мікроскопічного ансамбля з величезною власною похибкою. Із зростанням кількості дерев вона заспокоюється й підходить до тестової.
Коли OOB бреше. Якщо в даних є групи повʼязаних записів (кілька транзакцій одного клієнта, кілька знімків одного пацієнта), бутстреп розкидає їх по різні боки, і «невидимий» обʼєкт насправді майже дублює побачений. OOB тоді завищує якість — рівно так само, як звичайна випадкова крос-валідація. Рятує групова валідація за ідентифікатором.

ІнтерпретаціяВажливість ознак і її пастки

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

MDI — середнє зменшення забрудненості

Це те, що sklearn віддає у feature_importances_. Для кожного вузла беруть приріст чистоти від його розрізу, множать на частку обʼєктів у вузлі й додають до рахунку тієї ознаки, за якою різали. Потім усе усереднюють по деревах і нормують на суму:

MDI(f) = Σвузли по f (nвузла/N) · Δimpurity

Словами: пройди по всіх вузлах усіх дерев, де різали за ознакою f, і склади їхні прирости чистоти — кожен зважений тим, скільки обʼєктів через цей вузол пройшло.

Розбір по символах. f — ознака, важливість якої рахуємо. Σвузли по f — сума по всіх вузлах, де розріз зроблено саме за цією ознакою. nвузла — скільки обʼєктів дійшло до цього вузла, N — скільки всього обʼєктів у навчальній вибірці; їхнє відношення — вага вузла. Вона потрібна, щоб корінь, крізь який проходять усі 200 клієнтів, важив більше за листковий вузол із трьома обʼєктами. Δimpurity (грецька дельта — «зміна») — наскільки зменшилась забрудненість Джині після цього розрізу; це та сама величина, яку жадібний алгоритм із теми 23 · Дерева рішень максимізує, обираючи розріз. Наприкінці всі шість чисел ділять на їхню суму, щоб вони складались в одиницю — тому MDI читається як частка, а не як абсолютна величина.

Рахується безкоштовно — усі числа вже є після навчання. Але має дві відомі вади. Перша: зсув на користь ознак із багатьма різними значеннями. У неперервної ознаки сотні кандидатів на поріг, у бінарної — один; за чистої випадковості неперервна частіше знаходить розріз, який хоч трохи зменшує забрудненість. Друга: MDI рахується на навчальних даних, тому щедро оплачує розрізи, зроблені по шуму.

Перестановкова важливість — падіння якості від псування ознаки

Перестановкова важливість (permutation importance) — так вона зветься в глосарії курсу; у коді ти зустрінеш її під англійською назвою, як функцію permutation_importance з модуля sklearn.inspection, і далі в лекції ми теж користуємось коротким «PI». Підхід прямолінійний: візьми навчений ліс і тестову вибірку, виміряй точність. Потім перемішай значення однієї ознаки між обʼєктами — так її звʼязок із цільовою змінною руйнується, а розподіл лишається тим самим — і виміряй точність знову. Наскільки вона впала, настільки ознака й важлива.

PI(f) = точність(X) − точність(X із перемішаною колонкою f)

Дорожче (потрібні повторні прогони) і шумніше (перемішування випадкове, тому роблять кілька повторів і усереднюють), зате чесно: вимірюється на даних, яких модель не бачила.

Дві важливості на одному лісі

Той самий ліс, шість ознак. Дві останні — навмисний шум, який нічого не пояснює.

MDI · id сесії—
PI · id сесії—
MDI · канал—
PI · канал—
Головне спостереження: «ідентифікатор сесії» — випадкове число, яке за побудовою не несе жодної інформації. MDI все одно дає йому помітну частку, бо в нього багато різних значень. Permutation importance майже нульова — і вона права.

Випишімо те, що показує ця фігура, числами — бо в них увесь сенс розділу. Ліс із 30 дерев, шість ознак, mtry = 3, базова точність 82.8% на 500 тестових клієнтах:

ознакаMDI, часткаPI, падіння точностіщо це насправді
стаж21.2%10.4 в.п.справжня ознака
витрати26.2%10.4 в.п.справжня ознака
транзакції29.6%13.4 в.п.майже дублікат витрат
у застосунку16.0%0.6 в.п.майже дублікат стажу
id сесії6.1%−0.2 в.п.чистий шум
канал0.9%0.0 в.п.чистий шум, два значення

Два останні рядки — та сама пастка, показана в лоб. Обидві ознаки шумові за побудовою, обидві мали б отримати нуль. Але «id сесії» — випадкове дійсне число, у якого 200 різних значень і, отже, 199 кандидатів на поріг; «канал» приймає лише два значення, тобто дає рівно один можливий поріг. Вибір із двохсот дає більше шансів випадково натрапити на розріз, який хоч трохи зменшує забрудненість — і MDI віддає шуму з багатьма значеннями 6.1% проти 0.9% у шуму з двома. Вся різниця між ними — у кількості значень, бо інформації нема ні там, ні там. Permutation importance ставить обох на місце: −0.2 і 0.0 відсоткових пункти, тобто нуль у межах похибки перемішування.

Значення нижче нуля не має бентежити: якщо ознака нічого не важить, зіпсувати її іноді означає випадково покращити результат. Саме тому перемішування повторюють кілька разів і усереднюють — покрути повзунок повторів і подивись, як число заспокоюється.

А рядок «у застосунку» показує другу пастку, ще до того, як ми до неї дійшли: MDI дає йому 16.0%, permutation importance — 0.6 в.п. Ознака справжня, але вона майже повторює «стаж», і викинути її можна майже безкарно — бо все, що вона знає, уже є в іншій колонці.

Обидві важливості відповідають на питання «що впливає загалом». Питання «чому модель так вирішила про це конкретне оголошення» — інше, і відповідають на нього іншими засобами: значеннями Шеплі, локальними наближеннями, частинною залежністю. Разом із тим, чому переконливе пояснення буває небезпечнішим за його відсутність, це розібрано в темі 40 · Інтерпретованість.

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

Це легко перевірити на тих самих даних. Приберімо обидва майже-дублікати — «транзакції» й «у застосунку» — і навчімо ліс наново: ті самі 30 дерев, те саме зерно, чотири ознаки замість шести й mtry = 2 (та сама половина ознак на вузол, що й раніше).

ознакаMDI · шість ознакMDI · чотири ознаки
витрати0.2620.494
стаж0.2120.351
id сесії0.0610.144
канал0.0090.012

Важливість «витрат» піднялась із 0.262 до 0.494, «стажу» — з 0.212 до 0.351, і сталося це без жодної зміни в самих ознаках: витрати лишились тими самими витратами. Змінилось тільки те, що їм більше ні з ким ділити заслугу. Точність лісу при цьому майже не ворухнулась — 84.2% проти 84.4% на тестовій вибірці, тобто дві викинуті колонки не несли нічого, чого не було в решті.

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

⚠️ І ще один побічний ефект. У таблиці вище в шумового «id сесії» важливість теж зросла — з 0.061 до 0.144. Це не тому, що шум став кориснішим. Просто ознак стало менше, а MDI нормують на суму: коли ділиш ті самі гроші між чотирма, а не шістьма, частка кожного зростає. Ще одна причина не читати MDI як абсолютну величину.

ТеоріяЧому ліс не перенавчається

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

Спершу — про саму назву розділу. Фраза «ліс не перенавчається» ходить по підручниках і форумах, і в такому вигляді вона неправильна. Перенавчання — це коли модель вивчила шум навчальної вибірки замість закономірності; ліс на таке цілком здатен, і ми покажемо, як саме. Точне твердження вужче: ліс не перенавчається від додавання дерев. Це єдина ручка, яку можна крутити нескінченно без ризику, і саме її мають на увазі, коли кажуть коротку фразу. Тримай цю різницю в голові до кінця розділу — наприкінці ми повернемось і назвемо межу точно.
крок 1 · незалежні моделі

Нехай кожне дерево дає прогноз із дисперсією σ². Якщо прогнози незалежні, дисперсія середнього з M штук — класична формула:

Var(середнє) = σ2 / M

Тобто при M = 100 розкид падає в сто разів. Занадто добре, щоб бути правдою.

крок 2 · корельовані моделі

Насправді дерева вчаться на тих самих даних, і їхні помилки корельовані з коефіцієнтом ρ. Тоді формула стає такою:

Var(середнє) = ρ·σ2 + (1 − ρ)·σ2 / M

Перевірмо її на краях, це найшвидший спосіб повірити формулі. При ρ = 0 (дерева незалежні) перший доданок зникає, і лишається σ²/M — рівно крок 1. При ρ = 1 (усі дерева ідентичні) другий доданок зникає, і лишається σ² — дисперсія одного дерева, тобто ансамбль не дав нічого. Обидва краї сходяться зі здоровим глуздом.

крок 3 · читаємо результат

Другий доданок згасає з ростом M — його ми перемагаємо кількістю дерев. Перший не залежить від M взагалі: скільки дерев не додавай, нижче ρσ² дисперсія не опуститься. Ось чому декореляція така важлива: вона знижує саме ту стелю, яку кількістю не пробити.

Розбір по символах.

Порахуймо руками. Візьмімо σ² = 1 (щоб дивитись на частки) і подивімось, що дає кількість дерев при різній кореляції:

Mρ = 0 (мрія)ρ = 0.1 (сильна декореляція)ρ = 0.4 (типовий ліс)ρ = 0.9 (дерева-близнюки)
11.0001.0001.0001.000
100.1000.1900.4600.910
1000.0100.1090.4060.901
10 0000.00010.10010.40010.9001
стеля00.10.40.9

Перевірмо один рядок вручну, щоб не було магії: ρ = 0.4, M = 10 дає 0.4 · 1 + (1 − 0.4) · 1 / 10 = 0.4 + 0.06 = 0.46. Тепер прочитаймо таблицю цілком. Перехід від 10 до 100 дерев при ρ = 0.4 знижує розкид із 0.460 до 0.406 — виграш є, але скромний. Перехід від 100 до 10 000 дерев (у сто разів більше обчислень!) дає 0.406 → 0.4001, тобто майже нічого. А ось перехід від ρ = 0.4 до ρ = 0.1 при тих самих 100 деревах — це 0.406 → 0.109, розкид учетверо менший. Кореляція важить незмірно більше за кількість, і саме тому лекція витратила два розділи на два трюки декореляції й один абзац на вибір n_estimators.

Стеля, яку не пробити кількістю

Дисперсія середнього за формулою кроку 2 при σ² = 1. Пунктир — стеля ρσ².

Var(середнє)—
стеля ρσ²—
лишилось до стелі—
подвоєння дерев зніме—
Постав ρ = 0 і потім ρ = 0.4. Перша крива йде до нуля, друга — зупиняється на 0.4 і далі йде горизонтально. Це та сама формула, різниця лише в одному числі. Табло «подвоєння дерев зніме» показує, скільки виграє наступне подвоєння n_estimators: після кількох десятків дерев це вже треті знаки після коми.

І тепер стає видно, як ліс усе-таки може перенавчитись, попри назву розділу. Формула нічого не обіцяє про зміщення — вона лише прибирає дисперсію. Якщо дерева вивчили шум однаково (наприклад, вибірка крихітна, і всі бутстреп-жереби майже збігаються; або в даних є ознака-витік, за яку хапається кожне дерево), то помилка перестала бути дисперсією й стала зміщенням — а зміщення усередненням не лікується. Формально це видно як ρ, що поповзла до одиниці: стеля піднялась до σ², і кількість дерев уже нічого не варта.

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

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

ПорівнянняЛіс проти бустингу

Випадковий ліс — не єдиний спосіб зібрати ансамбль із дерев. Другий великий підхід — бустинг (XGBoost, LightGBM, CatBoost), і різниця між ними принципова. Тут — коротке порівняння; механіку бустингу крок за кроком розібрано в наступній темі 25 · Бустинг.

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

критерійвипадковий лісградієнтний бустинг
дереваглибокі, незалежнімілкі (3–8), послідовні
зменшуєдисперсіюзміщення
навчанняпаралельне, легко масштабуєтьсяпослідовне за побудовою
налаштуванняпрацює «з коробки»чутливий до learning_rate і глибини
перенавчанняне росте з кількістю деревросте — потрібна рання зупинка
стеля якостітрохи нижчазазвичай вища на табличних даних

Практичне правило просте. Ліс — це надійна базова лінія, яку варто отримати за пʼять хвилин на початку роботи: він майже не вимагає налаштування, дає OOB-оцінку задарма й рідко поводиться несподівано. Бустинг — це те, чим виграють змагання, коли готовий витратити час на підбір гіперпараметрів і маєш достатньо даних.

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

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

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