问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

【深度学习基础】一篇弄懂训练集、验证集和测试集

创作时间:
作者:
@小白创作中心

【深度学习基础】一篇弄懂训练集、验证集和测试集

引用
CSDN
1.
https://blog.csdn.net/m0_67656158/article/details/146159448

训练集、验证集和测试集是深度学习中非常重要的概念,它们分别用于模型训练、超参数选择和模型评估。本文将详细解释这三个数据集的作用、划分方法以及如何合理使用它们来提高模型性能。

1. 前言

其实这三个名词大家都经常听到,训练用训练集,测试用测试集,模型验证使用验证集。但是,我们真的都彻底明白他们的含义以及彼此的关系吗?

比如测试、训练、验证集分别是从哪里来的?比如三者分别在什么时候使用?比如三者出现的原因是什么,合理使用能够给模型带来什么好处?好多东西,我们都认为自己明白了,但是本质上都是囫囵吞枣,只知道一个大概而已。

写这篇文章起因是看了一篇论文,里面提到用测试集的数据修正验证集的数据,从而提高了模型整体的效果。当时想问的就是验证集不是用来选择模型、验证模型的吗?修正验证集的数据为什么能起到提升模型效果的功能。于是,查阅了很多相关的资料有了本篇文章。

2. 训练、验证、测试集分别是什么

2.1 训练集是什么

训练集用来训练模型,确定模型的权重和偏置等参数,通常我们称这些参数为学习参数。训练集相当于课后的练习题,用于日常的知识巩固。

总结:训练集是用来训练模型的,并不能用来判断模型质量是否高。

2.2 验证集是什么

而验证集用于模型的选择,更具体地来说,验证集并不参与学习参数的确定,也就是验证集并没有参与梯度下降的过程。验证集只是为了选择超参数,比如网络层数、网络节点数、迭代次数、学习率这些都叫超参数。比如在KNN算法中,k值就是一个超参数。所以可以使用验证集来求出误差率最小的k。验证集相当于周考,用来调整自己的状态,看看要用什么样的心态,什么样的时间安排能够发挥最好的实力。

总结:验证集用来选择模型的超参数,同时也参与训练。

2.3 测试集是什么

测试集只使用一次,即在训练完成后评价最终的模型时使用。它既不参与学习参数过程,也不参数超参数选择过程, 仅仅使用于模型的评价。注意:千万不能在训练过程中使用测试集,而后再用相同的测试集去测试模型。这样子做虽然起来模型测试时准确率很高,但是这将导致测试结果并不准确不能反映模型的真实效果。测试集用于训练,就像考试前偷偷看了试卷的题目,那么考试自然高,但是这并不是真实实力的体现。

总结:测试集用来测试模型的效果,不参与学习参数和超参数选择过程。

3. 为什么要划分三类数据集

这一部分,想要引用另外一位友友的文章,实在是他写的太好了。完全让搞清楚了,当初前辈们为什么会研究出三个数据集的划分方式,而不是其他划分方式。我相信通过这一部分的学习,你也一定能够明白为什么这三类数据集必不可少。

收拾收拾行囊,我们来假设自己就是研究这个领域的前辈,我们并不知道要如何划分数据集,仅仅知道我们手头有一堆数据和一个模型,我们要如何通过这些数据让模型达到一个最好的效果。

第一种方式:把数据集全部作为训练集,然后用训练集训练模型,用训练集验证模型(如果有多个模型需要进行选择,那么最后选出训练误差最小的那个模型作为最好的模型)

这种方式显然不可行,因此训练集数据已经在模型拟合时使用过了,再使用相同的数据对模型进行验证,其结果必然是过于乐观的。如果我们对多个模型进行评估和选择,那么我们可以发现,模型越复杂,其训练误差也就越小,当某个模型的训练误差看似很完美时,其实这个模型可能已经严重地过拟合了。

第二种方式:把数据集随机分为训练集和测试集,然后用训练集训练模型,用测试集验证模型(如果有多个模型需要进行选择,那么最后选出测试误差最小的那个模型作为最好的模型)

什么样的模型是好的?显然泛化误差最小的模型最好,但是我们没有这样的测试集能够测出模型的泛化误差。因此,我们把一部分数据作为测试集,用它的误差来模拟泛化误差。把数据分出一部分作为测试集意味着训练集比原来小了。由学习曲线可知,使用较少的数据训练出来的模型,其测试误差会比较大。因此,对于多个模型的评估和选择,合理的做法是:用训练集训练出各个模型后,用测试集选出其中最好的模型,记录最好模型的各项设置(比如说使用哪个算法,迭代次数是几次,学习速率是多少,特征转换的方式是什么,正则化方式是哪种,正则化系数是多少等等),然后用整个数据集再训练出一个新模型,作为最终的模型,这样得出的模型效果会更好,其测试误差会更接近于泛化误差。

下图展示了随着测试集的增大,各个模型 -- gm-hat(黑实线),gm*(蓝线),gm*-(红线)的期望泛化误差和理想泛化误差(黑虚线)的变化趋势:

可以看到,gm*(蓝线)的表现最好,最接近于理想的泛化误差(黑虚线)。而随着测试集越来越大, gm*-(红线)的表现先是和gm*(蓝线)比较接近,然后越来越不如gm*(蓝线),最后甚至都不如gm-hat(黑实线)。这是因为测试集越大,用于训练的数据就越少,此时训练出的模型的效果肯定也就不好了。因此,在选择测试集的大小时,其实有个两难境地:如果要使gm*(蓝线)的期望泛化误差接近于理想泛化误差,就需要让测试集比较大才好,因为这样有足够多的数据模拟未知情况,但是这样一来,gm*(蓝线)和gm*-(红线)的期望泛化误差之间的差距就比较大;而要想让gm*(蓝线)和gm*-(红线)的期望泛化误差接近,就需要测试集比较小才好,因为这样有足够多的数据训练模型,但是此时gm*(蓝线)的期望泛化误差和理想泛化误差之间的差距较大。一般来说,人们通常将测试集的大小设置为所有数据的20%~30%。

很多资料都是这样把数据分为训练集(70%-80%)和测试集(20%-30%)。这样做的前提是:把模型各个可能的设置分别列出来,训练出各个不同的模型,然后用测试集选出最好的模型,接下来用全部数据按照最好模型的各项设置重新训练出一个最终的模型。这样做有两个问题。第一,模型的超参数通常很多,我们不太有可能把所有可能的设置全部罗列出来,超参数通常需要根据实际情况进行调整。如果模型的测试成绩不理想,那么我们需要返回,重新训练模型。虽然测试集不用于模型的训练,但是我们如果基于测试误差来不断调整模型,这样会把测试集的信息带入到模型中去。显然,这样是不可行的,因为测试集必须是我们从未见过的数据,否则得出的结果就会过于乐观,也就会导致过拟合的发生。第二,得出的最终的模型,其泛化误差是多少?我们还是无法评估。因为我们又把全部数据重新训练出了这个最终的模型,因此也就没有从未见过的数据来测试这个最终的模型了。

第三种方式:把数据集随机分为训练集,验证集和测试集,然后用训练集训练模型,用验证集验证模型,根据情况不断调整模型,选择出其中最好的模型,再用训练集和验证集数据训练出一个最终的模型,最后用测试集评估最终的模型

这其实已经是模型评估和模型选择的整套流程了。在第二种方式中,我们已经把数据集分为了训练集和测试集,现在我们需要再分出一个测试集,用于最终模型的评估。因为已经有一个测试集了,因此我们把其中一个用于模型选择的测试集改名叫验证集,以防止混淆。(有些资料上是先把数据集分为训练集和测试集,然后再把训练集分为训练集和验证集)

前几个步骤和第二种方式类似:首先用训练集训练出模型,然后用验证集验证模型(注意:这是一个中间过程,此时最好的模型还未选定),根据情况不断调整模型,选出其中最好的模型(验证误差用于指导我们选择哪个模型),记录最好的模型的各项设置,然后据此再用(训练集+验证集)数据训练出一个新模型,作为最终的模型,最后用测试集评估最终的模型。

由于验证集数据也会参与训练,因此,验证误差通常比测试误差要小。同时需要记住的是:测试误差是我们得到的最终结果,即便我们对测试得分不满意,也不应该再返回重新调整模型,因为这样会把测试集的信息带入到模型中去。

4. 训练、验证集如何划分

4.1 为什么要考虑训练集和验证集的划分

看到前面的那么一大段讲训练集、验证集和测试集的东西,我相信大家多多少少对这三者有了一定的认识。但是我不知道大家会不会好奇:这三者要如何划分?前面我们说到一个困境:测试集过大会使得训练集过小,模型学习不充分;测试集过小会使得模型测试的不充分,模型的效果不能真实反映实际情况。然后我们用下面这张图,从统计角度去说了测试集应该是20%-30%。

但是从最开始的一张图,如下。我们训练集中分为验证集和训练集,这两者都要参与训练,但是又有不同的用处,这两者又要如何划分呢?

回顾验证集作用是用来选择超参数,那么我们的超参数最好就是尽可能符合所有的数据,也就是说这个超参数要在考虑所有数据的情况下,平均的效果最好。如果仅仅选择一部分数据作为验证集去调整超参数,由于这个验证集并不能很大就会导致模型仅仅偏向于这一部分数据,对其他数据效果非常差。简单点说,模型泛化性差。这不是我们想要的,因此我们划分验证集和训练集的方式并不是一刀切那么简单。(这里一刀切的方法叫做留出法)

4.2 交叉验证

交叉验证:是划分训练集和验证集的一种方法。简单来说就是重复使用数据。除去测试集,把剩余数据进行划分,组合成多组不同的训练集和验证集,某次在训练集中出现的样本下次可能成为验证集中的样本,这就是所谓的“交叉”。最后用各次验证误差的平均值作为模型最终的验证误差。交叉验证有几种不同的方法,但是本质都是要让数据轮流做验证集和训练集从而让超参数尽可能适应所有的数据,提高泛化性。

4.2.1 留一法

假设数据集一共有m个样本,依次从数据集中选出1个样本作为验证集,其余m-1个样本作为训练集,这样进行m次单独的模型训练和验证,最后将m次验证结果取平均值,作为此模型的验证误差。留一法的优点是结果近似无偏,这是因为几乎所有的样本都用于模型的验证,对超参数进行了影响。缺点是计算量大。假如m=1000,那么就需要训练1000个模型,计算1000次验证误差。因此,当数据集很大时,计算量是巨大的,很耗费时间。除非数据特别少,一般在实际运用中我们不太用留一法。

总结:留一法就是一个班主任想要给班里同学买礼物,他询问了班里50位同学的意见,然后买了一个礼物尽可能符合大家所有人的意愿。

4.2.2 K折交叉验证

把数据集分成K份,每个子集互不相交且大小相同,依次从K份中选出1份作为验证集,其余K-1份作为训练集,这样进行K次单独的模型训练和验证,最后将K次验证结果取平均值,作为此模型的验证误差。当K=m时,就变为留一法。可见留一法是K折交叉验证的特例。

总结:K折交叉法就是一个班主任想要给班里同学买礼物,他询问了班里10个小组的意见,然后买了一个礼物尽可能符合10个小组的意愿,老师并不考虑50个人的意愿而是仅仅考虑10个小组的意愿,至于小组的意愿由小组内部决定。

根据经验,K一般取10。(在各种真实数据集上进行实验发现,10折交叉验证在偏差和方差之间取得了最佳的平衡。)

4.2.3 多次K折交叉验证

每次用不同的划分方式划分数据集,每次划分完后的其他步骤和K折交叉验证一样。例如:10 次 10 折交叉验证,即每次进行10次模型训练和验证,这样一共做10次,也就是总共做100次模型训练和验证,最后将结果平均。这样做的目的是让结果更精确一些。(研究发现,重复K折交叉验证可以提高模型评估的精确度,同时保持较小的偏差。)

4.2.4 蒙特卡洛交叉验证

将留出法(holdout)进行多次。每次将数据集随机划分为训练集和验证集,这样进行多次单独的模型训练和验证,最后将这些验证结果取平均值,作为此模型的验证误差。与单次验证(holdout)相比,这种方法可以更好地衡量模型的性能。与K折交叉验证相比,这种方法能够更好地控制模型训练和验证的次数,以及训练集和验证集的比例。缺点是有些观测值可能从未被选入验证子样本,而有些观测值可能不止一次被选中。(偏差大,方差小)

4.3 训练集、验证集划分总结

在数据较少的情况下,使用K折交叉验证来对模型进行评估是一个不错的选择。如果数据特别少,那么可以考虑用留一法。当数据较多时,使用留出法则非常合适。如果我们需要更精确一些的结果,则可以使用蒙特卡洛交叉验证。此外,需要特别注意的是:如果我们要对数据进行归一化处理或进行特征选择,应该在交叉验证的循环过程中执行这些操作,而不是在划分数据之前就将这些步骤应用到整个数据集。

5. 总结

训练集、验证集和测试集的合理划分和使用对于深度学习模型的训练和评估至关重要。通过本文的介绍,相信读者已经对这三个数据集有了更深入的理解。在实际应用中,可以根据数据量的大小和具体需求选择合适的划分方法,以获得最佳的模型性能。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号