任何学习任务,只要模型容量足够,都可以在训练集上达到最优性能,最直观的一点是,模型足够复杂,训练时它记住了训练数据中的所有输入输出的映射关系,从而达到最优性能。然而,这并不是我们想要的模型,因为模型只是“记住”训练样本,而非学习到所有样本包括测试集合从未见过的样本的一般特征。为解决这个问题,引入交叉验证方法相对有意义。需要注意,不恰当的交叉验证方法可能会引起数据泄漏。

交叉验证方法

在监督的机器学习任务中,数据集会划分成训练集(train)、测试集(test)和验证集(validation),一般使用Holdout检验重复多次或者直接使用k-fold交叉验证进行划分,而在样本较少时可以采用自助法bootstrap。如果数据是时间序列数据需要注意不能shuffle。

训练集:训练集在梯度下降算法下训练模型的参数。

验证集:每轮训练后,用验证集来测试当前模型的性能指标,如召回率。由于验证集与训练集没有交集,因此能够准确验证模型的性能。

测试集:通常我们在训练集和测试集上训练一轮又一轮,直到模型在验证集尽可能最优。为达到这个结果,期间我们人工调节了模型的很多超参数,俗称调参。这样一来,验证集就间接参与了模型的训练,这不可避免地出现验证集不能可靠地验证模型的性能。为此,引申出一个新的数据集—测试集,和训练集、验证集完全独立。使用测试集验证模型的性能更可靠。

这就是开发一个模型在交叉验证上的常规操作。然而,在具体的数据集上,不恰当的数据集划分方法可能会引起数据泄漏。看起来这个过程还是有bug,如果测试集的效果也不过,那么是不是重新训练,于是,一个递归开始了~。所以,即便测试集效果好,最终还是要上线对吧。

最后,需要注意为提高验证集效果,不是模型越复杂越好,而是契合奥卡姆剃刀定律:“如无必要,勿增实体”。

数据泄漏与避免

数据泄漏是指模型通过训练集的数据特点,预知测试集的特点,而非学习到样本的普遍特点。构造样本的方式不恰当,例如滑动窗口构造多个样本。有些样本在训练集,有些在验证集,由于这些样本存在关联,模型会很trick学会然而在现实任务中,不存在。

如何避免数据泄漏?根据生产环境抽象出严格的交叉验证方法。一些具体的场景介绍,如NLP中,全局词汇表应该只从训练集构建。句子的切分,对于来自同一段落的句子集,要么只在训练集中,要么只在测试集中。对于时间序列预测,交叉验证应该在时间轴方向上进行,而不是逐个时间步验证。

总结

因此,交叉验证方法一定要设置合理,否则导致数据泄漏,进而验证方法无效

转载请包括本文地址:https://allenwind.github.io/blog/7044/

更多文章请参考:https://allenwind.github.io/blog/archives/