4.1.3 如何划分数据集

实际上,划分数据集是由于模型评估和选择的需要,此处主要讲述其概念和实际操作方式。一般来说数据集分为3个部分:训练集、验证集和测试集。其含义分别为:训练模型、模型调参(验证集上的模型表现提供调参的参考依据)、模型性能的最终评估(测试集上的模型表现作为最终评价,即泛化误差的无偏估计)。这是非常传统的机器学习数据集划分方式,但现在更为推崇的是使用K折交叉验证的模式。当选择在训练数据集上使用K折交叉验证来调整模型参数时,将不再有显式验证数据集。

笔者初学机器学习时发现有几个容易混淆的概念:混淆矩阵、测试数据集和验证数据集。混淆矩阵本身有“混淆”二字,对其容易混淆也无可厚非,但为什么测试集和验证集也容易让人混淆呢?这主要是由于个人惯性理解的偏差和建模场景的不同,比如模型验证使用的却是测试集,还比如图4-4所示的常见的3种数据集划分方式。

图4-4 数据集划分

·a图是传统数据集划分方式,实际工作中也将训练集和验证集统一称为训练集。

·b图是使用K折交叉验证的划分方式。

·c图是具有时间属性的数据集的划分方式,在这个划分方法里,前两项数据集也可统一称为训练集。在统一的训练集上应用sklearn中的train_test_split函数将其划分为两个部分。测试集-2表示时间范围外的样本(OOT)。

不管哪种划分方式,我们要铭记训练模型的初衷:预测。数据集划分时还需注意如下几点。

1)分析数据集的总体分布,提前发现可能分布差异大的问题。如果存在这样的问题,需要重新考虑样本。

2)尽量保证各子数据集的分布一致性,尤其是处理不平衡样本,比如二分类中推荐使用分层采样(Stratified Sampling)技术。有文献[1]表明,由于分层交叉验证有着较低的偏差和方差,因此可以更准确地估计模型性能。sklearn中有相关实现:


train_test_split(xy, stratify=y)
StratifiedKFold()

需要注意的是,上述分层方法并不适用于回归问题,回归问题可考虑使用排序分层(Sorted Stratification),即y排序后再分区采样。不过笔者暂未发现其有开源实现,在sklearn中也不支持[2],需要机器学习工程师自己实现。对于有严重长尾分布的y,可考虑对y值进行Box-Cox变换后再进行模型评估。总之,样本的处理技巧和细节很多,需要深耕学习。

[1] http://web.cs.iastate.edu/~jtian/cs573/Papers/Kohavi-IJCAI-95.pdf

[2] https://github.com/scikit-learn/scikit-learn/issues/4757