web-dev-qa-db-ja.com

scikit-learnでカスタム相互検証ジェネレーターを生成する方法は?

不均衡なデータセットがあるため、データのトレーニング中にのみ適用するオーバーサンプリングの戦略があります。 GridSearchCVcross_val_scoreなどのscikit-learnのクラスを使用して、推定器(SVCなど)のいくつかのパラメーターを探索または相互検証したいと思います。ただし、cvフォールドの数、または標準の交差検定ジェネレーターのいずれかを渡すことがわかります。

カスタムcvジェネレーターを作成したいので、5倍に階層化して、トレーニングデータ(4倍)のみをオーバーサンプリングし、scikit-learnに推定量のパラメーターのグリッドを調べさせ、残りの倍を検証に使用してスコアを付けます。

前もって感謝します。

14
ssierral

交差検定ジェネレーターは、長さn_foldsの反復可能変数を返します。その各要素は、その交差検定のテストセットとトレーニングセットのインデックスを含む2タプルのnumpy1次元配列(train_index, test_index)です。実行します。

したがって、10分割交差検定の場合、カスタム交差検定ジェネレーターには10個の要素が含まれている必要があり、各要素には2つの要素を持つタプルが含まれています。

  • データの90%をカバーする、その実行のトレーニングサブセットのインデックスの配列
  • データの10%をカバーする、その実行のテストサブセットのインデックスの配列

私は、データのさまざまなフォールドに対して整数ラベルを作成するという同様の問題に取り組んでいました。私のデータセットは、相互検証ラベル用の列myDfを持つPandasデータフレームcvLabelに格納されています。カスタム相互検証ジェネレーターmyCViterator次のように:

myCViterator = []
for i in range(nFolds):
    trainIndices = myDf[ myDf['cvLabel']!=i ].index.values.astype(int)
    testIndices =  myDf[ myDf['cvLabel']==i ].index.values.astype(int)
    myCViterator.append( (trainIndices, testIndices) )
16
emunsing

Scikit-Learnは、Label k-foldイテレーターを使用して、この回避策を提供します。

LabelKFoldはk-foldのバリエーションであり、同じラベルがテストセットとトレーニングセットの両方に含まれないようにします。これは、たとえば、さまざまな主題からデータを取得し、さまざまな主題でテストおよびトレーニングすることによって過剰適合(つまり、個人固有の機能の学習)を回避したい場合に必要です。

オーバーサンプリングの場合にこのイテレータを使用するには、最初に、各行のインデックス値を格納する列(cv_labelなど)をデータフレームに作成できます。

df['cv_label'] = df.index

次に、オーバーサンプリングを適用し、オーバーサンプリングのcv_label列もコピーするようにします。この列には、オーバーサンプリングされたデータの重複値が含まれます。後で処理するために、これらのラベルから別のシリーズまたはリストを作成できます。

cv_labels = df['cv_label']

クロスバリデーター/分類子を実行する前に、データフレームからこの列を削除する必要があることに注意してください。

データを機能(cv_labelを含まない)とラベルに分割した後、LabelKFoldイテレーターを作成し、必要な相互検証関数を実行します。

clf = svm.SVC(C=1)
lkf = LabelKFold(cv_labels, n_folds=5)
predicted = cross_validation.cross_val_predict(clf, features, labels, cv=lkf)
8

私は同様の問題を抱えていました、そしてこの速いハックは私のために働いています:

class UpsampleStratifiedKFold:
    def __init__(self, n_splits=3):
        self.n_splits = n_splits

    def split(self, X, y, groups=None):
        for rx, tx in StratifiedKFold(n_splits=self.n_splits).split(X,y):
            nix = np.where(y[rx]==0)[0]
            pix = np.where(y[rx]==1)[0]
            pixu = np.random.choice(pix, size=nix.shape[0], replace=True)
            ix = np.append(nix, pixu)
            rxm = rx[ix]
            yield rxm, tx

    def get_n_splits(self, X, y, groups=None):
        return self.n_splits

これは、バランスの取れた(k-1)-foldトレーニングセットのマイノリティクラスを(置換して)アップサンプリングしますが、k番目のテストセットはアンバランスのままにします。これは、 sklearn.model_selection.GridSearchCV およびCVジェネレーターを必要とする他の同様のクラスでうまく機能するようです。

7
stevemo