入れ子の交差検証の実装


10

私は入れ子の交差検証の私の理解が正しいかどうかを把握しようとしています。したがって、このおもちゃの例を書いて、私が正しいかどうかを確認します。

import operator
import numpy as np
from sklearn import cross_validation
from sklearn import ensemble
from sklearn.datasets import load_boston

# set random state
state = 1

# load boston dataset
boston = load_boston()

X = boston.data
y = boston.target

outer_scores = []

# outer cross-validation
outer = cross_validation.KFold(len(y), n_folds=3, shuffle=True, random_state=state)
for fold, (train_index_outer, test_index_outer) in enumerate(outer):
    X_train_outer, X_test_outer = X[train_index_outer], X[test_index_outer]
    y_train_outer, y_test_outer = y[train_index_outer], y[test_index_outer]

    inner_mean_scores = []

    # define explored parameter space.
    # procedure below should be equal to GridSearchCV
    tuned_parameter = [1000, 1100, 1200]
    for param in tuned_parameter:

        inner_scores = []

        # inner cross-validation
        inner = cross_validation.KFold(len(X_train_outer), n_folds=3, shuffle=True, random_state=state)
        for train_index_inner, test_index_inner in inner:
            # split the training data of outer CV
            X_train_inner, X_test_inner = X_train_outer[train_index_inner], X_train_outer[test_index_inner]
            y_train_inner, y_test_inner = y_train_outer[train_index_inner], y_train_outer[test_index_inner]

            # fit extremely randomized trees regressor to training data of inner CV
            clf = ensemble.ExtraTreesRegressor(param, n_jobs=-1, random_state=1)
            clf.fit(X_train_inner, y_train_inner)
            inner_scores.append(clf.score(X_test_inner, y_test_inner))

        # calculate mean score for inner folds
        inner_mean_scores.append(np.mean(inner_scores))

    # get maximum score index
    index, value = max(enumerate(inner_mean_scores), key=operator.itemgetter(1))

    print 'Best parameter of %i fold: %i' % (fold + 1, tuned_parameter[index])

    # fit the selected model to the training set of outer CV
    # for prediction error estimation
    clf2 = ensemble.ExtraTreesRegressor(tuned_parameter[index], n_jobs=-1, random_state=1)
    clf2.fit(X_train_outer, y_train_outer)
    outer_scores.append(clf2.score(X_test_outer, y_test_outer))

# show the prediction error estimate produced by nested CV
print 'Unbiased prediction error: %.4f' % (np.mean(outer_scores))

# finally, fit the selected model to the whole dataset
clf3 = ensemble.ExtraTreesRegressor(tuned_parameter[index], n_jobs=-1, random_state=1)
clf3.fit(X, y)

どんな考えでも感謝します。


3
Pythonを読まない人のために、テキストの相互検証について理解したバージョンも提供できますか?
ガン-モニカの回復

scikit-learn自身のバージョン:scikit-learn.org/stable/auto_examples/model_selection/...
ayorgo

回答:


14

UPS、コードは間違っていますが、非常に微妙な方法で!

a)トレインセットを内部トレーニングセットとテストセットに分割しても問題ありません。

b)問題は最後の2行で、ネストされた相互検証の目的に関する微妙な誤解を反映しています。ネストされたCVの目的は、パラメータを選択することではなく、アルゴリズムの予想される精度を公平に評価することです。この場合ensemble.ExtraTreesRegressor、このデータでは、何であれ最適なハイパーパラメータを使用します

そして、これはあなたのコードが行まで正しく計算するものです:

    print 'Unbiased prediction error: %.4f' % (np.mean(outer_scores))

ネストされたCVを使用して、分類子の不偏予測を計算しました。しかし、行を書いたときに知っていたように、外側のループの各パスが異なる最適なハイパーパラメーターを生成する可能性があることに注意してください。

   print 'Best parameter of %i fold: %i' % (fold + 1, tuned_parameter[index])

したがって、フォールドを使用して、最終的な最適なハイパーパラメータを選択するための標準のCVループが必要になります

tuned_parameter = [1000, 1100, 1200]
for param in tuned_parameter:

    scores = []

    # normal cross-validation
    kfolds = cross_validation.KFold(len(y), n_folds=3, shuffle=True, random_state=state)
    for train_index, test_index in kfolds:
        # split the training data
        X_train, X_test = X[train_index], X[test_index]
        y_train, y_test = y[train_index], y[test_index]

        # fit extremely randomized trees regressor to training data
        clf2_5 = ensemble.ExtraTreesRegressor(param, n_jobs=-1, random_state=1)
        clf2_5.fit(X_train, y_train)
        scores.append(clf2_5.score(X_test, y_test))

    # calculate mean score for folds
    mean_scores.append(np.mean(scores))

# get maximum score index
index, value = max(enumerate(mean_scores), key=operator.itemgetter(1))

print 'Best parameter : %i' % (tuned_parameter[index])

これはあなたのコードですが、内部への参照が削除されています。

これで最適なパラメータはtuned_parameter[index]になりclf3、コードのように最終的な分類子を学習できるようになります。


ありがとう!best異なるフォールドで異なるパラメーターを選択することを検討しましたが、最適なパラメーターを選択する方法がわかりませんでした。stats.stackexchange.com/questions/65128/…-ここでは、答えとして、外側のkモデルの中から最適なモデルを選択することは実際には望ましくないと述べています。多分まだ誤解しているかもしれませんが、内側のCVループのアイデアは最高のパフォーマンスのモデルを選択することであり、外側のCVループはパフォーマンスを推定することだと思いました。完全に変更されたコードを提供していただけませんか?
アブディス2015

わかった。念のため、完全に変更されたコードを確認したいと思います。ありがとう。
アブディス2015

1
Jacques Wainerの答えについて混乱しており、明確にする価値があると思います。それでは、Wainerは、標準のCVループが最初の質問によって提供されたコードに従うべきか、それとも最初の「内部」の部品コードを置き換えるだけであるべきだと提案していますか?thanx

標準のCVループはネストされたCVループに従います
Jacques Wainer

2
最初の部分は、エラーの公平な予測を計算することです。多くの異なるアルゴリズムをテストする場合は、最初の部分のみを実行してから、エラーが最も少ないアルゴリズムを選択し、その部分についてのみ、2つの部分を実行してハイパーパラメーターを選択する必要があります。アルゴリズムを1つだけ使用するように設定されている場合、上司またはクライアントに分類子の将来のエラーの最良の予測はxであり、最初の部分を使用してxを計算する必要があることを伝えたくない限り、最初の部分はそれほど重要ではありませんネストされたCV。
Jacques Wainer、2016

0

ジャックの答えを要約すると、

ネストされたCVは、モデルの不偏誤差推定に必要です。このようにして、さまざまなモデルのスコアを比較できます。この情報を使用して、選択したモデルのパラメーター調整のために別のKフォールドCVループを実行できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.