You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scikit-learn GridSearchCV交叉验证返回错误均值问题求助

问题分析与解决思路

我之前也碰到过一模一样的问题!核心原因是sklearn对分类任务的交叉验证结果默认采用加权平均(按各折测试集的样本数量加权),而不是你手动计算的简单算术平均。

为什么会出现这个差异?

当你使用分类器时,GridSearchCV底层调用的cross_validate函数会自动将每折测试集的样本数作为权重,计算加权平均的mean_test_*结果。举个例子,假设你的第一折测试集有100个样本,第二折有200个样本,那么加权平均的计算方式是:

(100 * 0.935603198 + 200 * 0.933665455) / (100 + 200) ≈ 0.9343

这正好和你给出的mean_test_f1数值完全匹配,而不是简单的(0.9356 + 0.9337)/2 ≈ 0.9346。

验证方法

你可以检查自定义train_test_iterable中每折的测试集大小,验证加权平均是否和cv_results_里的均值一致:

# 获取各折测试集的大小
test_sizes = [len(test_idx) for _, test_idx in train_test_iterable.split(X, Y)]
# 对第一行结果计算加权平均
weighted_mean = (test_sizes[0] * 0.935603198 + test_sizes[1] * 0.933665455) / sum(test_sizes)
print(weighted_mean)  # 应该等于0.934310796

如何得到算术平均的结果?

如果你更倾向于使用简单算术平均,可以试试以下几种方法:

方法1:让各折测试集大小一致

使用StratifiedKFold(针对分类任务)这类默认会均分样本的交叉验证器,这样加权平均就等同于算术平均。如果必须使用自定义迭代器,调整逻辑让每折测试集的样本数尽量相等。

方法2:手动计算算术平均

在获取cv_results_之后,手动对各折的测试结果求均值:

import numpy as np

# 提取所有折的f1测试结果
split_test_f1 = [gscv.cv_results_[f'split{i}_test_f1'] for i in range(2)]
# 计算算术平均
mean_test_f1_manual = np.mean(split_test_f1, axis=0)

方法3:自定义交叉验证器,强制使用等权重

通过继承BaseCrossValidator自定义一个交叉验证器,返回全1的权重,让cross_validate计算算术平均:

from sklearn.model_selection import BaseCrossValidator

class EqualWeightCV(BaseCrossValidator):
    def __init__(self, base_cv):
        self.base_cv = base_cv
    
    def split(self, X, y=None, groups=None):
        # 复用基础CV的split逻辑
        yield from self.base_cv.split(X, y, groups)
    
    def get_n_splits(self, X=None, y=None, groups=None):
        return self.base_cv.get_n_splits(X, y, groups)
    
    @property
    def weights(self):
        # 返回全1的权重,强制算术平均
        return [1] * self.get_n_splits()

# 用自定义包装器包裹你的train_test_iterable
cv = EqualWeightCV(train_test_iterable)
# 传入GridSearchCV
gscv = GridSearchCV(
    n_jobs=n_jobs,
    cv=cv,
    estimator=pipeline,
    param_grid=param_grid,
    verbose=10,
    scoring=['accuracy', 'precision','recall','f1'],
    refit='f1',
    return_train_score=return_train_score,
    error_score=error_score
)

另外,注意到你有两行完全相同的拆分结果,这可能是param_grid里存在重复的参数组合,或者自定义迭代器生成了重复的折,建议检查一下参数网格的配置。

内容的提问来源于stack exchange,提问作者mlengg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:50:18