
细说深度学习训练集、验证集、测试集(为什么有的论文的数据集只有训练集和验证集而无测试集)
为什么有的论文的数据集只有训练集和验证集而无测试集
验证集的作用:验证集是用来让我们验证一下网络的当前训练结果,以便于我们观察模型的泛化能力,看模型是否有过拟合,以调整网络的超参数如网络架构,学习率等。注意网络的训练并没有真的用到验证集,因为验证期间没有计算梯度,没有更新参数!
我们知道,传统机器学习的根本假设是:用于训练模型的数据和用来测试模型的数据来自同一个概率分布。
对于规模很大的数据集,我们可以理想一点,认为他们服从这个根本假设。既然数据集很大,那我们就可以奢侈一点,把数据集划分为术业有专攻的三块:训练集,验证集,测试集。
但是其实很多时候只分为两块,即训练集和测试集,一是因为数据量有限,二是因为测试集可以身兼两职,既可以用作验证集来验证模型的训练结果,又可以用来得到最终测试结果。
分为两块的这种划分还有个专门的名字,叫做“留出法”。
训练集用来训练NN,即根据反向传播的误差对每个参数的梯度进行参数更新;
验证集专门用来看看每经过1个epoch的训练之后,NN的性能如何,即验证一下当前模型的能力,那当然要用模型从来没见过的数据,即验证集绝对不能来自训练集!
(如果把训练集的一部分作为验证集,那模型当然会表现很好,因为已经见过了,并且根据这些数据还做了自我校正。就像考试出原题无法验证考生的真实学习能力一样。)
最重要的一点:验证NN性能的过程不会更新网络的参数,因为验证时停止了梯度的反向传播!这一点一看代码就知道了。
所以!验证就是测试,测试就是验证,使用的是同样的代码,只是由于目的不同而有了不同的名字。
所以!如果你的任务中数据集比较小的话,完全可以拿测试数据作为验证数据,而不必非要分为三部分,害的每一部分的size都很捉襟见肘,搞得训练集太小不够训练,测试集太小使得测试精度不那么可信,很尴尬。
这也是为什么很多论文中给出的训练过程图中给的是训练精度(train_accuracy)和测试精度(test_accuracy)的变化,而非训练精度和验证精度(validation_accuracy)。比如:
如果验证集就是测试数据的话,那么test_accuracy曲线的最后一个值就是最终的测试精度啦。
测试集就是最终要测试的数据了,是要得到一个结果,比如精度或者误差。
既然测试集可以用作验证集,那为啥还要分成三个集呢?
这太简单了,因为测试数据会变化啊。训练好一个模型后,之后可能会把他用到新的测试数据上,但是之前训练过程中用了当时任务的测试数据做验证集。
有必要说一说交叉验证,因为我之前把交叉验证和验证集搞混。
上面的留出法多做几次,把结果取平均就是交叉验证了。
交叉验证是针对数据集太小的情况,想要充分榨干这个小数据集的光和热,数据集够大就不需要折腾这个了。直接举个例子说明:
如果一个数据集有100条数据,按照8:2分为训练集和测试集(直接用测试集作为验证集),则应该用训练集的80条数据训练模型,用测试集的20条数据来测试训练的效果如何。
显然,这个模型只见到了80条数据,而有20条没见过,如果这俩数字是80000和20000,那我们觉得这个模型是可信的,毕竟8万条数据含有的多样性大概率已经包含了这2万条所含的多样性,所以无需钻研交叉验证。
但是80和20这两个数字,样本量太吝啬,我们会觉得这80条数据很可能没有包含着20条所能展示的多样性(信息),所以用这80条数据训练的模型的效果也就不那么可信了,因为这个模型没见过这20条数据的模式,所以识别效果也许也不好,即过拟合。
如果不考虑扩充数据集,那就只能充分利用这个小数据集。于是就有了交叉验证:我们再重新划分4次训练集和测试集,每次拿不同的80条作为训练集,另外20条作为测试集;最后把五次实验结果一平均,就是5折交叉验证。
注意在实现中,5次实验的5个测试集,不是说必须完全不同(第一次以编号为0-19的作为测试集,第二次20-39,第三次40-59,第四次60-79...),当然,这样做才严格符合交叉验证的定义,这样最好。
但是为了实现方便,一般是用随机法来近似。即:随机选择20条作为测试集,剩下的就是训练集了,5折就选5次,10折就选10次。
总之,训练集是用来通过梯度反向传播更新参数的,而验证集和测试集不会通过梯度反向传播更新参数,所以测试集和验证集完全可以是同一个数据集,而他俩都不可以和训练集有交叠,即必须互斥。
更多推荐
所有评论(0)