web-dev-qa-db-ja.com

パイプラインでsklearnのGridSearchCVを使用し、1回だけ前処理する

私はscickit-learnを使用して、モデルのハイパーパラメーターを調整しています。パイプラインを使用して、推定器と前処理を連鎖させています。私の問題の簡単なバージョンは次のようになります。

import numpy as np
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression


grid = GridSearchCV(make_pipeline(StandardScaler(), LogisticRegression()),
                    param_grid={'logisticregression__C': [0.1, 10.]},
                    cv=2,
                    refit=False)

_ = grid.fit(X=np.random.Rand(10, 3),
             y=np.random.randint(2, size=(10,)))

私の場合、前処理(おもちゃの例ではStandardScale()になる)に時間がかかり、パラメーターを調整していません。

したがって、例を実行すると、StandardScalerが12回実行されます。 2適合/予測* 2 cv * 3パラメーター。ただし、パラメーターCの異なる値に対してStandardScalerが実行されるたびに同じ出力が返されるため、一度計算してからパイプラインの推定器部分を実行する方がはるかに効率的です。

前処理(チューニングされたハイパーパラメーターなし)と推定器の間でパイプラインを手動で分割できます。ただし、データに前処理を適用するには、トレーニングセットのみを提供する必要があります。そのため、分割を手動で実装する必要があり、GridSearchCVはまったく使用しません。

GridSearchCVの使用中に前処理を繰り返すことを避けるための簡単な/標準的な方法はありますか?

19
Marc Garcia

基本的に、GridSearchCVは推定器でもあり、パイプラインで使用されるfit()およびpredict()メソッドを実装します。

代わりに:

_grid = GridSearchCV(make_pipeline(StandardScaler(), LogisticRegression()),
                    param_grid={'logisticregression__C': [0.1, 10.]},
                    cv=2,
                    refit=False)
_

これを行う:

_clf = make_pipeline(StandardScaler(), 
                    GridSearchCV(LogisticRegression(),
                                 param_grid={'logisticregression__C': [0.1, 10.]},
                                 cv=2,
                                 refit=True))

clf.fit()
clf.predict()
_

それがすることは、あなたが説明したように複数の呼び出しの代わりにclf.fit()を1回呼び出すために、StandardScalar()を一度だけ呼び出すことです。

編集:

GridSearchCVがパイプライン内で使用される場合、refitをTrueに変更しました。 ドキュメントに記載

refit:boolean、default = Trueデータセット全体で最適な推定量を再適合します。 「False」の場合、フィッティング後にこのGridSearchCVインスタンスを使用して予測を行うことはできません。

Refit = Falseの場合、パイプライン内のGridSearchCVオブジェクトはclf.fit()の後に再初期化されるため、fit()は効果がありません。 _refit=True_の場合、GridSearchCVは、fit()で渡されるデータ全体で最高のスコアリングパラメーターの組み合わせで再調整されます。

したがって、パイプラインを作成する場合は、グリッド検索のスコアを確認するためだけに、_refit=False_が適切です。 clf.predict()メソッドを呼び出す場合は、_refit=True_を使用する必要があります。使用しない場合、Not Fittedエラーがスローされます。

25
Vivek Kumar

現在のバージョンのscikit-learn(0.18.1)ではこれを行うことはできません。 githubプロジェクトで修正が提案されています。

https://github.com/scikit-learn/scikit-learn/issues/88

https://github.com/scikit-learn/scikit-learn/pull/8322

2
Victor Deplasse

ちょっと違う問題に出会った人たちにとっても、私もそうでした。

このパイプラインがあるとします:

classifier = Pipeline([
    ('vectorizer', CountVectorizer(max_features=100000, ngram_range=(1, 3))),
    ('clf', RandomForestClassifier(n_estimators=10, random_state=SEED, n_jobs=-1))])

次に、パラメーターを指定するときに、推定器に使用したこの「clf _」の名前を含める必要があります。したがって、パラメータグリッドは次のようになります。

params={'clf__max_features':[0.3, 0.5, 0.7],
        'clf__min_samples_leaf':[1, 2, 3],
        'clf__max_depth':[None]
        }
0
Ayan Omarov