11.1 交叉验证模型
问题描述
评估算法生成的模型在实际应用中的表现。
解决方案
创建一个流水线,对数据进行预处理、训练模型,然后用交叉验证方法评估模型的性能。


讨论
评估有监督学习模型的方法非常直观:首先训练一个模型,然后计算一些性能指标(准确率、均方误差等)来评估它的预测效果。然而这种方法从根本上说是有缺陷的。如果使用同一份数据来训练和评估模型,那么得到的结果可能并不是我们想要的。评估模型的目的并不是要评估其在训练集数据上的表现,而是要评估它在从未见过的数据上(如新客户、新犯罪、新图像)的表现。因此,评估方法应该帮助我们评估模型在新数据上做预测时的准确性。
一种可行的策略是保留一部分数据作为测试数据,这种方式被称为Hold-out验证(Hold out validation)。在Hold-out验证中,数据(特征值和目标向量)被分成训练集(training set)和测试集(test set)两部分。首先将测试集放在一边,假定这部分数据不存在。然后使用训练集训练模型,使用特征矩阵和目标向量来教模型做出最佳预测。最后,通过评估模型在测试集上的预测效果,来模拟该模型在从未见过的数据上的预测效果。不过这种方法有两大缺点:首先,模型的性能高度依赖于所选取的测试集;其次,模型在训练和评估时都没有充分利用所有可用数据。
有一种方法可以克服以上缺陷,叫作k折交叉验证(K-Fold Cross-Validation,KFCV)。在k折交叉验证中,数据被分为k份,训练模型时将k-1份数据组合起来作为训练集,剩下的那一份数据作为测试集。将上述过程重复k次,每次取一份不同的数据作为测试集,对模型在k次迭代中的得分取平均值作为总体得分。
在本节的解决方案中,数据被分为10份来做交叉验证,并将评估结果输出到cv_results中。

在使用KFCV时,需要考虑三点。首先,KFCV假定每个样本都是独立于其他样本的(即数据是独立同分布的,Independent Identically Distributed,IID)。如果数据是独立同分布的,最好在数据分组前将其顺序打乱。在scikit-learn中,可以通过设置shuffle =True来打乱数据。
其次,当我们使用KFCV 来评估分类器时,通常将每一类数据大致平均地分配到k组数据中(这被称为分层k折)。例如,如果目标向量中包含性别,并且80%的样本是男性,则每组数据都包含80%的男性和20%的女性样本。在scikit-learn中,可以用StratifiedKFold替换KFold来使用分层k折交叉验证。
最后,使用Hold-out验证或交叉验证时,应该基于训练集对数据进行预处理,然后将这些预转换同时应用于训练集和测试集,这是非常重要的。例如,使用standardizer对数据进行标准化时,我们只需要计算训练集的平均值和方差,然后将这个预处理转换(使用transform方法)同时应用于训练集和测试集:


这样做是因为我们假定测试集是未知数据。如果使用训练集和测试集中的样本一起训练预处理器,测试集中的一些信息就会在训练过程中泄露。这个规则适用于任何预处理步骤,比如特征选择。
有了scikit-learn的流水线(pipeline),使用交叉验证就变得十分简单。
首先创建一个预处理数据的流水线(如standardizer),然后训练一个模型(logit逻辑回归):

然后,只要对创建好的流水线执行cross_val_score方法,scikit-learn就会帮我们完成所有工作。

cross_val_score方法带有三个我们尚未讨论过的参数,这三个参数也很重要。 cv参数用于指定使用什么样的交叉验证方法。k折交叉验证是迄今为止最常见的方法,也有一些其他的方法,如留一交叉验证法(leave-one-out-cross-validation),该方法的折数k等于样本数。scoring参数指定了衡量模型性能的标准,本章的其他节会讨论这些标准。最后,n_jobs = -1告诉scikit-learn使用所有可用的CPU核来进行计算。例如,如果你的计算机有4个核(一般笔记本电脑中的内核数),那么scikit-learn将使用全部4个CPU核来加速操作。
延伸阅读
● 为什么每个统计学家都应该了解交叉验证(http://bit.ly/2Fzhz6X)
●《交叉验证中的陷阱》(http://bit.ly/2FzfIiw)



本书评论