Sklearn:针对分组数据的交叉验证

15

我正在尝试在分组数据上实现交叉验证方案。我希望使用GroupKFold方法,但我一直出现错误。我做错了什么吗? 以下是代码(与我使用的代码略有不同--我的数据不同,因此我有更大的n_splits,但其他所有内容都相同)

from sklearn import metrics
import matplotlib.pyplot as plt
import numpy as np
from sklearn.model_selection import GroupKFold
from sklearn.grid_search import GridSearchCV
from xgboost import XGBRegressor
#generate data
x=np.array([0,1,2,3,4,5,6,7,8,9,10,11,12,13])
y= np.array([1,2,3,4,5,6,7,1,2,3,4,5,6,7])
group=np.array([1,0,1,1,2,2,2,1,1,1,2,0,0,2)]
#grid search
gkf = GroupKFold( n_splits=3).split(x,y,group)
subsample = np.arange(0.3,0.5,0.1)
param_grid = dict( subsample=subsample)
rgr_xgb = XGBRegressor(n_estimators=50)
grid_search = GridSearchCV(rgr_xgb, param_grid, cv=gkf, n_jobs=-1)
result = grid_search.fit(x, y)

错误:

Traceback (most recent call last):

File "<ipython-input-143-11d785056a08>", line 8, in <module>
result = grid_search.fit(x, y)

File "/home/student/anaconda/lib/python3.5/site-packages/sklearn/grid_search.py", line 813, in fit
return self._fit(X, y, ParameterGrid(self.param_grid))

 File "/home/student/anaconda/lib/python3.5/site-packages/sklearn/grid_search.py", line 566, in _fit
n_folds = len(cv)

TypeError: object of type 'generator' has no len()

改变这行

gkf = GroupKFold( n_splits=3).split(x,y,group)
gkf = GroupKFold( n_splits=3)

同样没有起作用。然后出现了以下错误信息:

'GroupKFold' object is not iterable

1
你使用的sklearn版本是哪一个?GridSearchCVcv参数通常需要使用生成器。 - Moses Koledoye
2个回答

29

GroupKFoldsplit函数每次生成一对训练和测试索引。您应该使用list将拆分值转换为列表,以便可以计算其长度:

gkf = list(GroupKFold( n_splits=3).split(x,y,group))

它似乎可以工作。但是,我尝试了gkf = list(GroupKFold(n_splits=3).split(x,y,group))gkf = list(GroupKFold(n_splits=3).split(x[:-100],y[:-100],group[:-100])),并且对于这两种情况,使用grid_search.fit(x, y)进行训练。它们都以几乎相同的结果顺利运行,而我预期第二个会失败(因为它在gkf上的元素比fit上的少)。我该如何检查它的行为? - Rodrigo Laguna
还尝试了gkf = list(GroupKFold(n_splits=3).split(x,y,group))grid_search.fit(x[:100], y[:100]),但是它会引发一个奇怪的错误IndexError: index 100 is out of bounds for size 100 - Rodrigo Laguna

0

这里是对Moses答案的一个优化。同时存储所有划分可能会占用过多内存,因此我们可以将原始的yield机制进行包装,一次只返回一个训练/测试划分。

class KFoldHelper:
    def __init__(self, kfold: sklearn.model_selection._split._BaseKFold, x: np.ndarray,
                 classes: np.ndarray = None, groups: np.ndarray = None):
        self.iter = kfold.split(x, y = classes, groups=groups)

    def __iter__(self):
        for idxsTrain, idxsTest in self.iter:
            yield idxsTrain, idxsTest

现在我们可以调用

kfold = KFoldHelper(GroupKFold(n_splits=3), x, classes=y, groups=group)

并且

GridSearchCV(rgr_xgb, param_grid, cv=kfold, n_jobs=-1)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接