CNN模型交叉验证准确率高但测试集准确率低的问题咨询
分类任务CNN模型训练问题
我正在实现一个用于分类任务的CNN模型,步骤如下:
- 划分数据集:
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.2, random_state=42, shuffle=True, stratify=Y) - 构建CNN模型并采用分层交叉验证训练,代码如下:
from statistics import mean, stdev # Loop through the splits lst_accu_stratified = [] for train_index, val_index in skf.split(X_train, y_train): X_train_fold, X_val_fold = X_train[train_index], X_train[val_index] y_train_fold, y_val_fold = y_train[train_index], y_train[val_index] # print('Fold :') ResNet50 = model.fit(X_train_fold, y_train_fold, batch_size=16, epochs=20, verbose=1) val_loss, val_acc = model.evaluate(X_val_fold, y_val_fold, verbose=0) print("Validation Loss: ", val_loss, "Validation Accuracy: ", val_acc) lst_accu_stratified.append(val_acc) # Print the output. print('List of possible accuracy:', lst_accu_stratified) print('\nMaximum Accuracy That can be obtained from this model is:', max(lst_accu_stratified)*100, '%') print('\nMinimum Accuracy:', min(lst_accu_stratified)*100, '%') print('\nOverall Accuracy:', mean(lst_accu_stratified)*100, '%') print('\nStandard Deviation is:', stdev(lst_accu_stratified))
训练后各fold的验证准确率分别为0.8000、0.8571、1.0、1.0、1.0,整体均值达93.14%,但用以下代码评估测试集时准确率仅为69.13%:
model.evaluate(X_test, y_test,batch_size=32)
咨询问题
- 我的建模方法是否正确?
- 测试准确率偏低的原因是什么?
问题解答
1. 建模方法存在明显错误
你的分层交叉验证实现逻辑有问题:
- 模型未重置:每次fold训练时,你没有重新初始化模型,而是在同一个
model实例上叠加训练。后续fold的训练是基于前面fold的训练结果继续迭代,不是独立的交叉验证,导致模型不断记住之前的训练数据,验证准确率被虚高。 - 未保留最优模型:交叉验证的核心是筛选泛化能力最好的模型,你仅记录了每个fold的验证准确率,但最终用来评估测试集的是最后一个fold训练完的模型,这个模型不一定具备最优泛化能力。
- 预处理一致性未明确:如果训练集、验证集、测试集的预处理(如归一化、标准化)操作不一致,也会直接影响模型性能,但从代码中看不到这部分的保障逻辑。
2. 测试准确率偏低的核心原因
- 交叉验证错误导致验证准确率失真:由于模型在各fold间未重置,相当于用整个训练集反复训练,验证集的高准确率是模型“记住”数据后的虚假表现,并没有真正学到泛化能力,遇到完全独立的测试集自然表现拉胯。
- 严重过拟合:从后期验证准确率达到100%可以看出,模型在单个fold训练中已经严重过拟合,加上交叉验证的错误操作,进一步放大了过拟合的影响,导致模型无法适配测试集的新数据。
- 数据分布潜在差异:虽然用
stratify=Y保证了类别分布一致,但如果测试集和训练集的特征分布(如图片风格、样本复杂度)差异较大,也会导致模型性能下降,但结合验证准确率的异常表现,这不是首要原因。 - 评估参数不一致:训练用
batch_size=16,测试用batch_size=32,如果模型包含BatchNorm这类依赖batch的层,可能会有轻微影响,但不是主要因素。
修正建议
- 把模型构建代码放到fold循环内,每次训练都初始化全新模型,确保各fold训练独立。
- 为每个fold添加早停(EarlyStopping),并保存验证准确率最高的模型,最后用这些最优模型做集成,或选择平均性能最好的模型评估测试集。
- 统一预处理逻辑:用训练集计算的归一化、标准化参数,同步应用到验证集和测试集,避免单独处理测试集。
- 添加正则化手段(如Dropout、L2正则),缓解模型过拟合问题。
内容的提问来源于stack exchange,提问作者Rezuana Haque
相关产品推荐
相关产品推荐

