LoginSignup
11
16

More than 3 years have passed since last update.

スタッキングで分類・回帰 (scikit-learn)

Last updated at Posted at 2020-09-15

複数の機械学習モデルを組み合わせる方法の一つとしてスタッキングがありますが、Python の scikit-learnのStackingClassifierとStackingRegressorを使ってみました。

StackingClassifier

スタッキングによる分類

分類モデルの性能を確認するため、乳がんデータを使ってみます。

from sklearn.datasets import load_breast_cancer
X, y = load_breast_cancer(return_X_y=True)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y)

ろくなパラメータチューニングもしてないので改良の余地はありますが、とりあえず

from sklearn.ensemble import RandomForestClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.ensemble import StackingClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.linear_model import LogisticRegression

estimators = [
        ('svc', make_pipeline(StandardScaler(), SVC())),
        ('rf', RandomForestClassifier()),
        ('mlp', MLPClassifier(max_iter=10000))
        ]
clf = StackingClassifier(
    estimators=estimators,
    final_estimator=LogisticRegression(max_iter=10000)
)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)
0.972027972027972

単独の分類モデルの性能

比較として、単独の分類モデルの正解率を計算してみます。

make_pipeline(StandardScaler(), SVC()).fit(X_train, y_train).score(X_test, y_test)
0.965034965034965
RandomForestClassifier().fit(X_train, y_train).score(X_test, y_test)
0.951048951048951
MLPClassifier(max_iter=10000).fit(X_train, y_train).score(X_test, y_test)
0.9090909090909091
LogisticRegression(max_iter=10000).fit(X_train, y_train).score(X_test, y_test)
0.958041958041958

単独で使うよりも、組み合わせた方が良いという結果になりました。

ですが、train_test_split から計算し直すと、分割のされ方によっては単独の分類モデルのほうが性能が良くなったりします。

性能比較には、ランダムシードを固定せずに、何度も計算を繰り返して、その性能がどのくらい安定なのかを確認した方がいいと思っています。

StackingRegressor

スタッキングによる回帰

回帰モデルの性能を確認するため、糖尿病データを使ってみます。

from sklearn.datasets import load_diabetes
X, y = load_diabetes(return_X_y=True)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y)

こちらも、ろくなパラメータチューニングしてないので改良の余地はありますが、

from sklearn.ensemble import RandomForestRegressor
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVR
from sklearn.ensemble import StackingRegressor
from sklearn.neural_network import MLPRegressor
from sklearn.cross_decomposition import PLSRegression

estimators = [
        ('svr', make_pipeline(StandardScaler(), SVR())),
        ('rf', RandomForestRegressor()),
        ('mlp', MLPRegressor(max_iter=10000))
        ]
clf = StackingRegressor(
    estimators=estimators,
    final_estimator=PLSRegression(),
)
clf.fit(X_train, y_train)
clf.score(X_test, y_test)
0.4940607294168183

単独の回帰モデルの性能

比較として、単独の回帰モデルののR2値を計算してみます。

make_pipeline(StandardScaler(), SVR()).fit(X_train, y_train).score(X_test, y_test)
0.17571936903725216
RandomForestRegressor().fit(X_train, y_train).score(X_test, y_test)
0.46261715392586217
MLPRegressor(max_iter=10000).fit(X_train, y_train).score(X_test, y_test)
0.4936782755875562
PLSRegression().fit(X_train, y_train).score(X_test, y_test)
0.4927059150604132

こちらも、単独で使うよりも、組み合わせた方が良いという結果になりました。

ですが、train_test_split から計算し直すと、分割のされ方によっては単独の回帰モデルのほうが性能が良くなったりします。

性能比較には、ランダムシードを固定せずに、何度も計算を繰り返して、その性能がどのくらい安定なのかを確認した方がいいと思っています。

11
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
16