机器学习
上QQ阅读APP看书,第一时间看更新

2.2 评估方法

在现实任务中往往还会考虑时间开销、存储开销、可解释性等方面的因素,这里暂且只考虑泛化误差。

通常,我们可通过实验测试来对学习器的泛化误差进行评估并进而做出选择。为此,需使用一个“测试集”(testing set)来测试学习器对新样本的判别能力,然后以测试集上的“测试误差”(testing error)作为泛化误差的近似。通常我们假设测试样本也是从样本真实分布中独立同分布采样而得。但需注意的是,测试集应该尽可能与训练集互斥,即测试样本尽量不在训练集中出现、未在训练过程中使用过。

测试样本为什么要尽可能不出现在训练集中呢?为理解这一点,不妨考虑这样一个场景:老师出了10道习题供同学们练习,考试时老师又用同样的这10道题作为试题,这个考试成绩能否有效反映出同学们学得好不好呢?答案是否定的,可能有的同学只会做这10道题却能得高分。回到我们的问题上来,我们希望得到泛化性能强的模型,好比是希望同学们对课程学得很好、获得了对所学知识“举一反三”的能力;训练样本相当于给同学们练习的习题,测试过程则相当于考试。显然,若测试样本被用作训练了,则得到的将是过于“乐观”的估计结果。

可是,我们只有一个包含m个样例的数据集D={(x1,y1),(x2,y2),...,(xm,ym)},既要训练,又要测试,怎样才能做到呢?答案是:通过对D进行适当的处理,从中产生出训练集S和测试集T。下面介绍几种常见的做法。

2.2.1 留出法

“留出法”(hold-out)直接将数据集D划分为两个互斥的集合,其中一个集合作为训练集S,另一个作为测试集T,即D=S∪T,S∩T=。在S上训练出模型后,用T来评估其测试误差,作为对泛化误差的估计。

以二分类任务为例,假定D包含1000个样本,将其划分为S包含700个样本,T包含300个样本,用S进行训练后,如果模型在T上有90个样本分类错误,那么其错误率为(90/300)×100%=30%,相应的,精度为1−30%=70%。

需注意的是,训练/测试集的划分要尽可能保持数据分布的一致性,避免因数据划分过程引入额外的偏差而对最终结果产生影响,例如在分类任务中至少要保持样本的类别比例相似。如果从采样(sampling)的角度来看待数据集的划分过程,则保留类别比例的采样方式通常称为“分层采样”(stratified sampling)。例如通过对D进行分层采样而获得含70%样本的训练集S和含30%样本的测试集T,若D包含500个正例、500个反例,则分层采样得到的S应包含350个正例、350个反例,而T则包含150个正例和150个反例;若S、T中样本类别比例差别很大,则误差估计将由于训练/测试数据分布的差异而产生偏差。

参见习题(2.1 数据集包含1000个样本,其中500个正例、500个反例,将其划分为包含70%样本的训练集和30%样本的测试集用于留出法评估,试估算共有多少种划分方式。)。

同时可得估计结果的标准差。

另一个需注意的问题是,即便在给定训练/测试集的样本比例后,仍存在多种划分方式对初始数据集D进行分割。例如在上面的例子中,可以把D中的样本排序,然后把前350个正例放到训练集中,也可以把最后350个正例放到训练集中,……这些不同的划分将导致不同的训练/测试集,相应的,模型评估的结果也会有差别。因此,单次使用留出法得到的估计结果往往不够稳定可靠,在使用留出法时,一般要采用若干次随机划分、重复进行实验评估后取平均值作为留出法的评估结果。例如进行100次随机划分,每次产生一个训练/测试集用于实验评估,100次后就得到100个结果,而留出法返回的则是这100个结果的平均。

可从“偏差–方差”(参见2.5 偏差与方差)的角度来理解:测试集小时,评估结果的方差较大;训练集小时,评估结果的偏差较大。

一般而言,测试集至少应含30个样例[Mitchell,1997].

此外,我们希望评估的是用D训练出的模型的性能,但留出法需划分训练/测试集,这就会导致一个窘境:若令训练集S包含绝大多数样本,则训练出的模型可能更接近于用D训练出的模型,但由于T比较小,评估结果可能不够稳定准确;若令测试集T多包含一些样本,则训练集S与D差别更大了,被评估的模型与用D训练出的模型相比可能有较大差别,从而降低了评估结果的保真性(fidelity)。这个问题没有完美的解决方案,常见做法是将大约2/3~4/5的样本用于训练,剩余样本用于测试。

2.2.2 交叉验证法

亦称“k倍交叉验证”。

“交叉验证法”(cross validation)先将数据集D划分为k个大小相似的互斥子集,即D=D1∪D2∪...∪Dk,Di∩Dj=(i≠j)。每个子集Di都尽可能保持数据分布的一致性,即从D中通过分层采样得到。然后,每次用k−1个子集的并集作为训练集,余下的那个子集作为测试集;这样就可获得k组训练/测试集,从而可进行k次训练和测试,最终返回的是这k个测试结果的均值。显然,交叉验证法评估结果的稳定性和保真性在很大程度上取决于k的取值,为强调这一点,通常把交叉验证法称为“k折交叉验证”(k-fold cross validation)。k最常用的取值是10,此时称为10折交叉验证;其他常用的k值有5、20等。图2.2给出了10折交叉验证的示意图。

图2.2 10折交叉验证示意图

“10次10折交叉验证法”与“100次留出法”都是进行了100次训练/测试。

与留出法相似,将数据集D划分为k个子集同样存在多种划分方式。为减小因样本划分不同而引入的差别,k折交叉验证通常要随机使用不同的划分重复p次,最终的评估结果是这p次k折交叉验证结果的均值,例如常见的有“10次10折交叉验证”。

参见习题(2.2 数据集包含100个样本,其中正、反例各一半,假定学习算法所产生的模型是将新样本预测为训练样本数较多的类别(训练样本数相同时进行随机猜测),试给出用10折交叉验证法和留一法分别对错误率进行评估所得的结果。)。

NFL定理参见(1.4 归纳偏好)。

假定数据集D中包含m个样本,若令k=m,则得到了交叉验证法的一个特例:留一法(Leave-One-Out,简称LOO)。显然,留一法不受随机样本划分方式的影响,因为m个样本只有唯一的方式划分为m个子集――每个子集包含一个样本;留一法使用的训练集与初始数据集相比只少了一个样本,这就使得在绝大多数情况下,留一法中被实际评估的模型与期望评估的用D训练出的模型很相似。因此,留一法的评估结果往往被认为比较准确。然而,留一法也有其缺陷:在数据集比较大时,训练m个模型的计算开销可能是难以忍受的(例如数据集包含1百万个样本,则需训练1百万个模型),而这还是在未考虑算法调参的情况下。另外,留一法的估计结果也未必永远比其他评估方法准确;“没有免费的午餐”定理对实验评估方法同样适用。

2.2.3 自助法

关于样本复杂度与泛化性能之间的关系,参见(第12章 计算学习理论)。

我们希望评估的是用D训练出的模型。但在留出法和交叉验证法中,由于保留了一部分样本用于测试,因此实际评估的模型所使用的训练集比D小,这必然会引入一些因训练样本规模不同而导致的估计偏差。留一法受训练样本规模变化的影响较小,但计算复杂度又太高了。有没有什么办法可以减少训练样本规模不同造成的影响,同时还能比较高效地进行实验估计呢?

Bootstrap本意是“解靴带”;这里是在使用德国18世纪文学作品《吹牛大王历险记》中解靴带自助的典故,因此本书译为“自助法”。自助采样亦称“可重复采样”或“有放回采样。

“自助法”(bootstrapping)是一个比较好的解决方案,它直接以自助采样法(bootstrap sampling)为基础[Efron and Tibshirani,1993].给定包含m个样本的数据集D,我们对它进行采样产生数据集D′:每次随机从D中挑选一个样本,将其拷贝放入D′,然后再将该样本放回初始数据集D中,使得该样本在下次采样时仍有可能被采到;这个过程重复执行m次后,我们就得到了包含m个样本的数据集D′,这就是自助采样的结果。显然,D中有一部分样本会在D′中多次出现,而另一部分样本不出现。可以做一个简单的估计,样本在m次采样中始终不被采到的概率是,取极限得到

e是自然常数。

“\”表示集合减法。

即通过自助采样,初始数据集D中约有36.8%的样本未出现在采样数据集D中。于是我们可将D′用作训练集,D\D′用作测试集;这样,实际评估的模型与期望评估的模型都使用m个训练样本,而我们仍有数据总量约1/3的、没在训练集中出现的样本用于测试。这样的测试结果,亦称“包外估计”(out-of-bag estimate)。

集成学习参见(第8章 集成学习)。

自助法在数据集较小、难以有效划分训练/测试集时很有用;此外,自助法能从初始数据集中产生多个不同的训练集,这对集成学习等方法有很大的好处。然而,自助法产生的数据集改变了初始数据集的分布,这会引入估计偏差。因此,在初始数据量足够时,留出法和交叉验证法更常用一些。

2.2.4 调参与最终模型

大多数学习算法都有些参数(parameter)需要设定,参数配置不同,学得模型的性能往往有显著差别。因此,在进行模型评估与选择时,除了要对适用学习算法进行选择,还需对算法参数进行设定,这就是通常所说的“参数调节”或简称“调参”(parameter tuning)。

机器学习常涉及两类参数:一类是算法的参数,亦称”超参数”,数目常在10以内;另一类是模型的参数,数目可能很多,例如大型“深度学习”模型甚至有上百亿个参数。两者调参方式相似,均是产生多个模型之后基于某种评估方法来进行选择;不同之处在于前者通常是由人工设定多个参数候选值后产生模型,后者则是通过学习来产生多个候选模型(例如神经网络在不同轮数停止训练)。

读者可能马上想到,调参和算法选择没什么本质区别:对每种参数配置都训练出模型,然后把对应最好模型的参数作为结果。这样的考虑基本是正确的,但有一点需注意:学习算法的很多参数是在实数范围内取值,因此,对每种参数配置都训练出模型来是不可行的。现实中常用的做法,是对每个参数选定一个范围和变化步长,例如在[0,0.2]范围内以0.05为步长,则实际要评估的候选参数值有5个,最终是从这5个候选值中产生选定值。显然,这样选定的参数值往往不是“最佳”值,但这是在计算开销和性能估计之间进行折中的结果,通过这个折中,学习过程才变得可行。事实上,即便在进行这样的折中后,调参往往仍很困难。可以简单估算一下:假定算法有3个参数,每个参数仅考虑5个候选值,这样对每一组训练/测试集就有53=125个模型需考察;很多强大的学习算法有不少参数需设定,这将导致极大的调参工程量,以至于在不少应用任务中,参数调得好不好往往对最终模型性能有关键性影响。

给定包含m个样本的数据集D,在模型评估与选择过程中由于需要留出一部分数据进行评估测试,事实上我们只使用了一部分数据训练模型。因此,在模型选择完成后,学习算法和参数配置已选定,此时应该用数据集D重新训练模型。这个模型在训练过程中使用了所有m个样本,这才是我们最终提交给用户的模型。

另外,需注意的是,我们通常把学得模型在实际使用中遇到的数据称为测试数据,为了加以区分,模型评估与选择中用于评估测试的数据集常称为“验证集”(validation set)。例如,在研究对比不同算法的泛化性能时,我们用测试集上的判别效果来估计模型在实际使用时的泛化能力,而把训练数据另外划分为训练集和验证集,基于验证集上的性能来进行模型选择和调参。