Распределенное обучение XGBoost и параллельное прогнозирование с Apache Spark

МЕНЮ


Искусственный интеллект
Поиск
Регистрация на сайте
Помощь проекту

ТЕМЫ


Новости ИИРазработка ИИВнедрение ИИРабота разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика

Авторизация



RSS


RSS новости


Привет, Хабр! Уже в конце июля Otus запускает новый курс «Промышленный ML на больших данных». Традиционно, в преддверии старта нового курса, мы подготовили для вас перевод полезного материала.


Общие сведения

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

Один из алгоритмов бустинга, градиентный бустинг, использует градиентный спуск для минимизации функции потерь прямо в этих последовательных моделях (в отличие от алгоритма AdaBoost, где обучение происходит посредством изменения весов обучающих экземпляров). Слабые обучающие алгоритмы, созданные при градиентном бустинге во время обучения, обычно реализуются в виде деревьев решений. Самое неэффективное в градиентном бустинге – это последовательный процесс создания деревьев, поскольку в таком случае создается всего одно дерево за раз.

Чтобы обойти это ограничение Тяньцзи Ченом и Карлосом Гестрином было предложено улучшение алгоритма градиентного бустинга, которое называется XGBoost, что расшифровывается как Extreme Gradient Boosting или экстремальный градиентный бустинг. Это своего рода градиентный бустинг на стероидах, который используется в основном для классификации, но также порой для регрессии и ранжирования.
По сравнению со стандартным градиентным бустингом, новый метод существенно увеличивает производительность за счет гиперпараметров, поддержки GPU, кроссвалидации и регуляризации алгоритмов. В целом модель получается более эффективной, быстрее обучается и менее подвержена переобучению.

В последнее время XGBoost обрел большую популярность и выиграл множество соревнований по машинному обучению в Kaggle. Считается, что он обладает большой вычислительной мощностью и точностью.

XGBoost и Apache Spark

Во время стандартного workflow в ML используются такие системы как Spark для создания пайплайна машинного обучения, где вы предварительно обрабатываете и чистите данные, а затем результат передается на этап машинного обучения, зачастую с помощью Spark MLlib, если вы уже используете Spark.

В контексте этой статьи важно то, что в XGBoost есть распараллеливание процесса построения дерева, что позволяет производить между узлами распределенное обучение и прогнозирование. То есть если я, как пользователь Apache Spark MLlib, могу использовать его для расширения возможностей обучения XGBoost и работы на продакшене, то, по сути, я могу радоваться высокой производительности XGBoost и мощным механизмам работы Spark для инженерии признаков и построения ML-пайплайнов.

Встречайте XGBoost4J-Spark — проект, который объединяет XGBoost и Apache Spark, добавляя XGBoost к фреймворку Apache Spark MLlib.

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

Чтобы начать писать приложение с машинным обучением на XGBoost4J-Spark, вам нужно сначала добавить соответствующую зависимость:
<dependency>     <groupId>ml.dmlc</groupId>     <artifactId>xgboost4j-spark</artifactId>     <version>0.90</version> </dependency>

Подготовка данных (пример с ирисами)

Как говорилось ранее, XGBoost4J-Spark позволяет «подогнать» данные под интерфейс XGBoost.

Как только мы считаем датасет «Цветы Ириса» в DataFrame, нам нужно будет:

  • Преобразовать столбцы из String к Double;
  • Объединить столбцы признаков в вектора, чтобы данные соответствовали интерфейсу фреймворка машинного обучения Spark.

import org.apache.spark.ml.feature.StringIndexer import org.apache.spark.ml.feature.VectorAssembler val stringIndexer = new StringIndexer().   setInputCol("class").   setOutputCol("classIndex").   fit(irisDF) val labelTransformed = stringIndexer.transform(irisDF).drop("class") val vectorAssembler = new VectorAssembler().   setInputCols(Array("sepal length", "sepal width", "petal length", "petal width")).   setOutputCol("features") val xgbInput = vectorAssembler.transform(labelTransformed).select("features", "classIndex")

В DataFrame выше в результате будут два столбца, “features”: вектор – представляющий признаки ириса и “classIndex”: лейбл типа Double. Такой DataFrame можно спокойно скормить обучающему движку XGBoost4J-Spark.

Распределенное обучение

import ml.dmlc.xgboost4j.scala.spark.XGBoostClassifier  val xgbClassifier = new XGBoostClassifier().       setFeaturesCol("features").       setLabelCol("classIndex").       setObjective("multi:softmax")       setMaxDepth(2).       setNumClass(3).       setNumRound(100).       setNumWorkers(10).

Полный список параметров XGBoost вы можете найти здесь. Обратите внимание, что в XGBoost4J-Spark вы также можете использовать camelСase, как в примере выше.

Заметки

  1. multi:softmax означает, что мы делаем многоклассовую классификацию с помощью функции softmax. Для этого нужно задать количество классов с помощью параметра num_class.
  2. max_depth – это максимальная глубина дерева, созданного на каждой итерации бустинга. Увеличение этого значения сделает модель сложной и склонной к переобучению. При обучении глубоких деревьев XGBoost потребляет много памяти.
  3. num_rounds – количество раундов бустинга.
  4. Параметр num_workers определяет сколько параллельных воркеров нам нужно при обучении XGBoostClassificationModel. Позже этот параметр станет отложенными тасками в Spark, которые в перспективе будут обрабатываться менеджером кластера (в большинстве случаев YARN).

Ранняя остановка поддерживается с помощью параметров num_early_stopping_rounds и maximize_evaluation_metrics.

Теперь мы можем создать трансформер, обучив классификатор XGBoost на входном DataFrame. В результате процесса обучения мы получаем модель, которую можно использовать для получения прогнозов.

val xgbClassificationModel = xgbClassifier.fit(xgbInput)

Параллельное прогнозирование

XGBoost4j-Spark поддерживает пакетное прогнозирование и точечное прогнозирование.

Для пакетного прогнозирования модель берет DataFrame со столбцом, содержащим векторы признаков, делает прогноз для каждого вектора признаков и выводит новый DataFrame с результатами. В этом процессе XGBoost4J-Spark запускает таск Spark с воркером XGBoost для каждой части входного DataFrame для параллельного пакетного прогнозирования.

val predictionsDf = xgbClassificationModel.transform(inputDF) predictionsDf.show() +----------------+----------+-------------+-------------+----------+ |       features |classIndex|rawPrediction| probability |prediction| +----------------+----------+-------------+-------------+----------+ |[5.1,3.5,1.2,.. |       0.0|[3.4556984...|[0.9957963...|       0.0| |[4.7,3.2,1.3,.. |       0.0|[3.4556984...|[0.9961891...|       0.0| |[5.7,4.4,1.5,.. |       0.0|[3.4556984...|[0.9964334...|       0.0| +----------------+----------+-------------+-------------+----------+

Для точечного прогнозирования модель принимает один вектор.

val features = xgbInput.head().getAs[Vector]("features") val result = xgbClassificationModel.predict(features)

Точечное прогнозирование с помощью XGBoost не рекомендуется из-за больших накладных расходов, поскольку они будут сравнимы с единичным прогнозом.

На данный момент последняя версия (0.9) XGBoost4J-Spark требует Spark 2.4.x., в основном потому, что теперь в нем используются средства org.apache.spark.ml.param.shared, которые доступны не полностью в более ранних версиях Spark.

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

Узнать больше вы можете в документации XGBoost.

Источники

XGBoost с CUDA XGBoost в Spark c GPU и RAPIDS XGboost4J-Spark


Узнать о курсе подробнее.

Источник: habr.com

Комментарии: