複数モデルの結果を組み合わせるstacked-model作成について

House Pricesで使われていた、複数モデルの予測結果を一つにまとめる手法について


参考サイト:


  1. クラス設計

 以下の3つを行う

      1. BestEstimatorを継承する
      2. 回帰ならRegressorMixin,、分類ならClassfierMixinを継承する
      3. fit()predict()を実装する



例1)複数のモデルを渡して、それぞれのモデルの予測結果の平均を返すclassと予測

-- 複数の回帰モデルの予測結果の平均を返すクラスの作成

コード:

from sklearn.pipeline import make_pipeline

from sklearn.preprocessing import RobustScaler

from sklearn.base import BaseEstimator, TransformerMixin, RegressorMixin, clone

from sklearn.model_selection import KFold, cross_val_score


# -- 複数モデルを受け取って予測するclass --

class AveragingModels(BaseEstimator, RegressorMixin, TransformerMixin):

  # 初期化

  def __init__(self, models):

    # インスタンス作成時にモデルのタプルを渡すので、それを受け取る

    self.models = models

  # fitメソッド

  def fit(self, X, y):

    # 受け取ったモデル達のクローンを作成しリスト化して渡す。

    self.models_ = [clone(x) for x in self.models]

    # クローンしたモデル達を学習させる

    for model in self.models_:

      models.fit(X, y)

    # 学習済みモデルを返す

    return self

  # クローンしたモデル達で予測して、各予測値の平均を計算して返すメソッド

  def predit(self, X):

    predictions = np.column_stack([ model.predict(X) for model in self.models_])

    # 各モデルの予測結果の平均を返す

    return np.mean(predictions, axis=1)


# -- 各モデルの作成 --

# 評価用関数

n_fold=5

def rmsle_cv(model):

  '''

  引数 model : モデルインスタンス

  '''

  kf = KFold(n_folds, shuffle=True, random_state=42).get_n_splits(train.values)

  rmse = np.sqrt(-cross_val_score(model, train.values, y_train,

                 scoring='neg_mean_squared_error',

                 cv = kf))

  return (rmse)


# モデリング

lasso = make_pipeline(RobustScaler(), Lasso(alpha=0.0005, random_state=1))

ENet = make_pipeline(RobustScaler(), ElasticNet(alpha-0.0005, l1_ratio=0.9,

                                                                                random_state=3))

KRR = KernelRidge(alpha=0.6, kernel='polynomial', degree=2, coef0=2.5)

GBoost = GradientBoostingRegressor(n_estimators=3000, learing_rate=0.05,

                                                            max_depth=4, max_features='sqrt',

                                                            min_samples_leaf=15, min_samples_split=10,

                                                            loss='huber', random_state=5)

# 予測

averaged_models = AveragingModels(models = (lasso, ENet, KRR, GBoost))

score = rmsle_cv(averaged_models)

print('Averaged base models score: {:.4f} ({:.4f})'.format(score.mean(), score.std()))

>>> Averaged base models score: 0.1087 (0.0077)



例2)Stacked Model2: メタモデルの作成と予測結果のアンサンブル

  • メタモデルの作成とは?:
    ベースモデルとして何種類かのモデルを用意し、それらモデルで訓練を行う。個々のモデルの訓練から得られた予測結果を新たな特徴量として別なモデルの訓練に利用し、モデルを作成する(それをメタモデルと呼ぶ)。その後、ベースモデルの予測結果とメタモデルの予測結果の平均を取った値を予測値として出力する。
  • 予測結果のアンサンブルとは?:
    複数のモデルの予測結果に重み付けをして平均を取ることで、最終的な予測結果として利用する。
  • stacked_model作成アルゴリズム:
      1. いくつかのモデルをベースモデルとして、別にモデルを一つメタモデル用に用意する
      2. 訓練データを、trainとholdoutの2つのデータに分ける
      3. ベースモデル達をtrainデータで交差検証する。
      4. holdoutデータでテストする。
      5. 2~4の繰り返しの中でholdoutデータでの検証結果を集めて新たな特徴量とし、その特徴量を用いて、メタモデル用に用意したモデルを訓練しメタモデルを作成する。
      6. ベースモデル達とメタモデルの結果をまとめてstacked_modelとして予測を行う。

詳しくは、サイト参照

  • コード例:
    • stacked_modelのベースモデルとして、ElasticNet, Gradinet Boosting, Kernel Ridge Regressionを、メタモデルの元としてLASSOを利用。
    • 予測結果のアンサンブルとして、(stacked_modelの結果 * 0.75 + XGboostの結果 * 0.15 + lightGBMの結果 * 0.15)の平均値を最終予測値として利用。
      ※ この重みは自分でいい具合のを探さないといけないっぽい。
    • stack_model作成用クラス
    • アンサンブル予測

上記コード元サイト:Stacked Regressions : Top 4% on LeaderBoard



補1:cloneについて

パラメータが同じオブジェクトのインスタンスを作成する(オブジェクトのコピー作成)

例)

from sklearn.base import clone

from sklearn.linear_model import LogisticRegression


lr1 = LogisticRegression()

lr2 = clone(lr1)

cloneの参考サイト:


補2:TransformerMixinクラスについて

fitやtransform、fit_transformが実装されているのがTransformerMixinクラス

なので、TransformMixinを継承すれば、fitや、transform、predictメソッドがその名称のまま利用できる。


補3:np.column_stack((行列1, 行列2))について

1次行列の組み合わせなら2次元行列を作り、多次元の組み合わせならhstackと同じ振る舞いをする。

a = np.array([1, 2, 3])

b = np.array([4, 5, 6])

np.column_stack((a, b))

>>> array([[1, 4],

                  [2, 5],

                  [3, 6]])




機械学習Tips保管庫

データ解析、機械学習のための学習内容の保管庫。復習用。

0コメント

  • 1000 / 1000