はじめに
Rubyの機械学習ライブラリであるRumaleに、スタッキング(stacking / stacked generalization)を用いた分類器と回帰分析を追加して、ver. 0.22.2としてリリースした。
rumale | RubyGems.org | your community gem host
使い方
Rumaleはgemコマンドでインストールできる。
$ gem install rumale
今回は高速化のためにparallelとnumo-openblasもインストールする(必須ではない)。
$ gem install parallel numo-openblas
スタッキングは、アンサンブル手法の一種で、一般的に学習器を二段階構成でつなげる。複数の学習器(first-level learner)を訓練し、それらの推定結果を特徴量として、最終的な推定をおこなう学習器(second-level learner / meta-leaner)を訓練する。これを実装しようとすると、割と大変というか、コードが冗長なものになる。そこで、専用のものを作った(scikit-learnでも ver. 0.22 で追加された)。
回帰分析を例に使ってみる。まずは、ランダム森による回帰分析を試す。データセットにはLIBSVM Dataのabaloneを用いた。
$ wget https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/regression/abalone_scale
require 'numo/openblas' require 'parallel' require 'rumale' # データセットを読み込む. x, y = Rumale::Dataset.load_libsvm_file('abalone_scale') # 訓練とテストに分割する. x_train, x_test, y_train, y_test = Rumale::ModelSelection.train_test_split(x, y, test_size: 0.2, random_seed: 1) # ランダム森を学習する. reg = Rumale::Ensemble::RandomForestRegressor.new(n_jobs: -1, random_seed: 1) reg.fit(x_train, y_train) # 決定係数 (1に近づくほどよい) により回帰の精度を評価する. puts reg.score(x_test, y_test)
これを実行すると、以下のようになる。
$ ruby regression.rb R2-Score: 0.5224
これがスタッキングにより、どれだけスコアが向上するか試してみる。ランダム森による回帰を、以下のスタッキングに置き換える。一段目の学習機の種類やハイパーパラメータは適当なものである。
# ランダム森のところをスタッキングに置き換える. # estimatorsにHashで特徴抽出に使う一段目の推定器を指定する. # meta_estimatorに実際に推定結果を返す二段目の推定器を指定する. reg = Rumale::Ensemble::StackingRegressor.new( estimators: { rnd: Rumale::Ensemble::RandomForestRegressor.new(n_jobs: -1, random_seed: 1), ext: Rumale::Ensemble::ExtraTreesRegressor.new(n_jobs: -1, random_seed: 1), grd: Rumale::Ensemble::GradientBoostingRegressor.new(n_jobs: -1, random_seed: 1), rdg: Rumale::LinearModel::LinearRegression.new }, meta_estimator: Rumale::LinearModel::Ridge.new(reg_param: 10), random_seed: 1 )
これを実行すると、以下のようになる。ランダム森単体のときよりも、スコアが向上していることがわかる。
$ ruby regression.rb R2-Score: 0.5751
さらにもう一歩スコアを伸ばしたい場合に、スタッキングを試してみるのは、有効であると考える。
おわりに
スタッキングはKaggleでよく使われ、アンサンブル手法として有名になった。研究自体は90年代初頭からあり、回帰分析では、二段目のメタ学習器の係数に、非負の制限をつけたほうが良いという知見もあったりする。次のバージョンで、非負最小二乗法による回帰を実装しても良いかなとか思ったり。