воскресенье, 4 июня 2017 г.

Библиотека H2O: запуск на кластере; обобщенные низкоранговые модели и градиентный бустинг

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

1. Установка

Сама библиотека H2O написана на Java и может быть скачана и использована в виде готового .jar-файла, если в системе есть JDK. Прямая ссылка на скачивание актуальной на момент написания этого сообщения версии: http://h2o-release.s3.amazonaws.com/h2o/rel-ueno/8/h2o-3.10.4.8.zip. После распаковки можно воспользоваться командой java -jar h2o.jar и начать работать с библиотекой при помощи веб-интерфейса Flow, который по умолчанию доступен на http://localhost:54321.
Помимо графического веб-интерфейса доступен также R-пакет и Python-библиотека для доступа ко всем функциям H2O. Полный скрипт для установки всех зависимостей есть на http://h2o-release.s3.amazonaws.com/h2o/rel-ueno/8/index.html во вкладке Install in R. Самое главное - нужно не ставить с CRAN, а использовать команду
install.packages("h2o", type = "source",
    repos = (c("http://h2o-release.s3.amazonaws.com/h2o/rel-ueno/8/R")))
Тогда будет установлена последняя стабильная версия, и мы сможем избежать проблем с совместимостью при использовании кластеров (об этом ниже).

2. Запуск

Запустить библиотеку локально очень просто:
library(h2o)
h2o.init(nthreads = 2,        # 2 потока
         max_mem_size = "2g") # не более 2 Гб ОЗУ

# java version "1.8.0_112"
# Java(TM) SE Runtime Environment (build 1.8.0_112-b15)
# Java HotSpot(TM) 64-Bit Server VM (build 25.112-b15, mixed mode)
# 
# Starting H2O JVM and connecting: .. Connection successful!
# 
# R is connected to the H2O cluster: 
#     H2O cluster uptime:         6 seconds 745 milliseconds 
#     H2O cluster version:        3.10.4.8 
#     H2O cluster version age:    13 days  
#     H2O cluster name:           H2O_started_from_R_andrey_lxo832 
#     H2O cluster total nodes:    1 
#     H2O cluster total memory:   1.78 GB 
#     H2O cluster total cores:    4 
#     H2O cluster allowed cores:  2 
#     H2O cluster healthy:        TRUE 
#     H2O Connection ip:          localhost 
#     H2O Connection port:        54321 
#     H2O Connection proxy:       NA 
#     H2O Internal Security:      FALSE 
#     R Version:                  R version 3.4.0 (2017-04-21) 

# Остановка кластера
h2o.shutdown(prompt = FALSE)
При этом работа все равно происходит в режиме клиент-сервер, но и клиентом, и сервером выступает один и тот же ПК.
Гораздо интереснее запустить вычисления в распределенном режиме на кластере из нескольких компьютеров. Это можно сделать как поверх Spark-а, так и средствами самой библиотеки H2O (инструкция, также см. http://docs.h2o.ai/h2o/latest-stable/h2o-docs/starting-h2o.html и https://stackoverflow.com/questions/36927443/how-to-connect-another-machine-to-standalone-h2o-installation-to-create-a-cluste). Второй вариант мы и рассмотрим.
Я буду использовать три ПК, соединенных в локальную сеть (теоретически можно даже добавить к локальной сети несколько удаленный серверов, но тогда нужно позаботиться о соответствующей скорости коммуникации с ними): два под управлением Linux и один под управлением Windows. Опытным путем было установлено, что с Linux-машинами узел под Windows дружить не хочет, то есть фактически кластер будет состоять из двух узлов, а третий ПК выступит клиентом.
Прежде всего нужно узнать ip-адреса всех компьютеров и на каждом из них создать одинаковые flat-файлы с перечнем этих адресов и используемых портов. Он может выглядеть, например, так (flatfile.txt):
192.168.1.2:54321
192.168.1.7:54321
192.168.1.8:54321
Кладем этот файл в папку с .jar-файлом H2O, переходим в эту папку и последовательно на обоих узлах выполняем запуск. Общий вид команды:
java -Xmx1g -jar h2o.jar -flatfile flatfile.txt -ip 192.168.1.7 -port 54321 -name testh2o -nthreads 2
ip-адрес для каждого ПК нужно указать свой. Опция -Xmx1g говорит о выделении 1 Гб памяти на каждом узле (объем ОЗУ на всех узлах суммируется - данные делятся между узлами, а не копируются; но при этом все узлы должны иметь равный объем выделенной памяти). -nthreads 2 запускает работу с использованием двух потоков/ядер. Полезно всегда указывать имя создаваемого кластера, в данном случае это testh2o.
Теперь в R на клиентском ПК можно запустить команду
library(h2o)

h2o.init(ip = "192.168.1.7", port = 54321)

# Connection successful!
# 
# R is connected to the H2O cluster: 
#     H2O cluster uptime:         19 seconds 253 milliseconds 
#     H2O cluster version:        3.10.4.8 
#     H2O cluster version age:    13 days  
#     H2O cluster name:           testh2o 
#     H2O cluster total nodes:    2 
#     H2O cluster total memory:   1.78 GB 
#     H2O cluster total cores:    4 
#     H2O cluster allowed cores:  4 
#     H2O cluster healthy:        TRUE 
#     H2O Connection ip:          192.168.1.7 
#     H2O Connection port:        54321 
#     H2O Connection proxy:       NA 
#     H2O Internal Security:      FALSE 
#     R Version:                  R version 3.4.0 (2017-04-21) 
## 
## ----------------------------------------------------------------------
## 
## Your next step is to start H2O:
##     > h2o.init()
## 
## For H2O package documentation, ask for help:
##     > ??h2o
## 
## After starting H2O, you can use the Web UI at http://localhost:54321
## For more information visit http://docs.h2o.ai
## 
## ----------------------------------------------------------------------
## 
## Attaching package: 'h2o'
## The following objects are masked from 'package:stats':
## 
##     cor, sd, var
## The following objects are masked from 'package:base':
## 
##     %*%, %in%, &&, ||, apply, as.factor, as.numeric, colnames,
##     colnames<-, ifelse, is.character, is.factor, is.numeric, log,
##     log10, log1p, log2, round, signif, trunc
##  Connection successful!
## 
## R is connected to the H2O cluster: 
##     H2O cluster uptime:         1 hours 36 minutes 
##     H2O cluster version:        3.10.4.8 
##     H2O cluster version age:    13 days  
##     H2O cluster name:           H2O_started_from_R_andrey_afq663 
##     H2O cluster total nodes:    1 
##     H2O cluster total memory:   1.66 GB 
##     H2O cluster total cores:    4 
##     H2O cluster allowed cores:  3 
##     H2O cluster healthy:        TRUE 
##     H2O Connection ip:          localhost 
##     H2O Connection port:        54321 
##     H2O Connection proxy:       NA 
##     H2O Internal Security:      FALSE 
##     R Version:                  R version 3.4.0 (2017-04-21)
Если версии H2O везде одинаковые, никаких проблем не возникнет.

3. Загрузка данных

Будем использовать набор данных MNIST в виде .csv-файла. Сначала загрузим его в R на клиентском ПК:
mnist <- data.table::fread("G:/KAGGLE/MNIST/train.csv")
## 
Read 0.0% of 42000 rows
Read 71.4% of 42000 rows
Read 42000 rows and 785 (of 785) columns from 0.072 GB file in 00:00:05
Затем отправим на кластер:
mnist_h2o <- as.h2o(mnist)
## 
  |                                                                       
  |                                                                 |   0%
  |                                                                       
  |=================================================================| 100%
mnist_h2o - ссылка на данные, находящиеся на кластере. Данные на клиенте при необходимости можно удалить. Для загрузки таблицы с кластера обратно на клиент используется функция as.data.frame().

4. Обобщенные низкоранговые модели

Обобщенные низкоранговые модели (Generalized Low Rank Models) - относительно новый метод понижения размерности и feature engineering-а, способный работать с количественными и категориальными данными, в том числе при наличии пропущенных значений (также позволяет эти пропущенные значения восстанавливать, что особенно полезно). Примеры от разработчиков доступны по ссылке: показана работа с категориальными данными с большим количеством категорий (ZIP-коды). Мы же попробуем применить этот метод к набору данных MNIST, то есть к количественным признакам.
fit_glrm <- h2o.glrm(
    training_frame = mnist_h2o, 
    cols = 2:ncol(mnist_h2o), 
    k = 25, 
    loss = "Huber", 
    regularization_x = "L1", 
    regularization_y = "L1", 
    max_iterations = 100,
    seed = 100)
## Warning in .h2o.startModelJob(algo, params, h2oRestApiVersion): Dropping constant columns: [pixel729, pixel644, pixel645, pixel448, pixel727, pixel728, pixel560, pixel52, pixel760, pixel10, pixel54, pixel53, pixel168, pixel56, pixel11, pixel55, pixel57, pixel16, pixel18, pixel17, pixel19, pixel754, pixel755, pixel756, pixel757, pixel758, pixel759, pixel83, pixel196, pixel82, pixel85, pixel671, pixel84, pixel111, pixel672, pixel112, pixel673, pixel476, pixel392, pixel700, pixel701, pixel141, pixel780, pixel30, pixel781, pixel782, pixel420, pixel783, pixel31, pixel421, pixel140, pixel699, pixel139, pixel8, pixel9, pixel6, pixel7, pixel4, pixel5, pixel2, pixel3, pixel0, pixel21, pixel1, pixel20, pixel23, pixel532, pixel730, pixel22, pixel731, pixel25, pixel24, pixel27, pixel26, pixel29, pixel28].
## 
  |                                                                       
  |                                                                 |   0%
  |                                                                       
  |=                                                                |   1%
  |                                                                       
  |=                                                                |   2%
  |                                                                       
  |==                                                               |   3%
  |                                                                       
  |===                                                              |   4%
  |                                                                       
  |===                                                              |   5%
  |                                                                       
  |====                                                             |   6%
  |                                                                       
  |====                                                             |   7%
  |                                                                       
  |=====                                                            |   8%
  |                                                                       
  |======                                                           |   9%
  |                                                                       
  |======                                                           |  10%
  |                                                                       
  |=======                                                          |  11%
  |                                                                       
  |========                                                         |  12%
  |                                                                       
  |========                                                         |  13%
  |                                                                       
  |=========                                                        |  14%
  |                                                                       
  |==========                                                       |  15%
  |                                                                       
  |==========                                                       |  16%
  |                                                                       
  |===========                                                      |  17%
  |                                                                       
  |===========                                                      |  18%
  |                                                                       
  |============                                                     |  19%
  |                                                                       
  |=============                                                    |  20%
  |                                                                       
  |=============                                                    |  21%
  |                                                                       
  |==============                                                   |  22%
  |                                                                       
  |===============                                                  |  23%
  |                                                                       
  |===============                                                  |  24%
  |                                                                       
  |================                                                 |  25%
  |                                                                       
  |=================                                                |  25%
  |                                                                       
  |=================                                                |  26%
  |                                                                       
  |==================                                               |  27%
  |                                                                       
  |==================                                               |  28%
  |                                                                       
  |===================                                              |  29%
  |                                                                       
  |====================                                             |  30%
  |                                                                       
  |====================                                             |  31%
  |                                                                       
  |=====================                                            |  32%
  |                                                                       
  |======================                                           |  33%
  |                                                                       
  |======================                                           |  34%
  |                                                                       
  |=======================                                          |  35%
  |                                                                       
  |========================                                         |  36%
  |                                                                       
  |========================                                         |  37%
  |                                                                       
  |=========================                                        |  38%
  |                                                                       
  |=========================                                        |  39%
  |                                                                       
  |==========================                                       |  40%
  |                                                                       
  |===========================                                      |  41%
  |                                                                       
  |===========================                                      |  42%
  |                                                                       
  |============================                                     |  43%
  |                                                                       
  |=============================                                    |  44%
  |                                                                       
  |=============================                                    |  45%
  |                                                                       
  |==============================                                   |  46%
  |                                                                       
  |===============================                                  |  47%
  |                                                                       
  |===============================                                  |  48%
  |                                                                       
  |================================                                 |  49%
  |                                                                       
  |================================                                 |  50%
  |                                                                       
  |=================================                                |  51%
  |                                                                       
  |==================================                               |  52%
  |                                                                       
  |==================================                               |  53%
  |                                                                       
  |===================================                              |  54%
  |                                                                       
  |====================================                             |  55%
  |                                                                       
  |====================================                             |  56%
  |                                                                       
  |=====================================                            |  57%
  |                                                                       
  |======================================                           |  58%
  |                                                                       
  |======================================                           |  59%
  |                                                                       
  |=======================================                          |  60%
  |                                                                       
  |========================================                         |  61%
  |                                                                       
  |========================================                         |  62%
  |                                                                       
  |=========================================                        |  63%
  |                                                                       
  |=========================================                        |  64%
  |                                                                       
  |==========================================                       |  65%
  |                                                                       
  |===========================================                      |  66%
  |                                                                       
  |===========================================                      |  67%
  |                                                                       
  |============================================                     |  68%
  |                                                                       
  |=============================================                    |  69%
  |                                                                       
  |=============================================                    |  70%
  |                                                                       
  |==============================================                   |  71%
  |                                                                       
  |===============================================                  |  72%
  |                                                                       
  |===============================================                  |  73%
  |                                                                       
  |================================================                 |  74%
  |                                                                       
  |================================================                 |  75%
  |                                                                       
  |=================================================                |  75%
  |                                                                       
  |==================================================               |  76%
  |                                                                       
  |==================================================               |  77%
  |                                                                       
  |===================================================              |  78%
  |                                                                       
  |====================================================             |  79%
  |                                                                       
  |====================================================             |  80%
  |                                                                       
  |=====================================================            |  81%
  |                                                                       
  |======================================================           |  82%
  |                                                                       
  |======================================================           |  83%
  |                                                                       
  |=======================================================          |  84%
  |                                                                       
  |=======================================================          |  85%
  |                                                                       
  |========================================================         |  86%
  |                                                                       
  |=========================================================        |  87%
  |                                                                       
  |=========================================================        |  88%
  |                                                                       
  |==========================================================       |  89%
  |                                                                       
  |===========================================================      |  90%
  |                                                                       
  |===========================================================      |  91%
  |                                                                       
  |============================================================     |  92%
  |                                                                       
  |=============================================================    |  93%
  |                                                                       
  |=============================================================    |  94%
  |                                                                       
  |==============================================================   |  95%
  |                                                                       
  |==============================================================   |  96%
  |                                                                       
  |===============================================================  |  97%
  |                                                                       
  |================================================================ |  98%
  |                                                                       
  |================================================================ |  99%
  |                                                                       
  |=================================================================| 100%

plot(fit_glrm)

Получаем интересующие нас признаки, являющиеся сжатым представлением набора данных:
glrm_features <- h2o.getFrame(fit_glrm@model$representation_name)
head(glrm_features)
##          Arch1         Arch2        Arch3         Arch4        Arch5
## 1 -0.023838934 -0.0067042793 -0.004798666 -6.710037e-03  0.102796326
## 2  0.452191476 -0.1164057377 -0.010008216 -4.589649e-03 -0.042187363
## 3  0.003063037 -0.0006779755 -0.004529025  5.728521e-05  0.061967327
## 4 -0.009267637  0.0085549730  0.109841063  2.879811e-03  0.004881383
## 5  0.567460535 -0.0901968375 -0.029656044  3.620274e-03 -0.010112527
## 6  0.014677485 -0.0111327070  0.005435568  1.276020e-02 -0.017158013
##          Arch6        Arch7         Arch8        Arch9       Arch10
## 1 -0.002049838 -0.011255783  0.0034964740  0.010380343  0.018448194
## 2  0.005293711  0.043573942  0.0061000309  0.131212260  0.067356075
## 3  0.002982732  0.015083789  0.0024269767 -0.001736844 -0.000883601
## 4  0.014332247  0.005040471  0.0005916958 -0.001883092  0.016010417
## 5 -0.005696558  0.020819434 -0.0442964470  0.157357947  0.054486820
## 6  0.022734507 -0.011243639  0.0058288395  0.002825124 -0.038099438
##         Arch11       Arch12        Arch13       Arch14      Arch15
## 1  0.001200594  0.007197661  0.0021446493  0.001857507  0.08096261
## 2  0.525883406 -0.033701542 -0.0232480347  0.018670082 -0.03842530
## 3 -0.021079587 -0.011358200  0.0034904765  0.009786409  0.11508169
## 4  0.012919209 -0.011661424  0.0076284178  0.003351322 -0.01107815
## 5  0.489205293 -0.019818808 -0.0333772140 -0.014468126 -0.03416595
## 6  0.158107565  0.043943450  0.0006898032  0.007206788 -0.03082703
##         Arch16        Arch17       Arch18        Arch19       Arch20
## 1 -0.003358851 -0.0377203500  0.012996650 -0.0013443249  0.015897515
## 2 -0.035396735  0.0002071116  0.008402813  0.0232244285 -0.021953933
## 3  0.003258883  0.0090865828  0.006932886 -0.0033793350  0.012514092
## 4 -0.001208038 -0.0018296902 -0.007259402  0.0058200663  0.003020545
## 5 -0.038373904  0.0096029611  0.023356840  0.0006823575 -0.018395582
## 6  0.006673400  0.0470293919 -0.019715101 -0.0034832835 -0.004540402
##         Arch21        Arch22       Arch23       Arch24       Arch25
## 1  0.008320434  0.0180432932  0.038976883  0.006455668 -0.022873458
## 2  0.038728343 -0.0698869359 -0.053297260  0.143510786  0.029518731
## 3 -0.012342968 -0.0010012054 -0.007652164  0.001941723  0.022512209
## 4  0.011570149  0.0003030875 -0.003557875 -0.009540136 -0.003078434
## 5  0.092758089 -0.0980393480 -0.027618168  0.150369768 -0.025269772
## 6  0.017737585 -0.0347679852 -0.009547614  0.058552958  0.046623420

5. Градиентный бустинг

Теперь применим градиентный бустинг для решения задачи классификации, используя полученные признаки.
Объединяем признаки с метками классов:
mnist_glrm <- h2o.cbind(mnist_h2o[, 1], glrm_features)

# Кодируем метку класса как фактор
mnist_glrm[, 1] <- as.factor(mnist_glrm[, 1])
Делим данные на обучающую и тестовую выборки:
set.seed(100)
split <- h2o.runif(mnist_glrm)
mnist_train <- mnist_glrm [split <= 0.8,]
mnist_test <- mnist_glrm [split > 0.8,]
Обучаем модель:
fit_gbm <- h2o.gbm(
    x = 2:26, 
    y = 1, 
    training_frame = mnist_train, 
    model_id = "MNIST",
    max_depth = 4,
    min_rows = 10,
    learn_rate = 0.1,
    col_sample_rate = 0.8,
    sample_rate = 0.9,
    ntrees = 200,
    seed = 100)
## 
  |                                                                       
  |                                                                 |   0%
  |                                                                       
  |=                                                                |   2%
  |                                                                       
  |==                                                               |   4%
  |                                                                       
  |====                                                             |   6%
  |                                                                       
  |=====                                                            |   7%
  |                                                                       
  |======                                                           |   9%
  |                                                                       
  |=======                                                          |  11%
  |                                                                       
  |========                                                         |  13%
  |                                                                       
  |==========                                                       |  15%
  |                                                                       
  |===========                                                      |  17%
  |                                                                       
  |============                                                     |  19%
  |                                                                       
  |==============                                                   |  21%
  |                                                                       
  |===============                                                  |  23%
  |                                                                       
  |================                                                 |  25%
  |                                                                       
  |==================                                               |  27%
  |                                                                       
  |===================                                              |  29%
  |                                                                       
  |====================                                             |  31%
  |                                                                       
  |=====================                                            |  32%
  |                                                                       
  |======================                                           |  34%
  |                                                                       
  |========================                                         |  36%
  |                                                                       
  |=========================                                        |  38%
  |                                                                       
  |==========================                                       |  40%
  |                                                                       
  |============================                                     |  42%
  |                                                                       
  |=============================                                    |  44%
  |                                                                       
  |==============================                                   |  46%
  |                                                                       
  |================================                                 |  49%
  |                                                                       
  |=================================                                |  51%
  |                                                                       
  |==================================                               |  53%
  |                                                                       
  |====================================                             |  55%
  |                                                                       
  |=====================================                            |  57%
  |                                                                       
  |======================================                           |  59%
  |                                                                       
  |========================================                         |  61%
  |                                                                       
  |=========================================                        |  63%
  |                                                                       
  |==========================================                       |  65%
  |                                                                       
  |============================================                     |  67%
  |                                                                       
  |=============================================                    |  69%
  |                                                                       
  |==============================================                   |  71%
  |                                                                       
  |================================================                 |  74%
  |                                                                       
  |=================================================                |  76%
  |                                                                       
  |==================================================               |  78%
  |                                                                       
  |====================================================             |  80%
  |                                                                       
  |=====================================================            |  82%
  |                                                                       
  |======================================================           |  84%
  |                                                                       
  |========================================================         |  86%
  |                                                                       
  |=========================================================        |  88%
  |                                                                       
  |==========================================================       |  90%
  |                                                                       
  |===========================================================      |  92%
  |                                                                       
  |=============================================================    |  94%
  |                                                                       
  |==============================================================   |  96%
  |                                                                       
  |===============================================================  |  98%
  |                                                                       
  |=================================================================| 100%
Качество модели на тестовых данных:
h2o.performance(fit_gbm, mnist_test)
## H2OMultinomialMetrics: gbm
## 
## Test Set Metrics: 
## =====================
## 
## MSE: (Extract with `h2o.mse`) 0.06971822
## RMSE: (Extract with `h2o.rmse`) 0.2640421
## Logloss: (Extract with `h2o.logloss`) 0.2386396
## Mean Per-Class Error: 0.0771282
## Confusion Matrix: Extract with `h2o.confusionMatrix(<model>, <data>)`)
## =========================================================================
## Confusion Matrix: vertical: actual; across: predicted
##          0   1   2   3   4   5   6   7   8   9  Error           Rate
## 0      823   0   3   2   2  13   6   0   6   1 0.0386  =    33 / 856
## 1        0 935   4   5   1   1   1   1   3   1 0.0179  =    17 / 952
## 2        2   0 787   9   7   5   8  17   9   3 0.0708  =    60 / 847
## 3        2   4  20 759   2  33   2   7  21  11 0.1185  =   102 / 861
## 4        2   2   6   1 769   2   4   6   2  45 0.0834  =    70 / 839
## 5       10   1   5  16   2 708  12   1   9  12 0.0876  =    68 / 776
## 6        9   1   9   1   2  19 790   0   7   0 0.0573  =    48 / 838
## 7        0   6   6   1   4   1   0 822   5  27 0.0573  =    50 / 872
## 8        5   4  15  41   5  12   3   4 784  19 0.1211  =   108 / 892
## 9        0   3   3  19  30   9   0  24   8 712 0.1188  =    96 / 808
## Totals 853 956 858 854 824 803 826 882 854 831 0.0763 = 652 / 8A 541
## 
## Hit Ratio Table: Extract with `h2o.hit_ratio_table(<model>, <data>)`
## =======================================================================
## Top-10 Hit Ratios: 
##     k hit_ratio
## 1   1  0.923662
## 2   2  0.975647
## 3   3  0.988760
## 4   4  0.993795
## 5   5  0.996956
## 6   6  0.998244
## 7   7  0.999063
## 8   8  0.999649
## 9   9  0.999883
## 10 10  1.000000
Если бы мы использовали loss = "Quadratic" и regularization_x = "None", regularization_y = "None", получился бы PCA. Результат не впечатляет, хоть он и неплох для не-нейросетевого метода.
Полезные ссылки:
  • Deep Water - оболочка для создания моделей глубокого обучения с использованием в качестве бэкенда Caffe, Mxnet или Tensorflow (в самой библиотеке H2O глубокое обучение ограничено многослойным перцептроном).
  • https://www.h2o.ai/gpu/ - в разработке находится версия H2O, использующая GPU для ускорения вычислений (также ожидается GPU-ускоренная версия data.table).
Продолжение следует.

2 комментария:

  1. Было бы логично привести ссылку на файл с данными, для воспроизводимости приведенного в статье кода

    ОтветитьУдалить
  2. Так это же классический набор данных, примерно как ирисы. Можно взять здесь: https://www.kaggle.com/c/digit-recognizer

    ОтветитьУдалить