有监督学习是日常使用最多的建模范式,它有许多更具体的名字,比如预测模型、回归模型、分类模型或者分类器。这些名字或来源统计,或来源于机器学习。关于统计学习与机器学习的区别已经有不少讨论,不少人认为机器学习侧重于目标预测,而统计学习侧重于机制理解和建模。个人更加直观的理解是,统计学习侧重于从概率分布来描述数据生成机制,除了预测之外,还关心结果(参数假设、误差分布假设)的检验,而机器学习侧重于从函数拟合角度来描述数据生成机制,基本目的就是为了拟合和预测,缺乏严谨的参数、误差的检验机制,比如下式:
1. 统计学习目标是获取 Pr(Y|X) 的条件分布,通过对数据概率生成机制的理解与建模进而获取良好的预测效果,这个过程会涉及 X,Y,ϵ 的分布假设,因此最后会衍生出对参数假设和误差分布的假设检验,以验证整个概率分布的假设的正确性,比如经典的线性模型、非参数回归等模型,预测能力并不是其主要目的;
2. 而机器学习基本不会从概率分布的角度着手,虽然可能也会涉及 X,Y 的分布假设,但目的就是学习到一个能够较好描述数据生成机制的函数 f ,对误差的假设基本忽略,也不会涉及参数和误差的检验,模型好坏基本由预测效果来判断,同时也会提供一些比较一般的误差上界,所以机器学习中不会出现参数估计渐进性、一致性等结果的讨论,而多半最终结果的评判。比如SVM、神经网络、KNN等模型。
不过即使有上述区别,关于高维统计推断(Lasso类带正则项的线性模型)的理论也逐渐完善,但相对于传统的生物制药、生物实验、社会调查、经济分析等领域,当前图像、文本、推荐系统等应用领域中,人们更关心模型的预测能力,而不是解释能力甚至是模型的可靠性,主要原因即这些领域模型预测能力相比于模型的假设检验要重要得多,因此如何根据模型预测能力来选择最优模型变得越来越重要。本文下面就逐步介绍模型选择的思路和方法,主要参考ELS这本书。
模型的预测能力通常也被称作模型的泛化能力,表示模型在新的、独立的测试数据上的预测能力。在很多关于模型泛化能力的介绍中,我们总会看到这样一幅图:模型在训练集上的训练误差与在测试集上的测试误差的变化趋势对比。
图上横轴表示模型的复杂度大小(比如线性模型中特征维度大小),纵轴表示预测误差,衡量预测值与真实值间的平均损失大小 E(L(Y,f^(X))) ,损失函数根据分类、回归问题做合适的选择,比如0-1损失、负似然函数、平方损失、对数损失、指数损失、交叉熵损失、Hinge损失等。平均损失大小在训练集上预测误差称作训练误差,在测试集上称作测试误差。图中每一条线都表示同一个训练集(浅蓝色)和测试集(浅红色)上的预测误差表现,从图上可以看到两个现象
看到这上面的现象,我们的脑中可能会冒出下面几个问题:
这四个问题由浅入深,最终目的就是想获取泛化能力最好和最稳定的预测模型。在回答这四个问题前,我们首先需要做一个假设:模型能够较好的预测,说明预测集与训练集有较好的相似性,更严格来说,很可能来源于同一分布,下文做分析时均假设来源于统一总体分布。如果测试集相对于训练集发生了巨大的变化,那么从训练到预测的思路将不可行。下面我们逐步来解答这四个问题。
现假设我们有个研究项目,想根据学生的平时表现和性格的 p 个指标 X 来预测最终该学生的期末综合成绩 Y 。为达到这个目的,我们在一个学校中我们随机抽了一批学生,选用某个模型训练,估计其模型参数,然后找一批新的学生预测来评价模型好坏,发现预测误差的相对误差非常小。但是通常人们会问,这个模型预测能力真的那么好么?我咋不相信根据学生平时表现和性格就可以得到这么好的预测效果呢?是不是你们特意挑选的一批学生呐?为了让他们相信这个模型还不赖,我们从这个学校重新抽了好几批学生,分别根据这些学生的指标去训练模型和估计模型参数。随后我们发现,换了几批学生样本,估计的模型参数确实有些差别,而且预测效果也是时好时坏,整体而言,平均的预测误差也还差强人意,能够控制预测误差的相对误差在20%以内,此时再把结果拿给其他人看,估计很多人对你的模型可能就不会有那么大疑问了。
对应到上文的图,其实上图的波动产生的原因也和该例子操作是一样的,有多条线就意味着重复抽了多组训练集来分别训练,因此训练误差和测试误差的波动是由训练样本的变化带来的。在理想的实验条件下,为了能公正地衡量模型的预测能力,通常需要多换几组训练集和测试集来综合评价模型的预测能力,这样的结果才可能让人更信服模型的预测能力,而不是偶然结果。
但是实际情况中,我们却可能仅有一个训练集和一个测试集。用数学化语言描述,新的测试集中,目标变量 Y0 和预测变量 X0 均从两者的联合分布中抽取,独立于训练集 T=(X,Y) ,此时我们获取的测试误差(泛化误差)为某个训练集 T 上测试集上损失的条件期望
这里训练集 T 是固定的,即仅有一个训练集。而从统计分析(重复试验)上来说,我们可能更关注测试误差的期望,即去掉训练集随机性所带来的影响:
这个目标即上图预测误差波动想要表达的含义,想要通过多个训练集训练来获取平均的预测误差,抹平训练集变动带来的影响,这是评价模型预测能力最理想方法,可以防止某个训练集上训练所得模型表现过好而夸大模型的预测能力。但是实际情况中,我们手边通常可能只有一个训练集,实际的需求是在此训练集上模型做到最好,所以 ErrT 又是我们最关心的目标,即希望在当前训练集下获取最佳的预测能力,也就是说我们想获取上图的一条线的趋势中最小的测试误差的点,如下
换句话说,很多时候人们给你一个训练集就希望你能够给他一个相对最稳定的预测模型,这个目标相对获取平均预测误差来说更难,后续模型选择方法比如CV法、bootstrap法、Cp法等其实都是估计测试误差的期望,即第一幅图中的红色均线。
图上反映的两个现象一句话表示即:随着模型复杂度增加,训练误差波动降低,平均训练误差降低趋向于0,而测试误差波动上升,平均测试误差先降低后升高。这个现象说明训练误差不能代替测试误差来作为模型选择和评价的手段。随着模型复杂度变化,训练误差与测试误差并不是一个良好的正相关关系,而是呈现较为复杂的非线性关系。用数学式子表示即
用更通俗的话说,复杂的模型可能在训练集上拟合的很好,但是面对新的测试集,预测误差不降反升,发生了所谓的“过拟合”现象。如果一个模型在不同的测试集上测试结果不仅波动性大,而且预测误差也比较大,就要警惕发生了过拟合现象,此时不妨将模型的复杂度降低些(关于模型的复杂度含义下文会做更细致的说明),即使用变量更少的简单模型,比如线性模型。
过拟合的原因有很多,其中一个很可能的原因是,随着模型复杂度升高,对于训练数据刻画的很细,但是训练数据中可能某些特征仅出现过一次或者很少,信息不足,而测试集中该特征却出现了很多其他的值,虽然模型在训练集上刻画的足够细致,但是由于测试集的变动,模型反而往测试机上的迁移性能下降,训练误差变化并不正比于测试误差。
那究竟是什么原因导致了随着模型复杂度增加,训练误差与测试误差不呈现良好的正比关系呢?为何同样都是预测误差,训练误差很小的模型反而预测能力很差呢?下面我们以线性模型为例来阐释原因,假设
如果用线性函数 fp(x)=xTβ 去近似 f(x) ,其中 p 表示特征个数,损失函数取平方损失,最小化 1N∑i(yi–xTiβ)2 ,则在训练集 T=(X,Y) 下得到参数估计为 β^ ,同时记 β∗ 是 f(x) 最佳线性近似的估计参数
在某个新样本点 X=x0 处预测误差为
如果 x0 此时取所有训练集中的 xi ,则其平均预测误差(该误差也被称作样本内(in-sample)误差,因为 x0 都是来自与训练样本内。不过 y0 都是新的观测,且真实的 f(xi) 仍未知,因此该预测误差不是训练误差,后续会AIC等准则中会详细讲解):
对于普通线性模型易知其“估计偏移(Estimation Bias)”为0(最小二乘估计也是线性估计类中的最佳估计),易知随着特征个数 p 增加,方差(注:第一个等式根据线性回归很容易推导方差(Variance)为 pNσ2ϵ )逐步增大,而对于真实 f(X) 却近似越好,模型偏误(Model Bias)越小,但预测误差是这两者的综合,则整体变化趋势如下图
这与上图测试集误差变化一致。另外,之所以特地提到还有“估计偏移”,因为对于线性模型类,还有其他诸如岭回归、Lasso等受限的回归类别,他们都属于线性模型类,相比纯线性模型,他们由于对回归系数做了不同程度的压缩,因此相比于最佳线性估计 β∗ 会有些差距,产生“估计偏移”,进而整体上导致“模型偏移”增加,但是他们限制了参数个数和压缩了回归系数,模型可能更加简单,因此直观上这类模型估计平均而言会稳定些(模型方差小),用图形来表示他们的关系即如下图
箭头组合长短即表示了平均预测误差,可以看到在受限模型空间中由于较小的模型估计方差,可能使得整体的平均预测误差更小。
从“偏移-方差”分解可以看到,在有限的模型空间中,对某个模型类控制好模型的复杂度非常重要,否则不容易获取较好(包含稳定与预测误差小两方面)的预测模型,这便是模型选择阶段的工作。可能不少人觉得此处获取较好模型是指模型评价,但是模型评价与模型选择是两个不同的概念,代表两个不同的阶段:
从定义看,两者的目标不同,模型评价是模型选择的后一步。换句话说,模型选择是在某个模型类中选择最好的模型,而模型评价对这个最好的模型进行评价。模型评价可以比较多个模型类中的最佳模型,然后从中挑选出最佳模型,亦或者进行模型融合再进行评价。在模型选择阶段,常见的指标有AIC准则、BIC准则、CV值、结构风险上界等比较普适的准则,而在模型评价阶段,我们可以根据分类、回归、排序等不同问题关心的问题选择不同的评价指标,多与模型选择时的损失不同:(1)分类:ROC、AUC、TPR、FPR、F1 score;(2)排序:DCG、NDCG;(3)回归:RMSE、MAE、Deviance。根据具体业务,实际的评价指标有很多种,最好的方式当然是模型选择时即设计其损失函数即为评价指标,但是通常而言这些指标包含了某些非线性变化,优化起来难度颇大,因此实际模型选择仍是选用经典的那些损失函数,而模型评价则会与其略有不同。
随着机器学习普及,大家都有了“训练-验证-评价”的思维,这其实就是完整重现模型选择、模型评价的过程。如下图我们将数据集分成三个不相交的集合来做模型选择和模型评价:
使用训练集、验证集目的就是做模型选择,测试集自然是做模型评价。这三个集合的划分,并没有严格的准则,根据样本大小不同而做不同的选择,但是一个原则是测试集需要保持未知和与训练集、验证集的独立性。在数据挖掘比赛的时候,主办方通常会给我们一个训练集,然后自己持有一个未知的测试集。实际上这个测试集并不是真正的“测试集”,更应该称作“验证集”。因为随着参赛选手不断提交结果,他们在这个数据集也做了很多探索和尝试,能够逐渐发现这个所谓的“测试集”上的规律,模型选择和模型评价都依赖该数据集进行调整,因此从模型评价的独立性角度来说,这并不能当做最终的测试集,往往会低估预测误差,最好的做法是重新更换几组未知的数据集来当做新的“测试集”做模型评价,这也是秉承统计随机的思想——仅仅在某个“测试集”好是不够的(最近ImageNet事件也确实存在这样的问题)。
所以结合文章开始的方差-偏移图,对模型选择和模型评价的指导可以凝缩为一句话:根据已知的训练集和验证集在特定模型空间中进行模型选择,获取合适复杂度的模型,然后在多种模型空间做模型选择获取多种模型,最后的最优模型需要通过多个独立未知的测试集来做模型评价决定,否则很容易导致模型过拟合。(这实际上就是一个完整而规范的机器学习过程。)
模型选择核心思想就是从某个模型类中选择最佳模型。注意,它与一般的“调参”意义不同,调参很多时候可能是针对优化算法中的某些参数进行调整,比如步长(学习速率)、mini-batch大小、迭代次数等,也会涉及到模型 f(x,α) 中调整参数(也称正则参数) α 的选择,但是模型选择不涉及算法中的参数,仅涉及模型目标函数中的调整参数 α 。
从上面叙述可得知模型选择阶段,最标准的方法自然在训练集 T=(X,Y) 上训练模型,然后在验证集上获取预测误差 ErrT=EX0,Y0(L(Y0,f^(X0))|T) ,该误差也被称作“样本外(extra-sample)误差”,可真实反映出模型的样本外的预测能力,最后选择最小预测误差所对应的模型作为最佳模型即可。但通常而言,独立的验证集我们也没有,手头仅有的信息就是训练集,那么要想估计测试误差或者其期望曲线,就只能在训练集上做文章,一般而言可能仅有两种思路:
第一种思路是非常自然的思路,只要对训练集进行合适的划分,我们就有可能近似出预测误差 ErrT 。但是对原始训练集 T 划分为新的训练集 Tnew 和验证集,不同的划分比例可能使得新训练集与原训练集相差较大,进而使得 ErrT 差异很大,因此用这种划分的方式来估计条件期望形式的预测误差 ErrT 比较困难。那么此时我们可以不估计 ErrT 转为估计其期望,即平均预测误差 Err ,通过重复抽样的方式来多次估计预测误差 ErrT ,然后取其平均即可,这种方式我们可以称其为“重复抽样法”:通过训练集多次切分、抽样来模拟训练集、验证集,计算多个“样本外误差”,然后求其平均预测误差,这是一种密集计算型方法,比如交叉验证(Cross Validation)、自助法(bootstrap)等。
第二种思路相比第一种思路更加考虑计算效率,因为重复抽样需要计算多次估计,因此做一次模型选择可能需要花费不少时间,如果单单从训练集的训练误差就可以近似出测试误差 ErrT ,那么模型选择效率便会大大提高。这种方式以统计学中的AIC、BIC等为代表,深刻剖析训练误差与之前提到的“样本内(in-sample)误差”、预测误差 ErrT 间的关系,给出了预测误差估计的解析式,因此第二种思路我们可以称之为“解析法”。
这两种思路在统计学习和机器学习中都有大量应用,相比较而言,统计学习更喜欢第二种解析法,这样容易计算,并且会较好的理论性质(似然角度);而机器学习则更喜欢第二种重复抽样法和从VC维衍生出来的结构风险最小化法,不需要计算基于分布的似然,普适性更好。
一般而言模型选择准则有如下几种:
首先我们从更加普适的重复抽样法入手来介绍这些模型选择的方法和思路。
交叉验证法(CV法)是最自然的重复抽样法,过程如下图所示
将一个训练集随机分成K份(图中所示为5份),然后选择第K份作为验证集(图中为第3份),然后剩余的K-1份作为训练集训练模型,这样便可以得到K个“预测误差”,求其平均值即为所谓的“CV值”,所以常说的CV值实际上是预测误差期望 Err 的一个估计值。数学语言叙述如下:记 τ:{1,…,N}→{1,…,K} 是一个划分函数,表示随机地将第 i 个观测分配 {1,…,K} 中某个指标;记 f^−k(x) 表示去除第 k 部分数据训练所得的模型,则预测误差的交叉验证估计(CV值)为
如果该模型有调整参数 α 来调整模型的复杂度,记该模型集为 f(x,α) ,则CV值为
此时通过调整参数 α 可以获得不同模型复杂度下的CV值,然后选择最小的CV时所对应的模型 f^(x,αcv−min) 作为最后的预测模型即可,这便是利用CV值来做模型选择的思路。
从CV估计定义可以看到,划分的份数 K 粒度大小不同时,CV值对平均预测误差 Err 的估计也有好坏之分,这里将涉及“偏误”、“方差”以及“计算效率”的权衡,主要是“偏误”与“计算效率”的权衡。以两个极端例子为例:
实际中,训练集切分带来的估计偏误与计算量才是我们真正关心的量。权衡偏误与效率的得失,由于CV对于预测误差的估计与训练样本大小有关,如果本身样本量就不大,交叉验证切分将导致训练样本更少,这会引起更大的估计偏差,所以实际折数 K 经验是:
另外,由于5折或者10折CV估计有偏误,实际模型选择中还使用“one standard error”规则,即不选择CV值最小的模型,而是选择高于最小CV值一个标准差之内的最简模型,比如glmnet通常推荐lambda.1se,即这个准则。原因仍是5或10折CV很可能会低估平均测试误差,所以要保守选择平均预测误差略高于最小CV值得简单模型。
对于交叉验证法的实际操作,我们多半可能还会涉及变量筛选等预处理。对于这类预处理步骤,如果后续使用CV来做模型选择便需要考虑使用顺序的问题,一个使用原则是:
目前变量筛选的方法有很多,传统的有监督包含相关性筛选、熵增筛选等都是有监督方法,由于这种筛选已经利用了全体 X 和 Y 间的关系信息,如果利用这种筛选后的数据来做交叉验证将会导致模型低估预测误差,高估了模型的泛化效果,因此实际使用时尤其需要注意这种筛选方法与交叉验证的联合使用,防止犯错。
另外,在分类问题中,特别是对于类别不平衡问题,由于CV法可能会导致每折中的类分布不一致,使得训练不稳定,因此实际中分层CV(stratified CV)也会使用。其相比较CV的不同之处就是不使用经典CV的均匀随机抽样方法来切分样本,而是根据总体类别比例,对每折都使用依赖于类别比例的分层抽样,保证每折的类别分布与原始数据差不多。学习过分层抽样的同学可能知道,分层抽样可以降低估计量方差,因此实际使用分层CV相比经典CV选择模型可能更稳定些。
由于计算CV是一个密集计算的模型选择法,即使可以利用并行计算来提高模型选择的效率,但是如果能够找到无需重复计算的替代方法,那么实际应用中,人们可能更倾向于使用这种模型选择方法。对于线性模型,如果使用平方损失,广义交叉验证(GCV)是LOO法解析形式的近似估计,可以避免计算N个模型来快速做模型选择。对于线性模型,对于目标变量的估计可以写成如下投影形式
其中 Sii 是 S 的对角元素,则GCV近似为
关于CV的衍生方法比较新的时ES-CV,由Yu Bin在2013年提出,不过实际上这种方法对于核心是估计稳定性的定义,CV法只是来改进估计稳定性的一种方式而已,感兴趣的同学可以参考Yu老师的论文。
对于bootstrap,不管是统计还是机器学习的同学,可能对这个名词以及实施方式都比较熟悉。bootstrap法由Efron于1979年提出,随后在统计中得到了大量的应用,主要用于解决复杂统计量的置信区间等估计问题;而在机器学习中,由Breiman在94年提出bagging方法(全称为bootstrap aggregating)实际上就是bootstrap的直接应用,它是一种模型组合方法,主要用于分类问题中以获取比较稳定的结果。bootstrap的思路和操作都非常简单,如下图
假设有样本 Z ,则不断重复随机抽同样大小的B个样本集 Z∗b ,这些样本被称作bootstrap样本,随后用着B个样本分别训练模型,得到B个目标估计量 S(Z∗b) 。然后可以用这些统计量求某些指标,比如统计量的均值、方差、偏移等。对于分类问题,用这些bootstrap样本训练多个分类器,比如决策树或神经网络,然后将这B个分类模型对新的样本做预测,把B个分类结果做一个投票获取最终的结果即可,这边是所谓的bagging。
不过上述都是对于估计量或者模型而言,那么如何利用bootstrap来做模型选择呢?如果我们用着B个模型对每个观测都进行评价,然后求其平均误差
看起来似乎可行,但仔细一思考就可以发现这并不是一个好的平均预测误差的估计,主要原因是bootstrap样本即被训练又被评价,与CV不同训练集被重复分割为独立的训练集与验证集相比,数据评价存在重合,所以 Errboot(α) 肯定与训练误差可能比较接近,而与平均预测误差有较大偏差,那么用该估计来调模型复杂度参数 α 显然更不是个好选择。那如何利用bootstrap法来更好的近似平均预测误差呢?我们可以借助于CV的分割思想。
我们知道,bootstrap样本的获取其实就是重复有放回的N次抽样,那么对于观测 i 属于该bootstrap样本,至少被抽中一次的概率即
换句话说,每个bootstrap样本中,总有些观测没被抽到,那么根据CV法的思路,这部分观测就可以拿出来作为验证集来作为平均预测误差的估计。
熟悉随机森林或者Bagging的同学对于OOB(out of bag)这个词肯定不陌生。OOB其实就是这种思路,不过只是对未抽中的样本再次做了投票然后再估计预测误差,对于此处我们则不做投票,直接取那些没出现过 i 观测的bootstrap样本训练的模型分别估计 i 的误差,然后求个平均即可
其中 C−i 即不包含 i 观测的bootstrap样本集。你可能想万一有个观测所有bootstrap都出现了怎么办?直接去掉就好了嘛,不过你可以算算B个bootstrap样本都出现的概率有多小。实际而言,B大点便很容易保证观测 i 很难在所有bootstrap样本集中出现了。
下面在思考下,这种估计是对平均预测误差估计是个好估计吗?虽然不会像第一个估计量那样低估平均预测误差,但是这种估计量也很容易高估平均预测误差,主要原因是每个bootstrap样本中仅有差不多63.2%的不同观测用来建模,这样使得 Err^(1)boot(α) 估计量表现得很像2折或3折交叉验证,分割太少导致可能偏差很大,特别是对于样本量不够多的训练集。如果改进,直观想法便是将训练误差 Errtrain 与该估计量 Err^(1)boot(α) 按照某种比例加权 (1–w)Errtrain+wErr^(1)boot(α) 来纠正这种偏移,具体细节可以看ESL的阐述,实际中由于bootstrap计算量过大,所以用来做模型选择不多,所以此处不再详述。
不过在大数据时代,分布式思维逐深入统计学家和计算机学家脑中,由于bootstrap具备良好的可并行性,以及良好的统计性质和估计稳定性,Jordan在2012便提出了基于bootstrap的[BLB(Bag of Little Bootstraps)](http://arxiv.org/pdf/1112.5016v2.pdf),能够给出较稳定的估计量以及估计量的区间估计,这是其他方法不具备的特点。比如能告诉你预测误差大小,同时可以告诉你预测误差的偏误以及方差,那这是不是一件更令人安心的事情呢?在现在这种环境下,与其不停做实验等待结果,不妨考虑下bootstrap这类有可靠性估计的方法的好处。BLB的算法思路很清晰,简单来说:subsampling + bootstrap + average;先无放回抽样,然后bootstrap抽样,获取参数bootstrap估计量,以及其置信区间、偏移、预测误差等估计量,最后将这些估计量平均起来即可。细节可以参考其论文,只要有多机可并行环境便可很容易实施该方法。
bootstrap思想是一种非常重要思想,后来著名的random forest便充分利用了该思路。而且相比目前的数据并行、模型并行的分布式算法思路,我觉得可以从bootstrap抽样角度获取更加稳定的估计量,当然这些都是题外话,与本文话题不相符合,以后可以再谈谈抽样与并行算法之间的感想,实际上都会在“计算效率”与“精度”之间做些权衡。
根据上述重复抽样法可知,CV等方法直接来估计“样本外误差”,并求其期望,而解析解思路由于不像CV法通过原始训练集切分构建验证集,仅仅从训练集出发,构建训练误差与“样本内误差”间等式关系,因此需要深刻理解训练误差、“样本内误差”、模型复杂度这几个概念,才能较好的理解为何解析解思路的那几个准则是有效的。
在本文第一节提到,实际应用中通常只有一个训练集 T={(x1y1),…,(xn,yn)} ,此时我们希望能在该训练样本上获得最好的预测模型 f^ ,在新样本点 (X0,Y0) 能得到最小的泛化误差 ErrT=EX0,Y0[L(Y0,f^(X0))|T] 。这是训练集 T