Градиентный бустинг на практике
Особенности реализаций XGBoost, LightGBM и CatBoost: стратегии роста деревьев, histogram-разбиения, GOSS/EFB, ordered target statistics, монотонные ограничения и гиперпараметры.
11 вопросов
JuniorТеорияОчень частоЧто делает learning rate в градиентном бустинге и почему при малых значениях нужно больше деревьев?
Что делает learning rate в градиентном бустинге и почему при малых значениях нужно больше деревьев?
Learning rate (shrinkage) умножает вклад каждого дерева перед добавлением в ансамбль, поэтому один шаг исправляет лишь часть остаточной ошибки. Меньшие значения требуют пропорционально больше деревьев для той же подгонки, зато лучше обобщают.
Типичные ошибки
- ✗Думают, что меньший learning rate улучшает качество без увеличения числа деревьев
- ✗Подбирают n_estimators и learning_rate по отдельности, а не совместно
- ✗Считают, что learning rate управляет глубиной или размером каждого дерева
Уточняющие вопросы
- →Как выбрать число деревьев после того, как learning rate зафиксирован?
- →Почему shrinkage работает как регуляризация, а не просто как замедление?
MiddleТеорияОчень частоКакая выборка питает метрику ранней остановки в бустинге и что ломается, если останавливаться по тесту?
Какая выборка питает метрику ранней остановки в бустинге и что ломается, если останавливаться по тесту?
Обучение останавливается, когда метрика на отложенной валидационной выборке не улучшается early_stopping_rounds подряд, и сохраняется лучшая итерация. Остановка по тесту настраивает модель под него, и его результат перестаёт быть несмещённой оценкой.
Типичные ошибки
- ✗Передают тестовую выборку как eval-выборку, а потом отчитываются её результатом
- ✗Отчитываются последней итерацией вместо сохранённой лучшей
- ✗Останавливаются по обучающей потере, которая не растёт и потому не срабатывает
Уточняющие вопросы
- →Как выбрать значение
early_stopping_rounds? - →Как ранняя остановка сочетается с фолдами кросс-валидации?
JuniorТеорияЧастоЧто делают subsample и colsample_bytree в библиотеке бустинга XGBoost и почему случайность помогает?
Что делают subsample и colsample_bytree в библиотеке бустинга XGBoost и почему случайность помогает?
subsample обучает дерево на случайной доле строк, colsample_bytree выдаёт дереву случайное подмножество столбцов. Оба декоррелируют деревья, поэтому ансамбль перестаёт эксплуатировать один доминирующий признак, что снижает разброс и переобучение.
Типичные ошибки
- ✗Считают оба параметра только регуляторами скорости, не влияющими на качество
- ✗Ставят очень низкий subsample и ждут меньшего переобучения вместо недообучения
- ✗Путают выбор столбцов для дерева с глобальным удалением признаков
Уточняющие вопросы
- →Чем
colsample_bylevelотличается отcolsample_bytree? - →Почему слишком низкое значение subsample начинает вредить качеству?
MiddleДебаггингЧастоМодель CatBoost даёт 0.94 ROC-AUC на кросс-валидации и 0.78 в проде — найдите причину.
Модель CatBoost даёт 0.94 ROC-AUC на кросс-валидации и 0.78 в проде — найдите причину.
Среднее по мерчанту считается по всем меткам до разбиения, поэтому кодировка каждого фолда содержит его собственные таргеты — это утечка, а не переобучение на CV. Передайте merchant_id в cat_features, чтобы его кодировали ordered statistics, и валидируйте по времени.
Типичные ошибки
- ✗Списывают всё на переобучение CV, хотя кодировщик видел метки всех строк
- ✗Считают, что ordered statistics CatBoost защищают самодельные числовые кодировки
- ✗Валидируют упорядоченные по времени события случайным K-fold
Уточняющие вопросы
- →Как посчитать target encoding без утечки вручную?
- →Какая схема валидации подходит для лога событий за 18 месяцев?
MiddleТеорияЧастоПри кардинальности в 10 тысяч категорий выберите между one-hot, target encoding и нативной поддержкой категорий.
При кардинальности в 10 тысяч категорий выберите между one-hot, target encoding и нативной поддержкой категорий.
One-hot на 10 тысячах уровней раздувает матрицу и оставляет разбиениям мало сигнала; target encoding компактен, но течёт, если считать его не вне фолда. Лучше нативная поддержка — ordered statistics в CatBoost, разбиения по отсортированным категориям в LightGBM.
Типичные ошибки
- ✗Делают one-hot для столбца с 10 тысячами уровней и удивляются слабым разбиениям
- ✗Считают target encoding на всей обучающей выборке, а не вне фолда
- ✗Передают произвольную целочисленную кодировку как числовой признак
Уточняющие вопросы
- →Как LightGBM упорядочивает категории перед поиском разбиения?
- →Когда всё же стоит схлопывать редкие уровни в отдельную категорию?
MiddleТеорияЧастоЧем рост leaf-wise в библиотеке бустинга LightGBM отличается от роста level-wise в XGBoost?
Чем рост leaf-wise в библиотеке бустинга LightGBM отличается от роста level-wise в XGBoost?
Level-wise разбивает узлы уровнями, поэтому деревья сбалансированы. Leaf-wise всегда делит лист с наибольшим уменьшением потерь — потери на дерево ниже, но ветви глубокие и переобучаются на малых данных, если не ограничить num_leaves и min_data_in_leaf.
Типичные ошибки
- ✗Считают leaf-wise строго лучше, раз потери на дерево ниже
- ✗Ограничивают leaf-wise только через max_depth, игнорируя num_leaves
- ✗Думают, что стратегии различаются лишь скоростью, а не построенным деревом
Уточняющие вопросы
- →Как выбирать
num_leavesотносительноmax_depthв LightGBM? - →На каких размерах выборки рост leaf-wise становится рискованным?
MiddleТеорияИногдаЧто даёт градиентному бустингу поиск разбиений по гистограммам и какой ценой?
Что даёт градиентному бустингу поиск разбиений по гистограммам и какой ценой?
Признаки заранее разбиваются примерно на 255 корзин, поэтому поиск разбиения перебирает корзины, а не все значения — стоимость падает с O(#data) до O(#bins) на признак, а вычитание гистограмм даёт один дочерний узел бесплатно. Плата — квантованные пороги.
Типичные ошибки
- ✗Думают, что биннинг приближает градиент, а не пороги разбиения
- ✗Ждут большой потери точности от 255 корзин на табличных данных
- ✗Упускают, что гистограмма второго потомка получается вычитанием, а не пересчётом
Уточняющие вопросы
- →Когда имеет смысл поднимать
max_binвыше значения по умолчанию? - →Как вычитание гистограмм вдвое сокращает работу на каждом разбиении?
MiddleДизайнИногдаНужно отдавать GBDT-ранкер в бюджете 5 мс по p99 на CPU. Ограничения — один под с 4 vCPU и без GPU; каждый запрос скорит 300 кандидатных документов по 120 признакам; пик нагрузки 8 тысяч запросов в секунду. Текущая офлайн-модель — 3000 деревьев глубины 10, даёт NDCG@10 равный 0.41 и показывает 40 мс по p99 в этом поде. Выберите библиотеку, число деревьев и глубину, опишите, как удержать ранкер в бюджете, и явно скажите, каким качеством ранжирования вы жертвуете.
Нужно отдавать GBDT-ранкер в бюджете 5 мс по p99 на CPU. Ограничения — один под с 4 vCPU и без GPU; каждый запрос скорит 300 кандидатных документов по 120 признакам; пик нагрузки 8 тысяч запросов в секунду. Текущая офлайн-модель — 3000 деревьев глубины 10, даёт NDCG@10 равный 0.41 и показывает 40 мс по p99 в этом поде. Выберите библиотеку, число деревьев и глубину, опишите, как удержать ранкер в бюджете, и явно скажите, каким качеством ранжирования вы жертвуете.
Сократить модель до 300-500 неглубоких деревьев (глубина 6, num_leaves около 64) в LightGBM, скорить все 300 кандидатов одним батчем и скомпилировать лес в нативный код. Это укладывается в 5 мс ценой одного-двух пунктов NDCG.
Типичные ошибки
- ✗Обещают полное офлайн-качество в бюджете задержки, меньшем в восемь раз
- ✗Скорят кандидатов по одному вместо батча на запрос
- ✗Считают, что рост числа потоков на 4 vCPU масштабируется линейно при 8 тысячах запросов в секунду
Уточняющие вопросы
- →Как измерить потерю NDCG до выката уменьшенной модели?
- →Где двухстадийная схема отбора и переранжирования изменила бы эти цифры?
MiddleТеорияРедкоКакую утечку даёт наивное mean target encoding и как ordered target statistics в CatBoost её убирают?
Какую утечку даёт наивное mean target encoding и как ordered target statistics в CatBoost её убирают?
Наивное mean encoding использует метку самой строки в среднем по её категории, поэтому признак протаскивает таргет — обучающая потеря обваливается, а валидация нет. Ordered target statistics фиксируют перестановку и кодируют строку только по меткам предшествующих строк.
Типичные ошибки
- ✗Считают средние по категориям на всём наборе данных до разбиения
- ✗Верят, что сглаживание или шум сами по себе убирают утечку собственной метки
- ✗Думают, что ordered statistics нужны только для упорядоченных по времени данных
Уточняющие вопросы
- →Как ordered boosting переносит ту же идею на оценку градиента?
- →Почему CatBoost усредняет результат по нескольким случайным перестановкам?
MiddleТеорияРедкоКогда применяют монотонные ограничения в бустинге и что именно они ограничивают внутри разбиения?
Когда применяют монотонные ограничения в бустинге и что именно они ограничивают внутри разбиения?
Их ставят, когда доменные правила или регулятор требуют направления — рост долга не должен снижать предсказанный риск. Библиотека отвергает разбиения, где значения потомков нарушают порядок, и делает модель монотонной по этому признаку.
Типичные ошибки
- ✗Ждут, что ограничение выполняется в среднем, а не для каждого предсказания
- ✗Навешивают ограничения на признаки, чей истинный эффект не монотонен
- ✗Забывают, что ограничения стоят части качества подгонки на обучающих данных
Уточняющие вопросы
- →Каким качеством обычно платят за добавление монотонного ограничения?
- →Как проверить, что ограничение действительно выполняется на новых данных?
MiddleПроизводительностьРедкоЧто делают Gradient-based One-Side Sampling (GOSS) и Exclusive Feature Bundling (EFB) в LightGBM?
Что делают Gradient-based One-Side Sampling (GOSS) и Exclusive Feature Bundling (EFB) в LightGBM?
GOSS сохраняет все строки с большим градиентом, сэмплирует остальные и повышает их вес, поэтому градиент остаётся почти несмещённой на меньшем числе строк. EFB объединяет редко пересекающиеся разреженные признаки в бандлы, сокращая число гистограмм с #features до #bundles.
Типичные ошибки
- ✗Думают, что GOSS выбрасывает строки с большим градиентом, а не сохраняет их все
- ✗Забывают про повышение веса, которое удерживает оценку градиента почти несмещённой
- ✗Считают, что EFB нужны строго непересекающиеся признаки, а не редко пересекающиеся
Уточняющие вопросы
- →Почему GOSS повышает вес отобранных строк с малым градиентом?
- →На какой матрице признаков EFB даёт наибольший выигрыш?