分类目录:《机器学习中的数学》总目录
通常我们把分类错误的样本数占样本总数的比例称为错误率(Error Rate),即如果在 m m m个样本中有 a a a个样本分类错误,则错误率 E = a m E=\frac{a}{m} E=ma相应的, Accuracy = 1 − a m \text{Accuracy}=1-\frac{a}{m} Accuracy=1−ma称为准确率(Accuracy),即“准确率=1-错误率”。更一般地,我们把学习器的实际预测输出与样本的真实输出之间的差异称为误差(Error),学习器在训练集上的误差称为训练误差(Training Error)/经验误差(Empirical Error),在新样本上的误差称为泛化误差(Generalization Error)。
显然,我们希望得到泛化误差小的学习器。然而,我们事先并不知道新样本是什么样,实际能做的是努力使经验误差最小化。在很多情况下,我们可以学得一个经验误差很小、在训练集上表现很好的学习器,例如甚至对所有训练样本都分类正确,即分类错误率为零,分类准确率为100%,但遗憾的是,这样的学习器在多数情况下都不好,我们实际希望的,是在新样本上能表现得很好的学习器。为了达到这个目的,应该从训练样本中尽可能学出适用于所有潜在样本的“普遍规律”,这样才能在遇到新样本时做出正确的判别。然而,当学习器把训练样本学得“太好”了的时候,很可能已经把训练样本自身的一些特点当作了所有潜在样本都会具有的一般性质,这样就会导致泛化性能下降。这种现象在机器学习中称为“过拟合”(Overfitting)。与“过拟合”相对的是“欠拟合”(Underfitting),这是指对训练样本的一般性质尚未学好。图2.1给出了关于过拟合与欠拟合的一个便于直观理解的类比。
有多种因素可能导致过拟合,其中最常见的情况是由于学习能力过于强大,以至于把训练样本所包含的不太一般的特性都学到了,而欠拟合则通常是由于学习能力低下而造成的。欠拟合比较容易克服,例如在决策树学习中扩展分支、在神经网络学习中增加训练轮数等,而过拟合则很麻烦。在后面的文章中我们将看到,过拟合是机器学习面临的关键障碍,各类学习算法都必然带有一些针对过拟合的措施;然而必须认识到,过拟合是无法彻底避免的,我们所能做的只是“缓解”,或者说减小其风险。关于这一点,可大致这样理解:机器学习面临的问题通常是NP难甚至更难,而有效的学习算法必然是在多项式时间内运行完成,若可彻底避免过拟合,则通过经验误差最小化就能获最优解,这就意味着我们构造性地证明了“P=NP”;因此,只要相信“P≠NP”,过拟合就不可避免在现实任务中,我们往往有多种学习算法可供选择,甚至对同一个学习算法,当使用不同的参数配置时,也会产生不同的模型。那么,我们该选用哪一个学习算法、使用哪一种参数配置呢?这就是机器学习中的“模型选择”问题。理想的解决方案当然是对候选模型的泛化误差进行评估,然后选择泛化误差最小的那个模型。然而如上面所讨论的,我们无法直接获得泛化误差,而训练误差又由于过拟合现象的存在而不适合作为标准。
通常,我们可通过实验测试来对学习器的泛化误差进行评估并进而做出选择。为此,需使用一个“测试集”(testing set)来测试学习器对新样本的判别能力,然后以测试集上的“测试误差”(testing error)作为泛化误差的近似。通常我们假设测试样本也是从样本真实分布中独立同分布采样而得。但需注意的是,测试集应该尽可能与训练集互斥,即测试样本尽量不在训练集中出现。为理解这一点,不妨考虑这样一个场景:老师出了10道习题供同学们练习,考试时老师又用同样的这10道题作为试题,这个考试成绩就不能有效反映出同学们学得好不好,原因是可能有的同学只会做这10道题却能得高分。回到我们的问题上来,我们希望得到泛化性能强的模型,好比是希望同学们对课程学得很好、获得了对所学知识“举一反三”的能力;训练样本相当于给同学们练习的习题,测试过程则相当于考试。显然,若测试样本被用作训练了,则得到的将是过于“乐观”的估计结果可是,我们只有一个包含 m m m个样例的数据集 D = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯ , ( x m , y m ) } D=\{(x_1, y_1), (x_2, y_2), \cdots, (x_m, y_m)\} D={(x1,y1),(x2,y2),⋯,(xm,ym)},既要训练,又要测试,则通过对 D D D进行适当的处理,从中产生出训练集 S S S和测试集 T T T。下面介绍几种常见的做法。
留出法
“留出法”(Hold-out)直接将数据集 D D D划分为两个互斥的集合,其中一个集合作为训练集 S S S,另一个作为测试集 T T T,即 D = S ∪ T , S ∩ T = ∅ D=S\cup T, S\cap T=\varnothing D=S∪T,S∩T=∅。在 S S S上训练出模型后,用 T T T来评估其测试误差,作为对泛化误差的估计以二分类任务为例,假定 D D D包含1000个样本,将其划分为 S S S包含700个样本, T T T包含300个样本,用 S S S进行训练后,如果模型在 T T T上有90个样本分类错误,那么其错误率为 90 300 × 100 \frac{90}{300}\times100%=30% 30090×100,相应的,准确率为1-30%=70%。
需注意的是,训练/测试集的划分要尽可能保持数据分布的一致性,避免因数据划分过程引入额外的偏差而对最终结果产生影响,例如在分类任务中至少要保持样本的类别比例相似。如果从采样(Sampling)的角度来看待数据集的划分过程,则保留类别比例的采样方式通常称为“分层采样”(Stratified sampling)。例如通过对 D D D进行分层采样而获得含70%样本的训练集 S S S和含30%样本的测试集 T T T,若 D D D包含500个正例、500个反例,则分层采样得到的 S S S应包含350个正例、350个反例,而 T T T则包含150个正例和150个反例;若 S S S、 T T T中样本类别比例差别很大,则误差估计将由于训练/测试数据分布的差异而产生偏差。
另一个需注意的问题是,即便在给定训练/测试集的样本比例后,仍存在多种划分方式对初始数据集 D D D进行分割。例如在上面的例子中,可以把 D D D中的样本排序,然后把前350个正例放到训练集中,也可以把最后350个正例放到训练集中等等。这些不同的划分将导致不同的训练/测试集,相应的,模型评估的结果也会有差别。因此,单次使用留出法得到的估计结果往往不够稳定可靠,在使用留出法时,一般要采用若干次随机划分、重复进行实验评估后取平均值作为留出法的评估结果。例如进行100次随机划分,每次产生一个训练/测试集用于实验评估,100次后就得到100个结果,而留出法返回的则是这100个结果的平均。
此外,我们希望评估的是用 D D D训练出的模型的性能,但留出法需划分训练/测试集,这就会导致一个窘境:若令训练集 S S S包含绝大多数样本,则训练出的模型可能更接近于用 D D D训练出的模型,但由于 T T T比较小,评估结果可能不够稳定准确;若令测试集 T T T多包含一些样本,则训练集 S S S与 D D D差别更大了,被评估的模型与用 D D D训练出的模型相比可能有较大差别,从而降低了评估结果的保真性(Delity)。这个问题没有完美的解决方案,常见做法是将大约 2 3 ∼ 4 5 \frac{2}{3}\sim\frac{4}{5} 32∼54的样本用于训练,剩余样本用于测试。
交叉验证法
“交叉验证法”(cross validation)先将数据集 D D D划分为 k k k个大小相似的互斥子集,即 D = D 1 ∪ D 2 ∪ ⋯ D k , D i ∩ D k = ∅ ( i ≠ j ) D=D_1\cup D_2\cup\cdots D_k, D_i\cap D_k=\varnothing(i\neq j) D=D1∪D2∪⋯Dk,Di∩Dk=∅(i=j)。每个子集 D i D_i Di都尽可能保持数据分布的一致性,即从 D D D中通过分层采样得到。然后,每次用 k − 1 k-1 k−1个子集的并集作为训练集,余下的那个子集作为测试集;这样就可获得 k k k组训练/测试集,从而可进行 k k k次训练和测试,最终返回的是这 k k k个测试结果的均值。显然,交叉验证法评估结果的稳定性和保真性在很大程度上取决于 k k k的取值,为强调这一点,通常把交叉验证法称为“ k k k折交叉验证”(K-fold Cross Validation)。 k k k最常用的取值是10,此时称为10折交叉验证;其他常用的 k k k值有5、20等。下给出了10折交叉验证的示意图:
与留出法相似,将数据集 D D D划分为 k k k个子集同样存在多种划分方式。为减小因样本划分不同而引入的差别, k k k折交叉验证通常要随机使用不同的划分重复 p p p次,最终的评估结果是这 p p p次k折交叉验证结果的均值,例如常见的有“10次10折交叉验证”。
假定数据集 D D D中包含 m m m个样本,若令 k = m k=m k=m,则得到了交叉验证法的一个特例:留一法(Leave-One-Out,。简称LOO)。显然,留一法不受随机样本划分方式的影响,因为 m m m个样本只有唯一的方式划分为 m m m个子集一每个子集包含一个样本;留一法使用的训练集与初始数据集相比只少了一个样本,这就使得在绝大多数情况下,留一法中被实际评估的模型与期望评估的用 D D D训练出的模型很相似。因此,留一法的评估结果往往被认为比较准确。然而,留一法也有其缺陷:在数据集比较大时,训练 m m m个模型的计算开销可能是难以忍受的(例如数据集包含百万个样本,则需训练百万个模型),而这还是在未考虑算法调参的情况下。另外,留一法的估计结果也未必永远比其他评估方法准确;“没有免费的午餐”定理对实验评估方法同样适用。
自助法
我们希望评估的是用 D D D训练出的模型。但在留出法和交叉验证法中,由于保留了一部分样本用于测试,因此实际评估的模型所使用的训练集比 D D D小,这必然会引入一些因训练样本规模不同而导致的估计偏差。留一法受训练样本规模变化的影响较小,但计算复杂度又太高了。而“自助法”(bootstrapping)是一个比较好的解决方案,它直接以自助采样法(bootstrap sampling)为基础。给定包含 m m m个样本的数据集 D D D,我们对它进行采样产生数据集 D ′ D' D′:每次随机从 D D D中挑选一个样本,将其拷贝放入 D ′ D' D′,然后再将该样本放回初始数据集 D D D中,使得该样本在下次采样时仍有可能被采到;这个过程重复执行 m m m次后,我们就得到了包含 m m m个样本的数据集 D ′ D' D′,这就是自助采样的结果。显然, D D D中有一部分样本会在 D ′ D' D′中多次出现,而另一部分样本不出现。可以做一个简单的估计,样本在 m m m次采样中始终不被采到的概率是 ( 1 − 1 m ) m (1-\frac{1}{m})^m (1−m1)m,取极限得到:
lim m → ∞ ( 1 − 1 m ) m = 1 e ≈ 0.368 \lim_{m\rightarrow \infty} (1-\frac{1}{m})^m=\frac{1}{e}\approx0.368 m→∞lim(1−m1)m=e1≈0.368
即通过自助采样,初始数据集 D D D中约有36.8%的样本未出现在采样数据集 D D D中。于是我们可将 D D D用作训练集, D − D ′ D-D' D−D′用作测试集;这样,实际评估的模型与期望评估的模型都使用 m m m个训练样本,而我们仍有数据总量约 1 3 \frac{1}{3} 31的、没在训练集中出现的样本用于测试。这样的测试结果,亦称“包外估计”(out-of-bag estimate)。
自助法在数据集较小、难以有效划分训练/测试集时很有用;此外,自助法能从初始数据集中产生多个不同的训练集,这对集成学习等方法有很大的好处然而,自助法产生的数据集改变了初始数据集的分布,这会引入估计偏差。因此,在初始数据量足够时,留出法和交叉验证法更常用一些。
调参与最终模型
大多数学习算法都有些参数(parameter)需要设定,参数配置不同,学得模型的性能往往有显著差别。因此,在进行模型评估与选择时,除了要对适用学习算法进行选择,还需对算法参数进行设定,这就是通常所说的“参数调节”或简称“调参”(parameter tuning)。
我们可能马上想到,调参和算法选择没什么本质区别:对每种参数配置都训练出模型,然后把对应最好模型的参数作为结果。这样的考虑基本是正确的,但有一点需注意:学习算法的很多参数是在实数范围内取值,因此,对每种参数配置都训练出模型来是不可行的。
现实中常用的做法,是对每个参数选定一个范围和变化步长,例如在 [ 0 , 0.2 ] [0,0.2] [0,0.2]范围内以0.05为步长,则实际要评估的候选参数值有5个,最终是从这5个候选值中产生选定值。显然,这样选定的参数值往往不是“最佳”值,但这是在计算开销和性能估计之间进行折中的结果,通过这个折中,学习过程才变得可行。事实上,即便在进行这样的折中后,调参往往仍很困难。可以简单估算一下:假定算法有3个参数,每个参数仅考虑5个候选值,这样对每一组训练/测试集就有53=125个模型需考察;很多强大的学习算法有大量参数需设定,这将导致极大的调参工程量,以至于在不少应用任务中参数调得好不好往往对最终模型性能有关键性影响,给定包含 m m m个样本的数据集 D D D,在模型评估与选择过程中由于需要留出一部分数据进行评估测试,事实上我们只使用了一部分数据训练模型。因此,在模型选择完成后,学习算法和参数配置已选定,此时应该用数据集 D D D重新训练模型。这个模型在训练过程中使用了所有 m m m个样本,这才是我们最终提交给用户的模型。另外,需注意的是,我们通常把学得模型在实际使用中遇到的数据称为测试数据,为了加以区分,模型评估与选择中用于评估测试的数据集常称为“验证集”(Validation Set)。例如,在研究对比不同算法的泛化性能时,我们用测试集上的判别效果来估计模型在实际使用时的泛化能力,而把训练数据另外划分为训练集和验证集,基于验证集上的性能来进行模型选择和调参。