imageH2O – библиотека машинного обучения, предназначенная как для локальных вычислений, так и с использованием кластеров, создаваемых непосредственно средствами H2O или же работая на кластере Spark. Интеграция H2O в кластеры Spark, создаваемые в Azure HDInsight, была добавлена недавно и в этой публикации (являющейся дополнением моей прошлой статьи: R и Spark) рассмотрим построение моделей машинного обучения используя H2O на таком кластере и сравним (время, метрика) его с моделями предоставляемых sparklyr, действительно ли H2O киллер-приложение для Spark?


Обзор возможностей H20 в кластере HDInsight Spark


Как было сказано в предыдущем посте, на тот момент было три способа построения моделей МО используя R на кластере Spark, напомню, это:
1) Пакет sparklyr, который предлагает разные способы чтения из различных источников данных, удобную dplyr-манипуляцию данных и достаточно большой набор различных моделей.
2) R Server for Hadoop, ПО от Microsoft, использующее свои функции для манипуляций данных и свои реализации моделей МО.
3) Пакет SparkR, который предлагает свою реализацию манипуляций данных и предлагал малое число моделей МО (в настоящее время, в версии Spark 2.2 список моделей значительно расширился).


Подробнее функциональные возможности каждого варианта можно посмотреть в Таблице 1 предыдущего поста.


Теперь появился четвертый способ — использовать H2O в кластерах Spark HDInsight. Рассмотрим вкратце его возможности:


  1. Чтение-запись, манипуляция данными – непосредственно в H2O их нет, необходимо передавать (конвертировать) готовые данные из Spark в H20.
  2. Моделей машинного обучения чуть меньше, чем в sparklyr, но все основные имеются, вот их список:
    • Generalized Linear Model
    • Multilayer Perceptron
    • Random Forest
    • Gradient Boosting Machine
    • Naive-Bayes
    • Principal Components Analysis
    • Singular Value Decomposition
    • Generalized Low Rank Model
    • K-Means Clustering
    • Anomaly Detection via Deep Learning Autoencoder.
  3. Дополнительно можно использовать ансамбли и стекинг нескольких моделей, используя пакет h2oEnsemble.
  4. Удобство моделей H2O в том, что есть возможность сразу оценивать метрики качества, как на тренировочной, так и на валидационной выборке.
  5. Настройка гиперпараметров алгоритмов по фиксированной сетке или случайным выбором.
  6. Полученные модели можно сохранить в бинарный вид или в чистый Java код "Plain Old Java Object". (POJO)

В целом, алгоритм работы с H2O заключается в следующем:


  1. Чтение данных, используя возможности пакета sparklyr.
  2. Манипуляция, трансформация, подготовка данных, используя sparklyr и replyr.
  3. Конвертация данных в H2O формат, используя пакет rsparkling.
  4. Построение моделей МО и предсказывание данных, используя h2o.
  5. Возвращение полученных результатов в Spark и/или локально в R, используя rsparkling и/или sparklyr.

Используемые ресурсы


  • Кластер H2O Artificial Intelligence for HDInsight 2.0.2.
    Данный кластер представляет собой законченное решение с API для Python и Scala. R (видимо пока) не интегрирован, но его добавление не составляет труда, для этого необходимо следующее:
  • R и пакеты sparklyr, h2o, rsparkling инсталлировать на все узлы: головные и рабочие
  • RStudio инсталлировать на головной узел
  • putty клиент локально, для установления ssh сессии с головным узлом кластера и туннелирования порта RStudio на порт локального хоста для доступа к RStudio через веб-браузер.

Важно: устанавливать пакет h2o необходимо из исходников, выбирая версию, соответствующую версии как Spark, так и пакета rsparkling, при необходимости перед загрузкой rsparkling необходимо указывать используемую версию sparklingwater (в данном случае options(rsparkling.sparklingwater.version = '2.0.8'. Таблица с зависимостями по версиям приведена здесь. Устанавливать ПО и пакеты на головные узлы допустимо непосредственно через консоль узла, а вот на рабочие узлы прямого доступа нет, поэтому разворачивание дополнительного ПО необходимо делать через Action Script.

Вначале разворачиваем кластер H2O Artificial Intelligence for HDInsight, конфигурация используется такая же, с 2 головными узлами D12v2 и 4 рабочими узлами D12v2 и 1 узел Sparkling water (служебный). После успешного разворачивания кластера, используя подключение по ssh к головному узлу, устанавливаем туда R, RStudio (текущая версия RStudio уже с интегрированными возможностями по просмотру фреймов Spark и состояния кластера), и необходимые пакеты. Для установки пакетов на рабочие узлы создаем скрипт установки (R и пакетов) и инициируем его через Action Script. Возможно использовать готовые скрипты, располагающиеся здесь: на головные узлы и на рабочие узлы. После всех успешных установок переустанавливаем ssh соединение, используя туннелирование на localhost:8787. Итак, теперь в браузере по адресу localhost:8787 мы подключаемся к RStudio и продолжаем работать.


Достоинство использования R заключается еще и в том, что установив Shiny сервер на эту же головную ноду и, создав простой веб-интерфейс на flexdashboard, возможно все вычисления на кластере, подбор гиперпараметров, визуализацию результатов, подготовку отчетов и прочее, инициировать на созданном web-сайте, который уже будет доступен отовсюду по прямой ссылке в браузере (здесь не рассматривается).

Подготовка и манипуляция данных


Использовать я буду тот же набор данных, что и в прошлый раз, это информация о поездках на такси и их оплате. Скачав данные файлы и поместив их в hdfs, читаем их оттуда и делаем необходимые преобразования (код приведен в прошлом посте).


Модели машинного обучения


Для более-менее сопоставимого сравнения выберем общие модели как в sparklyr, так и в h2o, для задач регрессии таких моделей оказалось три — линейная регрессия, случайный лес и градиентный бустинг. Параметры алгоритмов использовались по умолчанию, в случае их отличий, они приводились к общим (по возможности), проверка точности модели осуществлялась на холдаут выборке в 30%, по метрике RMSE. Результаты приведены в Табл.1 и на Рис.1.


Табл.1. Результаты моделей


Модель RMSE Время, сек
lm_mllib 1,2507 10
lm_h2o 1,2507 5,6
rf_mllib 1,2669 21,9
rf_h2o 1,2531 13,4
gbm_mllib 1,2553 108,3
gbm_h2o 1,2343 24,9

image
Рис.1 Результаты моделей


Как видно из результатов, явно видно преимущество одних и тех же моделей h2o перед их реализацией в sparklyr, как по времени исполнения, так и по метрике. Безусловный лидер из h2o gbm, обладает хорошим временем исполнения и минимальным RMSE. Не исключено, что осуществляя подбор гиперпараметров по кросс-валидациям, картина могла бы быть иной, но в данном случае «из коробки» h2o быстрее и лучше.


Выводы


В данной статье дополнены функциональные возможности машинного обучения, используя R с H2O на кластере Spark, используя платформу HDInsight, и приведен пример преимущества данного способа в отличие от моделей МО пакета sparklyr, но в свою очередь sparklyr обладает существенным преимуществом по удобной предобработке и трансформации данных.


Исходный код
###Подготовительная часть (подготовка данных) приведена в прошлом посте

features<-c("vendor_id",
            "passenger_count",
            "trip_time_in_secs",
            "trip_distance",
            "fare_amount",
            "surcharge")

rmse <- function(formula, data) {
  data %>%
    mutate_(residual = formula) %>%
    summarize(rmse = sqr(mean(residual ^ 2))) %>%
    collect %>%
    .[["rmse"]]
}

trips_train_tbl <- sdf_register(taxi_filtered$training, "trips_train")
trips_test_tbl <- sdf_register(taxi_filtered$test, "trips_test")

actual <- trips.test.tbl %>%
  select(tip_amount) %>%
  collect() %>%
  `[[`("tip_amount")

tbl_cache(sc, "trips_train")
tbl_cache(sc, "trips_test")

trips_train_h2o_tbl <- as_h2o_frame(sc, trips_train_tbl)
trips_test_h2o_tbl <- as_h2o_frame(sc, trips_test_tbl)
trips_train_h2o_tbl$vendor_id <- as.factor(trips_train_h2o_tbl$vendor_id)
trips_test_h2o_tbl$vendor_id <- as.factor(trips_test_h2o_tbl$vendor_id)

#mllib  
lm_mllib <- ml_linear_regression(x=trips_train_tbl, response = "tip_amount", features = features)
pred_lm_mllib <- sdf_predict(lm_mllib, trips_test_tbl)

rf_mllib <- ml_random_forest(x=trips_train_tbl, response = "tip_amount", features = features)
pred_rf_mllib <- sdf_predict(rf_mllib, trips_test_tbl)

gbm_mllib <-ml_gradient_boosted_trees(x=trips_train_tbl, response = "tip_amount", features = features)
pred_gbm_mllib <- sdf_predict(gbm_mllib, trips_test_tbl)

#h2o
lm_h2o <- h2o.glm(x =features, y = "tip_amount", trips_train_h2o_tbl) 
pred_lm_h2o <- h2o.predict(lm_h2o, trips_test_h2o_tbl)

rf_h2o <- h2o.randomForest(x =features, y = "tip_amount", trips_train_h2o_tbl,ntrees=20,max_depth=5)
pred_rf_h2o <- h2o.predict(rf_h2o, trips_test_h2o_tbl)

gbm_h2o <- h2o.gbm(x =features, y = "tip_amount", trips_train_h2o_tbl)
pred_gbm_h2o <- h2o.predict(gbm_h2o, trips_test_h2o_tbl)

####
pred.h2o <- data.frame(
  tip.amount = actual,
  as.data.frame(pred_lm_h2o),
  as.data.frame(pred_rf_h2o),
  as.data.frame(pred_gbm_h2o),
)
colnames(pred.h2o)<-c("tip.amount", "lm", "rf", "gbm")

result <- data.frame(

  RMSE = c(
    lm.mllib = rmse(~ tip_amount - prediction, pred_lm_mllib),
    lm.h2o = rmse(~ tip.amount - lm, pred.h2o ),
    rf.mllib = rmse(~ tip.amount - prediction, pred_rf_mllib),
    rf.h2o = rmse(~ tip_amount - rf, pred.h2o),
    gbm.mllib = rmse(~ tip_amount - prediction, pred_gbm_mllib),
    gbm.h2o = rmse(~ tip.amount - gbm, pred.h2o)

  )
)

Комментарии (0)