На сегодняшний день градиентный бустинг (gradient boosting machine) является одним из основных production-решений при работе с табличными, неоднородными данными, поскольку обладает высокой производительностью и точностью, а если быть точнее, то его модификации, речь о которых пойдёт чуть позже.
В данной статье представлена не только реализация градиентного бустинга GBM с нуля на Python, но а также довольно подробно описаны ключевые особенности его наиболее популярных модификаций.
Ноутбук с данными алгоритмами можно загрузить на Kaggle (eng) и GitHub (rus).
Содержание
Gradient Boosting Machine
Особенности XGBoost
Особенности CatBoost
Особенности LightGBM
Какой бустинг лучше
Gradient Boosting Machine
Как и в случае с Adaboost, градиентный бустинг добавляет базовые модели в ансамбль последовательно, однако вместо обучения моделей с учётом весов на основе ошибок предшественников, в данном случае модели обучаются на остаточных ошибках (residual errors), допущенных предыдущими моделями.
Принцип работы градиентного бустинга для регрессии
Алгоритм строится следующим образом:
1) первоначальному прогнозу присваивается среднее значение y_train для всех образцов;
2) рассчитываются остатки модели на основе антиградиента функции потерь;
3) регрессионное дерево обучается на X_train и остатках, далее делается прогноз на X_train;
4) полученный прогноз добавляется к первоначальному и шаги 2-4 повторяются для каждого дерева;
5) после обучения всех моделей снова создаётся первоначальный прогноз из шага 1;
6) далее делаются прогнозы для X_test на обученных деревьях и добавляются к первоначальному;
7) полученная сумма и будет конечным прогнозом.
Формулы для расчётов
Функция потерь:
Остатки:
Принцип работы градиентного бустинга для классификации
В случае классификации дела обстоят немного сложнее: к каждому уникальному классу необходимо применить one-hot encoding и перевести в вероятности с помощью softmax-функции, а к прогнозам деревьев добавить коэффициент , который регулирует степень вклада каждого нового дерева в общую модель для снижения переобучения. Также качество прогнозов градиентного бустинга можно существенно улучшить, применив концепцию K-class LogitBoost: для каждого дерева рассчитываются веса, а только потом на их основе остатки.
Алгоритм строится следующим образом:
1) для y_train применяется one-hot encoding и первоначальному прогнозу приcваиваются значения 0 для каждого класса;
2) прогнозы преобразуются в вероятности с помощью softmax-функции;
3) рассчитываются остатки модели на основе антиградиента функции потерь и вероятностей (а также веса в случае LogitBoost);
4) регрессионное дерево обучается на X_train и остатках (а в случае LogitBoost ещё присваиваются веса), далее делается прогноз на X_train;
5) для каждого листа в дереве рассчитываются коэффициенты на основе остатков, взятых по позициям наблюдений, попавших в определённый в листовой узел;
6) полученные прогнозы для каждого класса и сумма коэффициентов добавляются к первоначальным;
7) шаги 2-6 повторяются для каждого дерева в каждом классе;
8) после обучения всех моделей создаётся первоначальный прогноз из шага 1;
9) далее делаются прогнозы для X_test на обученных деревьях по каждому классу и добавляются к первоначальным;
10) классы с максимальной суммой и будут конечным прогнозом.
Формулы для расчётов
Функция потерь:
Вероятность каждого класса:
Остатки:
Коэффициент :
Веса для K-class LogitBoost:
Остатки для K-class LogitBoost:
Импорт необходимых библиотек
import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.datasets import load_diabetes from sklearn.preprocessing import LabelEncoder from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, mean_absolute_percentage_error from sklearn.tree import DecisionTreeRegressor from sklearn.ensemble import GradientBoostingClassifier, GradientBoostingRegressor from sklearn.ensemble import HistGradientBoostingClassifier, HistGradientBoostingRegressor from mlxtend.plotting import plot_decision_regions
Реализация на Python с нуля
class GBMClassifier: def __init__(self, logitboost=False, learning_rate=0.1, n_estimators=100, max_depth=3, random_state=0): self.logitboost = logitboost self.learning_rate = learning_rate self.n_estimators = n_estimators self.max_depth = max_depth self.random_state = random_state def _softmax(self, predictions): exp = np.exp(predictions) return exp / np.sum(exp, axis=1, keepdims=True) def _compute_gammas(self, residuals, leaf_indexes, eps=1e-4): gammas = [] for j in np.unique(leaf_indexes): x_i = np.where(leaf_indexes == j) numerator = np.sum(residuals[x_i]) norm_residuals_xi = np.linalg.norm(residuals[x_i]) + eps denominator = np.sum(norm_residuals_xi * (1 - norm_residuals_xi)) gamma = (self.K - 1) / self.K * numerator / denominator gammas.append(gamma) return gammas def fit(self, X, y): self.K = len(np.unique(y)) self.trees = {k: [] for k in range(self.K)} one_hot_y = pd.get_dummies(y).to_numpy() # one-hot encoding predictions = np.zeros(one_hot_y.shape) for _ in range(self.n_estimators): probabilities = self._softmax(predictions) for k in range(self.K): if self.logitboost: # based on K-class LogitBoost numerator = (one_hot_y.T[k] - probabilities.T[k]) denominator = probabilities.T[k] * (1 - probabilities.T[k]) residuals = (self.K - 1) / self.K * numerator / denominator weights = denominator else: residuals = one_hot_y.T[k] - probabilities.T[k] weights = None tree = DecisionTreeRegressor(criterion='friedman_mse', max_depth=self.max_depth, random_state=self.random_state) tree.fit(X, residuals, sample_weight=weights) self.trees[k].append(tree) leaf_indexes = tree.apply(X) gammas = [] if self.logitboost else self._compute_gammas(residuals, leaf_indexes) predictions.T[k] += self.learning_rate * tree.predict(X) + np.sum(gammas) def predict(self, samples): predictions = np.zeros((len(samples), self.K)) for i in range(self.n_estimators): for k in range(self.K): predictions.T[k] += self.learning_rate * self.trees[k][i].predict(samples) return np.argmax(predictions, axis=1)
class GBMRegressor: def __init__(self, learning_rate=0.1, n_estimators=100, max_depth=3, random_state=0): self.learning_rate = learning_rate self.n_estimators = n_estimators self.max_depth = max_depth self.random_state = random_state self.trees = [] def fit(self, X, y): self.initial_leaf = y.mean() predictions = np.zeros(len(y)) + self.initial_leaf for _ in range(self.n_estimators): residuals = y - predictions tree = DecisionTreeRegressor(criterion='friedman_mse', max_depth=self.max_depth, random_state=self.random_state) tree.fit(X, residuals) predictions += self.learning_rate * tree.predict(X) self.trees.append(tree) def predict(self, samples): predictions = np.zeros(len(samples)) + self.initial_leaf for i in range(self.n_estimators): predictions += self.learning_rate * self.trees[i].predict(samples) return predictions
Для обучения моделей будет использован Glass Classification датасет, где необходимо верно определить тип стекла по его признакам. В случае регрессии используется Diabetes датасет из scikit-learn.
Данные ниже будут использоваться в примерах для всех модификаций градиентного бустинга.
В случае классификации ручная реализация немного отличается в плане точности от scikit-learn — это связано с тем, что в последней применяется более усложнённый подход для прогнозирования и расчёта остатков, но суть остаётся прежней, и в большинстве случаев работает примерно также как и ручная реализация, особенно в сравнении с LogitBoost модификацией.
В случае регрессии, ошибка в ручной реализации даже немного ниже, чем в scikit-learn — различия незначительны.
Также стоит отметить, что в scikit-learn есть особая версия градиентного бустинга — HistGradientBoosting на основе LightGBM, предназначенная для работы с большими наборами данных, которая отрабатывает гораздо быстрее и чаще лучше, чем классический градиентный бустинг.
Преимущества и недостатки градиентного бустинга (GBM)
Преимущества:
высокая точность;
хорошо работает с неоднородными данными;
лежит в основе других модификаций градиентного бустинга.
Недостатки:
низкая скорость обучения при работе с большими датасетами;
отсутствие возможности работы с категориальными признаками;
возможность переобучения из-за плохой предобработки данных.
Стоит отметить, что вышеперечисленные недостатки были устранены частично либо полностью в модификациях градиентного бустинга, про которые сейчас и пойдёт речь.
Дополнительные источники
Статья «Greedy Function Approximation: A Gradient Boosting Machine», Jerome H. Friedman.
XGBoost (Extreme Gradient Boosting) является, пожалуй, самой популярной модификацией градиентного бустинга на сегодняшний день, с помощью которой было выиграно множество соревнований на Kaggle. Рассмотрим причины по которым так произошло.
В отличие от GBM в XGboost изначальный прогноз регрессионного дерева устанавливается и вместо пней с глубиной 3 берутся более глубокие деревья с листьями в диапазоне от 8 до 32 как в случае регрессии, так и классификации, а к функции потерь добавляется регуляризация (L1 или L2 на выбор), которая штрафует дерево с высокой суммой нормы значений в листьях. Данная сумма представлена в виде целевой функции, расчёт значений которой аппроксимируется разложением в ряд Тейлора 2-го порядка.
Формулы для расчётов
Целевая функция:
L2-регуляризация:
Аппроксимация целевой функции разложением в ряд Тейлора 2-го порядка:
Где:
градиент первого порядка: ;
градиент второго порядка (гессиан): ;
параметры регуляризации: .
Приближение второго порядка удобно с вычислительной точки зрения, поскольку большинство членов одинаковы на каждой отдельной итерации и большая часть выражения может быть вычислена один раз и повторно использована как константа для всех остальных разбиений, и в таком случае единственное, что остаётся вычислить — это и .
Оптимальное значение веса j-го листового узла в дереве рассчитывается следующим образом:
Мера загрязнённости представляет из себя качество структуры дерева q и рассчитывается следующим образом:
Чем меньше это значение, тем лучше структура дерева.
Поскольку перечисление всевозможных древовидных структур и выбор наилучшей весьма осложнён, мы можем оптимизировать данную задачу, добавляя по одному разбиению узла дерева за раз. В частности, мы итеративно добавляем ветви к дереву, используя жадный алгоритм, а информационный прирост будет выглядеть следующим образом:
Информационный прирост будет показывать изменение чистоты узла после его разбиения. Его максимальное значение будет соответствовать наилучшему пороговому значению (критерию разбиения) узла в дереве.
Стоит также упомянуть, что в XGBoost поддерживается выбор линейных моделей в качестве базовых, но, в целом, они работают хуже деревьев.
Дополнительные оптимизации в XGBoost
Weighted quantile sketch
В случае работы с большими наборами данных в XGBoost используется приближённый жадный алгоритм. Это означает, что вместо тестирования всех возможных пороговых значений мы тестируем только квантили. Используя распараллеливание для разделения набора данных и создания ветвей в каждом дереве независимо друг от друга чтобы несколько ядер могли работать с ними одновременно, алгоритм взвешенных квантилей (weighted quantile sketch) объединяет данные в приближённую гистограмму, разделённую на взвешенные квантили, которые помещают наблюдения с прогнозами низкой достоверности в квантили с меньшим количеством наблюдений.
Cache-aware access & out-of-core computing
Для более быстрого вычисления прогнозов градиенты и гессианы хранятся в кэш-памяти (cache-aware access), а в случае с датасетами большого размера, когда недостаточно кэш и оперативной памяти, задействуется память из жёсткого диска. Учитывая, что чтение данных на жёстком диске выполняется гораздо медленнее чем в кэш-памяти, для ускоренной обработки производится их компрессия. Данные хранятся в единицах памяти, называемых блоками, информация в которых хранится в формате сжатых столбцов, отсортированных по соответствующим значениям параллельно с использованием всех доступных ядер ЦП, а распаковка каждого блока осуществляется в независимом потоке при загрузке в память. Данная техника называется "вычисление вне ядра" (out-of-core computing). При наличии нескольких жёстких дисков, применяется параллельное сегментирование блоков для каждого жёсткого диска (sharding).
При использовании сжатых данных необходимо учитывать, что процесс сжатия и распаковки занимает дополнительное время, поэтому выбор алгоритма сжатия (с потерями и без) и его параметров может повлиять на производительность в целом, однако это всё равно значительно быстрее чтения без сжатия.
Sparsity-aware split finding
В XGboost также поддерживается работа с пропусками. Суть заключается в следующем: из исходного датасета убираются наблюдения с пропусками и представляются как отдельный датасет. После построения дерева для наблюдений без пропусков рассчитываются их остатки, далее — остатки для наблюдений с пропусками, которые присоединяются к остаткам дерева как для левого, так и для правого узла. В конце рассчитывается информационный прирост (gain) для каждого узла в дереве: выбирается порог для разбиения с максимальным приростом. Данная техника называется "поиск разбиения с учётом разряженности" (sparsity-aware split finding).
Обучение на GPU
Для ускорения процесса обучения в XGBoost реализована поддержка GPU с помощью параметров device="cuda" и tree_method="gpu_hist". Также стоит отметить, что в данном алгоритме поддерживается полностью распределённое обучение на GPU с использованием Dask, Spark и PySpark.
Пакетная реализация XGBoost и оценка полученных результатов
Благодаря вышеуказанным оптимизациям и особенностям XGBoost работает лучше классической реализации, что видно на примере классификации, однако на примере регрессии в данном случае результат оказался хуже. Если хорошо подготовить данные и поэкспериментировать с настройкой гиперпараметров, XGBoost будет работать гораздо лучше как в случае регрессии, так и классификации.
относительно высокая скорость обучения и точность прогнозов;
возможность работы с пропусками;
гибкость в конфигурации из-за большого количества гиперпараметров.
Недостатки:
сложность в конфигурации из-за большого количества гиперпараметров;
на данный момент отсутствует полноценная (присутствует экспериментальная) возможность работы с категориальными признаками, что может сильно снизить производительность при кодировании больших объёмов данных.
Дополнительные источники
Статья «XGBoost: A Scalable Tree Boosting System», Tianqi Chen, Carlos Guestrin.
CatBoost (Categorical Boosting) — более эффективная реализация градиентного бустинга от компании Яндекс, особенностью которой является возможность работы с категориальными признаками без их предварительной обработки. Разберёмся подробнее как это происходит.
Ordered target (CatBoost) encoding
При кодировании категориальных признаков к бустингам применяется один из нескольких классических подходов:
target encoding;
one-hot encoding (хорошо работает лишь в том случае, когда в признаках содержится небольшое количество значений);
feature hashing в несколько корзин (исходные данные преобразуются в уникальную последовательность символов (хэш-значения), которые разбиваются на группы (корзины) и обрабатываются параллельно с последующим применением target или one-hot encoding);
mean target encoding (рассчитывается новое значение для текущего категориального признака как среднее значение целевой переменной по датасету);
leave-one-out (рассчитывается среднее значение целевой переменной по всем объектам кроме текущего);
leave-bucket-out (рассчитывается среднее значение целевой переменной на одной части данных и применяется для оставшихся других);
Однако все вышеперечисленные способы так или иначе приводят к утечке данных и переобучению, и данную проблему можно частично решить с применением mean target encoding на отложенной выборке, что работает заметно лучше, но такой способ не идеален так как остаётся меньше данных для обучения и вычисления статистик по категориальным признакам.
В CatBoost применяется модифицированный подход к mean target encoding, называемый Ordered target (CatBoost) encoding, который состоит из 3-х нижеперечисленных этапов.
Случайная перестановка
Образцы в наборе данных перемешиваются случайным образом, что позволяет создать более сбалансированный набор данных и снизить переобучение.
Статистики «по прошлому»
После случайной перестановки рассчитывается новое значение для текущего категориального признака следующим образом:
Prior — константа, определяемая как среднее арифметическое целевых значений.
TargetSum — сумма целевых значений для конкретного категориального признака до текущего момента.
TotalCount — количество всех наблюдений для конкретного категориального признака до текущего момента.
Данная формула может быть применима как для регрессии, так и для мультиклассификации.
В случае c числовыми признаками создаётся набор меток с помощью квантования и производится их бинаризация на k классов: все значения до границы (метки) относятся к классу 0, а после к классу 1. Далее процедура схожа со случаем выше.
В CatBoost поддерживаются следующие виды квантования:
мода;
медианная сетка;
равномерная сетка + квантили (размер квантования уменьшается вдвое и разбиения (пороговые значения) объединяются по одному из двух способов: медиана или равномерная сетка);
MaxLogSum — максимизируется значение следующего выражения внутри каждого сегмента:
MinEntropy — минимизируется значение следующего выражения внутри каждого сегмента:
GreedyLogSum — максимизируется аппроксимация жадным способом следующего выражения внутри каждого сегмента:
где n — число различных объектов в сегменте, w (weight) — число повторений объекта в сегменте.
Комбинация категориальных признаков
В CatBoost используется комбинация категориальных признаков (например, красный диван, синий диван, синий стул и так далее), что позволяет модели учитывать неочевидные взаимосвязи между ними и улучшить качество итоговых прогнозов в целом. Для избегания экспоненциального роста комбинаций категориальных признаков, их создание происходит не перед началом обучения, а в момент построения каждого дерева жадным алгоритмом отдельно.
Структура решающих деревьев и упорядоченный бустинг
В качестве базовых моделей в CatBoost используются симметричные односторонние деревья, имеющие одинаковую глубину и ширину. Создатели алгоритма считают, что такой подход позволяет ускорить обучение и создавать деревья, которые менее подвержены переобучению.
Для нахождения наилучшего критерия разбиения в узле используется косинусное сходство — его максимальное значение будет соответствовать лучшему критерию:
где A — вектор с остаточными ошибками, B — вектор с прогнозами в листовых узлах.
Проблема классического бустинга заключается в том, что прогнозы базовых моделей могут иметь высокое смещение, что в конечном счёте приводит к переобучению модели в целом — это обусловлено тем, что обучение и оценка деревьев производится на одинаковом наборе данных (X_train). Данная проблема решается с помощью метода линейной аппроксимации упорядоченного бустинга (Ordered Boosting), суть которого заключается в следующем: данные перемешиваются случайным образом и после чего текущее дерево обучается на m-1 образцах с учётом остатков предыдущего, что очень похоже на принцип в ordered target encoding, то есть изначально берётся один образец из набора данных и модель учится на всех образцах до него, то есть на нулях, далее берётся два образца и модель учится на одном, после чего рассчитываются остатки, которые будут использованы для следующей модели и так далее. Такой подход позволяет произвести обучение дерева со сложностью вместо .
Структура симметричного одностороннего дерева
Дополнительные возможности CatBoost
Работа с пропусками
Поддерживаются следующие режимы обработки пропусков:
"Forbidden" — пропуски интерпретируются как ошибки.
"Min" — пропуски обрабатываются как минимальное значение (меньшее, чем все остальные значения) для объекта.
"Max" — пропуски обрабатываются как максимальное значение (превышающее все остальные значения) для объекта.
Режим обработки по умолчанию — Min. Также при выборе деревьев учитывается разбиение, отделяющее пропущенные значения от всех остальных.
Snapshots
Данный параметр (save_snapshot=True) позволяет создавать резервные копии промежуточных результатов. Если происходит неожиданное прерывание обучения (например, случайное выключение компьютера), то оно может быть продолжено из сохранённого состояния и в таком случае не нужно повторять завершённые итерации построения деревьев.
Обучение на GPU
В CatBoost возможно обучение не только на нескольких GPU, но и сразу на нескольких серверах с GPU, что фактически позволяет запустить распределённое обучение и использовать датасеты любого размера. Данная процедура позволяет значительно ускорить работу алгоритма: чем больше датасет, тем больше будет прирост в производительности в сравнении с обучением на CPU. Для того чтобы этим воспользоваться достаточно указать task_type="GPU".
Пакетная реализация CatBoost и оценка полученных результатов
Как можно заметить из примера классификации, не смотря на большое количество улучшений, CatBoost далеко не всегда показывает высокие результаты в сравнении с другими реализациями градиентного бустинга, как это заявляют его разработчики, особенно заметна разница в случае с несбалансированными наборами данных. Однако, стоит отметить, что в случае хорошей подготовки данных, при прочих равных, в ряде случаев CatBoost будет отличаться от других модификаций немного более высокой точностью.
В случае регрессии, когда нет явно выраженной проблемы как в случае выше, CatBoost справляется довольно хорошо.
высокая точность и скорость обучения в большинстве случаев;
возможность работы с категориальными признаками;
большое количество гиперпараметров для настройки алгоритма;
применяется для многих задач.
Недостатки:
нестабильная работа с несбалансированными данными;
сложность в конфигурации из-за большого количества гиперпараметров;
плохая документация (личное мнение).
Дополнительные источники
Статья «CatBoost: unbiased boosting with categorical features», Liudmila Prokhorenkova, Gleb Gusev, Aleksandr Vorobev, Anna Veronika Dorogush, Andrey Gulin.
LightGBM (Light Gradient Boosting Machine) — реализация градиентного бустинга от компании Microsoft, способная обрабатывать большие наборы данных и при этом обеспечивать высокую точность. Рассмотрим более подробно ключевые особенности, которые на это повлияли.
Gradient-based One-Side Sampling (GOSS)
В отличие от классического градиентного бустинга, где регрессионные деревья обучаются на всём множестве X_train, в LightGBM деревья обучаются на подмножестве данных, полученном с помощью одностороннего отбора на основе градиента (GOSS), суть которого заключается в сортировке и выборе образцов top N с наибольшим градиентом — это означает, что именно этим данным следует уделить особое внимание, поскольку на них дерево будет ошибаться больше всего. Помимо этого, случайным образом производится отбор части образцов с низким градиентом с последующим присвоением им весов , чтобы избежать изменений в распределении данных. В данном случае — доля образцов top N в процентах с наибольшим градиентом, — доля образцов в процентах с низким градиентом.
Проще говоря, использование GOSS позволяет значительно ускорить обучение каждого последующего дерева в ансамбле путём уменьшения обучающего набора данных без особой потери в качестве прогнозов в большинстве случаев.
Histogram-based tree node splitting
При поиске наилучшего критерия разбиения узла в LightGBM также можно использовать гистограмму значений признаков: перебираются все пороговые значения гистограммы вместо всех значений признаков, что позволяет существенно ускорить поиск наилучшего критерия. Например, для признака "рост" можно использовать вопросы "рост" ? 160, "рост" ? 170 вместо "рост" ? 163, "рост" ? 167 и так далее. Как можно было заметить, гистограммы применяются в том или ином виде во всех трёх модификациях градиентного бустинга.
Exclusive Feature Bundling (EFB)
Предположим, что тем или иным образом в датасете имеются закодированные категориальные признаки, большинство из которых являются взаимоисключающими (те, которые одновременно не принимают ненулевые значения). При большом числе таких признаков обучение модели может занять слишком много времени и для решения данной проблемы в LightGBM применяется понижение размерности пространства признаков путём объединения взаимоисключающих признаков (EFB).
Стоит отметить, что в действительности строго взаимоисключающие признаки в данных встречаются крайне редко. Поэтому вводится такое понятие как доля конфликтов между признаками — отношение наблюдений от общего числа, где два признака принимают одновременно ненулевые значения.
Допустим, имеется датасет с признаками . В первую очередь стоит установить допустимую долю конфликтов, например, 25%. Тогда в случае из 8 образцов допустимое число конфликтов будет составлять 2. Далее строится матрица конфликтов между всеми признаками и производится подсчёт общей суммы конфликтов для каждого признака, после чего происходит их сортировка в порядке убывания.
На основе матрицы конфликтов строится взвешенный граф, у которого в полученном порядке отсекаются все рёбра с числом конфликтов, превышающим допустимое значение.
Работа Exclusive Feature Bundling с нуля на простом примере
Первой связкой будет . Не смотря на то что и не конфликтуют, их объединение невозможно из-за конфликтов и . Следующей связкой будет . Не смотря на то, что и не конфликтуют, их объединение невозможно из-за конфликта . Последним остаётся признак .
Новая связка будет состоять из ненулевых значений первого признака и ненулевых значений второго плюс смещение, равное максимальному значению первого признака: смещение каждого следующего признака будет равно сумме максимальных значений предыдущих. В случаях, когда наблюдается конфликт, берётся значение последнего признака со смещением.
Подробные расчёты приведены ниже.
Нетрудно заметить, что алгоритм EFB можно оптимизировать, игнорируя вычисления для всех нулевых значений в признаках. Также данную оптимизацию можно применить к histogram-based tree node splitting, что в целом снизит сложность построения гистограммы с O(data) до O(non-zero data).
Leaf-wise tree growth
Вместо построения деревьев слой за слоем, в LightGBM деревья строятся в глубину: рост продолжается в листовом узле с наибольшим информационным приростом, в результате чего дерево получается глубоким и несимметричным. Чаще всего такой подход превосходит симметричные деревья в плане точности.
Обучение на GPU
При работе с большими датасетами в LightGBM поддерживается обучение не только на GPU, но и распределённое обучение сразу на нескольких машинах.
На данный момент существуют следующие подходы:
Data parallel (образцы датасета разбиваются на локальные гистограммы, каждая из которых обрабатывается отдельно);
Feature parallel (признаки датасета разбиваются на локальные гистограммы, каждая из которых обрабатывается отдельно);
Voting parallel (на каждом процессе локально выбирается K лучших признаков для разбиения, после чего выбирается наилучший из них глобально).
Пакетная реализация LightGBM и оценка полученных результатов
Как можно заметить, в случае классификации LightGBM показал результат из коробки значительно лучше, чем предыдущие модификации бустинга. Также стоит отметить, что из всех трёх рассмотренных модификацией градиентного бустинга LightGBM является самой быстрой: чем больше датасет, тем сильнее будет заметна разница в плане скорости.
Однозначного ответа на вопрос какой бустинг лучше нет. Если раньше можно было сказать, что при работе с категориальными признаками лучше использовать CatBoost, когда важна скорость — LightGBM, ну или XGBoost, если хочется стабильное решение и нет времени на эксперименты, то сейчас такое утверждение будет неверным: как можно было заметить, все три модификации успели скопировать друг у друга много хороших идей, но исторически они отличались довольно сильно.
Более правильным будет утверждение, что выбор наилучшего бустинга будет зависеть от конкретной задачи и данных, которые применяются для обучения модели: в разных сценариях одни и те же алгоритмы могут показывать как лучшие результаты в плане скорости и точности, так и наоборот — худшие. Таким образом, выбор наиболее оптимального бустинга будет заключаться в проведении экспериментов с разными модификациями и сравнении полученных результатов.
Несколько полезных источников со сравнением бустингов: один, два, три.