🔴 Сложный ⏱️ 50 минут

Random Forest

📋 Содержание урока

Random Forest

В прошлом уроке ты построил дерево решений и увидел его главную слабость своими глазами: дерево обожает переобучаться. Дай ему расти без ограничений — и оно с готовностью выучит наизусть каждый шум в обучающей выборке, нарисует вокруг каждого отдельного объекта персональный лист и покажет ослепительную точность на тренировочных данных, которая тут же обрушится на новых примерах. Один и тот же алгоритм, обученный на двух чуть разных подвыборках одних и тех же данных, может построить два совершенно непохожих дерева — с разным корнем, разными узлами, разными итоговыми правилами. Это свойство называется нестабильностью, и долгое время оно считалось чистым недостатком дерева решений.

Random Forest, или случайный лес — идея, которая эту нестабильность не лечит, а обращает себе на пользу. Вместо того чтобы бороться за единственное «правильное» дерево, случайный лес выращивает сотни немного разных деревьев — каждое на своей случайной подвыборке данных и со своим случайным ограничением на признаки — а затем усредняет их предсказания. Отдельное дерево остаётся таким же неустойчивым и склонным к переобучению, каким было в прошлом уроке. Но усреднённое мнение сотен таких деревьев оказывается на удивление стабильным, точным и устойчивым к шуму — при том что каждое дерево строится тем же самым жадным алгоритмом ID3/CART, без единой новой идеи о том, как строить один узел.

За этим фокусом стоит не магия, а строгая математика, причём та самая, которую ты уже проходил в уроке 242 — закон больших чисел. Там ты доказывал, что среднее по $n$ независимым (или хотя бы слабо коррелированным) случайным величинам с ограниченной дисперсией имеет дисперсию, убывающую как $C/n$, и сходится к своему математическому ожиданию. Случайный лес — это, по сути, прямое инженерное приложение этого факта к предсказаниям деревьев: если сделать деревья «случайными величинами» с одинаковым матожиданием (правильным ответом) и по возможности низкой взаимной корреляцией, их среднее будет куда точнее и стабильнее, чем любое отдельное дерево.

Сегодняшний урок — про то, как именно случайный лес добивается низкой корреляции между деревьями (два независимых источника случайности: бэггинг по данным и случайность по признакам), почему усреднение снижает именно дисперсию, а не смещение, как получить честную оценку качества модели бесплатно — через out-of-bag ошибку — и почему sklearn.ensemble.RandomForestClassifier/RandomForestRegressor остаются одним из самых надёжных первых выборов в промышленном ML, даже спустя два десятилетия после появления градиентного бустинга и нейросетей.

🎯 Ты узнаешь:

  • Что такое бэггинг (bagging, bootstrap aggregating) и как строится bootstrap-выборка — подвыборка того же размера, что и обучающая, но взятая случайно с возвращением
  • Чем случайный лес отличается от простого бэггинга деревьев решений — и почему это отличие (случайное подмножество признаков в каждом узле) принципиально важно для качества
  • Почему усреднение предсказаний многих деревьев снижает дисперсию итогового предсказания, и как это напрямую следует из закона больших чисел (урок 242), только в версии, где слагаемые не полностью независимы
  • Что такое out-of-bag (OOB) ошибка и почему она даёт почти бесплатную, честную оценку качества модели без отдельной валидационной выборки
  • Как получить важность признаков (feature importance) как побочный продукт обучения леса, и чем отличаются два основных способа её посчитать
  • Почему интерпретируемость и качество модели находятся в компромиссе — и когда стоит жертвовать одним ради другого

История

Идею подсказал сам Лео Брейман — тот же статистик из Беркли, чьё имя фигурировало в прошлом уроке в связи с алгоритмом CART. В 1994 году, задолго до того, как «ансамблевые методы» стали отдельным разделом машинного обучения, Брейман опубликовал технический отчёт (а в 1996 году — статью «Bagging predictors» в журнале Machine Learning), в которой предложил простую идею: если алгоритм обучения нестабилен — то есть небольшое изменение обучающей выборки сильно меняет итоговую модель, — то усреднение предсказаний множества моделей, обученных на разных bootstrap-выборках одних и тех же данных, снижает дисперсию итогового предсказания почти без потерь в смещении. Брейман назвал это бэггингом — сокращением от bootstrap aggregating — и деревья решений оказались для него идеальным полигоном: они были максимально нестабильны, а значит, выигрывали от усреднения сильнее любого другого популярного на тот момент алгоритма.

Параллельно, в 1995 году, исследовательница из AT&T Bell Labs Тин Кам Хо предложила независимую идею — random decision forests: обучать каждое дерево не просто на своей подвыборке объектов, а ещё и на случайном подмножестве признаков, выбранном для всего дерева целиком. Идея опиралась на метод случайных подпространств (random subspace method) и была нацелена на задачи с большим числом признаков, где отдельное дерево, видя все признаки сразу, слишком легко «зацикливалось» на одних и тех же самых информативных переменных.

Брейман соединил обе идеи и довёл их до завершённой формы в статье 2001 года «Random Forests», опубликованной в том же журнале Machine Learning. Ключевое отличие от подхода Хо: случайное подмножество признаков теперь выбирается заново на каждом узле каждого дерева, а не один раз на всё дерево — это оказалось значительно эффективнее. В этой же статье Брейман (вместе с Адель Катлер, которая в дальнейшем поддерживала и коммерциализировала метод) вывел формальную оценку ошибки обобщения случайного леса через две величины: силу отдельных деревьев (strength, насколько хорошо каждое дерево предсказывает само по себе) и среднюю корреляцию между деревьями. Эта оценка — по сути формализация той самой интуиции про закон больших чисел, которую мы разберём чуть ниже: чем ниже корреляция между деревьями при сохранении их индивидуальной силы, тем ниже итоговая ошибка ансамбля. Название «Random Forests» Брейман и Катлер даже зарегистрировали как товарный знак — редкий случай, когда имя алгоритма машинного обучения оказалось юридически защищено (сейчас права принадлежат Minitab, и на практике это никак не мешает свободному использованию алгоритма в любых open-source библиотеках, включая scikit-learn).

К середине 2000-х случайный лес стал одним из самых используемых алгоритмов практического машинного обучения — задолго до бума глубокого обучения. Причина проста: он почти не требует настройки гиперпараметров, редко катастрофически переобучается даже при небрежном обращении, одинаково хорошо работает и на числовых, и на категориальных признаках, устойчив к выбросам и пропускам, и при этом даёт качество, которое ещё пятнадцать лет назад считалось эталонным на широком классе табличных задач. Именно эта репутация «надёжной рабочей лошадки» закрепилась за ним и в современных промышленных пайплайнах — даже там, где финальную модель в итоге заменяет градиентный бустинг (урок 318), случайный лес почти всегда остаётся первым baseline, с которым сравнивают всё остальное.


Бэггинг: почему много деревьев на разных подвыборках лучше одного

Интуиция

Представь, что тебе нужно оценить средний рост взрослого человека в городе, но измерить можно только 30 человек за раз, а бюджет позволяет провести измерение пять раз с разными случайными группами прохожих. Ты, конечно, не выбросишь четыре из пяти оценок и не оставишь только одну — ты усреднишь все пять полученных чисел, потому что интуитивно понимаешь: случайные ошибки отдельных выборок (кто-то попал в группу баскетболистов, кто-то — школьников) взаимно погасятся при усреднении, а систематическая часть (истинный средний рост) останется.

Бэггинг применяет ровно эту логику не к оценке среднего роста, а к обучению модели. Вместо того чтобы обучить одно дерево на всей доступной обучающей выборке, алгоритм несколько раз создаёт новую «версию» той же самой выборки — того же размера $n$, но собранную случайно, с возвращением (bootstrap-выборка), обучает на каждой такой версии отдельное дерево и в конце усредняет их предсказания. Слово «с возвращением» здесь ключевое: при формировании bootstrap-выборки каждый следующий объект выбирается заново из всех $n$ исходных объектов, поэтому один и тот же объект может попасть в подвыборку несколько раз, а какой-то другой может не попасть вовсе.

Определение

Определение (бэггинг, bootstrap aggregating): Бэггинг — это ансамблевый метод, в котором из обучающей выборки $D=\{(x_1,y_1),\dots,(x_n,y_n)\}$ строится $B$ независимых bootstrap-выборок $D_1,\dots,D_B$ того же размера $n$, каждая — путём случайного сэмплирования $n$ объектов из $D$ с возвращением. На каждой $D_b$ обучается отдельная базовая модель $f_b$ (в случайном лесе — дерево решений), а итоговое предсказание получается усреднением (для регрессии) или голосованием большинства (для классификации) предсказаний всех $B$ моделей:

$$\hat f_{\text{bag}}(x) = \frac{1}{B}\sum_{b=1}^{B} f_b(x) \quad \text{(регрессия)}, \qquad \hat f_{\text{bag}}(x) = \operatorname*{argmax}_{c} \sum_{b=1}^{B} \mathbb{1}[f_b(x)=c] \quad \text{(классификация)}$$

Примеры с разбором

Пример 1 (простой): как выглядит одна bootstrap-выборка на деле

Обучающая выборка состоит из 8 пациентов с индексами $\{1,2,\dots,8\}$. Алгоритм формирует bootstrap-выборку размера $n=8$, выбирая индексы случайно с возвращением, и получает последовательность $[3,7,3,1,8,7,5,3]$.

Решение. Посчитаем, сколько раз встретился каждый индекс: объект 3 попал в подвыборку трижды, объект 7 — дважды, объекты 1, 5, 8 — по одному разу, а объекты 2, 4, 6 не попали ни разу. Дерево, обученное на этой bootstrap-выборке, увидит объект 3 в три раза «весомее», чем объекты 2, 4, 6, которых оно вообще не увидит — для этого конкретного дерева они станут out-of-bag наблюдениями (к этому мы вернёмся в отдельном разделе).

Ответ: in-bag (видел дерево) $=\{1,3,5,7,8\}$ (с повторами: 3 — трижды, 7 — дважды), out-of-bag (не видел) $=\{2,4,6\}$ — три из восьми объектов, что близко к ожидаемой доле $\approx 36{,}8\%$.

Пример 2 (средний): агрегация предсказаний классификации голосованием

Случайный лес из 7 деревьев классифицирует нового пациента (болен/здоров, $1$/$0$) и получает предсказания $[1, 0, 1, 1, 0, 1, 1]$.

Решение. Считаем голоса: пять деревьев из семи сказали «$1$» (болен), два сказали «$0$». Итоговое предсказание — класс большинства, то есть $1$. Более того, лес может выдать не жёсткую метку, а оценку вероятности класса — как долю проголосовавших деревьев: $\hat p(\text{класс}=1) = 5/7 \approx 0{,}714$.

Ответ: итоговое предсказание — «болен» ($1$), с оценкой уверенности $\approx 71{,}4\%$. Обрати внимание: ни одно из семи деревьев не «знает» этой цифры — она появляется только на уровне ансамбля, как побочный продукт агрегации.

Пример 3 (сложный): агрегация предсказаний регрессии усреднением

Случайный лес из 4 деревьев оценивает стоимость квартиры и выдаёт предсказания $[5{,}2;\ 5{,}6;\ 4{,}9;\ 6{,}1]$ млн рублей.

Решение. Для регрессии агрегация — это простое арифметическое среднее: $\hat y = \dfrac{5{,}2+5{,}6+4{,}9+6{,}1}{4} = \dfrac{21{,}8}{4} = 5{,}45$ млн рублей. Заметь, что ни одно из отдельных деревьев не выдало число $5{,}45$ — каждое дерево дало собственную, довольно грубую оценку (дерево регрессии предсказывает константу в каждом листе, обычно среднее по обучающим объектам, попавшим в этот лист), а сглаженное, куда более правдоподобное число возникло только после усреднения.

Ответ: итоговое предсказание леса — $5{,}45$ млн рублей, при разбросе отдельных деревьев от $4{,}9$ до $6{,}1$ млн — усреднение «стянуло» широкий разброс индивидуальных оценок в куда более узкий и надёжный интервал.

Почему это важно

Бэггинг работает по-настоящему хорошо ровно тогда, когда базовый алгоритм нестабилен — то есть обладает высокой дисперсией, как дерево решений из прошлого урока: небольшое изменение данных (замена нескольких объектов при bootstrap-сэмплировании) кардинально меняет структуру дерева. Именно эта неустойчивость, которая в контексте одного дерева выглядела чистым недостатком, становится топливом для бэггинга: раз деревья, обученные на разных bootstrap-выборках, получаются существенно разными, у них будут отличаться и ошибки на конкретных объектах — а значит, усреднение этих ошибок будет эффективным. Для стабильных алгоритмов (например, для $k$ ближайших соседей с большим $k$, урок 314, или для линейной регрессии) бэггинг почти не даёт прироста именно потому, что модели, обученные на разных bootstrap-выборках, получаются слишком похожими друг на друга.


Случайность признаков: от бэггинга деревьев к настоящему случайному лесу

Интуиция

Бэггинг деревьев уже неплохо снижает дисперсию, но у него есть слабое место: если в данных есть один-два очень сильных признака (скажем, площадь квартиры при предсказании цены), почти каждое дерево в ансамбле — независимо от того, какая bootstrap-выборка ему досталась, — выберет именно этот признак для разбиения в корне, а следом и в верхних уровнях. В результате деревья получаются структурно очень похожими друг на друга, их ошибки оказываются сильно скоррелированы, и усреднение теряет значительную часть своей силы: усреднять почти одинаковые оценки — почти то же самое, что не усреднять вовсе.

Решение, которое и превращает «бэггинг деревьев» в настоящий «случайный лес», обманчиво простое: запретить каждому дереву на каждом отдельном узле видеть все признаки сразу. Вместо этого при разбиении каждого узла алгоритм сначала случайно выбирает небольшое подмножество из $m$ признаков (обычно $m \approx \sqrt{p}$ для классификации и $m \approx p/3$ для регрессии, где $p$ — общее число признаков), и только среди этих $m$ признаков ищет лучшее разбиение по критерию из прошлого урока (индекс Джини или information gain). На следующем узле того же дерева подмножество признаков выбирается заново, независимо от предыдущего узла.

Определение

Определение (случайность признаков в случайном лесе): При построении каждого внутреннего узла каждого дерева случайного леса из полного множества признаков размера $p$ случайно и без возвращения выбирается подмножество размера $m < p$ (гиперпараметр max_features), и наилучшее разбиение узла ищется только среди этих $m$ признаков, а не среди всех $p$. Подмножество выбирается заново на каждом узле. Именно эта дополнительная случайность, наложенная поверх бэггинга по объектам, и превращает бэггинг деревьев в случайный лес в терминологии Бреймана.

Примеры с разбором

Пример 1 (простой): конкретное разбиение узла со случайным подмножеством признаков

Датасет для скоринга имеет $p=9$ признаков: зарплата, возраст, стаж работы, кредитная история, число иждивенцев, регион, тип занятости, наличие недвижимости, сумма кредита. При классификации по умолчанию $m = \sqrt{9} = 3$. На конкретном узле алгоритм случайно выбрал подмножество {возраст, кредитная история, сумма кредита}.

Решение. Дерево ищет наилучшее разбиение (по индексу Джини, как в прошлом уроке) исключительно среди этих трёх признаков, даже если, например, зарплата на самом деле информативнее любого из выбранной тройки — на этом конкретном узле зарплата просто не участвует в конкурсе. Другой узел этого же дерева, а тем более узлы других деревьев леса, с высокой вероятностью получат другое случайное подмножество и, возможно, всё-таки используют зарплату.

Ответ: разбиение узла выбирается как лучшее среди 3 из 9 признаков — не потому что остальные 6 бесполезны, а потому что именно ограниченный выбор заставляет разные деревья опираться на разные комбинации признаков.

Пример 2 (средний): почему меньшая корреляция между деревьями снижает итоговую дисперсию сильнее, чем даёт простой бэггинг

Пусть каждое отдельное дерево имеет дисперсию предсказания $\sigma^2=50$ (в условных квадратных единицах ошибки), и в ансамбле $B=300$ деревьев. Простой бэггинг (без случайности признаков, max_features = все $p$ признаков) даёт среднюю корреляцию между деревьями $\rho_Б = 0{,}45$ — деревья похожи, потому что почти всегда используют одни и те же сильные признаки в верхних узлах. Случайный лес с $m=\sqrt p$ снижает корреляцию до $\rho_А = 0{,}15$.

Решение. Для усреднённого предсказания $B$ коррелированных оценок с одинаковой дисперсией $\sigma^2$ и попарной корреляцией $\rho$ дисперсия среднего равна $\text{Var}(\bar f) = \rho\sigma^2 + \dfrac{(1-\rho)\sigma^2}{B}$ (вывод — в следующем разделе). Для леса А: $\text{Var}_А = 0{,}15\cdot 50 + \dfrac{0{,}85\cdot 50}{300} = 7{,}5 + 0{,}142 \approx 7{,}64$. Для леса Б: $\text{Var}_Б = 0{,}45\cdot 50 + \dfrac{0{,}55\cdot 50}{300} = 22{,}5 + 0{,}092 \approx 22{,}59$.

Ответ: при абсолютно одинаковом числе деревьев и одинаковой «силе» каждого дерева случайный лес с ограничением на признаки даёт дисперсию почти в три раза ниже ($\approx 7{,}64$ против $\approx 22{,}59$) — вся разница объясняется исключительно снижением корреляции между деревьями, а не чем-то ещё.

Пример 3 (сложный): классификация против регрессии — разные значения max_features по умолчанию

В sklearn.ensemble.RandomForestClassifier значение max_features по умолчанию — "sqrt", а в RandomForestRegressor1.0 (то есть по умолчанию используются все признаки, начиная с версии 1.1; в более старых версиях по умолчанию было 1/3 от общего числа). Датасет содержит $p=30$ признаков.

Решение. Для классификации: $m = \sqrt{30} \approx 5{,}48$, округляется до $5$. Для регрессии с классическим правилом $p/3$: $m = 30/3 = 10$. Разница объясняется эмпирическим наблюдением Бреймана: для классификации меньшее $m$ обычно работает лучше (нужна более сильная декорреляция, поскольку у голосования большинством высокая устойчивость к ошибкам отдельных деревьев), тогда как для регрессии усреднение более чувствительно к качеству отдельных деревьев, и излишне малое $m$ может ослабить каждое дерево сильнее, чем оправдывает выигрыш от декорреляции.

Ответ: одна и та же идея случайного подмножества признаков реализуется с разными настройками по умолчанию для классификации ($m\approx\sqrt p$) и регрессии (исторически $m\approx p/3$, в современном sklearn — все признаки). max_features при этом всё равно стоит подбирать по кросс-валидации (урок 306), а не полагаться слепо на значение по умолчанию.

Почему это важно

Случайность признаков — не какая-то декоративная надстройка над бэггингом, а именно тот ингредиент, который делает случайный лес значительно сильнее простого бэггинга деревьев на практике. Формула $\text{Var}(\bar f) = \rho\sigma^2 + (1-\rho)\sigma^2/B$ из примера 2 показывает главное: увеличение числа деревьев $B$ снижает лишь второе слагаемое, а первое — «этаж» дисперсии, ниже которого спуститься нельзя, сколько бы деревьев ты ни добавил, — определяется исключительно корреляцией $\rho$. Именно поэтому случайность признаков — способ снизить этот этаж — приносит больше пользы, чем простое увеличение числа деревьев сверх нескольких сотен, и именно поэтому max_features — один из немногих гиперпараметров случайного леса, который реально стоит подбирать (в отличие, например, от n_estimators, где почти всегда «больше — не хуже»).


Почему усреднение снижает дисперсию: связь с законом больших чисел

Интуиция

В уроке 242 ты доказывал: если $X_1,\dots,X_n$ — попарно независимые случайные величины с одинаковым математическим ожиданием $\mu$ и дисперсиями, ограниченными константой $C$, то дисперсия их среднего $\overline X_n = \frac1n\sum X_i$ равна $\mathbb{D}\overline X_n = \frac{1}{n^2}\sum \mathbb{D}X_i \le \frac{C}{n}$ — и убывает к нулю при росте $n$. Предсказания $B$ деревьев случайного леса на одном и том же новом объекте $x$ — это ровно такой же набор случайных величин: случайность в них появляется из-за случайности bootstrap-выборки и случайности выбора признаков на каждом узле, а их общее математическое ожидание (при достаточно сильных деревьях) близко к истинному значению $y$. Если бы деревья были попарно независимы, урок 242 гарантировал бы: дисперсия среднего предсказания леса убывает как $\sigma^2/B$ — добавляй деревья, и дисперсия предсказания устремится к нулю.

Загвоздка в том, что деревья случайного леса не являются независимыми в строгом смысле: все они обучены на подвыборках одной и той же исходной выборки $D$, поэтому неизбежно немного похожи друг на друга. Брейман в статье 2001 года формализовал именно эту поправку — и это ровно та же самая математика, что в уроке 242, только выведенная без предположения о попарной независимости, а с учётом ненулевой ковариации между слагаемыми.

Определение

Определение (дисперсия усреднённого предсказания ансамбля): Пусть $B$ деревьев дают предсказания $f_1(x),\dots,f_B(x)$ на объекте $x$, каждое с дисперсией $\mathbb{D}f_b(x)=\sigma^2$ и средней попарной корреляцией $\rho$ между любыми двумя деревьями. Тогда дисперсия усреднённого предсказания $\bar f(x)=\frac1B\sum_b f_b(x)$ равна

$$\mathbb{D}\bar f(x) = \rho\sigma^2 + \frac{(1-\rho)\sigma^2}{B}$$

При $\rho=0$ (независимые деревья) это в точности формула из закона больших чисел урока 242: $\mathbb{D}\bar f(x)=\sigma^2/B \to 0$. При $\rho>0$ второе слагаемое всё равно стремится к нулю с ростом $B$, но первое слагаемое — «этаж» $\rho\sigma^2$ — остаётся неизменным и не убывает ни при каком числе деревьев.

Примеры с разбором

Пример 1 (простой): идеальный случай независимых деревьев — прямое применение урока 242

Пусть каким-то образом удалось добиться полной независимости деревьев ($\rho=0$), $\sigma^2=100$. Найди дисперсию среднего предсказания для $B=25$ и для $B=100$ деревьев.

Решение. По формуле (с $\rho=0$ она в точности совпадает с формулой дисперсии среднего из урока 242): $\mathbb{D}\bar f = \sigma^2/B$. При $B=25$: $100/25=4$. При $B=100$: $100/100=1$.

Ответ: учетверение числа деревьев ровно вчетверо уменьшило дисперсию предсказания — та же самая логика, что в примере про размер батча из урока 242, только теперь роль «одного наблюдения» играет предсказание одного дерева.

Пример 2 (средний): реалистичный случай с корреляцией — где именно останавливается выгода от добавления деревьев

$\sigma^2=100$, но реалистичная корреляция между деревьями (даже после случайного выбора признаков) $\rho=0{,}1$. Посчитай $\mathbb{D}\bar f$ для $B=10$, $B=100$ и $B=1000$ деревьев.

Решение. $\mathbb{D}\bar f(B{=}10) = 0{,}1\cdot 100 + \dfrac{0{,}9\cdot 100}{10} = 10+9=19$. $\mathbb{D}\bar f(B{=}100) = 10+\dfrac{90}{100}=10{,}9$. $\mathbb{D}\bar f(B{=}1000) = 10+\dfrac{90}{1000}=10{,}09$.

Ответ: переход от 10 к 100 деревьев снижает дисперсию заметно (с $19$ до $10{,}9$), а переход от 100 к 1000 деревьев — почти незаметно (с $10{,}9$ до $10{,}09$): практически вся выгода от простого добавления деревьев исчерпывается уже в районе нескольких сотен, а дальше дисперсия упирается в этаж $\rho\sigma^2=10$, который может снизить только уменьшение корреляции (то есть работа с max_features, а не с n_estimators).

Пример 3 (сложный): эмпирическая кривая ошибки леса от числа деревьев

На реальном датасете тестовая ошибка (MSE) случайного леса измерена при разном числе деревьев: $B{=}10 \to 0{,}420$; $B{=}50 \to 0{,}318$; $B{=}200 \to 0{,}296$; $B{=}500 \to 0{,}291$; $B{=}2000 \to 0{,}290$.

Решение. Разности между соседними точками: $0{,}420\to0{,}318$ (падение на $0{,}102$), $0{,}318\to0{,}296$ (падение на $0{,}022$), $0{,}296\to0{,}291$ (падение на $0{,}005$), $0{,}291\to0{,}290$ (падение на $0{,}001$). Кривая ошибки убывает всё медленнее и явно выходит на плато — форма кривой в точности повторяет форму $\rho\sigma^2 + (1-\rho)\sigma^2/B$: быстрое падение на малых $B$ (доминирует убывающее слагаемое) и почти горизонтальная асимптота на больших $B$ (доминирует этаж $\rho\sigma^2$).

Ответ: после определённого порога (здесь — уже в районе $B=200$–$500$) увеличение числа деревьев почти не улучшает качество, но и не ухудшает его — именно поэтому n_estimators на практике принято выбирать «с запасом» (несколько сотен), не опасаясь переобучения от избыточного количества деревьев.

Почему это важно

Формула $\rho\sigma^2 + (1-\rho)\sigma^2/B$ — это закон больших чисел, работающий на реальных, не полностью независимых данных, и она объясняет сразу три вещи, которые иначе выглядели бы разрозненными эмпирическими наблюдениями. Во-первых, почему усреднение вообще снижает ошибку: каждое дерево в отдельности может сильно ошибаться на конкретном объекте, но эти ошибки — при достаточно низкой корреляции — частично гасят друг друга при усреднении, ровно как в уроке 242 гасились случайные отклонения при усреднении по большой выборке. Во-вторых, почему добавление деревьев сверх нескольких сотен почти не помогает: убывающее слагаемое стремится к нулю, но не может пробить этаж $\rho\sigma^2$. В-третьих, почему max_features — куда более чувствительный гиперпараметр, чем n_estimators: он напрямую управляет тем самым этажом, который не пробить количеством деревьев.


Out-of-bag ошибка и важность признаков

Интуиция: out-of-bag ошибка

Вспомни пример 1 из раздела про бэггинг: при формировании bootstrap-выборки размера $n$ из $n$ объектов некоторые объекты не попадают в неё вовсе — просто потому, что сэмплирование идёт с возвращением, и «невезучему» объекту может ни разу не выпасть шанс быть выбранным. Для каждого дерева случайного леса эти непопавшие объекты называются out-of-bag (OOB) — дерево их в обучении не видело вообще. А раз дерево их не видело, его предсказание на них — честная оценка качества на новых данных, ничем принципиально не отличающаяся от предсказания на отложенном тестовом наборе.

Ключевая идея OOB-ошибки: у каждого объекта обучающей выборки почти наверняка найдётся какое-то количество деревьев в лесе, для которых этот объект был out-of-bag (не участвовал в их обучении). Усредняя предсказания именно этих деревьев для каждого объекта, можно получить оценку качества модели, которая использует ту же самую обучающую выборку, но никогда не смешивает роль обучающих и проверочных данных для одного и того же дерева — а значит, не требует выделения отдельной валидационной выборки.

Определение: OOB-ошибка

Определение (out-of-bag ошибка): Для каждого объекта $(x_i,y_i)$ обучающей выборки пусть $S_i \subseteq \{1,\dots,B\}$ — множество индексов деревьев, для которых объект $i$ оказался out-of-bag (не вошёл в их bootstrap-выборку). OOB-предсказание объекта $i$ вычисляется как агрегация (усреднение для регрессии, голосование для классификации) предсказаний только деревьев из $S_i$: $\hat y_i^{\text{OOB}} = \text{agg}\{f_b(x_i) : b \in S_i\}$. OOB-ошибка — это ошибка (MSE, accuracy и т. п.), посчитанная по всем таким предсказаниям на всей обучающей выборке.

Примеры с разбором: out-of-bag ошибка

Пример 1 (простой): доля out-of-bag наблюдений — точная формула против предела

Bootstrap-выборка размера $n$ формируется из $n$ объектов. Найди вероятность того, что конкретный объект не попадёт в неё, для $n=10$ и сравни с пределом при $n\to\infty$.

Решение. На каждом из $n$ независимых актов выбора вероятность НЕ выбрать данный конкретный объект равна $1-1/n$. Вероятность, что он не будет выбран ни разу за все $n$ актов: $\left(1-\dfrac1n\right)^n$. При $n=10$: $(0{,}9)^{10} \approx 0{,}349$. При $n\to\infty$: $\left(1-\dfrac1n\right)^n \to e^{-1} \approx 0{,}368$.

Ответ: для $n=10$ доля OOB $\approx 34{,}9\%$, для очень больших выборок доля стабилизируется около $36{,}8\%$ (то есть примерно $63{,}2\%$ объектов оказываются in-bag хотя бы раз) — эта последовательность монотонно растёт к своему пределу $1/e$ по мере увеличения $n$, так что для реальных датасетов (тысячи и десятки тысяч объектов) можно смело пользоваться приближением $\approx 36{,}8\%$.

Пример 2 (средний): численный расчёт OOB-предсказания на маленьком лесе

Обучающая выборка из 8 объектов, лес из 5 деревьев. Известно, какие объекты были out-of-bag для каждого дерева: дерево 1 — $\{3,4,7\}$, дерево 2 — $\{1,5,6\}$, дерево 3 — $\{2,3,8\}$, дерево 4 — $\{3,6,7\}$, дерево 5 — $\{1,4,5\}$. Для объекта 3 деревья 1, 3 и 4 дали предсказания класса $[1, 0, 1]$.

Решение. Объект 3 является out-of-bag для деревьев 1, 3 и 4 (ровно тех, у кого он есть в списке OOB) — значит, только их предсказания честно использовать для оценки. Голосование большинством по $[1,0,1]$: два голоса за класс $1$, один за класс $0$ → итоговое OOB-предсказание для объекта 3 — класс $1$.

Ответ: OOB-предсказание объекта 3 — класс $1$, при этом деревья 2 и 5 в голосовании не участвуют, потому что объект 3 входил в их обучающие bootstrap-выборки, и их мнение было бы нечестным (они его уже «видели»).

Пример 3 (сложный): агрегированная OOB-ошибка по всей выборке

Повторяя процедуру примера 2 для всех 8 объектов датасета, получили OOB-предсказания и сравнили их с истинными метками: из 8 объектов OOB-предсказание совпало с истинным классом у 7.

Решение. OOB accuracy $= 7/8 = 0{,}875$. Это число получено вообще без отдельной тестовой выборки — исключительно за счёт того, что для каждого объекта нашлось подмножество деревьев, которые его не видели при обучении, и их коллективное мнение сыграло роль «честного экзаменатора».

Ответ: OOB accuracy $\approx 0{,}875$ — в sklearn это значение доступно напрямую как атрибут oob_score_ при передаче oob_score=True в конструктор RandomForestClassifier/RandomForestRegressor, без единой лишней строчки кода для ручного разбиения на train/validation.

from sklearn.ensemble import RandomForestClassifier

rf = RandomForestClassifier(
    n_estimators=500,
    max_features="sqrt",
    oob_score=True,
    random_state=42,
    n_jobs=-1,
)
rf.fit(X_train, y_train)
print(rf.oob_score_)          # честная оценка accuracy без отдельного val-сета
print(rf.feature_importances_)  # важность признаков — бесплатный побочный продукт

Интуиция: важность признаков

Одно дерево решений легко интерпретировать: достаточно посмотреть на его структуру, и сразу видно, какие признаки оказались в корне и верхних узлах — значит, они и есть самые важные. У леса из сотен деревьев такого «взгляда на структуру» уже не существует — деревьев слишком много, и у каждого своя, отличная от других структура. Но именно множественность деревьев даёт возможность получить оценку важности признака куда более надёжную, чем структура одного дерева: можно усреднить вклад признака по сотням разных деревьев, что сглаживает случайные артефакты конкретного дерева.

Определение: важность признаков

Определение (важность признаков, feature importance): Наиболее распространённый способ — Mean Decrease in Impurity (MDI, среднее уменьшение примеси): для каждого узла, где использовался признак $j$, вычисляется вклад этого узла в снижение критерия неоднородности (индекс Джини или дисперсия для регрессии), взвешенный по доле обучающих объектов, дошедших до этого узла; вклады суммируются по всем узлам всех деревьев, где встретился признак $j$, и нормируются так, чтобы сумма важностей по всем признакам была равна $1$. Альтернативный способ — permutation importance: важность признака $j$ измеряется как падение качества модели (например, OOB accuracy) после случайного перемешивания значений этого признака между объектами, при неизменных значениях всех остальных признаков.

Примеры с разбором: важность признаков

Пример 1 (простой): MDI-важности для задачи кредитного скоринга

Лес обучен на 4 признаках: доход, кредитная история, возраст, регион. Атрибут feature_importances_ вернул: доход $0{,}35$, кредитная история $0{,}40$, возраст $0{,}15$, регион $0{,}10$.

Решение. Проверяем, что это корректно нормированный вектор: $0{,}35+0{,}40+0{,}15+0{,}10 = 1{,}00$ — сумма равна единице, как и должна быть по определению MDI. Самый важный признак — кредитная история ($0{,}40$), далее доход ($0{,}35$).

Ответ: ранжирование признаков по важности: кредитная история > доход > возраст > регион; это ранжирование получено усреднением по всем узлам всех деревьев леса, а не взято из одного «репрезентативного» дерева.

Пример 2 (средний): permutation importance и расхождение с MDI

Baseline OOB accuracy модели — $0{,}90$. После перемешивания значений признака «кредитная история» между объектами (при сохранении всех остальных признаков как есть) accuracy упала до $0{,}77$. После перемешивания признака «регион» accuracy упала лишь до $0{,}895$.

Решение. Permutation importance «кредитная история» $= 0{,}90 - 0{,}77 = 0{,}13$. Permutation importance «регион» $= 0{,}90-0{,}895 = 0{,}005$.

Ответ: обе метрики (MDI из примера 1 и permutation importance здесь) согласованно ставят «кредитную историю» на первое место, а «регион» — на последнее, что придаёт уверенности в устойчивости вывода; но абсолютные числа между MDI и permutation importance не сопоставимы напрямую — это два разных способа измерения, и полагаться стоит на согласованность их ранжирования, а не на точные значения.

Пример 3 (сложный): почему MDI склонен переоценивать признаки с большим числом уникальных значений

Датасет содержит признак «ID клиента» (уникален для каждого объекта, по сути шум с точки зрения обобщения) и признак «пол» (бинарный, две градации). MDI-важность «ID клиента» оказалась заметно выше, чем можно было ожидать от заведомо бесполезного признака, тогда как permutation importance для него оказалась близка к нулю.

Решение. Признак с большим числом уникальных значений (вроде ID) даёт дереву формально огромный выбор точек разбиения, и на обучающей выборке такое разбиение почти всегда способно случайно немного снизить примесь (impurity) — MDI это фиксирует как «важность», хотя на самом деле дерево просто нашло случайную закономерность, которая не обобщается на новые данные. Permutation importance свободна от этого искажения, потому что измеряет реальное падение качества на данных, которые дерево не видело при обучении (OOB), — а перемешанный «ID» не даёт никакого реального сигнала для OOB-объектов.

Ответ: для признаков с сильно разным числом уникальных значений permutation importance надёжнее MDI — это известное ограничение MDI, о котором стоит помнить, интерпретируя feature_importances_ из sklearn (это MDI по умолчанию); для permutation importance в sklearn есть отдельная функция sklearn.inspection.permutation_importance.

Почему это важно

OOB-ошибка и важность признаков — не два случайных приятных бонуса, а прямое следствие одной и той же структуры случайного леса. Раз каждое дерево обучено лишь на части данных, у алгоритма автоматически появляется встроенный механизм честной валидации, который не требует выделения дополнительных данных из и без того ограниченного датасета — особенно ценно это на небольших выборках, где каждый лишний объект, отданный под валидацию, — это объект, потерянный для обучения. А раз модель состоит из сотен деревьев, каждое из которых явно фиксирует, какой признак и насколько снизило неопределённость в каждом узле, эту информацию можно агрегировать в интерпретируемую сводку — то немногое, что позволяет заглянуть внутрь модели, которую иначе невозможно прочитать целиком.


Интерпретируемость против качества: цена ансамбля

Одно дерево решений из прошлого урока можно распечатать на листе бумаги и провести по нему пальцем: «зарплата больше 50 000 → возраст больше 25 → одобрить». Любой человек — клиент банка, регулятор, коллега без технического бэкграунда — способен пройти по этой цепочке условий и понять, почему модель приняла именно такое решение. Случайный лес из 500 деревьев такой возможности не даёт в принципе: даже если распечатать все 500 деревьев, ни один человек не станет вручную сверять их голоса, чтобы понять логику конкретного предсказания.

Это не техническая недоработка, которую можно устранить более удобной визуализацией, — это неизбежная цена, заплаченная за снижение дисперсии, разобранное в этом уроке. Формула $\rho\sigma^2+(1-\rho)\sigma^2/B$ буквально требует много разных деревьев с низкой взаимной корреляцией, а «много разных» и «легко читается как единое целое» — противоречащие друг другу требования: чем разнообразнее деревья, тем меньше у леса единой, компактно формулируемой логики.

На практике компромисс решается контекстом задачи. Там, где решение модели должно быть объяснено человеку индивидуально и юридически обоснованно — почему именно этому заявителю отказали в кредите, почему именно этому пациенту назначили именно такое лечение, — часто сознательно жертвуют несколькими процентными пунктами качества в пользу одного интерпретируемого дерева или простой линейной модели с понятными коэффициентами (урок 310). Там же, где важна прежде всего точность предсказания, а объяснимость нужна лишь на уровне «какие признаки в целом важны» (это как раз даёт важность признаков из предыдущего раздела), случайный лес — почти всегда более выгодный выбор: разница в качестве между одним деревом и лесом из нескольких сотен обычно измеряется не долями процента, а несколькими процентными пунктами accuracy или заметным снижением MSE, и в большинстве промышленных сценариев эта разница куда важнее, чем возможность прочитать модель вручную.


Практика: 30 заданий

Базовые (задания 1-10)

Задание 1: Bootstrap-выборка размера $n=6$ формируется из 6 объектов. Оцени вероятность того, что конкретный объект не попадёт в неё.


Задание 2: То же самое для $n=20$.


Задание 3: Чему равен предел $\left(1-\dfrac1n\right)^n$ при $n\to\infty$? Какую долю обучающей выборки дерево в среднем НЕ видит, а какую — видит хотя бы раз?


Задание 4: Лес из 7 деревьев классифицирует объект и даёт предсказания $[1,0,1,1,0,1,1]$. Найди итоговое предсказание голосованием большинства и оценку $\hat p(\text{класс}=1)$.


Задание 5: Лес из 4 регрессионных деревьев предсказал цену квартиры: $[200,\ 215,\ 190,\ 205]$ тыс. рублей. Найди итоговое предсказание леса.


Задание 6: В RandomForestClassifier по умолчанию max_features="sqrt". При $p=16$ признаках найди $m$.


Задание 7: По классическому правилу для регрессии $m = p/3$. При $p=12$ найди $m$.


Задание 8: Одно дерево решений дало accuracy $0{,}81$ на тесте, случайный лес из 200 деревьев на том же тесте — $0{,}89$. На сколько процентных пунктов лес точнее?


Задание 9: Объясни своими словами, почему несколько деревьев решений, каждое обученное на bootstrap-выборке, но без случайного ограничения признаков на каждом узле, — это ещё не «случайный лес» в терминологии Бреймана, а просто бэггинг деревьев.


Задание 10: Что именно оценивает OOB-ошибка, и почему для неё не требуется отдельная валидационная выборка?


Средние (задания 11-20)

Задание 11: Датасет из 10 объектов $\{1,\dots,10\}$. Для дерева $T_1$ bootstrap-выборка (in-bag, с повторами) — $[1,1,2,3,5,6,6,8,9,10]$. Найди OOB-множество для $T_1$.


Задание 12: Датасет из 8 объектов, лес из 5 деревьев. OOB-множества: $T_1=\{3,4,7\}$, $T_2=\{1,5,6\}$, $T_3=\{2,3,8\}$, $T_4=\{3,6,7\}$, $T_5=\{1,4,5\}$. Для объекта 3 деревья $T_1, T_3, T_4$ дали предсказания $[1,0,1]$. Найди OOB-предсказание объекта 3.


Задание 13: Деревья независимы ($\rho=0$), $\sigma^2=64$, $B=16$. Найди дисперсию усреднённого предсказания леса.


Задание 14: Теперь учти реалистичную корреляцию $\rho=0{,}25$ при тех же $\sigma^2=64$, $B=16$. Сравни с ответом задания 13 и с пределом $B\to\infty$.


Задание 15: MDI-важности признаков: доход $0{,}35$, кредитная история $0{,}40$, возраст $0{,}15$, регион $0{,}10$. Проверь корректность нормировки и назови самый важный признак.


Задание 16: Baseline OOB accuracy $=0{,}90$. После перемешивания признака $X$ accuracy упала до $0{,}77$. Найди permutation importance признака $X$.


Задание 17: При $p=9$ признаках сравни $m=\sqrt9=3$ (случайный лес) с $m=9$ (то есть все признаки на каждом узле). Объясни, во что вырождается лес при $m=p$.


Задание 18: Для $n=10$ найди точную долю OOB (не предел) и сравни с асимптотическим значением $1/e\approx 0{,}368$.


Задание 19: Перечисли, какие параметры RandomForestClassifier в sklearn отвечают за: (а) число деревьев, (б) число признаков на узел, (в) включение bootstrap-сэмплирования, (г) вычисление OOB-оценки.


Задание 20: Объясни, почему OOB-ошибка и ошибка на отдельной отложенной тестовой выборке обычно близки, но не обязаны совпадать в точности.


Продвинутые (задания 21-30)

Задание 21: Выведи формулу $\mathbb{D}\bar f = \rho\sigma^2+(1-\rho)\sigma^2/B$, используя $\mathbb{D}X_i=\sigma^2$ и $\text{Cov}(X_i,X_j)=\rho\sigma^2$ при $i\ne j$.


Задание 22: Найди $\lim_{B\to\infty} \mathbb{D}\bar f$ и объясни, почему бесконечное число коррелированных деревьев не убирает дисперсию полностью.


Задание 23: $\sigma^2=100$. Для $\rho=0$ найди минимальное $B$, чтобы $\mathbb{D}\bar f \le 1$. Возможно ли достичь $\mathbb{D}\bar f\le1$ при $\rho=0{,}1$?


Задание 24: Датасет: $p=100$ признаков, из которых 5 информативны, остальные 95 — шум. При $m=\sqrt{100}=10$ оцени вероятность того, что случайное подмножество из 10 признаков для конкретного узла не содержит НИ ОДНОГО из 5 информативных признаков (приближённо, считая выбор независимым: $\left(\frac{95}{100}\right)^{10}$).


Задание 25: Докажи, что ожидаемое число различных объектов, попавших в bootstrap-выборку размера $n$ из $n$ объектов, равно $n\left(1-\left(1-\frac1n\right)^n\right)$, и найди предел этой доли при $n\to\infty$.


Задание 26: Опиши псевдокодом алгоритм вычисления OOB accuracy для случайного леса из $B$ деревьев на выборке из $n$ объектов.


Задание 27: Сравни одно глубокое дерево решений (низкое смещение, высокая дисперсия) и случайный лес по компонентам bias-variance разложения. Что происходит со смещением при усреднении многих таких деревьев?


Задание 28: Почему увеличение n_estimators почти никогда не приводит к переобучению леса, в отличие от увеличения глубины одного дерева?


Задание 29: Два леса по $B=300$ деревьев, $\sigma^2=50$ у каждого дерева. Лес А ($m=\sqrt p$) имеет $\rho_А=0{,}15$, лес Б (без ограничения признаков, простой бэггинг) — $\rho_Б=0{,}45$. Сравни $\mathbb{D}\bar f$ для обоих лесов.


Задание 30: Опиши весь путь от одного дерева решений (урок 316) к случайному лесу как последовательность из трёх шагов, и укажи, на каком именно шаге напрямую вступает в игру закон больших чисел (урок 242).


Частые ошибки

Ошибка 1: считать, что «случайный лес» — это просто «много деревьев решений»

Неправильно: «Обучим 100 одинаковых деревьев на одних и тех же данных и усредним их предсказания».

Правильно: случайный лес требует двух независимых источников случайности — bootstrap-выборки для каждого дерева и случайного подмножества признаков на каждом узле. Без первого все деревья будут идентичны (одна и та же выборка, тот же жадный алгоритм даёт то же дерево), без второго — сильно скоррелированы.

Почему важно: пропуск любого из двух источников случайности резко повышает корреляцию между деревьями $\rho$ и, по формуле $\rho\sigma^2+(1-\rho)\sigma^2/B$, поднимает недостижимый «этаж» дисперсии, который не убрать никаким числом деревьев.


Ошибка 2: думать, что чем больше n_estimators, тем сильнее риск переобучения

Неправильно: «Поставлю поменьше деревьев, чтобы модель не переобучилась».

Правильно: увеличение числа деревьев практически никогда не ухудшает качество леса — оно лишь снижает дисперсию усреднённого предсказания и выходит на плато (задание 28). Переобучение случайного леса контролируется совсем другими гиперпараметрами: глубиной отдельных деревьев (max_depth), минимальным числом объектов в листе (min_samples_leaf) и max_features.

Почему важно: искусственное занижение n_estimators «для профилактики переобучения» — распространённая, но бессмысленная предосторожность, которая только ухудшает качество модели, ничего не выигрывая взамен.


Ошибка 3: интерпретировать MDI-важность признаков как абсолютную, объективную величину

Неправильно: «feature_importances_ показал 0,40 для признака X — значит, этот признак отвечает ровно за 40% решения модели».

Правильно: MDI-важность систематически завышена для признаков с большим числом уникальных значений (пример 3 раздела про важность признаков) и отражает лишь относительный вклад признака в снижение примеси (impurity) на обучающих данных, а не причинно-следственную связь с целевой переменной.

Почему важно: слепое доверие к MDI может привести к ложным выводам о важности признаков вроде ID или временных меток с высокой детализацией — для надёжности стоит сверять MDI с permutation importance.


Ошибка 4: использовать OOB-ошибку и одновременно отдельный val-сет как будто это две независимые проверки на одних и тех же данных

Неправильно: «Разобью данные на train/val, а потом ещё посчитаю OOB accuracy на train — получу две независимые оценки для более надёжного вывода».

Правильно: OOB-ошибка уже сама по себе — полноценная оценка качества на данных вне обучения каждого конкретного дерева; выделять отдельный val-сет поверх неё означает терять данные без необходимости, если единственная цель — оценка качества (а не, например, подбор порога классификации или ранняя остановка).

Почему важно: на небольших датасетах каждый объект, отданный под val-сет, а не под обучение, снижает качество итоговой модели — OOB-ошибка существует именно для того, чтобы избежать этой платы.


Ошибка 5: ждать от случайного леса экстраполяции за пределы диапазона обучающих данных

Неправильно: «Лес обучен на ценах квартир от 2 до 15 млн, ожидаю разумного предсказания и для квартиры за 40 млн».

Правильно: предсказание регрессионного дерева — это среднее значение целевой переменной в листе, куда попал объект; случайный лес, усредняя такие предсказания по многим деревьям, всё равно не может выдать значение за пределами диапазона, встречавшегося в обучающих листьях — в отличие, например, от линейной регрессии, которая экстраполирует по построению.

Почему важно: применение случайного леса к объектам, сильно выходящим за пределы распределения обучающих данных, даёт систематически заниженные или завышенные (но не экстраполированные) предсказания — это стоит явно проверять при деплое модели на новых, потенциально смещённых данных.


Ошибка 6: игнорировать max_features и оставлять значение по умолчанию без проверки на своей задаче

Неправильно: «Оставлю max_features как есть — sklearn наверняка выбрал разумное значение по умолчанию».

Правильно: значение по умолчанию — разумная отправная точка, но не универсально оптимальный выбор; на задачах с малым числом сильно информативных признаков или, наоборот, с большим числом слабо информативных признаков оптимальное $m$ может заметно отличаться от $\sqrt p$ или $p/3$, и его стоит подбирать по кросс-валидации (урок 306), как и любой другой значимый гиперпараметр.

Почему важно: именно max_features, а не n_estimators, определяет недостижимый «этаж» дисперсии предсказания — гиперпараметр, наиболее чувствительно влияющий на итоговое качество леса.


Главное запомнить

  1. Случайный лес (Random Forest) — ансамбль из множества деревьев решений (урок 316), предсказания которых агрегируются усреднением (регрессия) или голосованием большинства (классификация).

  2. Бэггинг (bootstrap aggregating) — каждое дерево обучается на своей bootstrap-выборке: случайной подвыборке того же размера $n$, что и исходные данные, взятой с возвращением.

  3. Случайность признаков — на каждом узле каждого дерева для поиска разбиения рассматривается только случайное подмножество из $m$ признаков ($m\approx\sqrt p$ для классификации, $m\approx p/3$ для регрессии по умолчанию), а не все $p$ сразу. Именно это дополнительное ограничение отличает случайный лес от простого бэггинга деревьев.

  4. Дисперсия усреднённого предсказания равна $\rho\sigma^2+(1-\rho)\sigma^2/B$, где $\rho$ — средняя корреляция между деревьями. При $\rho=0$ это в точности формула из закона больших чисел (урок 242); при $\rho>0$ дисперсия не может опуститься ниже «этажа» $\rho\sigma^2$ ни при каком числе деревьев.

  5. Больше деревьев почти никогда не вредитn_estimators снижает дисперсию монотонно и выходит на плато, не увеличивая смещение; переобучение леса контролируется глубиной деревьев и max_features, а не количеством деревьев.

  6. Out-of-bag (OOB) ошибка — оценка качества модели без отдельной валидационной выборки: для каждого объекта используются предсказания только тех деревьев, которые не видели этот объект при обучении (в среднем $\approx 36{,}8\%$ деревьев для каждого объекта).

  7. Важность признаков (feature importance) — побочный продукт обучения леса: MDI усредняет вклад признака в снижение примеси по всем узлам всех деревьев; permutation importance измеряет падение качества после перемешивания признака и надёжнее для признаков с большим числом уникальных значений.

  8. Компромисс интерпретируемости и качества — одно дерево легко прочитать целиком, лес из сотен деревьев — нет; взамен лес почти всегда точнее, а feature importance даёт частичную, агрегированную интерпретируемость.

  9. sklearn.ensemble.RandomForestClassifier/RandomForestRegressor — одна из самых надёжных «рабочих лошадок» промышленного ML: устойчива к переобучению без сложной настройки, хорошо работает «из коробки» (out-of-the-box) практически на любых табличных данных.

  10. Случайный лес не экстраполирует — предсказание всегда лежит в диапазоне значений, встречавшихся в обучающих листьях, независимо от того, сколько деревьев усреднено.


Связь с темами курса

Что было до этого урока. Случайный лес целиком опирается на дерево решений из урока 316 — тот же жадный алгоритм построения (ID3/CART, индекс Джини или information gain на каждом узле), только применённый много раз к разным bootstrap-выборкам и разным случайным подмножествам признаков. Именно нестабильность дерева решений — свойство, которое в уроке 316 выглядело недостатком, — оказывается топливом для случайного леса: чем сильнее одно дерево реагирует на изменение данных, тем эффективнее усреднение множества таких деревьев.

Математический фундамент урока — закон больших чисел (урок 242): дисперсия усреднённого предсказания леса $\rho\sigma^2+(1-\rho)\sigma^2/B$ — прямое обобщение формулы дисперсии среднего $\sigma^2/n$ из урока 242 на случай слабо коррелированных, а не строго независимых слагаемых. Идея снижения шума через усреднение большого числа наблюдений, впервые доказанная для среднего арифметического независимых случайных величин, здесь применяется к предсказаниям деревьев — и именно поэтому случайный лес специально конструируется так, чтобы деревья были как можно менее коррелированы (бэггинг плюс случайность признаков), приближая реальную ситуацию к идеализированному случаю из урока 242.

Куда ведёт. Следующий урок 318 — градиентный бустинг: ещё один ансамблевый метод, но построенный на принципиально другой идее — не параллельном усреднении независимых деревьев, а последовательном исправлении ошибок предыдущих деревьев. Сравнение бэггинга и бустинга — один из важнейших концептуальных водоразделов классического машинного обучения, и понимание того, почему бэггинг снижает именно дисперсию (а не смещение), — прямая подготовка к пониманию того, почему бустинг устроен ровно наоборот.

Где это применяется в жизни и в ML/данных:

🏦 Кредитный скоринг: случайный лес — один из стандартных baseline-алгоритмов для оценки риска дефолта заёмщика, ценится за устойчивость к выбросам в финансовых данных и встроенную важность признаков для объяснения решений регулятору.

🧬 Биоинформатика и геномика: при тысячах признаков (экспрессия генов) и малом числе объектов (пациентов) случайный лес особенно эффективен именно благодаря случайности признаков — она не даёт модели зациклиться на нескольких генах, которые случайно коррелируют с исходом на маленькой выборке.

🛒 Рекомендательные системы и прогноз спроса: случайный лес часто используется как сильный baseline для табличных признаков пользователей и товаров, прежде чем переходить к более сложным моделям градиентного бустинга (урок 318) или нейросетям.

🌦 Прогноз погоды и климатические модели: ансамбли деревьев решений применяются для предсказания экстремальных погодных явлений по множеству метеорологических признаков — устойчивость к шуму в отдельных измерениях оказывается критичным преимуществом.


Интересные факты

💡 Название «Random Forests» — зарегистрированный товарный знак. Лео Брейман и Адель Катлер закрепили за термином права, что делает случайный лес редким (возможно, единственным широко используемым) алгоритмом машинного обучения с юридически защищённым именем — на практике это никак не мешает свободной реализации метода в scikit-learn и любых других open-source библиотеках.

💡 Идея бэггинга родилась из наблюдения за нестабильностью, которую все остальные считали недостатком. Брейман в статье 1996 года «Bagging predictors» прямо пишет, что чем сильнее алгоритм «дёргается» от небольших изменений данных, тем больше он выигрывает от усреднения по bootstrap-выборкам — неустойчивость дерева решений, обычно воспринимаемая как проблема, оказалась именно тем свойством, которое делает случайный лес возможным.

💡 Случайный лес почти не требует подбора гиперпараметров, чтобы быть «достаточно хорошим». В отличие от градиентного бустинга (урок 318), который часто требует тщательной настройки learning rate (скорости обучения) и числа итераций, чтобы не переобучиться, случайный лес с параметрами по умолчанию на многих задачах уже даёт качество, близкое к оптимальному для этого класса моделей — отсюда его репутация надёжной «рабочей лошадки», о которой почти не нужно беспокоиться.

💡 Формула Бреймана про силу и корреляцию предвосхитила современный язык bias-variance trade-off для ансамблей. Оригинальная оценка ошибки обобщения случайного леса из статьи 2001 года через среднюю силу деревьев и их среднюю корреляцию — по сути та же логика, что формула $\rho\sigma^2+(1-\rho)\sigma^2/B$, разобранная в этом уроке, только выведенная другим путём и на двадцать лет раньше, чем эта связка стала общим местом в литературе по ансамблевым методам.


Лайфхаки

1. Всегда включай oob_score=True при первом обучении леса

Это практически бесплатная (не требует отдельного val-сета, не требует дополнительного кода) честная оценка качества модели прямо после .fit() — особенно ценно на небольших датасетах, где каждый объект, отданный под валидацию, был бы потерян для обучения.


2. Не экономь на n_estimators — экономь время на n_jobs=-1

Поскольку каждое дерево обучается независимо, случайный лес идеально распараллеливается. Вместо того чтобы уменьшать число деревьев ради скорости, лучше задать n_jobs=-1 (использовать все ядра процессора) и оставить n_estimators достаточно большим (несколько сотен) — прирост качества почти никогда не бывает отрицательным, а обучение при этом занимает считаные секунды на средних датасетах.


3. Если качество леса кажется недостаточным, сначала подбирай max_features, а не n_estimators

Как показано в разделе про дисперсию, именно max_features управляет недостижимым «этажом» ошибки, который не убрать увеличением числа деревьев, — поэтому при упорно застрявшем качестве стоит проверить сетку значений max_features (например, sqrt, log2, доли от 0,2 до 1,0) по кросс-валидации, прежде чем наращивать n_estimators дальше нескольких сотен.


4. Сверяй MDI-важность с permutation importance перед тем, как делать выводы о признаках

Если ранжирование признаков по обеим метрикам совпадает — вывод устойчив. Если сильно расходится (особенно для признаков с большим числом уникальных значений, вроде ID или временных меток с высокой детализацией), доверяй permutation importance — она свободна от систематического смещения MDI в пользу таких признаков.


5. Используй случайный лес как быстрый baseline перед более тяжёлыми моделями

Прежде чем переходить к градиентному бустингу (урок 318) с его чувствительной настройкой гиперпараметров или к нейросетям, обучи случайный лес с параметрами по умолчанию — за минуты ты получишь ориентир по качеству, важности признаков и осмысленности задачи в целом, который сэкономит часы на более сложных моделях, если базовое качество окажется неожиданно низким (сигнал о проблеме в данных, а не в алгоритме).


6. Не пытайся распечатать и прочитать структуру всех деревьев леса — используй частичные зависимости

Если нужно понять, как именно конкретный признак влияет на предсказание (а не просто насколько он важен в целом), используй графики частичной зависимости (partial dependence plots, sklearn.inspection.PartialDependenceDisplay) — они показывают усреднённое по всем деревьям и объектам влияние признака на предсказание, оставаясь куда информативнее, чем попытка вручную сопоставить сотни отдельных деревьев.


Случайный лес — редкий пример алгоритма, у которого почти нет очевидных недостатков в обмен на очевидное преимущество: он не требует ювелирной настройки, не разваливается от лишнего шума в данных и честно говорит, каким признакам доверяет больше. За этой практичностью стоит идея, которую ты уже видел в уроке 242 в куда более абстрактной форме — что среднее по множеству слабо связанных друг с другом оценок надёжнее любой отдельной оценки. Дерево решений даёт одну, часто нервную и переобученную догадку; случайный лес превращает сотни таких догадок в спокойный, устойчивый консенсус. В следующем уроке (318) ты увидишь, что градиентный бустинг добивается похожей силы совершенно другим путём — не усреднением независимых мнений, а последовательным обучением на ошибках, — и сравнение этих двух философий ансамблирования станет одним из ключевых водоразделов твоего понимания классического машинного обучения.

Понял тему? Закрепи в боте! 🚀

Попрактикуйся на задачах и получи персональные рекомендации от AI

💪 Начать тренировку
💬 Есть вопрос? Спроси бота!