为什么我们应该在传递 StratifiedKFold() 作为 GridSearchCV 的参数时调用 split()



我想做什么?

我正在尝试在GridSearchCV()中使用StratifiedKFold().

那么,是什么让我感到困惑?

当我们使用 K 折叠交叉验证时,我们只需将 CV 的数量传递GridSearchCV()如下所示。

grid_search_m = GridSearchCV(rdm_forest_clf, param_grid, cv=5, scoring='f1', return_train_score=True, n_jobs=2)

然后,当我需要使用StratifiedKFold()时,我认为程序应该保持不变。也就是说,仅设置拆分次数 -StratifiedKFold(n_splits=5)cv.

grid_search_m = GridSearchCV(rdm_forest_clf, param_grid, cv=StratifiedKFold(n_splits=5), scoring='f1', return_train_score=True, n_jobs=2)

但这个答案说

无论使用何种交叉验证策略,所需要的只是 使用函数拆分提供生成器,如建议的那样:

kfolds = StratifiedKFold(5)
clf = GridSearchCV(estimator, parameters, scoring=qwk, cv=kfolds.split(xtrain,ytrain))
clf.fit(xtrain, ytrain)

此外,这个问题的答案之一也建议这样做。这意味着,他们建议在使用GridSearchCV()期间调用split函数:StratifiedKFold(n_splits=5).split(xtrain,ytrain)。但是,我发现打电话split()而不打电话给我split()给我相同的 f1 分数。

因此,我的问题

  • 我不明白为什么我们需要在分层 K 折叠期间调用split()函数为 在 K 折叠 CV 期间,我们不需要做这类事情。

  • 如果调用split()函数,当函数返回训练和测试数据集索引时Split()GridSearchCV()将如何工作?也就是说,我想知道GridSearchCV()将如何使用这些指数?

基本上,GridSearchCV很聪明,可以为该cv参数提供多个选项 - 一个数字,一个拆分索引的迭代器或一个带有拆分函数的对象。你可以在这里查看代码,复制在下面。

cv = 5 if cv is None else cv
if isinstance(cv, numbers.Integral):
if (classifier and (y is not None) and
(type_of_target(y) in ('binary', 'multiclass'))):
return StratifiedKFold(cv)
else:
return KFold(cv)
if not hasattr(cv, 'split') or isinstance(cv, str):
if not isinstance(cv, Iterable) or isinstance(cv, str):
raise ValueError("Expected cv as an integer, cross-validation "
"object (from sklearn.model_selection) "
"or an iterable. Got %s." % cv)
return _CVIterableWrapper(cv)
return cv  # New style cv objects are passed without any modification

基本上,如果你不传递任何东西,它使用带有 5 的 KFold。如果它是一个分类问题并且目标是二进制/多类,则自动使用 StratifedKFold 也足够聪明。

如果你传递一个带有split函数的对象,它只是使用它。如果你没有传递其中任何一个,而是传递一个可迭代对象,它会假设它是拆分索引的可迭代对象,并为你包装它。

因此,在您的情况下,假设这是二进制/多类目标的分类问题,则以下所有内容都将给出完全相同的结果/拆分 - 您使用哪一个并不重要!

cv=5
cv=StratifiedKFold(5)
cv=StratifiedKFold(5).split(xtrain,ytrain)

最新更新