首页 > 解决方案 > 为什么 10 倍交叉验证的准确度得分比使用 sklearn 的 90-10 train_test_split 最差?

问题描述

任务是通过神经网络进行二元分类。数据存在于字典中,其中包含每个条目的复合名称(作为键)和标签(0 或 1,作为向量值中的第三个元素)。第一个和第二个元素是复合名称的两部分,后面用来提取对应的特征。

在这两种情况下,为了对多数类(存在于 66% 的数据中)执行平衡欠采样,字典都被转换为两个数组:

data_for_sampling = np.asarray([key for key in list(data.keys())])
labels_for_sampling = [element[2] for element in list(data.values())]

sampler = RandomUnderSampler(sampling_strategy = 'majority')
data_sampled, label_sampled = sampler.fit_resample(data_for_sampling.reshape(-1, 1), labels_for_sampling)

然后使用重新采样的名称和标签数组通过 Kfold 方法创建训练和测试集:

kfolder = KFold(n_splits = 10, shuffle = True)
kfolder.get_n_splits(data_sampled)

for train_index, test_index in kfolder.split(data_sampled):

        data_train, data_test = data_sampled[train_index], data_sampled[test_index]

或者 train_test_split 方法:

data_train, data_test, label_train, label_test = train_test_split(data_sampled, label_sampled, test_size = 0.1, shuffle = True)

最后,来自 data_train 和 data_test 的名称用于从原始字典中重新提取相关条目(按键),然后用于收集这些条目的特征。就我而言,10 折集的单个拆分应该提供与 90-10 train_test_split 相似的训练测试数据分布,这在训练期间似乎是正确的,两个训练集的准确度都约为 0.82仅在一个 epoch 之后,使用 model.fit() 单独运行。然而,当相应的模型在所述时期之后的测试集上使用 model.evaluate() 进行评估时,来自 train_test_split 的集合给出了 ~0.86 的分数,而来自 Kfold 的集合是~0.72。我做了很多测试,看看它是否只是一个坏的随机种子,它没有界限,但结果保持不变。

标签: pythonmachine-learningscikit-learnk-fold

解决方案


根据数据中的噪声量和数据集的大小,这可能是预期的行为,即看到样本数据外的分数偏离这个量。不能保证一个拆分与任何其他拆分一样,这就是为什么您首先有 10 个,然后对所有结果进行平均。

您应该相信最通用的不是任何一个给定的拆分(无论是来自 10 个折叠之一还是train_test_split()),但更值得信赖的是所有 N 折叠的平均结果

深入挖掘数据可以揭示一个或多个拆分与另一个拆分如此大的差异是否存在某种原因。例如,您的数据中可能存在某些特征(例如,“收集样本的日期”和每月更改的收集方法)使数据以一种有偏见的方式彼此不同。如果是这种情况,您应该使用分层测试拆分(在您的 CV 中也是如此)(请参阅scikit-learn 文档),这样您就可以获得更公正的数据分组。


推荐阅读