分类模型评价指标说明

分类模型评价指标说明

分类涉及到的指标特别容易搞混,不是这个率就是那个率,最后都分不清谁是谁,这份文档就是为此给大家梳理一下。

混淆矩阵

混淆矩阵很重要,很多指标都是源于混淆矩阵,这个务必要弄懂。

例子

为了解释混淆矩阵,先来看看下面这个二分类的例子。

例:有20个病人来医院检查,是否患病的预测值和真实值如下表所示。

病号 预测值 真实值 病号 预测值 真实值
1 1 1 11 0 0
2 0 0 12 0 0
3 1 1 13 0 0
4 0 0 14 1 1
5 0 0 15 0 0
6 1 1 16 1 0
7 0 0 17 1 1
8 0 0 18 0 0
9 0 1 19 0 0
10 0 0 20 0 1

其中,1表示患病,0表示不患病。

本文档默认用0和1来作为二分类符号。

你也可以用其他符号来表示,如1表示患病,-1表示不患病。只要能区分就行。

这样就出现4种结果:

  • 预测为1,实际也为1,包括病号1,3,6,14,17,一共5个样本;
  • 预测为1,实际为0,包括病号16,只有1个样本;
  • 预测为0,实际为1,包括病号9,20,只有2个样本;
  • 预测为0,实际也为0,包括病号2,4,5,7,8,10,11,12,13,15,18,19,一共12个样本。

我们把各个结果的数量填到下面这个表格中

在这里插入图片描述这就是病患例子的混淆矩阵。

混淆矩阵定义

二分类混淆矩阵的一般定义只是将1和0叫做正例和负例,把4种结果的样本数量用符号来表示,用什么符号呢?

如果我们用P(Positive)代表1,用N(Negative)代表0,那这四种结果分别是PP,PN,NP,NN,但这样表示有点问题,譬如,PN的意思是预测为1实际为0还是预测为0实际为1?需要规定好了,还得记住,好麻烦。

干脆再引入符号T(True)代表预测正确,F(False)表示预测错误,那么之前的P和N代表预测是1还是0,T和F表示预测是否正确。

四种情况可以分别表示为

  • TP:预测为1,预测正确,即实际也为1;
  • FP:预测为1,预测错误,即实际为0;
  • FN:预测为0,预测错误,即实际为1;
  • TN:预测为0,预测正确,即实际也为0。

混淆矩阵的定义如下:

在这里插入图片描述

混淆矩阵代码

采用sklearn.metrics中的confusion_matrix函数计算混淆矩阵,数据用的还是之前那个病患检查的样本。

from sklearn.metrics import confusion_matrix

# 真实值
y_true = [1,0,1,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,1]
# 预测值
y_pred = [1,0,1,0,0,1,0,0,0,0,0,0,0,1,0,1,1,0,0,0]

c_matrix = confusion_matrix(y_true, y_pred)
print(c_matrix)

代码输出

[[12  1]
 [ 2  5]]

有了混淆矩阵,就可以定义一些指标了。

正确率

准确率(Accuracy)的定义很简单,就是猜对的样本占总样本的比例,公式如下:
Accuracy = 猜 对 的 样 本 量 样 本 总 量 = T P + T N T P + F P + F N + T N \text{Accuracy} = \frac{猜对的样本量}{样本总量} = \frac{TP+TN}{TP+FP+FN+TN} Accuracy==TP+FP+FN+TNTP+TN

在这里插入图片描述

正样本是实际为正例的样本,负样本是实际为负例的样本。

计算正确率可以调用sklearn.metrics的accuracy_score函数,代码如下:

from sklearn.metrics import accuracy_score

# 真实值
y_true = [1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1]
# 预测值
y_pred = [1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0]

mc = accuracy_score(y_true, y_pred)
print('Accuracy: %.2f'%mc)

结果为

Accuracy: 0.85

正确率作为评价指标有一个很致命的缺点,就是样本不平衡时正确率无法反映模型结果的好坏。

举个例子,预估某个网站上某一天广告的点击率,假如一天有1000个人浏览,实际有50个人点击广告,假如分类器预测没有人会点击,那么这个模型结果的正确率是多少呢?

我们算一下:分类器预测正确的有950个样本,一共有1000个样本,根据定义 Accuracy = 950 1000 = 0.95 \text{Accuracy} = \frac{950}{1000} = 0.95 Accuracy=1000950=0.95,正确率为95%!!!

一个点击的人都没有预测对,正确率都能有95%,那这个指标对模型的评价不合理。

那样本不平衡的时候怎么办呢?

细心想想,样本不平衡的问题是正负样本在数量上有很大差距,数量少的那方被重视程度低,比较吃亏,要解决这个问题,把正负样本分开评价不就好啦,大家河水不犯井水。

按照这个思路,引入下面两个概念:真阳率和假阳率。

真阳率和假阳率

真阳率

真阳率(True Positive Rate, TPR)的定义是:正样本中猜对的比例。公式如下
T P R = T P T P + F N TPR = \frac{TP}{TP+FN} TPR=TP+FNTP

在这里插入图片描述

假阳率

假阳率(False Positive Rate, FPR)的定义是:负样本中猜错的比例。公式如下
F P R = F P T N + F P FPR = \frac{FP}{TN+FP} FPR=TN+FPFP

在这里插入图片描述

真阳率和假阳率的公式比较

T P R = T P T P + F N F P R = F P T N + F P \begin{aligned} TPR &= \frac{TP}{TP+FN} \\ FPR &= \frac{FP}{TN+FP} \end{aligned} TPRFPR=TP+FNTP=TN+FPFP

TPR公式的分母是正样本数量,FPR公式的分母是负样本数量,这就遵循了正负样本分开评价的思路。

TPR公式的分子是TP,说明这个指标关注正确率;FPR公式的分子是FP,说明这个指标关注错误率。

通常,这两个指标不单独使用,那要怎么用呢?

那就不得不介绍ROC/AUC的概念了。

ROC/AUC

例子

还是那个病患事例,不同在于预测值不是0和1的离散值,而是一个0到1的连续值,叫做置信度(confidence score),可以理解为”概率“,越接近1,结果越可能为1;越接近0,结果越可能为0。

病号 置信度 真实值 病号 置信度 真实值
1 0.8 1 11 0.8 0
2 0.2 0 12 0.1 0
3 0.4 1 13 0.2 0
4 0.1 0 14 0.9 1
5 0.4 0 15 0.3 0
6 0.8 1 16 0.6 0
7 0.3 0 17 0.8 1
8 0.2 0 18 0.2 0
9 0.6 1 19 0.2 0
10 0.5 0 20 0.4 1

预测值是置信度的话,要怎么算TPR和FPR呢?

很简单,给个阈值就行,不小于这个阈值就设为1,小于设为0。

注意,在实际的做法中,一般不用卡阈值的方法,而是按照置信度排序,然后取前N条样本,其实效果等同取阈值。

但阈值设多大好呢?

这就很关键了,因为阈值的大小会影响TPR和FPR。

阈值对TPR和FPR的影响

假如病患例子的阈值设为0.9,阈值判决后的预测结果如下表。

病号 预测值 真实值 病号 预测值 真实值
1 0 1 11 0 0
2 0 0 12 0 0
3 0 1 13 0 0
4 0 0 14 1 1
5 0 0 15 0 0
6 0 1 16 0 0
7 0 0 17 0 1
8 0 0 18 0 0
9 0 1 19 0 0
10 0 0 20 0 1

可以算出TP=1,TN=13,FP=0,FN=6,那么
T P R = T P T P + F N = 1 1 + 6 ≈ 0.14 F P R = F P T N + F P = 0 \begin{aligned} TPR &= \frac{TP}{TP+FN} = \frac{1}{1+6} \approx 0.14 \\ FPR &= \frac{FP}{TN+FP} = 0 \end{aligned} TPRFPR=TP+FNTP=1+610.14=TN+FPFP=0
这结果TPR和FPR都很低,FPR低是好事,说明负样本的预测错误率低,但TPR也低就不好了,因为正样本的预测正确率不高。

那换个阈值再试试,阈值设为0.1,就是全部猜作正例,不列详细计算过程了,直接给出结果
T P R = 1 F P R = 1 \begin{aligned} TPR &= 1 \\ FPR &= 1 \end{aligned} TPRFPR=1=1
这结果刚好相反,TPR和FPR都很高,正样本的预测正确率上来了,负样本的预测错误率也变大了。

通过上面的比较,能看出来:阈值设得越高,TPR和FPR越低;阈值设得越低,TPR和FPR越高。

ROC曲线

上一节我们知道了TPR和FPR会随阈值变化而变化,你要是把所有阈值对应的TPR和FPR求出来,画个直角坐标系,以FPR为横轴,TPR为纵轴,把不同阈值下的(FPR,TPR)坐标点标上并连起来,你就能看到TPR和FPR的整个变化曲线,而这条曲线就称为ROC(Receiver Operating Characteristic)曲线。

Receiver Operating Characteristic这名字挺奇怪的,可能是因为最早出现在雷达信号检测领域,用于评价接收器(Receiver)侦测敌机的能力。

尝试画出病患事例的ROC曲线,先求不同阈值下的FPR和TPR,置信度从大到小(重复的不算)排列为[0.9, 0.8, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1],一共有8个阈值,如果手算TPR和FPR那太费劲了,幸好sklearn.metrics模块有现成的roc_curve函数来算,代码如下:

import pandas as pd
from sklearn.metrics import roc_curve

# 置信度
y_score = [0.8, 0.2, 0.4, 0.1, 0.4, 0.8, 0.3, 0.2, 0.6, 0.5,
           0.8, 0.1, 0.2, 0.9, 0.3, 0.6, 0.8, 0.2, 0.2, 0.4]
# 真实值
y_true = [1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1]

# 计算TPR和FPR
fpr, tpr, thresholds = roc_curve(y_true, y_score)

# 把fpr,tpr,thresholds用DataFrame表格保存,方便显示
result = pd.DataFrame([thresholds,tpr,fpr], index=
                      ['threshold','TPR','FPR'])
print(result)

结果如下

             0         1         2         3         4         5         6  \
threshold  1.9  0.900000  0.800000  0.600000  0.500000  0.400000  0.300000   
TPR        0.0  0.142857  0.571429  0.714286  0.714286  1.000000  1.000000   
FPR        0.0  0.000000  0.076923  0.153846  0.230769  0.307692  0.461538   

                  7    8  
threshold  0.200000  0.1  
TPR        1.000000  1.0  
FPR        0.846154  1.0

上面结果有两点需要注意:

  • roc_curve函数结果的第一列没有什么实际意义,只是画ROC曲线图一般都会有原点(0,0),它直接帮用户给加上了。
  • 关于第一列的threshold为什么是1.9?根据官方API的解释,它是用max(y_score) + 1算的,为什么要这么算?官方API没有说明,所以我也不知道这脑洞是怎么来的。

接下来,就是根据FPR和TPR结果画ROC曲线,画出来如下图。

在这里插入图片描述
画图代码如下:

import matplotlib.pyplot as plt

plt.figure()
# 画散点图,标出点的位置
plt.scatter(fpr, tpr)
# 画ROC曲线图
plt.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve')

plt.xlim([-0.05, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic')
plt.legend(loc="lower right")
plt.show()

如果样本多了之后,画出来的ROC曲线会平滑得多。

ROC曲线的用处

当你需要评价多个分类模型结果时,ROC曲线能帮你看出这些模型的优劣。

下面给出了A和B两个分类模型的ROC曲线图,哪一个模型的结果比较好呢?

在这里插入图片描述
很显然是模型A,为什么呢?

因为模型A的ROC曲线要比模型B的往左上凸,这样的话,如果固定FPR,模型A的TPR大于模型B;如果固定TPR,模型A的FPR要小于模型B。怎么样都是模型A比模型B强。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qHPaDfif-1603466581745)(pict/2019-07-13 19-13-08屏幕截图.png)]

模型C是有特殊意义的,如果抛硬币来做二分类预测(取任一类的概率是0.5),最后画出来的ROC曲线图就跟C很接近。

可以做个实验:用概率为0.5取0或1来预测真实值,看看算出来的TPR和FPR的结果。

先构造一个1000样本的真实值列表。

from sklearn.metrics import confusion_matrix
import random

# 构造真实值,正例有100个,负例有900个,用shuffle随机打乱顺序
y_true = [1]*100+[0]*900
random.shuffle(y_true)

用概率为0.5取0或1做预测,并计算TPR和FPR。

import numpy as np
# 随机生成1000个0和1的预测值
y_pred = np.random.randint(0,2,size=1000)

# 计算TPR和FPR
tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()
print('FPR: %.2f'%(fp/(tn+fp)))
print('TPR: %.2f'%(tp/(tp+fn)))

结果如下

FPR: 0.50
TPR: 0.53

由于预测值是随机的,每次出来结果会有不同,但基本都围绕在点(FPR,TRP)=(0.5,0.5)附近,也就是说,按概率为0.5取0或1的方式做预测,势必经过(0.5,0.5),其ROC曲线就会表现为一条往右上的对角线。

某个模型全面碾压的情况不太多,大多数情况会如下图所示,两个模型的ROC曲线是相交的。

在这里插入图片描述
那哪个模型的结果比较好呢?

需要分情况。比如,如果限定FPR要小于相交点,无疑模型A好于模型B。

在这里插入图片描述

AUC

如果没有特定的限制,那怎么选模型呢?有一招,直接算ROC曲线下的面积,称为AUC(Area Under Curve)。

在这里插入图片描述
AUC越大,模型结果越好,下面算算医患事例的AUC,用sklearn.metrics的roc_auc_score函数。

from sklearn.metrics import roc_auc_score

# 置信度
y_score = [0.8, 0.2, 0.4, 0.1, 0.4, 0.8, 0.3, 0.2, 0.6, 0.5,
           0.8, 0.1, 0.2, 0.9, 0.3, 0.6, 0.8, 0.2, 0.2, 0.4]
# 真实值
y_true = [1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1]

# 计算AUC
auc = roc_auc_score(y_true, y_score)
print('AUC: %.2f'%auc)

结果是

AUC: 0.89

AUC能评价二分类模型结果,其实是有概率解释的,AUC的概率含义是:随机从样本集中取一对正负样本,正样本得分(置信度)大于负样本的概率。实际上可以理解为,模型把正样本(按照置信度)排在负样本前面的概率。

具体的解释参考下面链接:

https://tracholar.github.io/machine-learning/2018/01/26/auc.html#auc%E5%AF%B9%E6%AD%A3%E8%B4%9F%E6%A0%B7%E6%9C%AC%E6%AF%94%E4%BE%8B%E4%B8%8D%E6%95%8F%E6%84%9F

精准率和召回率

在信息检索、Web搜索领域,时常会关心“检索的信息有多少是用户感兴趣的”、“用户感兴趣的信息有多少被检索出来”,为满足这样的评价需求,有了精准率和召回率这两个指标。

精准率

精准率(Precision)的定义是:预测为正的样本中猜对的比例。公式如下
Precision = T P T P + F P \text{Precision} = \frac{TP}{TP+FP} Precision=TP+FPTP

在这里插入图片描述
这个指标反映的是你预测正样本预测有多准,关键在,因此Precision也被称为查准率。

召回率

召回率(Recall)的定义是:实际为正的样本中被猜对的比例。公式如下
Recall = T P T P + F N \text{Recall} = \frac{TP}{TP+FN} Recall=TP+FNTP

在这里插入图片描述
看定义,召回率是有点不好理解,举个例子吧。

假如患病的为正样本,不患病的为负样本,100个人里面有10个病患,医生检查出了病患中的8个,那这个结果的召回率是多少?

按照定义,先看实际为正的样本,也就是患病的人,共有10个,这里面医生猜对的有8个,那么 Recall = 8 10 = 0.8 \text{Recall} = \frac{8}{10} = 0.8 Recall=108=0.8。由此可知,召回率关注的是病患(正样本)是不是都找全了,关键在,因此Recall也被称为查全率。

两者公式比较</

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值