如何在scikit-learn中生成自定义交叉验证生成器?

ssi*_*ral 12 python validation svm scikit-learn

我有一个不平衡的数据集,所以我有一个过采样策略,我只在训练数据时应用.我想使用scikit-learn类GridSearchCV或者cross_val_score在我的估算器(例如SVC)上探索或交叉验证一些参数.但是我看到你要么传递cv折叠的数量,要么传递标准的交叉验证生成器.

我想创建一个自定义cv生成器,所以我得到并分层5折并仅过滤我的训练数据(4倍)并让scikit-learn通过我的估计器的参数网格查看并使用剩余的折叠进行验证.

提前致谢.

emu*_*ing 15

交叉验证生成器返回一个可迭代的长度n_folds,其中每个元素都是一个2元组的numpy 1-d数组,(train_index, test_index)包含该交叉验证运行的测试和训练集的索引.

因此,对于10倍交叉验证,您的自定义交叉验证生成器需要包含10个元素,每个元素包含一个包含两个元素的元组:

  • 该运行的训练子集的索引数组,覆盖了90%的数据
  • 该运行的测试子集的索引数组,覆盖10%的数据

我正在研究一个类似的问题,我为我的数据的不同折叠创建了整数标签.我的数据集存储在Pandas数据框中myDf,该数据框包含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) )
Run Code Online (Sandbox Code Playgroud)


Ger*_*roa 8

Scikit-Learn提供了一个解决方法,使用他们的Label k-fold迭代器:

LabelKFold是k-fold的变体,可确保同一标签不在测试和训练集中.这是必要的,例如,如果您从不同科目获得数据,并且您希望通过测试和培训不同科目来避免过度拟合(即,学习人员特定功能).

要在过采样的情况下使用此迭代器,首先,您可以在数据cv_label框中创建一个列(例如),该列存储每行的索引值.

df['cv_label'] = df.index
Run Code Online (Sandbox Code Playgroud)

然后,您可以应用过采样,确保cv_label在过采样中复制列.此列将包含过采样数据的重复值.您可以从这些标签创建单独的系列或列表,以便以后处理:

cv_labels = df['cv_label']
Run Code Online (Sandbox Code Playgroud)

请注意,在运行交叉验证器/分类器之前,您需要从数据框中删除此列.

将数据分成要素(不包括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)
Run Code Online (Sandbox Code Playgroud)

  • 在 0.18 中重命名为 [GroupKFold](http://scikit-learn.org/stable/modules/ generated/sklearn.model_selection.GroupKFold.html#sklearn.model_selection.GroupKFold)。 (2认同)

ste*_*emo 6

我有一个类似的问题,这个快速的黑客正在为我工​​作:

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
Run Code Online (Sandbox Code Playgroud)

这个上采样(替换)是一个平衡(k-1)折叠训练集的少数类,但是使k测试集不平衡.这似乎与sklearn.model_selection.GridSearchCV需要CV发生器的其他类似类很好地配合.