参考サイト:
- [Python] scikit-learn の交差検証で分割データをシャッフルする
- パラメータ選択を伴う機械学習モデルの交差検証について
- Stacked Regressions : Top 4% on LeaderBoard
- Tune your preprocessing steps and algorithm selection like hyperparameters
- Parameter estimation using grid search with a nested cross-validation
- Putting together sklearn pipeline+nested cross-validation for KNN regression
- Nested cross-validation and selecting the best regression model - is this the right SKLearn process?
内容:
- sklearnのgrid_searchでパラメータチューニングしつつcross_val_screで交差検証を行うコードについて
- 上記にpipelineを追加したコード
通常、データをtrain_test_splitで訓練データとテストデータにわけたら、そのテストデータで汎化性能を調べるが、それだと、テストデータが1種類だけなので、テストデータに偏りがあると汎化性能を測れない。なので、データをその都度訓練データとテストデータに分けることで、汎化性能をより確認できるようにする。
ただし、例えば、grid_searchのパラメータの組み合わせが9種類あるとして、grid_searchで5分割で交差検証し、さらにcross_val_scoreで5分割すると、9 * 5 * 5 = 225パターンのモデルが作られるので、計算コストがとても高い!のが欠点だが、並列できるので、PCスペックによる。
また、nested交差検証は、汎化性能を見るためのものなので、複数のモデルの比較するのに適している。というのも、nested交差検証にgridsearchを入れると、パラメーターが常に変わるので、一番いいパラメーターを決められない。なので、以下の例4では、GridSearchCVにrepeatedKFoldをセットして、ランダムに分割されたデータを繰り返すなかで最適なパラメータを見つけるようにしている。(※例4は、nested交差検証ではない。)
復習:
- 交差検証の目的:汎化性能の評価
- grid_searchの目的:パラメータチューニング
例1)
『Pythonではじめる機械学習』(ネストした交差検証 p267)より
以下、書籍による説明:
この例では、外側にループを設け、そこでデータを訓練セットとテストセットに分割する。それぞれの分割に対してグリッドサーチを実行する。(外側ループのそれぞれの分割に対して最良のパラメータの組み合わせは異なるかもしれない。)それぞれの分割に対して、最良のセッティングでテストセットを評価した結果が報告される。
この結果は、スコアのリストであり、モデルではなく、パラメータの設定ではない。スコアのリストからわかるのは、このモデルのグリッドから見つけた最適なパラメータによる汎化性能。新しいデータに対して利用できるモデルを与えるわけではないので、ネストした交差検証は、未来のデータに適用するための予測モデルを探すために用いられることはほとんどない。しかし、この手法は、あるモデルのあるデータセットに対する性能の評価には有用。
以下では、GridSearchCVのインスタンスをcross_val_scoreで呼び出している。(ただし、ランダムでデータ分割はしていない)
para_grid = {'C': [1, 10, 100, 1000],
'gamma': [0.0001, 0.001, 0.01, 0.1],
'kernel': ['rbf'] }
scores = cross_val_score(GridSearchCV(SVC(), param_grid, cv=5),
iris.data, iris_target, cv=5)
※ 上記では、全データをそのまま渡しているが、データを訓練データ・テストデータに分けて訓練データを渡せば良い。
例2)
GridSearchCVでのベストパラメータをcross_val_scoreに渡すコード(コード元)
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV, cross_val_score
parameters_svm = {
'C': [1, 10, 100, 1000],
'gamma': [0.0001, 0.001, 0.01, 0.1],
'kernel': ['rbf']
}
# グリッドサーチ設定
clf_cv_svm = GridSearchCV(
SVC(),
paramaters_svm,
cv=7,
scoring='accuracy')
# cross_val_scoreにGridSearchCV設定
scores_svm = cross_val_score(
SVC(C=clf_cv_svm.best_params_['C'],
gamma=clf_cv_svm.best_params_['gamma'],
kernel=clf_cv_svm.best_params_['kernel']),
X, y,
cv=KFold(n_split=7, shuffle=True, random_state=1),
scoring='accuracy')
※ KFold(shuffle=True)により、ランダムに抽出される。
例3)
回帰モデルでのRMSEスコアを算出する関数に適用(コード元)
※ ここでは、GridSearchは使わずに、単にcross_val_scoreでの分割データをランダムにするためにKFoldを利用しているコード
from sklearn.model_selection import KFold, cross_val_score
from sklearn.metrics import mean_squred_error
from sklearn.linear_model import Lass
from sklearn.pipeline import make_pipeline # データリーク防止
from sklearn.preprocessing import RobustScaler # 線形回帰モデルでの外れ値対応
n_folds=5
# rmseスコア算出関数
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)
return (rmse)
# lasso回帰モデル作成
lasso = make_pipeline(RobustScaler(), Lasso(alpha=0.0005, random_state=1))
# スコアリング
score = rmsle_cv(lasso) # 上で作ったrmsle_cv()関数呼び出し
print('Lasso score: {:.4f} ({:.4f})'.format(score.mean(), score.std()))
>>> Lasso score: 0.1115 (0.0074)
0コメント