在机器学习中,经常提到训练集和测试集,验证集似有似无。感觉挺好奇的,就仔细查找了文献。以下谈谈训练集、验证集和测试集。

为什么要划分数据集为训练集、验证集和测试集?

        做科研,就要提出问题,找到解决方法,并证明其有效性。这里的工作有3个部分,一个是提出问题,一个是找到解决方法,另一个是证明有效性。每一个部分都可以作为科研的对象,研究的越靠前,则越偏向科学,越靠后,则越偏向技术,因此叫做科学与技术。

        在人工智能领域,证明一个模型的有效性,就是对于某一问题,有一些数据,而我们提出的模型可以(部分)解决这个问题,那如何来证明呢?这和我们平时的考试也是一样的,证明我们掌握了某类知识,就是去参加考试。

        好,那么如何设计考试,让这个考试可以较为客观的考察出每个人的能力呢(注意,不是让每个人都得最高分)?回想我们的高中阶段,有一些教材,让我们平时学习其基本知识(训练集),有一些模拟考试,让我们知道我们到底掌握的怎么样,然后再改进我们的学习(验证集),最后的高考决定我们的去向(测试集)。这样的类比,是不是就很清楚了。

训练集、验证集和测试集

1. **训练集**:顾名思义指的是用于训练的样本集合,主要用来训练神经网络中的参数。

2. **验证集**:从字面意思理解即为用于验证模型性能的样本集合.不同神经网络在训练集上训练结束后,通过验证集来比较判断各个模型的性能.这里的不同模型主要是指对应不同超参数的神经网络,也可以指完全不同结构的神经网络。

3. **测试集**:对于训练完成的神经网络,测试集用于客观的评价神经网络的性能。

如何划分训练集、验证集和测试集

        这个问题其实非常基础,也非常明确,在Scikit-learn里提供了各种各样的划分方法。无论是单一的训练集、验证集和测试集,还是进行交叉验证,你都会找到调用的方法,因此我们这里主要介绍两种常见的方法。

1. 前人给出训练集、验证集和测试集
  对于这种情况,那么只能跟随前人的数据划分进行,一般的比赛也是如此。一定不要使用测试集来调整性能(测试集已知的情况下),尽管存在使用这种方法来提升模型的性能的行为,但是我们并不推荐这么做。最正常的做法应当是使用训练集来学习,并使用验证集来调整超参数。当在验证集上取得最优的模型时,此时就可以使用此模型的超参数来重新训练(训练集+验证集),并用测试集评估最终的性能。
    我们首先说明加入验证集重新训练和不加有啥区别,从理论上讲,一方面学习的样本增多,应当是会提升模型性能的,第二,其在验证集上取得最优的模型与验证集的分布的契合度是最高的,因此最终的模型会更接近验证集的分布。
    其次再说明验证集和测试集上的性能差异。事实上,在验证集上取得最优的模型,未必在测试集上取得最优。其原因就是训练的模型是否对于该问题有着较好的泛化能力,即没有对验证集产生过拟合现象。正因为有这种情况的发生,才会有人使用测试集的最优值作为最终的结果(而不管验证集的好坏)。

2. 前人没有明确给出数据集的划分
  这时候可以采取第一种划分方法,对于样本数较小的数据集,同样可以采取交叉验证的方法。
    交叉验证的方法的使用场景有很多,我们这里是针对不同的模型的性能好坏进行评估。
    使用交叉验证,可以获得更为客观的性能差异。当使用第一种方法时,我们更建议使用P值来做显著性检验,从而保证性能差异的客观性。而使用第二种方法,即交叉验证时,我们选取其性能表现的均值作为最终的结果,更能体现该模型的泛化能力。

                                 1.存在验证集
                                这里五倍交叉验证是用于进行调参,此时不接触测试集。
                                数据集首先划分出训练集与测试集(可以是4:1或者9:1)。
                                其次,在训练集中,再划分出验证集(通常也是4:1或者9:1)
                                然后对于训练集和验证集进行5折交叉验证,选取出最优的超参数,然后把训练集和验证集一起训练出最终的模型。
                                2.不存在验证集
                                该情况通常是对比不同的模型,如自己的模型和别人的模型的性能好坏。
                                只需要把数据集划分为训练集和测试集即可,然后选取5次试验的平均值作为最终的性能评价。

验证集和测试集的区别

        那么,训练集、校验集和测试集之间又有什么区别呢?一般而言,训练集与后两者之间较易分辨,校验集和测试集之间的概念较易混淆.个人是从下面的角度来理解的:

  • 神经网络在网络结构确定的情况下,有两部分影响模型最终的性能,一是普通参数(比如权重w和偏置b),另一个是超参数(例如学习率,网络层数).普通参数我们在训练集上进行训练,超参数我们一般人工指定(比较不同超参数的模型在校验集上的性能).那为什么我们不像普通参数一样在训练集上训练超参数呢?(花书给出了解答)一是:超参数一般难以优化(无法像普通参数一样通过梯度下降的方式进行优化).二是:超参数很多时候不适合在训练集上进行训练,例如,如果在训练集上训练能控制模型容量的超参数,这些超参数总会被训练成使得模型容量最大的参数(因为模型容量越大,训练误差越小),所以训练集上训练超参数的结果就是模型绝对过拟合.

  • 正因为超参数无法在训练集上进行训练,因此我们单独设立了一个验证集,用于选择(人工训练)最优的超参数.因为验证集是用于选择超参数的,因此校验集和训练集是独立不重叠的.

  • 测试集是用于在完成神经网络训练过程后,为了客观评价模型在其未见过(未曾影响普通参数和超参数选择)的数据上的性能,因此测试与验证集和训练集之间也是独立不重叠的,而且测试集不能提出对参数或者超参数的修改意见,只能作为评价网络性能的一个指标.

为了方便清楚直观的了解,上一个表格:

综述

        至此,我们可以将神经网络完整的训练过程归结为一下两个步骤:

        1.训练普通参数.在训练集(给定超参数)上利用学习算法,训练普通参数,使得模型在训练集上的误差降低到可接受的程度(一般接近人类的水平).

        2.’训练’超参数.在验证集上验证网络的generalization error(泛化能力),并根据模型性能对超参数进行调整.

        重复1和2两个步骤,直至网络在验证集上取得较低的generalization error.此时完整的训练过程结束.在完成参数和超参数的训练后,在测试集上测试网络的性能.

附言

说到底:

  • 验证集是一定需要的;

  • 如果验证集具有足够泛化代表性,是不需要再整出什么测试集的;

  • 整个测试集往往就是为了在验证集只是非训练集一个小子集的情况下,好奇一下那个靠训练集(训练)和验证集(调参)多次接力训练出来的模型是不是具有了泛化性能,因而加试一下图个确定。