Уяви редактора, який вичитує чужий рукопис. Перший прохід ловить грубе: пропущені коми, зламані відмінки. Другий прохід уже не шукає ком — вони виправлені; він шукає те, що лишилось. Третій працює з тим, що проґавив другий. Жоден окремий прохід не геніальний, жоден не переписує текст заново — і все ж після десятка проходів рукопис чистий.
У попередній темі ми зібрали ансамбль іншим способом: сто дерев виросли незалежно, кожне на своїй бутстреп-вибірці, і відповідь дало голосування. Це ансамбль-натовп. Сьогодні буде ансамбль-конвеєр: моделі з’являються по черзі, і кожна наступна працює виключно з тим, що недоробили попередні. Метод називається бустинг (boosting — «підсилення»), а його найпоширеніший різновид — градієнтний бустинг.
Наскрізний приклад лишається тим самим, що й у темах про перенавчання та регуляризацію: дошка оголошень про вживані телефони. Задача — передбачити ціну за роком випуску. На регресії послідовне виправлення видно найкраще: можна буквально подивитись, як на кожному кроці тане недорахована частина ціни.
01 / Два підходиДві філософії ансамблю
Ансамбль — це набір моделей, чиї відповіді зливають в одну. Способів зібрати такий набір рівно два, і вони протилежні за задумом.
Ліс — це паралель. Кожне дерево бачить свою випадкову підвибірку й свій випадковий набір ознак, кожне росте до кінця, тобто кожне саме по собі досить сильне. Дерева помиляються по-різному, і при усередненні їхні відхилення взаємно гасяться. Мовою розкладу помилки: ліс б’є по дисперсії, лишаючи зміщення таким, яким воно було в одного глибокого дерева — тобто малим.
Бустинг — це послідовність. Дерева тут навмисне слабкі: три-чотири питання, і все. Одне таке дерево має велике зміщення — воно грубо, приблизно описує залежність. Але кожне наступне додається саме туди, де попередні недобрали, і сума поступово згинається під форму даних. Бустинг б’є по зміщенню.
Ці ролі — «ліс проти дисперсії, бустинг проти зміщення» — задають усі практичні відмінності: глибину дерев, чутливість до налаштувань, поведінку при зростанні їхньої кількості. Порівняльна таблиця вже є в §12 попередньої теми; тут ми не переказуємо її, а розбираємо механіку, з якої вона виростає.
Схема 1 · Паралельно проти послідовно
Ліворуч — ліс: усі дерева бачать ті самі дані й голосують. Праворуч — бустинг: кожне дерево бачить лише те, що недорахували попередні.
02 / МатеріалНавіщо навмисне слабкий учень
Слабкий учень (weak learner) — модель, яка ледь краща за найпримітивнішу відповідь. Для регресії найпримітивніша відповідь — середня ціна по всій дошці; слабкий учень має бути хоч трохи точнішим за неї. Крайній випадок такої моделі має власне імʼя: пеньок (stump) — дерево глибиною один, тобто єдине питання й дві відповіді. На восьми оголошеннях, з якими ми зараз працюватимемо, він виглядає так: «рік випуску до 2021 включно?» — так, 3 133 грн; ні, 12 000 грн. Оце й уся модель.
Здається дивним: у нас є алгоритм, який уміє будувати повноцінні дерева, — навіщо свідомо себе обмежувати? Відповідь у тому, що́ саме ансамбль уміє виправляти.
Усереднення незалежних моделей — інструмент проти дисперсії, і йому потрібні учасники з малим зміщенням, тобто глибокі. Послідовне додавання — інструмент проти зміщення, і йому потрібно рівно навпаки: учасники з малою дисперсією, бо їхні власні випадкові похибки тут не гасяться, а накопичуються. Мілке дерево майже не залежить від того, які саме оголошення потрапили у вибірку: воно ставить одне-два питання по найсильнішій закономірності. Глибоке дерево гуляє від вибірки до вибірки — і ланцюжок із таких дерев успадкує весь цей розкид, помножений на кількість кроків.
Ось сорок пʼять оголошень із нашої дошки і чотири моделі на них. Три перші — одне дерево різної глибини, навчене одразу на ціні. Четверта — ланцюжок із двадцяти семи дерев глибини 2, той самий, що буде далі в цій лекції:
| модель | помилка на навчальних, грн | помилка на нових, грн |
|---|---|---|
| пеньок, глибина 1 | 2 715 | 2 572 |
| дерево, глибина 3 | 947 | 1 367 |
| дерево, глибина 10 | 0 | 1 575 |
| 27 дерев глибини 2 | 887 | 1 181 |
Читаємо рядки. Пеньок нікуди не годиться: 2 572 грн помилки — це майже ціна дешевого телефона. Дерево глибини 10 запамʼятало навчальні дані до нуля й на нових працює гірше, ніж дерево глибини 3, — класичне перенавчання. А ланцюжок із дерев глибини 2, жодне з яких саме по собі не варте нічого, дає 1 181 грн — на 186 грн краще за найкраще дерево в цій таблиці. Слабкість учня тут не вада, а умова роботи методу.
03 / МеханікаНавчання на залишках
Тепер найважливіше. Візьмімо вісім оголошень — по одному на кожні два роки — і пройдімо ланцюжок руками.
Крок нульовий: моделі ще немає, тому найкраща відповідь — середня ціна. Складаємо всі вісім і ділимо на вісім:
Позначення F (від function) — це прогноз усього ансамблю,
а нижній індекс — скільки дерев у нього вже додано. F0 — ансамбль із нуля
дерев, тобто просто константа.
Тепер визначимо головне слово теми. Залишок (residual) — це різниця між фактом і поточним прогнозом:
Тут y — справжня ціна оголошення, F(x) — те, що каже ансамбль,
а r — недорахована частина. Для найдорожчого телефона 2024 року залишок після
нульового кроку становить 15 200 − 5 350 = 9 850 грн. Модель недооцінила
його майже на десять тисяч.
Ідея бустингу вміщається в один рядок: навчімо наступне дерево не на цінах, а на залишках. Для дерева це звичайнісінька задача регресії — просто цільова змінна тепер називається «скільки гривень ми недорахували». Знайдене дерево додаємо до ансамблю:
Читаємо посимвольно. Fm−1 — ансамбль, який був;
hm — щойно навчене на залишках дерево;
ν (грецька «ню») — швидкість навчання, число від 0 до 1, яке
каже, яку частку поправки взяти. Дерево додається не цілком, а вкороченим — щоб ансамбль не
стрибав через ціль. Чому саме так і що буває при ν = 1, розберемо в §5; поки
що візьмімо ν = 0.5, тобто «додаємо половину знайденої поправки».
Перше дерево (глибина 2, тобто чотири листки) розбило вісім оголошень на чотири групи й для кожної порахувало середній залишок. Чотири найстаріші телефони, 2010–2016 років, константа переоцінила в середньому на 2 975 грн — їхній залишок вийшов від’ємним. Пару 2018 і 2020 — на 700 грн. А от телефон 2022 року вона недооцінила на 3 450 грн, телефон 2024-го — аж на 9 850 грн. Беремо половину кожної поправки й додаємо до 5 350. Ось що вийшло, і ось що з цього вчитиме друге дерево:
| рік | факт | прогноз F1 | залишок r1 | внесок 2-го | прогноз F2 | залишок r2 |
|---|---|---|---|---|---|---|
| 2010 | 2 000 | 3 863 | −1 863 | −715 | 3 148 | −1 148 |
| 2012 | 2 200 | 3 863 | −1 663 | −715 | 3 148 | −948 |
| 2014 | 2 400 | 3 863 | −1 463 | −715 | 3 148 | −748 |
| 2016 | 2 900 | 3 863 | −963 | −715 | 3 148 | −248 |
| 2018 | 3 800 | 5 000 | −1 200 | −715 | 4 285 | −485 |
| 2020 | 5 500 | 5 000 | +500 | +250 | 5 250 | +250 |
| 2022 | 8 800 | 7 075 | +1 725 | +863 | 7 938 | +862 |
| 2024 | 15 200 | 10 275 | +4 925 | +2 463 | 12 738 | +2 462 |
Порахуй кілька клітинок очима — арифметика тут уся на поверхні. Рядок 2024: прогноз після першого дерева 10 275, факт 15 200, залишок 15 200 − 10 275 = 4 925. Друге дерево внесло +2 463, отже 10 275 + 2 463 = 12 738, і новий залишок 15 200 − 12 738 = 2 462. Був 9 850, став 4 925, став 2 462. Рядок 2016: залишок стиснувся з −963 до −248. Рядок 2018: з −1 200 до −485.
Тепер зведімо всі вісім залишків в одне число — корінь із середнього квадрата помилки (RMSE, метрика з теми про метрики):
| дерев у ланцюжку | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|---|
| RMSE, грн | 4 290 | 2 186 | 1 115 | 587 | 302 | 161 | 102 |
| найбільший залишок, грн | 9 850 | 4 925 | 2 463 | 1 231 | 616 | 308 | 169 |
Обидва рядки приблизно діляться навпіл із кожним деревом. Це і є бустинг: жодне окреме дерево не вирішує задачу, але кожне забирає свою частку того, що лишилось.
Інтерактив 1 · Залишки крок за кроком
Ті самі вісім оголошень. Угорі — прогноз ансамблю, унизу — стовпчики залишків. Сірі контури позаду — залишки на старті, з чого все починалось.
04 / ЗбіркаАлгоритм у пʼять рядків
Тепер увесь градієнтний бустинг для регресії можна записати повністю. Задано навчальну
вибірку, кількість дерев M, швидкість навчання ν й обмеження на
одне дерево (глибина, мінімальний розмір листка):
- Почни з константи:
F0дорівнює середній ціні по навчальній вибірці. - Для кожного кроку
m = 1…Mпорахуй залишки всіх обʼєктів:ri = yi − Fm−1(xi). - Навчи мілке дерево
hmпередбачати ці залишки за тими самими ознаками. - Онови ансамбль:
Fm = Fm−1 + ν · hm. - Кінцевий прогноз — сума константи й усіх дерев із їхніми множниками.
Ніякої ваги обʼєктів, ніякого перезважування вибірки — лише зміна цільової змінної на кожному кроці. Це варто підкреслити, бо історично першим бустингом був AdaBoost (1995), і він працює інакше: вибірка там лишається тою самою, а змінюються ваги обʼєктів — після кожної ітерації неправильно класифіковані приклади важчають, і наступна модель приділяє їм більше уваги. Градієнтний бустинг (Джером Фрідман, 1999) замінив цю ідею на загальнішу: замість ваг — залишки, замість «правильно чи ні» — будь-яка диференційовна функція втрат. AdaBoost виявився окремим випадком градієнтного бустингу з експоненційною втратою.
05 / КрокШвидкість навчання
Повернімось до множника ν. Навіщо навмисне вкорочувати поправку, якщо дерево
вже знайшло її оптимальну величину?
Відповідь найлегше побачити на тому самому оголошенні 2024 року. У нашому ланцюжку воно
опинялось у власному листку — саме одне, — тому дерево щоразу вгадувало його залишок точно.
Підставмо це в правило оновлення. Якщо h дорівнює залишку r, то
новий залишок дорівнює:
Тобто кожен крок множить залишок на (1 − ν). При ν = 0.5
залишок ділиться навпіл: 9 850 → 4 925 → 2 463 → 1 231 → 616 → 308. Саме ці числа стоять у
таблиці вище — вони не «схожі» на геометричну прогресію, вони і є нею.
Порахуймо, скільки кроків треба, щоб недоплата за цей телефон упала нижче 500 грн:
| швидкість навчання | множник за крок | залишок після 1 кроку | кроків до 500 грн |
|---|---|---|---|
| 1.0 | 0 | 0 грн | 1 |
| 0.5 | 0.5 | 4 925 грн | 5 |
| 0.1 | 0.9 | 8 865 грн | 29 |
Тобто ν = 1 закриває помилку за один крок, а ν = 0.1 — за
двадцять девʼять. Виглядає так, ніби великий крок кращий у всьому. Пастка в слові
«точно»: дерево вгадало залишок точно лише на навчальних даних. У залишку сидить не
тільки закономірність, а й шум — випадкове відхилення ціни цього конкретного продавця. Крок
ν = 1 заганяє в ансамбль і сигнал, і шум одним рухом, без права на перегляд.
Малий крок додає потроху: сигнал, який повторюється в багатьох оголошеннях, накопичується
від дерева до дерева, а шум, який у кожного оголошення свій, накопичуватись не встигає.
Інтерактив 2 · Чотири швидкості навчання на одному наборі
45 оголошень для навчання, 300 нових для перевірки. Показано помилку на нових оголошеннях залежно від кількості дерев. Вісь кількості дерев — логарифмічна.
learning_rate і
n_estimators — не два незалежні гіперпараметри, а один із двома ручками:
зменшив крок удвічі — приблизно вдвічі збільш кількість дерев. Робочий рецепт: постав
learning_rate у діапазон 0.05–0.1, а кількість дерев підбирай ранньою зупинкою
з §7. Ще менший крок майже ніколи не окупається: дно вже не опускається, а рахувати
доводиться вдвічі-втричі довше. Про те, як узагалі шукають такі пари, — тема
про підбір гіперпараметрів.06 / МістокЧому це градієнтний спуск
Слово «градієнтний» у назві досі виглядало прикрасою: ми ніде не рахували жодної похідної, а просто віднімали прогноз від факту. Зараз стане видно, що це одне й те саме.
У темі про градієнтний спуск правило було таке: щоб зменшити втрату, зрушуй параметр проти градієнта. Виведімо, у що воно перетворюється тут.
Візьмімо звичайну квадратичну втрату, з половинкою попереду — вона потрібна лише щоб двійка від похідної скоротилась і формула була охайною:
Тут y — справжня ціна, F — число, яке видав ансамбль для
цього оголошення. Далі ми диференціюємо саме по F, а не по вагах моделі —
і в цьому весь фокус.
Похідна квадрата дає множник 2, який скорочується з половинкою, а внутрішня похідна
(y − F) по F дорівнює −1:
Словами: градієнт втрати по прогнозу — це залишок зі знаком мінус. А отже, антиградієнт (напрямок, куди треба рухатись) — це рівно залишок.
Правило спуску «відійди від градієнта на ν кроку» у позначеннях цієї теми виглядає так:
Порівняй із правилом бустингу Fm =
Fm−1 + ν·hm. Вони збігаються,
щойно дерево h передбачає залишок r. Дерево — це і є
наближення антиградієнта.
Оголошення 2024 року: y = 15 200, F0 = 5 350.
Градієнт: −(15 200 − 5 350) = −9 850. Антиградієнт: +9 850.
Перше дерево виділило це оголошення в окремий листок і поставило туди рівно 9 850.
Крок із ν = 0.5:
Саме це число стоїть у таблиці §3 у рядку 2024. Ми щойно зробили крок градієнтного спуску, навіть не назвавши його так.
Тепер найважливіше — у якому просторі робиться крок. У темі 16 ми
рухали число: вага w зсувалась на −η·∂L/∂w, і після кроку модель
лишалася тою самою прямою, просто з іншим нахилом. Тут ми рухаємо функцію: до
F додається ціле нове дерево. Прогноз для кожного оголошення робить свій крок
проти градієнта, а дерево — це спосіб задати всі ці кроки однією компактною формулою.
Звідси й назва: градієнтний спуск у просторі функцій. І звідси ж
випливає узагальнення, заради якого все й затівалось. Якщо взяти іншу втрату, антиградієнт
буде іншим — і дерева вчитимуться вже не на залишках. Для абсолютної втрати
|y − F| похідна дорівнює ±1, тож дерева вчаться на знаках помилок:
модель стає стійкою до викидів, бо оголошення з помилкою в 50 000 грн тягне рівно стільки
ж, скільки помилка в 50 грн. Для класифікації беруть логістичну втрату з
теми 17, і антиградієнт стає різницею
між міткою та передбаченою ймовірністю. Механіка ланцюжка при цьому не змінюється жодним
рядком.
Схема 2 · Той самий спуск у двох просторах
Ліворуч — те, що було в темі 16: крок змінює число. Праворуч — те, що робить бустинг: крок додає функцію.
07 / МежаКоли дерев забагато
Ось тут бустинг найсильніше відрізняється від лісу, і на цьому спотикаються найчастіше. У лісі кількість дерев — питання бюджету: більше дерев ніколи не шкодить, крива якості просто виходить на плато. У бустингу більше дерев цілком може зашкодити, і причина проста: кожне нове дерево вчиться на залишках, а коли закономірність уже вибрана, у залишках лишається сам лише шум. Ансамбль слухняно починає підганятися під шум.
Перевіримо це на 45 навчальних оголошеннях і 300 нових, яких модель не бачила.
Інтерактив 3 · Ланцюжок дерев і рання зупинка
Швидкість навчання 0.1, дерева глибини 2. Угорі — прогноз ансамблю на дошці оголошень, унизу — дві помилки як функції кількості дерев.
Розвʼязок стандартний і називається рання зупинка (early stopping).
Відкладаємо частину навчальних даних у валідаційну вибірку, після кожного дерева міряємо на
ній помилку й припиняємо, щойно вона перестала покращуватись протягом заданої кількості
кроків підряд. У бібліотеках це параметр на кшталт early_stopping_rounds=50:
«якщо пʼятдесят дерев поспіль не дали покращення — зупиняйся й повертай найкращий стан».
Друге спостереження з тієї самої картинки. Навчальна помилка падає монотонно й ніколи не розвертається — тому за нею неможливо помітити момент, коли стало гірше. У бустингу не буває «крива навчання сама покаже»: без відкладених даних ти не бачиш взагалі нічого.
08 / КеруванняГоловні ручки
Бустинг куди чутливіший до налаштувань, ніж ліс. Ліс працює «з коробки» майже завжди; бустинг зі значеннями за замовчуванням може дати як чудовий результат, так і посередній. Ось ручки, які вирішують, згруповані за тим, на що вони впливають.
Схема 3 · Ручки бустингу та їхні компроміси
Імена наведено як у scikit-learn; у XGBoost і LightGBM вони називаються трохи інакше, але означають те саме.
| ручка | що робить | більше означає | з чим торгується |
|---|---|---|---|
n_estimators | довжина ланцюжка | точніше на навчальних, ризик перенавчання | прямо з learning_rate |
learning_rate | частка дерева, що додається | швидше, але грубіше й із вищим дном | обернено з n_estimators |
max_depth | складність одного дерева | ловить взаємодії ознак і швидше перенавчається | з довжиною ланцюжка |
num_leaves | те саме в LightGBM, але через кількість листків | дерево росте вглиб нерівномірно | з min_data_in_leaf |
min_samples_leaf | скільки оголошень має бути в листку | грубіші дерева, менше листків на одну точку | з глибиною |
subsample | частка рядків на одне дерево | 0.5–0.8 додає різноманітності й пришвидшує | трохи більше шуму в кривій |
colsample_bytree | частка ознак на одне дерево | як mtry в лісі: декорелює дерева | з силою окремого дерева |
reg_lambda | штраф на величину значень у листках | обережніші поправки | з умінням дотягтись до складних ділянок |
learning_rate і
великий n_estimators з ранньою зупинкою. Потім підбирай глибину або
кількість листків — це друга за важливістю ручка. І лише в кінці, якщо є час, —
subsample, частку ознак і регуляризацію. Розробники XGBoost радять
задавати max_depth явно, а LightGBM — num_leaves: у цих
бібліотек значення за замовчуванням щедрі, і без явного обмеження перенавчання настає
швидко.09 / ІнструментиТри реалізації
Ідея бустингу одна, реалізацій багато, і три з них покривають майже всі практичні випадки. Розрізняються вони не якістю ідеї, а інженерією: як швидко знайти розріз і як рости дереву.
Спільне для всіх трьох — гістограмний пошук розрізу. Класичне дерево перебирає всі можливі пороги між сусідніми значеннями ознаки; при мільйоні рядків це мільйон кандидатів на кожну ознаку в кожному вузлі. Гістограмний підхід спершу розкладає значення ознаки по 255 кошиках і перебирає лише межі кошиків. Точність розрізу трохи падає, швидкість зростає на порядок — і на великих даних це вирішальна перевага.
Схема 4 · Чим три бібліотеки відрізняються по суті
Без реклами: усі три роблять те саме, різниця в тому, як саме.
| риса | XGBoost | LightGBM | CatBoost |
|---|---|---|---|
| як росте дерево | рівнями: спершу весь поточний рівень | листям: ділить той листок, що дає найбільший виграш | симетрично: один і той самий розріз на весь рівень |
| головне гальмо | max_depth | num_leaves | depth |
| категоріальні ознаки | потрібне кодування наперед | вміє напряму | вміє напряму, з упорядкованою статистикою по цілі |
| сильна сторона | найдовша історія, найбільше опцій і документації | швидкість на великих таблицях | найменше клопоту з коробки, менше витоку при кодуванні категорій |
| типова пастка | легко забути обмежити глибину | ріст листям перенавчається швидше за ріст рівнями | повільніший на малих даних |
num_leaves, бо
max_depth тут майже нічого не стримує.І чесна оцінка місця бустингу серед усього іншого. На табличних даних —
тобто там, де є рядки й колонки, числа й категорії, а не картинки чи текст — градієнтний
бустинг на деревах зазвичай найсильніше з наявного. Він регулярно виграє в нейронних мереж
на таких задачах і майже завжди — у лінійних моделей і одиночних дерев. Це не маркетинг, а
багаторічне спостереження за змаганнями й промисловими системами. У
scikit-learn є власна гістограмна реалізація —
HistGradientBoostingRegressor, — і для більшості задач її цілком досить, щоб
не ставити зовнішню бібліотеку.
10 / МежіКоли бустинг не потрібен
Найкращий алгоритм на табличних даних — не означає «завжди правильний вибір». Є три ситуації, у яких бустинг варто відкласти.
Мало даних. На двохстах рядках бустинг здебільшого програє лісу: ланцюжок із мілких дерев уміє дуже точно підганятись, а перевіряти цю точність нема на чому. Рання зупинка вимагає валідаційної вибірки, а відкласти двадцять рядків із двохсот — це отримати оцінку з таким розкидом, що вона ні на що не вкаже. Ліс у цьому режимі надійніший: він дає OOB-оцінку задарма й не має параметра, який можна катастрофічно не вгадати.
Потрібно пояснити рішення. Одне дерево можна намалювати й прочитати вголос. Сто дерев лісу вже ні, але ліс хоча б дає важливості ознак, які приблизно відповідають інтуїції. Бустинг у цьому сенсі найтемніший: його дерева передбачають не ціну, а залишок — величину, у якої немає побутового сенсу. Питання «чому модель поставила цьому телефону 12 700 грн» вимагає окремих інструментів пояснення, і відповідь на нього завжди буде наближеною.
Немає часу на налаштування. Ліс має по суті одну ручку
(max_features) і працює зі значеннями за замовчуванням. Бустинг має мінімум
дві повʼязані пари й вимагає ранньої зупинки. Якщо потрібна базова лінія за пʼять хвилин —
бери ліс. Якщо потрібен максимум і є година — бери бустинг.
11 / ПідсумокЩо варто винести
Бустинг — це відповідь на питання «а що, як робити моделі не паралельно, а по черзі». Відповідь виявилась потужнішою, ніж очікували, бо разом із нею прийшов цілий спосіб думати про навчання.
- Залишок — недорахована частина відповіді; наступне дерево вчиться саме на ній, а не на початковій цілі.
- Слабкий учень потрібен не для економії, а тому що похибки учасників у ланцюжку накопичуються, а не гасяться. Глибина 3–8 — робочий діапазон.
- Швидкість навчання множить залишок на (1 − ν) щокроку. Малий крок доходить до нижчого дна, але вимагає пропорційно більше дерев — це одна ручка з двома кінцями.
- Навчання на залишках — це градієнтний спуск, тільки крок робиться в просторі функцій: до прогнозу додається дерево, а не змінюється число. Змінивши функцію втрат, отримуєш іншу цільову величину для дерев — і той самий алгоритм.
- Більше дерев може зашкодити. Це головна практична відмінність від лісу. Рання зупинка по окремій валідаційній вибірці — не опція, а норма.
- Ліс проти дисперсії, бустинг проти зміщення. Дві протилежні хвороби — два протилежні ліки.
Ми пройшли блок цілком: від одного дерева через ліс до ланцюжка. Разом із лінійними моделями, kNN і наївним Баєсом у тебе тепер повна полиця алгоритмів — і одразу постає незручне питання, яке досі оминалось: як із них вибирати. Не «який алгоритм найкращий узагалі», бо такого немає, а як поставити чесне порівняння на конкретних даних, за якою метрикою й із яким запасом на випадковість. Це наступна тема.
practice.ipynb ти напишеш
градієнтний бустинг з нуля десятком рядків, звіриш його з
GradientBoostingRegressor до останнього знаку, прожене́ш три швидкості навчання,
побудуєш криву перенавчання й знайдеш точку ранньої зупинки, а наприкінці зіставиш ланцюжок
із випадковим лісом на тих самих даних.Далі в темі
Теорію прочитано. Тепер закріпи її на практиці.