预测分析:R语言实现1.4 性能衡量指标

1.4 性能衡量指标


在上一节讨论预测建模过程的时候,我们讨论了利用训练集和测试集对被训练模型的性能进行评估的重要性。在本节,我们要审视在描述不同模型的预测精确度时常遇见的某些性能衡量指标。其实,根据问题的不同类型,会需要使用略有差异的性能评估方式。由于本书讨论的重点是有监督的模型,所以我们会审视如何评估回归模型和分类模型。对于分类模型,我们还会讨论二元分类任务这样一个非常重要且经常遇到各类问题的模型所采用的某些额外的衡量指标。

1.4.1 评估回归模型

在一个回归的场景里,让我们回顾一下,通过模型,我们要构建一个函数,它是理论上的基础目标函数f的近似。该模型的输入是我们选择的输入特征的值。如果我们把这个函数运用到训练数据里的每个用函数真实值yi标记的观测数据xi,我们就会得到一组(yi, i)的配对数据。为了确保我们清楚最后一点,这里的第一个数据项是在我们训练数据的第i条观测数据的输出变量实际值,而第二个数据项则是把我们的模型运用到该观测数据的特征值上产生的预测值。

如果模型和数据拟合得很好,在训练集里这两个值就会相互非常接近。如果在测试集里也是如此,那么就认为这个模型应该能对将来的未知观测数据有良好的表现。为了对预测值和正确值在一个数据集的所有观测数据中相互接近的概念进行量化,我们要定义一个衡量指标,它称为均方差(Mean Square Error,MSE),如下所示:

 

这里的n是数据集里观测数据的总数。因此,这个方程告诉我们,首先要对测试集里每条观测数据i计算其输出值及预测值之差的平方,然后把它们累加起来再除以观测数据的数量,得到所有这些值的平均数。这样,这个衡量指标被称为均方差的原因就很清楚了。这个数值越低,观测数据中输出变量的实际值和我们预测结果之间的平均误差越小,我们的模型就越准确。我们有时候也会参考均方根误差(Root Mean Square Error,RMSE),它是均方差和误差平方和(Sum of Squared Error,SSE)的平方根,其中误差平方和SSE和均方差MSE 是相似的,只是它没有除以训练样本个数n而产生归一化结果。对训练数据集计算得到的这些数量值是很有价值的,它的较小数值就表明我们充分训练了模型。总体而言我们并不期望它达到0,而且由于过拟合的问题,我们也不能根据这些数量值在模型中进行取舍。而计算这些衡量指标的关键领域是测试数据。在大部分情况下,某个模型训练数据的均方差(或者等同的指标:均方根误差或误差平方和)会比对测试数据计算出的相应衡量指标更小。存在过拟合数据情况的模型m1和另一个模型m2对比,往往可以通过m1模型产生了更低的训练均方差却有更高的测试均方差来进行识别。

1.4.2 评估分类模型

在回归模型里,我们的预测函数对于特定观测数据xi产生近似输出yi的不正确程度是在均方差里体现的。具体而言,对较大的误差取平方会导致在某个数据点上的很大误差比多个数据点上的一些小误差影响更大。这恰恰是因为在回归中,我们处理的是数值型输出,这样不仅可以衡量我们对于哪些观测数据的预测不够好,还可以衡量我们偏离了多远。

对于进行分类的模型,我们也可以定义一个误差率,但这里我们只能讨论模型作出错误分类的数量。具体地说,错误率是由如下公式给出的:

 

这个衡量指标利用了指示函数(indicator function),它在预测类别和标签类别不同的情况下返回的值为1。因此,误差率就可以这样进行计算:对输出变量的类型预测错误个数进行计数,然后把这个计数除以数据集里的观测数据数量。在这种方式下,可以看到,误差率实际上是模型作出错误分类的观测数据所占的百分比。必须要指出的是,这种衡量指标把所有类型的分类错误视为等同的。如果某些错误分类的成本要高于其他错误分类,那么这种衡量指标可以通过加入权值来进行调整,这些权值的作用是给每种错误的分类乘以一个与其成本成比例的数量。

如果要诊断某个回归问题中误差的最大来源,我们往往会先查看预测值和实际值之间误差最大的那个点。而在进行分类时,计算所谓的混淆矩阵(confusion matrix)往往是很有用的。它能显示在数据上产生的所有配对的错误分类。现在,我们要回到鸢尾花品种分类问题了。在前面的小节,我们训练了3个kNN模型。我们现在会看到如何能够评估它们的性能。和很多分类模型一样,kNN返回的预测既可以是最终的类别标签,也可以是与每种可能的输出类型相关的一组评分。有时候就像这里的示例一样,这些评分实际上是该模型给出的每种可能输出的概率。不管该评分是不是概率,我们都可以根据这些评分来决定选取哪个输出标签,通常就是直接选取评分最高的那个标签。在R语言里,用来作出模型预测的最常见函数是predict()函数,我们在自己的kNN模型里会用到它:

 

在该kNN模型里,我们可以通过计算属于每个输出标签的最邻近样本的比例,从而把输出的评分指定为直接概率。在上面显示的三个测试示例中,virginica品种在其中两个示例中的概率为1,而在另一个示例中只有60%的概率。另外的40%属于versicolor品种,因此看起来在后面那个示例中,每5个最邻近样本中有3个属于virginica品种,而另外2个属于versicolor品种。很显然,相比这个分类结果,我们应该会对前面两个分类结果更有信心。我们现在要在测试数据上对这三个模型进行类别预测的计算:

 

我们可以利用caret包的postResample()函数来显示模型在测试集上的精确度指标:

 

 

在这里,精确度等于1减去误差率,也就是正确分类的观测数据比例。可以看到,所有的模型在精确度方面都非常接近,其中使用了Z评分(Z-score)变换进行归一化的那个模型胜出了。由于测试集较小,这个差别并不显著。卡巴统计量(Kappa statistic)的定义如下所示:

 

卡巴统计量是设计用来抵消随机因素的,它的取值空间为[-1, 1],其中1代表完全精确,-1代表完全不精确,而0是在精确度恰好等于随机猜测法的结果时出现的。注意,对于一个分类模型来说,随机猜测法猜测的是最常见的那个类别。在鸢尾花分类模型的示例中,3个品种在数据中出现的机会是均等的,因此期望精确度等于三分之一。我们鼓励读者通过给期望精确度运用这个值来进行检验,我们可以根据各个精确度的值来获得卡巴统计量的观测值。

我们还可以利用一个混淆矩阵来检查模型作出的特定错误分类。它可以通过用正确的输出标签对预测结果进行交叉分析(cross-tabulating)直接构建出来:

 

caret包还有一个非常有用的confusionMatrix()函数,它能自动计算这张表以及几种其他的性能衡量指标,该函数功能的说明可以查阅http://topepo.github.io/caret/other.html。

在前面的混淆矩阵里,我们可以看到正确分类的观测数据的数量是28个,它是主对角线上的数值10、9、9之和。该表格给我们展示的是setosa品种看起来用我们的模型更易于预测,因为它从来没有和其他品种混淆。不过,versicolor和virginica品种会互相混淆,该模型对这两个品种都各有1次错误的分类。因此,我们可以推测,计算混淆矩阵可以作为一个有用的练习。找出经常混淆的类别配对可以指导我们对模型作出改进,例如去寻找有助于区分这些类别的特征。

评估二元分类模型

有一种特殊的分类任务被称为二元分类(binary classification),它是在我们只有两个类别的情况下出现的。一些典型的二元分类的场景如下:

根据收到的电子邮件的内容和标题,把它们分类为垃圾邮件或非垃圾邮件

根据病人的症状和病史,把他们分类为是否患有某疾病

根据查询关键字和文档中的单词,把一个文档的大数据库中的某个文档分类为是否和该查询相关

把生产线上的某个产品分类为次品或不是次品

根据客户的信用评分和财务状况,预测在某银行申请贷款的某位客户还款时是否会发生违约

在二元分类任务里,通常把两个类别称为阳性类(positive class)和阴性类(negative class)。按照惯例,阳性类对应的是模型尝试预测的一种特殊情况,并且通常比阴性类更为少见。从之前的示例,我们可以给垃圾邮件、生产线的次品、违约客户等等使用阳性类标签。现在考虑医疗诊断领域的一个示例,在这个领域,我们要尝试训练一个模型来诊断某个在10 000人中只出现1例的疾病。我们会把阳性类分配给患有这个疾病的病人。注意,在这样的一个场景中,误差率本身不是模型的充分衡量指标。例如,可以通过把每个病人都预测为健康的来设计出最简单的分类器,它只有0.01%的误差率,但这样的一个分类器是没有用的。通过分析混淆矩阵,可以得出更有用的衡量指标。假定已经构建了一个诊断罕见疾病的模型,对于100 000病人的测试样本,我们获得了如下的混淆矩阵:

 

二元分类问题是如此常见,以至于它的二元混淆矩阵的单元都有它们自己的命名。在包含了正确分类条目的主对角线上,我们称其元素为真阴性(true negative)和真阳性(true positive)。在示例中,我们有99 900例真阴性和13例真阳性。当把实际上属于阴性类的观测数据错误分类为阳性类时,就得到了一个假阳性(false positive),也称为第一类错误(Type I error)。假阴性(false negative)或第二类错误(Type II error)则出现在把阳性类的观测数据错误分类为阴性类的情况下。在这个示例中,模型得到了78例假阳性和9例假阴性。

现在我们要引入两个在二元分类环境中非常重要的衡量指标,它们是查准率(precision)和查全率(recall)。查准率的定义是准确预测的阳性类例数占预测的阳性类总例数的比例。利用前面的二元混淆矩阵的标签,查准率可由如下公式得出:

 

因此,查准率实际上衡量的是我们对阳性类进行预测的精确度。根据定义,只要从不预测阳性类就能达到100%的查准率,因为以这种方式可以保证不会犯任何错误。反过来,查全率的定义是阳性类的正确预测数在数据集里所有阳性类成员中的占比。同理,利用二元混淆矩阵中的标签,可以把查全率的定义表示为:

 

查全率衡量的是从数据集中识别所有阳性类成员的能力。可以通过把所有数据点都预测为阳性类来轻松达到最大查全率。这样我们会犯很多错误,但永远不会有假阴性。注意,查准率和查全率构成了模型性能的一个权衡。一方面,如果对任何数据点都不预测为阳性类,我们会得到0查全率,但查准率是最大的。而另一方面,如果把所有的数据点都预测为属于阳性类(记住,阳性类是罕见的类),我们会得到最大查全率,但查准率是非常低的。换言之,尝试减小第一类错误会导致第二类错误增加,反之亦然。这种相反的关系经常可以针对具体的问题在查全-查准曲线(precision-recall curve)上绘制出来。通过采用一个适当的阈值参数,我们就可以对模型的性能进行调优,从而达到这个查全-查准曲线上适合我们情况的某个点。例如,在某些问题的领域,由于把阳性类的观测数据错误分类为阴性类的成本很高,因此,我们会偏向于得到更高的查全率而不是查准率。因为经常要用单个数值描述某个模型的性能,我们定义了一个叫做F1分数(F1 score)的衡量值,它合并了查全率和查准率。具体来说,F1分数的定义是查准率和查全率之间的调和平均数:

 

读者应该在示例的混淆矩阵里检验一下,查准率是14.3%,查全率是59.1%,而F1分数是0.23。

上一篇:《Splunk智能运维实战》——3.2 创建智能运维仪表盘


下一篇:Kafka项目实战-用户日志上报实时统计之分析与设计