【问题标题】:How to generate a custom cross-validation generator in scikit-learn?如何在 scikit-learn 中生成自定义交叉验证生成器?
【发布时间】:2015-07-14 10:57:33
【问题描述】:

我有一个不平衡的数据集,因此我有一个仅在数据训练期间应用的过采样策略。我想使用像GridSearchCVcross_val_score 这样的scikit-learn 类来探索或交叉验证我的估计器(例如SVC)上的一些参数。但是我看到您要么传递了 cv 折叠的数量,要么传递了标准的交叉验证生成器。

我想创建一个自定义 cv 生成器,这样我得到并分层 5 倍并仅对我的训练数据(4 倍)进行过采样,并让 scikit-learn 浏览我的估计器的参数网格并使用剩余的倍数进行评分进行验证。

【问题讨论】:

  • 你找到解决方案了吗?
  • 是的,我这周会发布。
  • 谢谢!请发帖,以帮助像我这样的人:p
  • 我真的很想看看你的解决方案,我也坚持这个。

标签: python validation scikit-learn svm


【解决方案1】:

我遇到了类似的问题,这个快速破解对我有用:

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 训练集对少数类进行了上采样(有替换),但使kth 测试集不平衡。这似乎与 sklearn.model_selection.GridSearchCV 和其他需要 CV 生成器的类似类配合得很好。

【讨论】:

    【解决方案2】:
    class own_custom_CrossValidator:#like those in source sklearn/model_selection/_split.py 
        def init(self):#coordinates,meter 
            pass # self.coordinates = coordinates # self.meter = meter 
        def split(self,X,y=None,groups=None):
        #for compatibility with #cross_val_predict,cross_val_score 
            for i in range(0,len(X)): yield tuple((np.array(list(range(0,len(X))))
    

    【讨论】:

      【解决方案3】:

      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)
      

      【讨论】:

      【解决方案4】:

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

      所以对于 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) )
      

      【讨论】:

      • 这列 (cvLabel) 不会作为无用的功能包含在训练和测试中吗?
      • 良好的观察@GerardoFigueroa;我创建此列以帮助生成 CV,然后子集 myDf 以从发送到预测器的数据集中删除此列(以及任何其他不相关的特征)。
      猜你喜欢
      • 2016-05-09
      • 2015-09-29
      • 2013-08-17
      • 2016-04-25
      • 2012-10-14
      • 2021-10-25
      • 2017-09-02
      • 1970-01-01
      • 2023-03-22
      相关资源
      最近更新 更多