train_test_split设定随机种子对score的影响

来源:9-8 OvR与OvO

McManfy

2022-06-15

我在自己实现的时候,在train_test_split的时候没有设定随机种子,每次score结果都不一样,最差的时候连90%都不到。

请问老师随机种子对结果的影响这么大的主要原因是不是依然是训练数据集的影响?有没有什么方法可以使得随机挑选训练数据时,拟合结果的差异不是很大?logistic_regression_CV可以吗?

另外这个现象让我有点好奇,train_test_split的时候有没有超参数?如果有,这些超参数怎么优化选取?

写回答

1回答

liuyubobobo

2022-06-16

这里的核心其实是:train_test_split 中的随机的种子不应该作为算法的一个参数。


为什么?因为 train_test_split 的本质是,把其中的一部分数据扔掉(test 部分),把它当做是没有见过的数据。然后针对 train 数据作模型训练。test 数据的作用是报告算法结果的,而不是为了调算法参数的。如果把随机种子作为算法参数,其实相当于在找那个测试数据集的效果最好,相当于 test 对算法是可见的,而非不可见的。此时,得到的模型将对 test 数据集过拟合。


我在讲验证数据集的时候讲过这个问题。这就是我们为什么要设立一份验证数据集的原因。验证数据集可以用于调参,而 test 数据集不可以。如果觉得有必要可以回顾一下这一小节,我们为什么要引入验证数据集:https://coding.imooc.com/lesson/169.html#mid=10031


对于大多数标准的用于测试算法的数据集,本身就已经定义好了什么是训练数据集,什么是测试数据集,比如课程中用的 MNIST 数据集。(甚至一些更严格的测试环境,本身算法人员就拿不到测试数据集)。所以也就不需要为怎么划分 train test 苦恼了。


==========


另一方面,如果 train_test_split 选取不同的随机种子,导致实验结果差距过大,大概率是数据的问题,而非算法的问题。


首先我们需要定义一下什么叫“实验结果差距过大”。非常简单,随机 1000 次(对于某些数据,1000 次过大,可以做调整)train_test_split,用同一组算法做训练,得到一组算法结果的统计数据。分析这组统计数据是否有显著的差异。(显著性分析是统计学最重要的作用之一。)如果有的话,最应该优化的是数据,而非算法。


首先,有可能是因为数据规模过小。

比如只有 10 个数据,5 个 A,5 个 B。选取 8 个做 train 的话。那么很容易选取的 train 是 5 个 A,3 个 B。这将导致 test 是 2 个 B。也就是根本 test 不到 A。而另一方面,如果取到的是 5 个 B,3 个 A,会导致 test 是 2 个 A,根本 test 不到 B。如果你的模型对某一类的鉴别远好于另一类,那么对这两组 test 的结果就会有天壤之别,甚至是 0 和 100 的差别。

但如果你有 100 个数据,50 个 A,50 个 B,选取 80 个做 train,20 和 test。那么随机出这 20 个 test 都是 A 或者都是 B 的概率就大大降低了。1000 个数据,10000 个数据,这种概率将更低。

此时,应该加大数据。


其次,有可能数据过于有偏。如果你有 100 个数据,但是只有 5 个 B,95 个 A。选取 20 个 test,也将大概率 5 个 B 都进 test,从而训练的信息中根本没有 B。那么 test 的结果就很差。但是如果随机出来 5 个 B 进了 4 个在 train,那么那一个 B 在 test 中的影响就很小,导致 test 结果很好。

此时,应该尽量让数据无偏。


在一些特殊的情况下,很难让数据无偏。(比如医疗数据,病人数据就是远远小于健康人的数据)。此时,在 split 上应该考虑“类别的分布”,即不是简单地把整个数据按照某个百分比随机划分,而是对每一个类别都随机按照固定比例划分,这样保证 train 和 test 中各个类别的数据比例和原始数据是相当的。这在机器学习或者统计学中有一个专有的术语,stratified sampling。(听着好像很复杂,但背后的原理就是这么简单。) 


再有就是最初要对整份数据做预处理,扔掉极端点(outliers),以防止计算点出现在测试数据集中影响对算法的评估。


暂时想到这么多。不管怎么样,这个问题的核心不在算法层面,在数据层面(或者采样层面)。


==========


针对你的文字,再补充一句。CV(Cross Validation)可以解决“随机的问题”,但不能解决 test 的问题。更准确地说,CV 一定程度解决了划分 validation 随机导致的数据过度有偏的问题(每一份数据都当一次 validation,把某一份 validation 可能的极端结果淡化掉了。)但是,如我一开始所说,因为 test 就是一上来就要扔掉的,作为假装不知道的数据集的。所以我们不能对整份数据做 CV,也就无法避免分出去的这份 test 很“极端”。


如果布置的是在线算法,对这个问题的容忍度会小很多。但在线算法的本质是对每一个新遇到的数据,都将其信息融入到模型中,其实相当于模型在运行过程中,逐渐“修补”数据的问题。(数据量逐渐增大,不同类别的数据也在逐渐积累。)


继续加油!:)

0
1
McManfy
回答的相当详细,感谢! 老师加油!:)
2022-06-17
共1条回复

Python3入门机器学习 经典算法与应用  

Python3+sklearn,兼顾原理、算法底层实现和框架使用。

5839 学习 · 2437 问题

查看课程