使用skorch训练模型时,5折交叉验证预测结果远差于直接拟合的原因
为什么两种训练方式的预测结果差异巨大?
这本质是训练集误差和泛化误差的区别,你的模型明显存在严重的过拟合问题,下面拆解具体原因:
核心差异:预测的数据集完全不同
方法1的预测逻辑:
net_reg.fit(X, y)用全部数据集训练模型,之后net_reg.predict(X)是对已经参与训练的所有样本做预测。模型对这些数据已经学习得非常透彻,所以MSE极低、R²接近1,这个结果只反映模型在训练数据上的拟合能力,不能代表真实泛化性能。方法2的预测逻辑:
cross_val_predict(net_reg, X, y, cv=5)是标准的5折交叉验证流程:- 每一轮将数据集划分为4份训练数据、1份测试数据;
- 用训练数据训练一个全新的模型(每折都会重新初始化模型参数);
- 用这个模型对从未见过的测试数据做预测;
- 最后把所有测试折的预测结果拼接成最终的
y_pred。
这个y_pred里的每个样本,都是被从未训练过它的模型预测出来的,反映的是模型在未知数据上的真实泛化能力。
训练loss相近的原因
你提到的方法2的train_loss(约30.0020),应该是各折模型在自己的训练折(4份数据)上的训练loss平均值,和方法1在全量数据上的训练loss(28.5202)相近,说明:
不管是用80%还是100%的数据训练,你的模型都能很好地拟合训练数据,但一旦遇到没见过的测试数据,性能就暴跌——这是典型的过拟合特征:模型把训练数据里的噪声当成了规律,无法迁移到新数据上。
你的设置加剧了过拟合
你设置了train_split=None,这意味着模型训练时没有划分验证集,也无法使用早停(Early Stopping)等策略来终止过拟合的训练过程。模型会一直训练到max_epochs=1000,在训练后期完全记住了训练数据的细节,泛化能力自然极差。
建议的改进方向
- 正确评估泛化能力:交叉验证的结果才是模型真实性能的参考,训练集的预测结果只能用来判断模型是否拟合了训练数据;
- 加入验证与早停:把
train_split设置为默认的skorch.dataset.CVSplit(5),同时添加早停回调:from skorch.callbacks import EarlyStopping net_reg = NeuralNetRegressor( Network_binaryDC, batch_size=32, lr=0.01, max_epochs=1000, criterion=nn.MSELoss, optimizer=torch.optim.Adam, train_split=skorch.dataset.CVSplit(5), callbacks=[EarlyStopping(patience=10)], iterator_train__shuffle=True ) - 添加正则化:在你的
Network_binaryDC中加入Dropout层,或者给优化器添加权重衰减(optimizer__weight_decay=1e-4),限制模型复杂度,缓解过拟合。
内容的提问来源于stack exchange,提问作者Xiao Zhao
相关产品推荐
相关产品推荐

