У грі «двадцять питань» один гравець загадує предмет, а другий має його вгадати, ставлячи запитання, на які можна відповісти лише «так» або «ні». Хороший гравець ніколи не питає навмання. Він починає з питання, яке ділить світ навпіл: «це жива істота?». Кожна відповідь відрізає половину варіантів, і за двадцять кроків можна дійти до мільйона предметів.
Дерево рішень — це та сама гра, тільки питання ставить алгоритм, а загаданий предмет — відповідь для конкретного обʼєкта. Модель складається з вузлів рішення (питання про одну ознаку), гілок (відповіді «так» і «ні») та листків (готовий прогноз). Навчити дерево — це підібрати самі питання і їхній порядок так, щоб дійти до впевненої відповіді за якнайменше кроків.
Уся лекція побудована навколо однієї задачі. Банк хоче знати, чи залишиться клієнт із ним на наступний рік. Про кожного клієнта відомі лише два числа: стаж — скільки місяців він уже обслуговується, і витрати — скільки в середньому тисяч гривень проходить через його картку щомісяця. Двовимірна задача зручна тим, що модель можна намалювати цілком: усе, що дерево «думає», видно на площині.
01 / ІдеяМодель, яку можна прочитати вголос
Почнімо з кінця — подивімось на готову модель. Кожне питання дерева має вигляд «ознака ≤ поріг». Питання про стаж проводить на площині вертикальну лінію, питання про витрати — горизонтальну. Кожна лінія розрізає прямокутник, у якому ми зараз перебуваємо, на два менші прямокутники. Після всіх розрізів площина розпадається на набір прямокутних клітин, і в кожній клітині дерево дає одну й ту саму відповідь.
Тому дерево рішень — це кусково-стала модель. Вона не проводить плавної межі; вона розкладає простір ознак на плитки й приписує кожній плитці мітку більшості. Порухай повзунок глибини й подивись, як плиток стає більше:
Інтерактив 1 · Як дерево ріже площину
Глибина — це максимальна кількість питань поспіль. Пунктир — справжня межа, за якою генерувались дані.
Зверни увагу на дві речі. По-перше, при глибині 0 модель вироджується в константу — вона завжди називає більший клас, як і «прогноз середнім» у регресії. По-друге, при великій глибині зʼявляються крихітні плитки навколо окремих точок: дерево виділяє під один-єдиний обʼєкт власну кімнату. Це вже перенавчання, і до нього ми ще повернемось окремо.
02 / ГеометріяЧому розрізи перпендикулярні осям
Питання дерева завжди стосується однієї ознаки: «витрати ≤ 4.7?». Воно ніколи не має вигляду «0.3·стаж + 0.7·витрати ≤ 5». Причина суто обчислювальна. Щоб перебрати всі пороги за однією ознакою, достатньо відсортувати обʼєкти й пройти список — це десятки операцій. Щоб перебрати всі можливі нахилені площини, треба шукати в неперервному багатовимірному просторі напрямків, а це вже окрема задача оптимізації всередині кожного вузла.
Наслідок такий: межа рішень дерева завжди складається з відрізків, паралельних осям. Якщо справжня межа в даних теж «прямокутна» — дерево влучає в неї майже точно. А якщо справжня межа діагональна, дерево змушене будувати сходинки: багато дрібних розрізів, які наближають пряму ламаною лінією. Кожна сходинка коштує вузла, а кожен вузол коштує даних.
У наступному інтерактиві дані ті самі — просто повернуті. Логістична регресія на них працювала б однаково добре під будь-яким кутом. Дерево — ні:
Інтерактив 2 · Та сама задача, повернута на кут
Справжня межа — одна пряма (пунктир). Повертаємо дані й дивимось, що робить дерево фіксованої глибини 3.
x ≤ t не
змінюється, якщо ознаку помножити на 100 або виміряти в інших одиницях — поріг просто
перерахується. Тому деревам, на відміну від градієнтних методів і kNN, стандартизація ознак
не потрібна. Це одна з причин, чому їх так люблять на «брудних» табличних даних.03 / ЧистотаЕнтропія: міра безладу
Тепер головне питання: як алгоритм обирає, де саме різати? Потрібна числова відповідь на питання «наскільки в цьому прямокутнику намішано класів». Набір, де всі обʼєкти одного класу, називають чистим; набір, де класи порівну, — максимально брудним.
Класична міра безладу прийшла з теорії інформації. Клод Шеннон 1948 року шукав, як виміряти кількість інформації в повідомленні, і отримав величину, яку назвав ентропією:
Читається так: беремо частку кожного класу в наборі, множимо на її логарифм за основою 2, додаємо все й міняємо знак. Логарифм частки завжди відʼємний (бо частка менша за одиницю), тому мінус спереду робить H додатним. Одиниця вимірювання — біт: це середня кількість двійкових питань, потрібна, щоб дізнатися клас навмання взятого обʼєкта.
Для двох класів формула спрощується: якщо частка першого класу дорівнює p, то другого — рівно (1 − p), і вся ентропія залежить від одного числа:
Інтерактив 3 · Ентропія і Джині як функції складу
Тягни повзунок: змінюється частка класу «лишиться» у вибірці. Дивись на обидві криві.
Розглянемо крайні випадки руками. Якщо всі 40 клієнтів у вузлі лишились, то p = 1:
−1·log₂1 = 0, ентропія нульова. Невизначеності немає, ставити питання нема сенсу.
Якщо клієнти розділились навпіл, p = 0.5:
−0.5·(−1) − 0.5·(−1) = 1 біт. Рівно одне двійкове питання відділяє нас від
відповіді — це максимум для двох класів. Для трьох рівних класів максимум становить
log₂3 ≈ 1.585, для восьми — рівно 3 біти.
04 / Вибір розрізуПриріст інформації
Ентропія міряє безлад в одному наборі. Але розріз створює два набори, і треба якось порівняти «було» з «стало». Тут є тонкість: після розрізу в нас дві ентропії, і просто додати їх не можна — вузол зі ста обʼєктів важить більше за вузол із трьох.
Розвʼязок — зважене середнє, де вага кожного нащадка дорівнює частці обʼєктів, які до нього потрапили. Різниця між ентропією до розрізу і зваженою ентропією після нього називається приростом інформації (information gain):
Уяви розріз, який відрізає одну-єдину точку. Вона одна, отже її вузол ідеально чистий: H = 0. Якби ми брали просте середнє двох ентропій, такий розріз здався б чудовим — половина доданків обнулилась! Зважування ставить усе на місце: вузол з однієї точки має вагу 1/N і майже не впливає на результат.
Зважена ентропія нащадків не може перевищити ентропію батька — це наслідок опуклості логарифма. У найгіршому випадку розріз нічого не змінює (обидва нащадки мають той самий склад, що й батько), і тоді IG = 0. Тому нульовий приріст — це сигнал «краще не різати».
Приріст залежить не від точного значення порога, а лише від того, як він розділяє
відсортовані обʼєкти. Тому кандидатів рівно на один менше, ніж різних значень
ознаки: беруть середини між сусідніми значеннями. Для n обʼєктів і p ознак це
p·(n−1) варіантів — і всі вони перебираються повним перебором.
Наступний інтерактив показує цей перебір наживо. Угорі — розріз, який ти рухаєш повзунком, унизу — приріст інформації для всіх можливих порогів одразу. Алгоритм обере вершину чорної кривої:
Інтерактив 4 · Перебір усіх порогів
Нижній графік — три криві: ентропія лівого вузла, правого і приріст інформації. Ромб — оптимум.
05 / АльтернативаКритерій Джині
Ентропія — не єдина міра безладу. На практиці частіше використовують
індекс Джині, і за замовчуванням у scikit-learn стоїть саме він:
У Джині є гарна ймовірнісна інтерпретація. Витягни з вузла випадковий обʼєкт, подивись на його клас, поверни назад. Витягни другий. Джині — це ймовірність, що класи двох витягнутих обʼєктів не збігуться. У чистому вузлі така подія неможлива, звідси нуль; при рівних класах вона трапляється в половині випадків, звідси 0.5.
Обидві криві на інтерактиві 3 мають однакову форму: нуль на краях, максимум у центрі, опуклість донизу. Різниця в масштабі (ентропія доходить до 1, Джині до 0.5) і в тому, що ентропія трохи «гостріше» карає майже-чисті вузли. Практичні наслідки:
| критерій | формула | максимум | особливість |
|---|---|---|---|
| Ентропія | −Σ p log₂ p | 1 біт | потребує логарифмів — трохи повільніша |
| Джині | 1 − Σ p² | 0.5 | тільки множення, за замовчуванням у sklearn |
| Помилка | 1 − max p | 0.5 | не опукла достатньо: погано розрізняє розрізи |
Третій рядок пояснює, чому дерева не оптимізують безпосередньо точність. Помилка більшості — кусково-лінійна функція, і дуже часто два різні розрізи дають однакову помилку, хоча один із них явно кращий за складом. Опуклі міри (Джині, ентропія) розрізняють такі випадки й тому «бачать» прогрес там, де точність його не помічає.
Інтерактив 5 · Джині проти ентропії на тих самих даних
Два дерева тієї самої глибини, навчені на однаковій вибірці різними критеріями.
06 / АлгоритмID3 крок за кроком
Тепер усі складники є, і можна зібрати алгоритм навчання. Історично перший його варіант
запропонував Росс Квінлан 1986 року під назвою ID3; сучасні CART і
DecisionTreeClassifier — його прямі нащадки.
- Почни з кореня. У корені лежить уся навчальна вибірка. Порахуй її ентропію (або Джині) — це відправна точка.
- Перебери кандидатів. Для кожної ознаки відсортуй обʼєкти й розглянь усі пороги між сусідніми значеннями. Для кожного порога порахуй зважену ентропію двох нащадків і приріст інформації.
- Візьми найкращий розріз. Той, у якого приріст максимальний. Створи вузол рішення з цією ознакою й цим порогом. Ніяких «а що як інший розріз краще спрацює через два кроки» — вибір робиться тут і зараз.
- Розділи дані на дві частини й запусти ту саму процедуру окремо для кожної. Це рекурсія: кожен нащадок стає новим коренем для своєї підзадачі.
- Зупинись і зроби листок, коли спрацював один із критеріїв зупинки. У листку записується мітка більшості (для класифікації) або середнє значення (для регресії).
07 / СтруктураЯк виглядає готове дерево
Ту саму модель, яку ми досі бачили як плитки на площині, можна намалювати як схему. Це не інша модель — це той самий обʼєкт з іншого боку. Корінь угорі, під ним два нащадки, під ними їхні нащадки. Кожен вузол підписаний питанням, а колірна смужка показує склад класів у ньому. Дивись, як дерево росте, коли ти дозволяєш йому ще один рівень:
Інтерактив 6 · Дерево як схема
Смужка під питанням — склад вузла. Число під нею — скільки навчальних обʼєктів сюди дійшло.
08 / ГальмаКритерії зупинки
Якщо алгоритму не заважати, він працюватиме, доки кожен листок не стане ідеально чистим. Для будь-яких даних без повторюваних обʼєктів це завжди можливо: у найгіршому випадку дерево виділить кожному обʼєкту власний листок. Навчальна точність стане рівно 100%, а модель — марною. Тому в кожній реалізації є набір гальм:
| параметр | що обмежує | як діє |
|---|---|---|
| max_depth | кількість питань поспіль | найгрубіше й найзрозуміліше гальмо |
| min_samples_leaf | розмір листка | забороняє листки з двох-трьох обʼєктів |
| min_samples_split | розмір вузла для розрізу | не дає різати й без того малі вузли |
| max_leaf_nodes | загальну кількість листків | ріже тільки найприбутковіші вузли |
| min_impurity_decrease | мінімальний приріст | відсікає розрізи «ні про що» |
Крім штучних обмежень, є природні: вузол чистий (усі обʼєкти одного класу) або жоден розріз не дає додатного приросту (усі обʼєкти мають однакові ознаки, але різні мітки — таке буває в реальних даних постійно).
09 / ПасткаЧому глибокі дерева перенавчаються
Розберімо механіку перенавчання буквально по кроках. Нехай у нашому наборі клієнт із дуже великими витратами все одно пішов — просто через обставини, які в даних не записані. Для дерева це не випадковість, а факт, який треба пояснити. Воно робить розріз, потім ще один, і зрештою будує навколо цього клієнта крихітний прямокутник, у якому лежить лише він.
Тепер у цьому прямокутнику модель прогнозує «піде» з упевненістю 100%. Будь-який новий клієнт, що випадково потрапить у цю зону, отримає впевнений і, найімовірніше, помилковий прогноз. Дерево вивчило не закономірність, а шум.
На кривих нижче видно два дуже різні сюжети. Навчальна точність росте монотонно й доходить до 100% — інакше й бути не може, бо глибше дерево завжди може дозаучити те, що не вмістилось. Тестова точність спочатку росте разом із нею, потім розвертається:
Інтерактив 7 · Глибина проти узагальнення
Рожева крива — точність на навчальних даних, бірюзова — на 800 нових клієнтах, яких модель не бачила.
10 / ЛікиОбрізання: до і після
Є два способи не дати дереву розростись, і вони працюють у різні моменти.
Попереднє обрізання (pre-pruning)
Це те, що ми вже бачили: обмеження, які зупиняють ріст під час навчання —
max_depth, min_samples_leaf і компанія. Дешево і просто.
Слабке місце — короткозорість: алгоритм зупиняється, побачивши слабкий розріз, і не дізнається,
що одразу за ним був сильний. Це та сама проблема жадібності, тільки з іншого боку.
Інтерактив 8 · Мінімальний розмір листка
Глибина не обмежена. Єдине гальмо — заборона листків, менших за поріг.
Наступне обрізання (post-pruning)
Другий підхід чесніший: спочатку виростити дерево повністю, а потім зрізати гілки, які не
виправдовують свого існування. У scikit-learn це
cost-complexity pruning, він же алгоритм слабкої ланки. Кожному піддереву
приписують «вартість»:
Тут R(T) — помилка дерева на навчальних даних, а α — ціна, яку
ми беремо з дерева за кожен листок. При α = 0 вигідне найбільше дерево. Зі зростанням α
листки один за одним стають нерентабельними, і алгоритм згортає найслабші піддерева у
листки. Виходить не одне дерево, а ціла послідовність вкладених дерев від найбільшого до
пенька; правильне α обирають крос-валідацією.
sklearn потрібні значення
ccp_alpha отримують викликом tree.cost_complexity_pruning_path(X, y) —
він повертає список усіх α, на яких дерево змінюється. Далі звичайний перебір по цьому списку
з крос-валідацією. Це на порядок надійніше, ніж вгадувати max_depth навмання.11 / Слабке місцеНестабільність
А тепер найважливіша вада дерев, і саме вона за одну лекцію приведе нас до випадкового лісу.
Згадай, як обирається корінь: перебір усіх порогів і вибір максимуму приросту. Часто два чи три різні розрізи мають майже однаковий приріст — скажімо, 0.181 і 0.179. Різниця в третьому знаку. Але алгоритм детермінований: він бере максимум, і другий кандидат не отримує нічого.
Тепер прибери з вибірки кілька випадкових обʼєктів або додай трохи шуму. Порядок кандидатів може помінятись: тепер виграє той, що був другим. Корінь інший — і вся структура під ним будується заново, бо кожен наступний розріз залежить від попереднього. Мала зміна на вході дає велику зміну на виході.
Інтерактив 9 · Те саме завдання, інша підвибірка
Кожне натискання — нова випадкова підвибірка тих самих клієнтів і навчання з нуля.
Мовою зміщення й дисперсії: у глибокого дерева мале зміщення (воно здатне описати майже будь-яку залежність) і велика дисперсія (результат сильно залежить від конкретної вибірки). Обрізання зменшує дисперсію ціною зміщення, але повністю проблему не знімає.
12 / БалансЩо дерево вміє краще за всіх
Попри всі вади дерева лишаються робочим інструментом, і не тільки як цеглинка для ансамблів. Ось за що їх цінують:
- Інтерпретованість. Модель можна роздрукувати й показати юристові. Кожен прогноз супроводжується явним ланцюжком правил — це те, чого вимагають регуляції в кредитуванні й медицині.
- Жодної підготовки ознак. Не треба стандартизувати, не треба прибирати монотонні перетворення (логарифм ознаки не змінить дерева взагалі), не треба будувати поліноміальні ознаки — взаємодії виникають самі, бо кожен розріз робиться всередині вже відрізаної області.
- Стійкість до викидів. Розріз реагує на порядок значень, а не на їхню величину. Клієнт із витратами в мільйон гривень зсуне середнє, але для дерева він просто «крайній праворуч».
- Змішані типи даних. Категоріальні ознаки, пропуски, різні шкали в одній таблиці — усе це дерева переживають без танців із бубном.
- Швидкий прогноз. Класифікація — це кілька порівнянь чисел; глибина дерева зазвичай менша за 20.
А ось за що не варто братися деревом: гладкі залежності (пряму воно апроксимує потворними сходинками), задачі з тисячами розріджених ознак (текст, кліки), екстраполяція за межі навчального діапазону — у листку записано константу, тому для стажу 200 місяців дерево видасть те саме, що й для 24.
13 / ПідсумокЩо варто винести
Дерево рішень — це послідовність питань «ознака ≤ поріг», яка розкладає простір на прямокутники. Питання обираються жадібно: на кожному кроці той розріз, що найбільше зменшує безлад. Безлад міряють ентропією або Джині; різниця між ними на практиці невелика, а от різниця між обмеженим і необмеженим ростом — величезна.
Три речі, які легко забути й дорого відновлювати:
- Дерево без обмежень завжди дає 100% на навчальних даних. Цей результат не означає нічого, крім того, що дерево має достатньо листків.
- Розрив між train і test — головний індикатор. Дивись на нього, а не на абсолютні числа.
- Одне дерево нестабільне за побудовою. Це не помилка налаштування, це властивість жадібного рекурсивного алгоритму, і лікується вона ансамблем.
practice.ipynb ти реалізуєш пошук
найкращого розрізу й рекурсивну побудову дерева на чистому NumPy, порівняєш свою реалізацію
з DecisionTreeClassifier, побудуєш криву ccp_alpha через
крос-валідацію і зобразиш готове дерево через plot_tree.Далі в темі
Теорію прочитано. Тепер закріпи її на практиці.