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

GridSearchCV(refit='accuracy')混淆矩阵数值与平均准确率不匹配问题

问题:GridSearchCV全量数据准确率与交叉验证均值不一致

我在使用GridSearchCV时设置了多评估指标,指定refit='accuracy'参数。由于refit会基于全量数据集重新训练模型,交叉验证各折的混淆矩阵或AUC曲线并无实际意义。但当我用全量数据集生成混淆矩阵后,通过(TP+TN)/总样本计算得到的准确率,与模型训练得到的mean_test_Accuracy数值不一致,不清楚遗漏了什么环节。

相关代码如下:

scoring = {'Accuracy':'accuracy','AUC': 'roc_auc'}
CV = StratifiedKFold(n_splits = 4, random_state = None, shuffle=True)

pipe = Pipeline([('transform', SimpleImputer(strategy='mean')), 
('kbest', SelectKBest(f_classif)), 
('classifier', SVC())]) 


search = GridSearchCV(
    estimator = pipe,
    param_grid = param_grid,
    refit= 'Accuracy',
    n_jobs=-1,
    scoring=scoring,
    cv=CV,
    verbose=0,
    error_score='raise'
)
search.fit(X, y)

df=pd.DataFrame(search.cv_results_)
df=df.sort_values('rank_test_Accuracy')
val_acc = df['mean_test_Accuracy'].iloc[0]

全量数据混淆矩阵计算代码:

from sklearn.metrics import confusion_matrix
y_pred = search.best_estimator_.predict(X)
print (confusion_matrix(y, y_pred))

核心原因分析

  • 计算对象不同:mean_test_Accuracy是4折交叉验证中,每折验证集准确率的平均值,反映的是模型在未见过的陌生数据上的泛化能力;而全量数据的准确率是模型在所有训练+验证数据上的表现,包含了模型已经学习过的信息,两者数值本就应该存在差异。
  • 特征选择的数据集依赖性:你的Pipeline包含SelectKBest,这个步骤会基于当前训练数据的F值筛选特征。交叉验证时,每折都会用该折的训练集重新计算特征优先级;而refit后的模型是用全量数据做的特征选择,两次筛选出的特征子集大概率不同,这会进一步放大准确率的差异。

验证方法

1. 手动复现交叉验证均值

通过手动模拟交叉验证过程,验证mean_test_Accuracy的计算逻辑:

import numpy as np
from sklearn.metrics import accuracy_score

cv_scores = []
for train_idx, val_idx in CV.split(X, y):
    X_train, X_val = X.iloc[train_idx], X.iloc[val_idx]
    y_train, y_val = y.iloc[train_idx], y.iloc[val_idx]
    # 使用最优参数训练当前折模型
    pipe.set_params(**search.best_params_)
    pipe.fit(X_train, y_train)
    y_pred_val = pipe.predict(X_val)
    cv_scores.append(accuracy_score(y_val, y_pred_val))

manual_mean_acc = np.mean(cv_scores)
print(f"手动计算的交叉验证均值:{manual_mean_acc:.4f}")
print(f"GridSearchCV输出的mean_test_Accuracy:{val_acc:.4f}")

两者数值应该完全一致,说明交叉验证的计算逻辑没问题。

2. 对比特征选择结果

查看全量数据训练的模型和交叉验证单折模型的特征选择差异:

# 查看refit模型选中的特征
refit_kbest = search.best_estimator_.named_steps['kbest']
refit_selected = refit_kbest.get_support()

# 查看交叉验证第一折模型选中的特征
train_idx, val_idx = next(CV.split(X, y))
X_train = X.iloc[train_idx]
pipe.set_params(**search.best_params_)
pipe.fit(X_train, y.iloc[train_idx])
cv_kbest = pipe.named_steps['kbest']
cv_selected = cv_kbest.get_support()

print(f"全量数据与交叉验证折的特征选择是否一致:{np.array_equal(refit_selected, cv_selected)}")

大概率会输出False,这就是造成准确率差异的关键因素之一。


结论

这种差异是正常且合理的:

  • mean_test_Accuracy是模型泛化能力的可靠估计,代表模型在新数据上的表现;
  • 全量数据准确率是模型在训练数据上的拟合结果,数值通常会更高,仅能反映模型对现有数据的学习程度,不能代表泛化能力。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 08:08:29