机器学习中二元分类模型是非常常见的,也有很多的算法模型,今天我们来简单汇总一下评估二分类模型性能的一些方法,当然有些不局限于二分类模型。这里的简单有两层含义:

  1. 只汇总了一部分,并不全面。
  2. 很多评估方式都来在统计学理论,而且有一些还是存在争论的(比如p-value),所以这里不是详细讲解每种评估方法,而是做简单说明,让你知道每个值表示的含义,从而知道自己的模型性能如何。或者说当你使用一些机器学习框架输出了模型的一些性能相关的描述时,你知道每一项代表什么含义。

为了保证一致性,术语类的优先采用原始英文,不做翻译。

Positive & Negative

所谓二分类,就是指预测的目标值为1或0,用来代表“是/否”、“成功/失败”等。对应的,我们可以把1称为Positive(P, 阳性),0称为Negative(N, 阴性)。当然也可以反过来,由你具体的研究决定。比如你的分类器是判断一个人是不是男性,那此时男性就是Positive,非男性就是Negative;如果你的分类器是判别一个人是不是女性,那此时女性就是Positive,非女性就是Negative。

这里我们用一个例子来具体介绍,假设现在有27个动物:8只猫,6只狗,13只兔子。我们现在有一个分类模型,该模型可以区分出一个动物是否为猫。此时:

  • Positive:猫,猫的数量等。
  • Negative:非猫,非猫的数量等。
  • TP(true positive, 真阳性):本来是猫,分类器预测出来也是猫。此时我们说命中了(hit).
  • TN(true negative, 真阴性):本来不是猫,分类器预测出来也不是猫。此时我们称正确拒绝(correct rejection)。
  • FP(false positive, 伪阳性):本来不是猫,分类器预测出来是猫。这种我们称为错误的肯定,或假警报(false alarm),也称为第一类型错误(Type I error)
  • FN(false negative, 伪阴性):本来是猫,分类器预测出来不是猫。这种我们称为错误的否定,或未命中(miss),也称为第二类型错误(Type II error)

好,这里已经涉及了一些术语了,有些后面会再介绍,我们接着看。

  • TPR(true positive rate, 真阳性率),又称命中率(hit rate)、敏感度(sensitivity)、召回率(recall),计算公式为:$$TPR=\frac{TP}{P}=\frac{TP}{TP+FN}$$
  • TNR(true negative rate, 真阴性率),又称特异度(specificity, SPC),计算公式为:$$TNR=\frac{TN}{N}=\frac{TN}{FP+TN}$$
  • PPV(positive predictive value, 阳性预测值),又称精度(precision),计算公式为:$$PPV=\frac{TP}{TP+FP}$$
  • NPV(negative predictive value, 阴性预测值),计算公式为:$$NPV=\frac{TN}{TN+FN}$$
  • FNR(false negative rate, 伪阴性率),又称未命中率(miss rate),计算公式为:$$FNR=\frac{FN}{P}=\frac{FN}{FN+TP}=1-TPR$$
  • FPR(false positive rate, 伪阳性率),又称错误命中率,误检率(fall-out rate),假警报率(false alarm rate),其计算公式为:$$FPR=\frac{FP}{N}=\frac{FP}{FP+TN}=1-TNR$$
  • FDR(false discovery rate, 假发现率),计算公式为:$$FDR=\frac{FP}{FP+TP}=1-PPV$$
  • FOR(false ommission rate, 假错过率),计算公式为:$$FOR=\frac{FN}{FN+TN}=1-NPV$$
  • ACC(accuracy, 准确率),计算公式为:$$ACC=\frac{TP+TN}{P+N}=\frac{TP+TN}{TP+TN+FP+FN}$$
  • $F_1$ score($F_1$-measure),是precision和recall的调和平均数,计算公式为:$$F_1=\frac{2}{\frac{1}{precision}+\frac{1}{recall}} =2*\frac{PPV*TPR}{PPV+TPR}=\frac{2TP}{2TP+FP+FN}$$

缩略词和公式有点多,当然实际中我们在同一个模型里面往往不会关注这么多,会根据应用场景关注几个比较在意的维度。比如ACC应该是我们经常比较关注的,但是也不能只关注ACC,因为ACC高往往并不一定能说明我们的分类器性能就好,这和数据是否balance有关系。比如我们有100个测试样本,里面有99只猫,1只狗。那现在有个分类器,不论任何输入,输出都是猫,那在这个测试集上面,ACC高达99%,但显然这种分类器不是我们想要的。上面的这种情况我们称数据集是unbalanced,即数据集中各个观测值的个数变化很大。

confusion matrix

confusion matrix即混淆矩阵,又称error matrix(错误矩阵),主要用于以可视化的方式衡量监督学习中算法模型的性能(在非监督学习中对应的概念是matching matrix)。混淆矩阵中行代表每个类的预测值,列代表实际值,当然也可以反过来。以上节中猫的预测为例,其可能的一个混淆矩阵如下(图片来自维基百科,链接见最后面):

confusion-matrix

如上图,可以看出来对于混淆矩阵而言,对角线上的预测都是正确的,其他都是错的的,非常直观。

实际中,如果是二值的,也就是说只有两类,比如上面的例子,我们也可以划归为猫和非猫两类,这样我们就得到了confusion table(有时也称为混淆矩阵,图片来自维基百科,链接见最后面):

confusion-table

可以看到,混淆表只有两行两列,且分别代表了TP、FP、FN、TN的个数。也就是说我们能从多个维度去看分类器的性能,而不只是准确率ACC。

precision & recall & F1-score

前面我们已经看了precision(PPV)和recall(TPR)的公式,那他们的实际含义是什么呢?这两个概念在模式识别、信息检索、二分类里面经常使用,用于衡量相关性(Relevance)。这里举维基百科上面的两个例子,第一个例子主要说明如何计算precision和recall,第二个例子主要说明他们代表的实际意义。

例子一:现在有一幅画,上面画了12个狗和若干只猫。有一个识别狗的程序识别出来该画上面有8个狗,而识别出来的8只里面实际只有5条是狗,其它3个实际是猫,那此时precision就是5/8,而recall是5/12。这个根据我们前面介绍的公式也很容易算出来。

例子二:现在搜索引擎根据我们搜索的关键字返回了30个相关的页面,但这30个页面里面实际只有20个页面是和我们的关键字相关的,另外10个是不相关的。但其实真正相关的页面除了刚才的20个以外,还有40个,只是搜索引擎没有检索到。那此时,precision就是20/30=2/3,recall是20/60=1/3。那在这个场景中,precision表征了返回结果的有用程度是多少,或者说和我们的关键字的相关程度有多高;recall则表征了返回的结果的完整程度,即所有相关的东西实际只返回了多少。

再来一张维基百科上面的图:

precision-recall

左半边的矩形区域内都是P(实心点),右半边矩形区域都是N(空心点);这里P表示相关,N表示不相关。FN表示预测不相关,但实际相关;TP表示预测相关,实际也相关;TN表示预测不相关,实际也不相关;FP表示预测相关,实际不相关;也即图中的四个区域。图中圆内的东西表示选择的元素,也即上面例子二中搜索引擎返回的页面,此时precision用来评价返回的页面里面有多少是真正相关的,recall评估返回的页面数是否完整/完全,或者说返回了多少个相关的页面。

也就是说:

precision是对精确程度或者质量(quality)的评价,recall是对完整程度或者数量(quantity)的评价。

我们再看下前面的例子一,里面有多少个第一类错误和第二类错误呢?第一类错误FP指本来不是,但预测是,例子中FP=8-5=3,因为预测的8个里面有3个不是狗,但预测成狗了。第二类错误FN指本来是,但预测不是,例子中FN=12-5=7,因为总共12个狗,只有5个预测成狗了,7个miss掉了。我们再看下precision和recall的公式就可以得到以下结论:

  • 第一类错误决定了precision所能取到的最大值。如果第一类错误个数FP为0,那precision将达到最大值1,即上面例子中找出来的8个都是狗。
  • 第二类错误决定了recall所能取到的最大值。如果第二类错误个数为FN=0,那recall将达到最大值1,即上面例子中找到了全部12条狗。

那这个结论什么意义呢?实际中几乎没有完美的模型,一个模型要么会“过度识别”,比如把不是狗的也识别成狗了;要么就会“欠识别”,本来是狗,却没识别出来,这两种情况也就对应上面的第一类错误和第二类错误,那我们总要有所取舍。一般情况下,我们会保证第一类错误不超过某个阈值的情况下,尽可能的减小第二类错误。因为往往过度识别经过再次确认可以发现问题,比如心脏病检查,不是心脏病的误识别为心脏病(第一类错误)最多就是再做一次复诊确认一下而已,但如果漏识别了(第二类错误),那就是人命关天的大事了。当然这也不是绝对的,也需要根据我们的实际场景,看我们能够容忍哪种情况来决定。

最后,我们看一下$F_1 score$,$F_1 score$又称$F_1 measure$,是precision和recall的加权平均,当然$F_1$是$F_\beta$的特殊形式,表示precision和recall的权值相等。$F_1 score$也是对模型性能评估的一种方式,最佳值为1(precision和recall都是最佳状态,即值为1),最差情况为0.

ROC & AUC

ROC和AUC在维基百科的中文版里面已经讲的比较清晰明了了,这里就不再赘述了,传送门:https://zh.wikipedia.org/wiki/ROC%E6%9B%B2%E7%BA%BF

个人觉得,主要明白以下两点就行:

  1. 在一个ROC曲线中,曲线越靠近左上角,分类效果越理想。左上角(0.0,1.0)是理想最佳的位置。此时,我们的分类器既不会错分(横轴FPR为0),也不会漏分(纵轴TPR为1)。如果是垃圾邮件分类器的话,那就是过滤掉了所有的垃圾邮件,也没有将正常的邮件划分为垃圾邮件。
  2. 在不同的ROC曲线中(取不同的阈值得到了多个ROC曲线),AUC值越大,该分类器正确率越高,相比于其他的ROC曲线更优。

p-value

要了解p-value,首先得知道什么是假设检验(Hypothesis Testing),什么又是显著性假设检验?一般而言,我不推荐在百度百科上面看专业知识,但关于假设检验的概念不得不说,百度百科上面的讲解还算不错,这里就不重复造轮子了,不了解假设检验的,先去这里:假设检验百度百科传送门

OK,如果你之前不懂,看了没看懂,那我就简单做一个不是那么准确的解释:简单说就是现在有一个问题,我们不知道真假,那怎么办?那我就先做一个假设,这个假设专业术语叫null hypothesis(一般翻译为零假设,记做$H_0$),然后零假设的对立面就叫alternative hypothesis(一般翻译为备择假设,记做$H_1$)。现在我们的任务就是要通过实验来确定我们是要接受这个$H_0$假设还是拒绝它(拒绝$H_0$假设就标识接受了$H_1$假设)。

那如何确定是接受还是拒绝呢?其原理就是(1)反证法(2)小概率事件在一次实验中不会发生。举一个例子:我们现在要确定一枚硬币是否均匀,一般正常的硬币都是均匀的,所以我们先做出一个$H_0$假设:硬币是均匀的(即抛一次正面出现的概率为0.5)。然后我们开始做实验,结果我们抛了10次硬币(抛硬币遵从二项分布),有8次是正面,2次是反面。那如果硬币是均匀的,出现这个结果的概率为$$p=\binom{10}{8}0.5^8(1-0.5)^2=0.044$$

注:可使用python scipy里面提供的二项分布函数计算:

from scipy.stats import binom
binom.pmf(n=10,k=8,p=0.5)    # 0.043945312499999993

那现在问题来了,如果原假设是正确的,即硬币是均匀的,那现在这个结果出现的概率应该是比较小的(0.04),可是它的确在一次实验中就出现了。我们是选择相信这是一次偶然事件呢?还是说我们刚开始的$H_0$假设(硬币是均匀的)是错误的呢?

这时,就有一个显著性水平(significance level, 记为$\alpha$),的概念了。我们一般会选取一个显著性水平值,一般这个值取0.05或0.01(因为一般定义发生的概率小于0.05或0.01的事件为小概率事件)。如果上面计算出来的那个0.044的概率(也就是p-value)大于这个$\alpha$,我们就认为这次事件是一次偶然事件,我们依旧接受之前做的假设(即认为假设是对的);如果p-value小于$\alpha$,我们就认为小概率事件在一次实验中发生了,但这是不可能的,所以我们就认为出现这种结果的原因是因为我们刚开始做的假设是不对的,所以拒绝之前的零假设,选择接受备择假设。这也就是我们经常会看到p-value和0.05做比较的原因。

这里我们需要注意一下,一般我们做假设的时候都选择对立面,比如我们想要判断两个随机变量是否相关,那我们的零假设就是它们不相关,然后根据上面的过程,如果拒绝了零假设,那就说明他们有很大概率是相关的,但是这个结论是通过反证法得到的,而不是我们直接证明了他们是相关的。再比如我们要证明两个随机变量是独立的,那我们就先做出假设他们不是相互独立的,然后最后如果通过实验拒绝了这个假设,那就说明它们是相互独立的了。也就是说显著性检验的原理就是我们虽然无法证明一个命题是真的,但是我们可以证明它的对立面是假的,证明的手段就是反证法+小概率事件在一次实验中不可能发生。

最后我们再说一下前面提到第一类错误和第二类错误。在显著性假设检验中,

  • 如果$H_0$(原假设、零假设)为真,但实验结果却告诉我们不可能,导致我们拒绝了零假设,那这种错误就是之前说的第一类错误,一般把第一类错误发生的概率记为$\alpha$。
  • 如果$H_0$(原假设、零假设)为假,而实验结果却告诉我们原来的假设是正确的,导致我们接受了零假设,这种错误就是我们之前说的第二类错误,一般把第二类错误发生的概率记为$\beta$。

在显著性假设中,我们一般会限定一个发生第一类错误的最大值,而这个值就是我们之前说的显著性水平(现在知道为什么那里记为$\alpha$了吧)。

如果你还想更加深入的了解,推荐知乎上面的一个问题:统计学假设检验中 p 值的含义具体是什么?

好吧,扯了那么多。其实对很多人来说,只要知道你的模型结果中的p-value表示什么含义就行。举个例子,很多分类算法就是根据样本求出一个线性方程的各个系数(比如Logistic Regression分类算法)。那最终的输出结果里面除了有系数外,可能每个系数还会对应一个p值。那其实是算法做了一个零假设:该系数(实质反映的是该系数对应的那个特征)和最终要预测的目标分类是没有关系的(即系数为0)。那如果对应的p-value小于0.05,那我们就可以决绝原假设,认为该系数和目标变量是有关系的。还是有点抽象哈,再举个例子说明下上面这个:比如现在我们选取了一些人的特征:年龄(x1)、性别(x2)、职业(x3)、身高(x4),现在我们要预测这个人是否有车,即目标变量是否有车。那如果使用Logistic Regression算法的话,我们就是要得到一个$$y=\omega_0+\omega_1x_1+\omega_2x_2+\omega_3x_3+\omega_4x_4$$中的系数($\omega_1$~$\omega_4$)以及截距$\omega_0$。那通过一些库提供的API计算出来系数以后,我们会发现年龄和职业两个特征对应的系数的p-value应该是小于0.05的,也就是说假设这两个特征对目标变量(是否有车)是没有影响的是不可以接受的,也就是说他们对目标变量有影响。而性别和身高这两个特征对应的系数的p-value很可能是大于0.05的,所以我们接受他们和目标变量没有关系的假设(原假设),实际中性别和身高的确和一个人有没有车关系不大。也就是说我们在做模型的时候最好就不要选这种特征了。不知道这样举例是不是稍微清楚了点。

当然,评测一个分类模型性能还有很多其他维度,后续再更新。

loss和val_loss

注:该部分增加于2020.2.21日

在深度学习中,经常还会看到用lossval_loss(与之对应的可能还会有accval_acc)来评价模型(当然一般是在训练过程中输出)的优劣,那它们分别代表什么含义呢?

这里的val是validation的缩写,我们训练模型的时候一般会将数据分为训练集和测试集,这里的validation就指的是测试集。所以lossacc都指的是模型在训练数据上面的表现,val_lossval_acc则是模型在训练集上的表现,lossval_loss都指的是损失函数(cost function或loss function)的值。如果一个模型的loss逐渐下降、收敛,但val_loss却升高、不收敛,则说明很可能过拟合了,只有当lossval_loss同时下降、收敛,才能说明模型的泛化能力比较好。

References