AI競馬で回収率100%越えを目指して

はなむけ競馬場

未分類

【2日目】Stacked Regressions to predict House Prices 写経

投稿日:

Stacked Regressions to predict House Pricesの写経をする。

前回はこっち。

BaseModelの作成

from sklearn.linear_model import ElasticNet, Lasso,  BayesianRidge, LassoLarsIC
from sklearn.ensemble import RandomForestRegressor,  GradientBoostingRegressor
from sklearn.kernel_ridge import KernelRidge
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, train_test_split
from sklearn.metrics import mean_squared_error
import xgboost as xgb
import lightgbm as lgb

 

必要なライブラリをインポート。

BaseEstimator, TransformerMixin, RegressorMixin, cloneについては、スタッキングを利用するために使用する。クラス作成に用いる。

 

交差検定を利用するため、cross_val_scoreを使う。

ただし、cross_val_scoreにはデータをシャッフルする機能がないので、KFoldを併用する。

 

n_folds = 5
def rmsle_cv(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))#マイナスをつけているのは、neg_mean_squared_errorがマイナスの数値を取るため、正に反転させている
    
    return rmse

 

これで5交差検定が実装された。

複数のモデルを作成し、スタッキングに備える

#Lassoは外れ値にすごい敏感なので、Robustscaler()を利用する
lasso = make_pipeline(RobustScaler(),Lasso(alpha=0.0005,random_state=1))

#elastic net regression
ENet =  make_pipeline(RobustScaler(),ElasticNet(alpha=0.0005,l1_ratio=0.9,random_state=3))

#kernel ridge regression
KRR = KernelRidge(alpha=0.6,kernel="polynomial",degree=2,coef0=0.5)

#Gradient boosting regression
GBoost = GradientBoostingRegressor(n_estimators=3000,learning_rate=0.05,
                                  max_depth=4,max_features="sqrt",
                                  min_samples_leaf=15,min_samples_split=10,
                                  loss="huber",random_state=5)

#XGBoost
model_xgb = xgb.XGBRegressor(colsample_bytree=0.4603, gamma=0.0468, 
                             learning_rate=0.05, max_depth=3, 
                             min_child_weight=1.7817, n_estimators=2200,
                             reg_alpha=0.4640, reg_lambda=0.8571,
                             subsample=0.5213, silent=1,
                             random_state =7, nthread = -1)

#lightgbm
model_lgb = lgb.LGBMRegressor(objective='regression',num_leaves=5,
                              learning_rate=0.05, n_estimators=720,
                              max_bin = 55, bagging_fraction = 0.8,
                              bagging_freq = 5, feature_fraction = 0.2319,
                              feature_fraction_seed=9, bagging_seed=9,
                              min_data_in_leaf =6, min_sum_hessian_in_leaf = 11)

それぞれのモデルのスコアを確認する。
恐らくだが、cross_val_scoreにモデルとデータを突っ込んだ時点で、データがfitされるような使用になっている。
だから、先ほど作成したrmsle_cv関数に入れるだけで、数値が出てくるのだと思う。

score = rmsle_cv(lasso)
print("\nLasso score: {:.4f} ({:.4f})\n".format(score.mean(), score.std()))

score = rmsle_cv(ENet)
print("ElasticNet score: {:.4f} ({:.4f})\n".format(score.mean(), score.std()))

#数字が出ることが確認できる

 

 

スタッキングさせる

手順

  1. トレーニングセットをトレーニング群とvalidation群に分ける
  2. 複数の計算方法でトレーニングセットを学習させて、validationデータでチェックする。
  3. 2で出てきた予測値をそれぞれのモデルで確保しつつ、この数値をメタモデルでのトレーニングデータとして用いる

Faron

この人かどうかは知らないが、スタッキングできるクラスを用意してくれているので、とても使いやすい。
class StackingAveragedModels(BaseEstimator, RegressorMixin, TransformerMixin):
    def __init__(self, base_models, meta_model, n_folds=5):
        self.base_models = base_models
        self.meta_model = meta_model
        self.n_folds = n_folds
   
    # We again fit the data on clones of the original models
    def fit(self, X, y):
        self.base_models_ = [list() for x in self.base_models]
        self.meta_model_ = clone(self.meta_model)
        kfold = KFold(n_splits=self.n_folds, shuffle=True, random_state=156)
        
        # Train cloned base models then create out-of-fold predictions
        # that are needed to train the cloned meta-model
        out_of_fold_predictions = np.zeros((X.shape[0], len(self.base_models)))
        for i, model in enumerate(self.base_models):
            for train_index, holdout_index in kfold.split(X, y):
                instance = clone(model)
                self.base_models_[i].append(instance)
                instance.fit(X[train_index], y[train_index])
                y_pred = instance.predict(X[holdout_index])
                out_of_fold_predictions[holdout_index, i] = y_pred
                
        # Now train the cloned  meta-model using the out-of-fold predictions as new feature
        self.meta_model_.fit(out_of_fold_predictions, y)
        return self
   
    #Do the predictions of all base models on the test data and use the averaged predictions as 
    #meta-features for the final prediction which is done by the meta-model
    def predict(self, X):
        meta_features = np.column_stack([
            np.column_stack([model.predict(X) for model in base_models]).mean(axis=1)
            for base_models in self.base_models_ ])
        return self.meta_model_.predict(meta_features)

#スタッキングしたモデルの作成</pre>
stacked_averaged_models = StackingAveragedModels(base_models = (ENet, GBoost, KRR),
                                                 meta_model = lasso)

score = rmsle_cv(stacked_averaged_models)
print("Stacking Averaged models score: {:.4f} ({:.4f})".format(score.mean(), score.std()))

#Stacking Averaged models score: 0.1105 (0.0072)

スタッキングとxgboost,lightgbmをアンサンブル


</pre>
<pre><span class="k">def</span> <span class="nf">rmsle</span><span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="n">y_pred</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">mean_squared_error</span><span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="n">y_pred</span><span class="p">))

#スタッキング
</span>stacked_averaged_models.fit(train.values, y_train)
stacked_train_pred = stacked_averaged_models.predict(train.values)
stacked_pred = np.expm1(stacked_averaged_models.predict(test.values))
print(rmsle(y_train, stacked_train_pred))

#xgboost
model_xgb.fit(train, y_train)
xgb_train_pred = model_xgb.predict(train)
xgb_pred = np.expm1(model_xgb.predict(test))
print(rmsle(y_train, xgb_train_pred))

#lightgbm
model_lgb.fit(train, y_train)
lgb_train_pred = model_lgb.predict(train)
lgb_pred = np.expm1(model_lgb.predict(test.values))
print(rmsle(y_train, lgb_train_pred))

#なぜか重みづけが、0.7:0.15:0.15となっている。
#説明がなく、もはや奥義</pre>
<pre><span class="n">ensemble</span> <span class="o">=</span> <span class="n">stacked_pred</span><span class="o">*</span><span class="mf">0.70</span> <span class="o">+</span> <span class="n">xgb_pred</span><span class="o">*</span><span class="mf">0.15</span> <span class="o">+</span> <span class="n">lgb_pred</span><span class="o">*</span><span class="mf">0.15</span></pre>
<pre>

-未分類

Copyright© はなむけ競馬場 , 2021 All Rights Reserved Powered by AFFINGER5.