Help us understand the problem. What is going on with this article?

scikit-learnでバギングとブースティングをやってみる

More than 1 year has passed since last update.

はじめに

複数のモデルを組み合わせて学習する方法をアンサンブル学習といいます。様々な分類器を組み合わせることで汎化性能を上げることが出来ます。

ここではバギングとブースティング(Adaboost)について見ていきます。

参考

環境

  • MacOS Mojave 10.14.2
  • scikit-learn==0.19.1

手順

バギング

元の訓練データからランダムにn個のデータを重複を許して抽出する、ということを繰り返してデータセットをn_estimators個作ります。これをブートストラップといいます。作成した各データそれぞれに対してモデルを作成します。予測はこの多数のモデルを集約して予測します。結果の集約は分類であれば多数決、回帰であれば平均値を取るなどします。

それぞれのモデルが学習の際に使用するデータは少しづつ異なるため、汎化性能を向上させられる可能性があります。

分類問題であればBaggingClassifierを、回帰問題であればBaggingRegressorを使用します。n_estimatorsが作成するデータセットの数=モデルの数で、max_samplesは抽出する際のデータ数の上限、max_featuresは抽出する際の特徴量の数の上限を指定できます。

import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import BaggingClassifier

loaded_data = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(
    loaded_data.data, loaded_data.target, random_state=0)

models = {
    'not bagging': DecisionTreeClassifier(random_state=0),
    'bagging': BaggingClassifier(DecisionTreeClassifier(random_state=0), n_estimators=100, random_state=0) 
}

scores = {}
for model_name, model in models.items():
    model.fit(X_train, y_train)
    scores[(model_name, 'train_score')] = model.score(X_train, y_train)
    scores[(model_name, 'test_score')] = model.score(X_test, y_test)

pd.Series(scores).unstack()
test_score train_score
bagging 0.986014 1.0
not bagging 0.881119 1.0

ブースティング

訓練データに対しモデルを作成し、学習します。学習後、予測と正解を比較し、誤ったデータに重み付けをして、重み付けしたデータを用いて新たなモデルで学習します。そして誤ったデータに、、、と繰り返し逐次的にモデルを作成していきます。最後はバギング同様に、多数のモデルを集約して予測します。

import pandas as pd
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import AdaBoostRegressor

loaded_data = load_boston()
X_train, X_test, y_train, y_test = train_test_split(
    loaded_data.data, loaded_data.target, random_state=0)

models = {
    'tree': DecisionTreeRegressor(random_state=0),
    'AdaBoost': AdaBoostRegressor(DecisionTreeRegressor(random_state=0), n_estimators=100, random_state=0) 
}

scores = {}
for model_name, model in models.items():
    model.fit(X_train, y_train)
    scores[(model_name, 'train_score')] = model.score(X_train, y_train)
    scores[(model_name, 'test_score')] = model.score(X_test, y_test)

pd.Series(scores).unstack()
test_score train_score
AdaBoost 0.741108 0.99971
tree 0.605167 1.00000

バギング&ブースティング

バギングとブースティングの代表的なモデルとしてランダムフォレストと勾配ブースティングが存在します。これらと、上記の決定木のバギング&ブースティングを比較してみます。モデルのチューンをしていないので、下記がモデルの優劣を表すわけではありませんが、大体の目安になります。

# バギング&ブースト
import pandas as pd
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import AdaBoostRegressor
from sklearn.ensemble import BaggingRegressor
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor

loaded_data = load_boston()
X_train, X_test, y_train, y_test = train_test_split(
    loaded_data.data, loaded_data.target, random_state=0)

models = {
    'tree': DecisionTreeRegressor(random_state=0),
    'AdaBoost': AdaBoostRegressor(DecisionTreeRegressor(random_state=0), random_state=0),
    'Bagging': BaggingRegressor(DecisionTreeRegressor(random_state=0), n_estimators=100, random_state=0),
    'Bagging & AdaBoost': AdaBoostRegressor(BaggingRegressor(DecisionTreeRegressor(random_state=0),
                                                   n_estimators=100,
                                                   random_state=0
                                                  ),
                                  random_state=0
                                 ),
    'RandomForest': RandomForestRegressor(random_state=0),
    'GradientBoost': GradientBoostingRegressor(random_state=0)
}

scores = {}
for model_name, model in models.items():
    model.fit(X_train, y_train)
    scores[(model_name, 'train_score')] = model.score(X_train, y_train)
    scores[(model_name, 'test_score')] = model.score(X_test, y_test)

pd.Series(scores).unstack()
test_score train_score
AdaBoost 0.740901 0.999597
Bagging 0.786746 0.982702
Bagging & AdaBoost 0.763452 0.994583
GradientBoost 0.816288 0.983166
RandomForest 0.757792 0.972705
tree 0.605167 1.000000

おわりに

scikit-learnでバギングとブースティングを試してみました。お手軽に試せて、精度も良いモデルとして、ランダムフォレストと勾配ブースティングが人気です。とりあえず使ってみるというのであれば、これらのモデルがおすすめです。

ground0state
「小さいネタでもoutput」をモットーに小ネタ投稿していきます。 統計検定準1級/G検定2018#2/IoTエキスパート/Signate/kaggle/AWS/Serverless
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away