こんにちわ。見習いデータ分析屋のやじろべえです。
データ分析コンペで上位を取ろうとしたらマストテクニックになるスタッキング(stacking)ですが、これまではお手軽に使えるクラスが無かったので、パイプラインを作るのが非常に面倒でした。
そんな中、scikit-learnのバージョン0.22.0からスタッキングクラスが実装されたと聞いて、早速どれだけお手軽か試してみました。
目次
スタッキングとは
スタッキングの詳細については、他のサイトでもたくさん解説されているので、そちらをご参考にしてもらえればと思います。
ここでは概念だけ説明します。
スタッキングとはアンサンブル学習の一つです。
アンサンブル学習とは、弱学習器を複数用いて学習させることでモデルの汎化性能を向上させるテクニックです。
そして、アンサンブル学習は下記の三種類に分けられます。
- バギング
- ブースティング
- スタッキング
バギングを使った有名な学習器と言えば、ランダムフォレストがあります。
ブースティングは、XGboostやlightGBMですね。
そして、スタッキングですが、その名の通り”積み上げる”という意味なのですが、すごくざっくり説明すると、複数の学習器の出した予測値を新たな特徴量として、最後の学習器が最終的な予測を行う手法です。
scikit-learn0.22.0に実装されたstacked generalization
scikit-learn0.22.0の公式ページを見てみると、StackingClassifierとStackingRegressorという二つのestimatorが実装されたようで、分類と回帰両方において使えるようです。
使い方としては、まずはクラスをインポート。
from sklearn.ensemble import StackingRegressor
学習するときは、
reg =StackingRegressor(estimators=estimators, final_estimator=GradientBoostingRegressor()) reg.fit(X_train, y_train)
みたいな感じで使えるようです。
とっても手軽そうですね。
早速試してみる
今回はsklearnのBreast Cancerデータセットを使ってsklearnのスタッキングの威力を試してみます。
import pandas as pd import matplotlib.pyplot as plt %matplotlib inline from sklearn import datasets import numpy as np breast_cancer_data = datasets.load_breast_cancer() breast_cancer_df = pd.DataFrame(breast_cancer_data.data, columns=breast_cancer_data.feature_names) breast_cancer_df_tgt = pd.DataFrame(breast_cancer_data.target, columns=['target']) from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(breast_cancer_df, breast_cancer_df_tgt, test_size=0.2, random_state=0) from sklearn.svm import LinearSVC from sklearn.tree import DecisionTreeClassifier from sklearn.linear_model import LogisticRegression
まずは三つの学習器それぞれの予測精度を見てみます。
- LinearSVC
clf = LinearSVC(random_state=0) clf.fit(X_train, y_train) print("prediction score:", clf.score(X_test, y_test))
-> prediction score: 0.9385964912280702
- ロジスティック回帰
clf = LogisticRegression(random_state=0) clf.fit(X_train, y_train) print("prediction score:", clf.score(X_test, y_test))
-> prediction score: 0.9473684210526315
- 決定木
clf = DecisionTreeClassifier(random_state=0) clf.fit(X_train, y_train) print("prediction score:", clf.score(X_test, y_test))
-> prediction score: 0.9122807017543859
では、いよいよスタッキングを試してみます。
今回は分類問題ですので、StackingClassifierをインポートします。
from sklearn.ensemble import StackingClassifier
scikit-learnのスタッキングクラスでは、弱学習器を設定するための引数としてestimatorsがあります。弱学習器をこのestimatorsにセットしていく感じになります。
そして最後にfinal_estimatorの引数で最終的な予測をする学習器を指定してあげます。
estimators = [('logreg', LogisticRegression(random_state=0)), ('lsvc', LinearSVC(random_state=0))] stacking_clf = StackingClassifier(estimators=estimators, final_estimator=DecisionTreeClassifier(random_state=0))
これだけでスタッキングモデルの出来上がりです!
とっても楽ですねー。
では、せっかくなので精度も見てみましょう。
print("prediction score:", stacking_clf.score(X_test, y_test))
-> prediction score: 0.9649122807017544
確かに三つの学習器単体よりも精度が向上したことが確認出来ました。
最後に
今回はscikit-learn0.22.0に新しく実装されたスタッキングクラスを試してみました。
とても簡単にスタッキングを試すことが出来たので、実務においてもモデル構築の一つの選択肢となりそうです。
ただ、各学習器のハイパーパラメータチューニングだったり、estimatorsの中にセットする学習器に精度が依存してくるようないわゆるスタッキング特有の黒魔術的な要素はありますので、結局はデータ分析者がデータの性質を理解し、試行錯誤しながら使っていく必要がありますね。