Category

Machine Learning

Automatikus gépi tanulás H2O-val

By | Data Science, Machine Learning, R | No Comments

Bevezetés

Az utóbbi években a gépi tanulás (machine learning, ML) növekedésének köszönhetően megnőtt az igény egy felhasználóbarát megoldásra, amellyel akár kevésbé tapasztalt felhasználók is elboldogulhatnak, ugyanakkor segítheti a data scientist-ek munkáját is. Ebben a cikkben az H2O AutoML eszközét fogom bemutatni, amit még 2016-ban kezdett el fejleszteni a cég.

Az H2O elérhető Java, R, Python és Scala platformokon is. Ebben a cikkben R-ből fogjuk használni.

Adatok

A tanuláshoz az MNIST számjegy adatait fogjuk használni. 70.000 db kézzel írt számról készültek képek 28×28-as felbontásban. Minden egyes pixelhez (28×28 = 784 pixel) egy egész szám tartozik 0 és 255 között, ami a szürkeárnyalatot mutatja.

Az adatok elérhetők több forrásból is, mi most a kaggle versenyén fogunk elindulni https://www.kaggle.com/c/digit-recognizer/data

Ahhoz hogy eljussunk az adatoktól a modellig a következő lépéseket fogjuk megtenni:

  1. Adatok beolvasása
  2. Betöltés H2O-ba
  3. Modellek tanítása
  4. Modell futtatása a teszt adatra
  5. Feltöltés kaggle-re

Modellezés

1. Adatok beolvasása

A Kaggle-ön a két csv fájlt (train.csv, test.csv) töltsük le és helyezzük a projekt mappánkba. A readr csomag segítségével olvassuk be a fájlokat R-be.

A train.csv 785 oszlopot tatartalmaz: az első a label, ami egy 0-9-ig terjedő faktor. Ez mutatja meg, hogy az egyes képek milyen számot ábrázolnak. A többi oszlop a pixelek szürkeárnyalata pixel0-tól egészen pixel 783-ig.

A test.csv csak a pixelek adatait tartalmazza. Az ellenőrzést a Kaggle fogja végezni feltöltés után.

 
library(readr)
library(magrittr)
library(h2o)

train <- read_csv("train.csv", col_types = cols(
  label = col_factor(levels = as.character(0:9)),
  .default = col_integer()
))

test <- read_csv("test.csv")

Fontos, hogy a label oszlopot faktorként olvassuk be, mert ha ezt elmúlasztjuk, akkor mennyiségi változóként fog a modell eredményt adni (pl. 2.31, 4.72). A train.csv fájl csak a pixelek adatait tartalmazza, ezért nem szükséges megadnunk az oszloptípusokat: automatikusan integer-ként fogja beolvasni.

2. Betöltés H2O-ba

Először indítsuk el a H2O-t , ami egy Java virutális környezetben fut (JVM)


h2o.init()

Ezután töltsük be a H2O JVM-be a train és test adatokat az as.h2o függvény segítségével:

train_h2o <- as.h2o(train)
test_h2o <- as.h2o(test)

3. Modellek tanítása

Az AutoML funkciót az h2o.automl függvénnyel érjük el, amely a „motorháztető alatt” különböző ML modelleket tanít be (GLM, Deep learning, GBM, DRF), illetve ezek együttesét is (ensemble).

A függvény legfontosabb argumentumai:

  • training_frame: az adathalmaz amely tartalmazza a befolyásoló változókat és a címkét. Ez alapján tanulnak a H2O modellek. (train.csv)
  • x: a befolyásoló (predictor) változók, amik alapján a modell besorolja a 0-9 számjegyek valamelyikébe a képeket. (pixel0, …, pixel783 változók)
  • y: címke: az oszlop amely tartalmazza a címkéket (label)
  • max_runtime_secs: meddig fusson maximum a modell (tetszőleges, én 10 percre állítom, alapértelmezetten 1 óráig fut)
  • exclude_algos: egyes modellek kizárása

Természetesen jóval több paramétert lehet állítani, ezekről az H2O dokumentációban olvashatsz bővebben.

 
automl_h2o <- h2o.automl(
  x = paste0("pixel", 0:783), 
  y = "label",
  training_frame = train_h2o,
  max_runtime_secs = 1200
)

Az AutoML a következő modelleket használja alapértelmezetten:

  • Random Forest
  • Extremely-Randomized Forest
  • Gradient Boosting Machines (GBM)
  • Mély neurális hálók (deep neural nets)
  • Generalized Linear Models (GLM),
  • illetve két ún. együttest (ensemble):
    • StackedEnsemble_AllModels minden modellt figyelembe vesz. Általában ez a legjobban teljesítő modell.
    • A StackedEnsemble_BestOfFamily minden modellcsaládból csak a legjobban teljesítő modellt használja.

A modellek a ranglistán (leaderboard) találhatók:

 

automl_h2o@leaderboard

                                               model_id mean_per_class_error   logloss      rmse        mse
1 StackedEnsemble_BestOfFamily_0_AutoML_20180706_143720           0.03660115 0.1188238 0.1810178 0.03276743
2    StackedEnsemble_AllModels_0_AutoML_20180706_143720           0.03660115 0.1188238 0.1810178 0.03276743
3                          DRF_0_AutoML_20180706_143720           0.04008693 0.2899887 0.2826129 0.07987007
4                          XRT_0_AutoML_20180706_143720           0.04107182 0.2913078 0.2832940 0.08025547

Összesen négy modell készült el. Két önálló modell (DRF (distributed random forest), XRT (extremely randomized trees)), illetve két együttes (ensemble).

Mivel a két különböző modellcsaládból (DRF, XRT) csak 1-1 modell készült el, így a StackedEnsemble_AllModels és a StackedEnsemble_BestOfFamily megegyezik.

4. Modell futtatása a teszt adatra

Használjuk a legjobban teljesítő modellt (automl_h2o@leader). Az h2o.predict függvénnyel futtathatjuk a modellt a teszt adatra:

 
model_pred <- h2o.predict(object = automl_h2o@leader, newdata = test_h2o)
model_pred

 

  predict           p0           p1           p2           p3           p4           p5           p6           p7
1       2 1.780870e-06 1.255231e-04 9.991817e-01 6.537366e-05 1.897766e-06 1.562988e-06 6.652430e-07 6.090773e-04
2       0 9.996370e-01 1.115405e-06 6.297555e-05 4.453476e-07 4.386726e-05 7.841050e-06 1.237303e-04 2.414906e-05
3       9 1.524223e-04 2.595324e-04 1.165269e-03 1.906389e-03 5.899059e-03 1.082756e-03 5.011537e-05 6.173151e-03
4       4 4.308413e-03 5.748119e-03 2.186001e-02 3.612890e-03 5.807449e-01 2.184924e-03 2.505739e-03 1.305842e-01
5       3 2.119758e-04 8.248249e-03 2.915150e-01 6.790016e-01 1.361538e-04 2.304432e-03 1.106066e-04 5.670405e-03
6       7 2.832275e-04 3.723656e-04 4.514339e-03 1.054196e-02 6.153598e-04 4.646419e-04 1.263733e-04 9.688050e-01
            p8           p9
1 8.066652e-06 4.339676e-06
2 4.947527e-06 9.393295e-05
3 1.908435e-03 9.814029e-01
4 7.465877e-03 2.409849e-01
5 6.964271e-03 5.837324e-03
6 5.466614e-04 1.373007e-02

A model_pred objektumnak 28.000 sora van (minden teszt képre egy) és 11 oszlopa: az első a predict, ami a modell által jósolt számjegyet tartalmazza, illetve p0-tól p9-ig az egyes számjegyek valószínűségét.

Pl. nézzük meg az első képet:

 
matrix(data = as.integer(test[1, ]), nrow = 28, ncol = 28, byrow = TRUE) %>% 
  as.raster(max = 255) %>% 
  plot()

erre a modell 2-es számjegyet prediktál. Annak a valószínűsége, hogy a kép 0-ás számjegyet ábrázol: 1.780870e-06, tehát 0.00000178. A 2-es számjegy valószínűsége: 9.991817e-01, vagyis 0.99. A model 99%-os valószínűséget állapított meg arra, hogy az első számjegy 2-est ábrázol, ezért lett a predict oszlop értéke 2.

5. Feltöltés Kaggle-re, eredmény

A Kaggle-re csv formátumban tudjuk feltölteni ImageId és Label oszlopnevekkel. A model_pred objektum H2O-ban van, ezért as.data.frame függvénnyel tudjuk R data.frame-re konvertálni.


data <- data.frame(
  ImageId = 1:nrow(model_pred),
  Label = as.data.frame(model_pred)$predict
)
write_csv(x = data, path = "submission.csv")

Feltöltés után a Kaggle rögtön kiértékeli, az eredmény pedig 96.67%, tehát a számjegyek kb. 3.4%-át osztályozta félre a modell. Ez a 2036.ik helyre elég, ami egész jó eredmény, ahhoz képest, hogy csak 2 modell együttese alapján értük el ezt az eredményt.

Összegzés

Az H2O AutoML eszköz egy nagyszerű lehetőség junior és senior data scientist-eknek egyaránt, hogy minimális paraméterezéssel több különböző ML modellt tanítsanak be. Az eredmény útmutatást adhat, hogy melyik modellt érdemes használni (amelyet aztán később manuállisan paraméterezhetünk), vagy akár benchmarknak is használható.

Ha tetszett a cikk, iratkozz fel hírlevelünkre (a jobb felső sarokban az “értesítésre” kattintva), vagy kövess minket LinkedIn és Facebook csatornákon!