スピードがむちゃくちゃ早いと有名なH2Oの機械学習アルゴリズムを試してみる

H2Oは、ハイパフォーマンスなオンメモリー機械学習プラットフォームとして最近特に人気があります。 こちらのquoraでの回答によると、とにかく速い!ということのようです。

実は、このライブラリを作っているH2O社が、RユーザーがH2Oのアルゴリズムを使って機械学習しやすいようにと”h2o” というRパッケージを出しているので、Exploratoryの中からも使えるんです。 今日はその使い方を紹介してみたいと思います。

H2Oにはいろいろなアルゴリムがありますが、今日はExploratoryの中でももともサポートされているRandomForestを使ってみたいと思います。例として100万件のUSのフライトデータを元に、飛行機の出発遅れの予測をするモデルを作ります。

セットアップ

“h2o” Rパッケージのインストール

まず、Exploratoryに h2o パッケージをインストールします。

h2oをインストールする前に、statmodとRCurlの二つのパッケージをインストールしておく必要があります。 プロジェクトメニューから、「Rパッケージの管理」を選択します。

パッケージをインストールのタブを選びます。

statmodと入力して、インストールボタンをクリックすると、statmodがインストールされます。

同様にして、RCurlもインストールしておきます。

h2oパッケージについてもCRANからインストールしましょう。

以下のように、インストール済みパッケージのユーザーのタブにて、h2oやstatmod、RCurlがあり、それらにチェックがついていたら使用が可能です。

インストールされたh2oのバージョンを確認する

インストール済みパッケージ一覧の h2o の行に、バージョン番号が表示されています(例:3.44.0.3)。

このバージョン番号を次のステップで使いますので、メモしておいてください。

H2Oのダウンロードと起動

h2o.jar は、Exploratoryにインストールした h2o Rパッケージと同じバージョンのものを使うと、エラーが発生しにくくなります。

以下のURLのフォーマットで、対応するバージョンのページにブラウザからアクセスしてください。

http://h2o-release.s3.amazonaws.com/h2o/rel-{X.Y.Z}/{B}/index.html

バージョン番号 X.Y.Z.B の読み替え例(バージョンが 3.44.0.3 の場合):

http://h2o-release.s3.amazonaws.com/h2o/rel-3.44.0/3/index.html

ダウンロードページが開いたら「Download H2O」ボタンからZIPファイルをダウンロードし、コマンドライン(Mac はターミナル、Windows はコマンドプロンプト)から以下のコマンドで展開・起動します。

cd ~/Downloads
unzip h2o-3.44.0.3.zip
# memoryを多めに8GB取って、起動しておきます。
java -Xmx8g -jar ~/Downloads/h2o-3.44.0.3/h2o.jar

※ バージョン番号の部分はご自身のバージョンに合わせて変更してください。また、~/Downloads はZIPを展開した実際のフォルダパスに置き換えてください。

ExploratoryのカスタムモデルとしてH2Oを使用出来るようにする

Exploratoryの中では、すでに多くの機械学習モデルがUIを通して使えるようサポートされていますが、それ以外にも自分の使いたいものをカスタムのRスクリプトを書くことによって追加できる仕込みが用意されています。

  • カスタムスクリプトの作り方シリーズ: スクリプト登録の方法 - リンク

こちらの仕組みを使って、H2OのRandomForestアルゴリズムを使用するためのコードが以下になります。

以下のコードをコピーして、Exploratoryプロジェクト内にスクリプトを作成します。

# H2Oによる二値予測ランダムフォレストモデルを作成するfunctionを、
# ExploratoryのCustom Model Functionとして実装。
# https://docs.exploratory.io/user-defined-model-function.html

# h2oの初期化
library(h2o)
h2o.init(max_mem_size="60g", nthreads=-1)

# 普通のdata.frameをH2OFrame (データフレームのH2O版)に変換するユーティリティー関数
as_h2o <- function(df) {
  # ramdom forestで使えるように、characterを全てfactorにする。
  for (colname in colnames(df)) {
    if (class(df[[colname]]) == "character") {
      df[[colname]] <- as.factor(df[[colname]])
    }
  }
  df <- as.h2o(df)
  df
}

# H2Oのrandom forest modelを作成する関数。
build_h2o_rf_model <- function(formula, data, ntrees = 5) {
  training_data <- data

  lhs_cols <- all.vars(lazyeval::f_lhs(formula)) #予測される変数
  rhs_cols <- all.vars(lazyeval::f_rhs(formula)) #予測の元となる変数
  if (rhs_cols == ".") { # .が指定されたときは、全ての列で予測する。
    rhs_cols <- colnames(training_data)[colnames(training_data) != lhs_cols]
  }

  training_data <- as_h2o(training_data) #学習データをH2OFrameに変換。
  # random forest modelを作成して学習。
  md <- h2o.randomForest(x = rhs_cols, y = lhs_cols, training_frame = training_data, ntrees = ntrees)

  # モデル、formulaを一つのオブジェクトとして返す。
  ret <- list(model = md, formula = formula)
  class(ret) <- c("h2o_rf_model")
  ret
}

# 学習済みのモデルに新しいデータを渡して予測させるfunction
augment.h2o_rf_model <- function(x, data = NULL, newdata = NULL, ...) {
  if (is.null(data)) {
    data <- newdata
  }
  formula <- x$formula

  h2o_data <- as_h2o(data) #データをH2OFrameに変換。
  predicted_data <- h2o.predict(x$model, h2o_data) #モデルによってデータを予測。
  predicted_data <- as.data.frame(predicted_data) #予測データをdata.frameに戻す。
  ret <- bind_cols(data, predicted_data) #予測データを元データにくっつけて返す。
  ret
}

# モデルからデータフレームとしてモデルサマリビューで表示する情報を抽出するfunction
# ここでは学習データでの予測性能を出力する。
glance.h2o_rf_model <- function(x, ...){
  mdperf<-h2o.performance(x$model)
  h2o.metric(mdperf)
}

# モデルからデータフレームとしてモデルサマリビューで表示する情報を抽出するfunction
# ここでは変数重要度を出力する。
tidy.h2o_rf_model <- function(x, ...){
  h2o.varimp(x$model)
}

H2Oが起動している状態で、実行ボタンをクリックし、「スクリプトは検証され、正常に保存されました。」というメッセージが表示されていることを確認してください。

これで、ExploratoryからH2OのRandomForestアルゴリズムを呼び出して使えるようになりました。

データの準備

データの取得

さまざまな機械学習プラットフォームのベンチマークを行っている、こちらのgithubレポでまとめられている、飛行機のフライトデータを使いましょう。

100万件のフライトデータがまとまった、train-1m.csvを今回の実験のためにこちらに用意しましたので、ダウンロードしてください。

このデータは、一行を一フライトとして、そのフライトに関する、出発日、出発時刻、出発地の空港、目的地の空港、また、出発到着がどれくらい遅れたのか、または早かったのかといった情報が列に入っています。

このデータをもとに、飛行機の出発が、15分以上遅れたかどうかの二値の予測をしてみましょう。

データの読み込み

ダウンロードしたtrain-1m.csv.zipを展開して、train-1m.csvを読み込みます。CSVファイルのインポート方法については、CSVやエクセルのデータをインポートする方法をご参照ください。

Random Forestモデルの作成

フライトが15分以上遅れたかどうかを表すdep_delayed_15min列を、以下の変数から予測するrandom forestモデルを作成します。

  • Month 月
  • DayofMonth 月の何日目か
  • DayOfWeek 曜日
  • DepTime 出発時刻
  • UniqueCarrier 航空会社
  • Origin 出発地の空港
  • Dest 目的地の空港
  • Distance 目的地までの距離

インポートしたデータフレームのステップメニューから「Rコマンド」を選択します。

Rコマンドの入力ダイアログが表示されたら、以下のコマンドを入力し、実行します。

1%にあたる10000行をテスト用に残しておくために test_rate=0.01 を、決定木の本数として ntrees=50 を指定しています。

build_model(model_func=build_h2o_rf_model, formula=dep_delayed_15min~., test_rate=0.01, ntrees=50) 

しばらく待っていると、モデルが完成し、実行結果が返ります。

この間にアクティビティを開けると、H2Oを走らせているjavaのプロセスがCPU使用率のトップに来ています。

564%ということは、CPUコアを約5.64個分並行して使うことによって、学習の計算速度を高めているということになります。

適合結果のサマリの欄には、学習データ自体での予測性能、パラメータ推定値の欄には、変数重要度が出ています。

変数重要度は、アナリティクスで表示されるもの同じですが、変数重要度の詳細は以下のリンクをご参照ください。

予測

先ほど、学習に使わずに取っておいた1%のテストデータで、フライトが15分以上遅れるかどうかの予測をしてみましょう。

ステップメニューを開きます。

続いて、ステップメニューから、「テストデータで予測」を選んで実行し、テストデータで予測をします。

すると以下のように予測結果が出力されます。

Y、Nはそれぞれ、15分以上遅れたか、遅れなかったかの、予測された確率になります。 predictは、この確率が大きい方で、遅れたのか遅れなかったのかの具体的な予測値となります。

予測精度の評価

予測がどの程度正しいかを評価する方法については、以下のノートをご参照ください。

  • 新しいデータに対する予測精度を評価したい - リンク
Export Chart Image
Output Format
PNG SVG
Background
Set background transparent
Size
Width (Pixel)
Height (Pixel)
Pixel Ratio