分类任务中的评价指标

本文参考:https://blog.csdn.net/hfutdog/article/details/88085878

分类是机器学习中比较常见的任务,对于分类任务一般有二分类、多分类和多标签分类。

多分类: 表示分类任务中有多个类别,但是对于每个样本有且仅有一个标签,例如一张动物图片,它只可能是猫,狗,虎等中的一种标签(二分类特指分类任务中只有两个类别)

多标签: **一个样本可以有多个标签 ** 。例如文本分类中,一个文本可以是宗教相关,也可以是新闻相关,所以它就可以有两个标签。

常见的评价指标有准确率(Accuracy)、精确率(Precision)、召回率(Recall)、F1 score、ROC曲线(Receiver Operating Characteristic Curve)等,本文将对上述指标进行讲解。

混淆矩阵

混淆矩阵是数据科学和机器学习中经常使用的用来总结分类模型预测结果的表,用n行n列的矩阵来表示,将数据集中的记录按照真实的类别和预测的类别两个标准进行汇总。以二分类任务为例,混淆矩阵的结构如下:
在这里插入图片描述
在这里插入图片描述

表中
TP = True Postive = 真阳性; FP = False Positive = 假阳性
FN = False Negative = 假阴性; TN = True Negative = 真阴性
TP表示实际为正被预测为正的样本数量,
FP表示实际为负但被预测为正的样本数量,
FN表示实际为正但被预测为负的样本的数量,
TN表示实际为负被预测为负的样本的数量。

另外,TP+FP=P’表示所有被预测为正的样本数量,同理FN+TN为所有被预测为负的样本数量,TP+FN为实际为正的样本数量,FP+TN为实际为负的样本数量。

1.分类模型之混淆矩阵:
每一行和每一列分别对应样本输出中的每一个类别,行表示实际类别,列表示预测类别。
在这里插入图片描述
上述矩阵即为理想的混淆矩阵。不理想的混淆矩阵如下:
在这里插入图片描述
查准率 = 主对角线上的值 / 该值所在列的和
召回率 = 主对角线上的值 / 该值所在行的和

2.分类模型之分类报告:
sklearn.metrics提供了分类报告相关API,不仅可以得到混淆矩阵,还可以得到交叉验证查准率、召回率、f1得分的结果,可以方便的分析出哪些样本是异常样本。

import sklearn.metrics as sm

# 获取混淆矩阵
m = sm.confusion_matrix(test_y, pred_test_y)
print('混淆矩阵为:', m, sep='\n')

# 获取分类报告
r = sm.classification_report(test_y, pred_test_y)
print('分类报告为:', r, sep='\n')

准确率

准确率是分类正确的样本占总样本个数的比例,即
在这里插入图片描述
其中,n_correct为被正确分类的样本个数,n_total为总样本个数。
结合上面的混淆矩阵,公式还可以这样写:
在这里插入图片描述
准确率是分类问题中最简单直观的评价指标,但存在明显的缺陷。
比如如果样本中有99%的样本为正样本,那么分类器只需要一直预测为正,就可以得到99%的准确率,但其实际性能是非常低下的。也就是说,当不同类别样本的比例非常不均衡时,占比大的类别往往成为影响准确率的最主要因素。
下面我们看一下sklearn中计算准确率的示例:

import numpy as np
from sklearn.metrics import accuracy_score

y_pred = [0, 2, 1, 3]
y_true = [0, 1, 2, 3]
print(accuracy_score(y_true, y_pred))  # 0.5
print(accuracy_score(y_true, y_pred, normalize=False))  # 2

# 在具有二元标签指示符的多标签分类案例中
print(accuracy_score(np.array([[0, 1], [1, 1]]), np.ones((2, 2))))  # 0.5

函数接口的描述是这样的:

准确度分类得分

在多标签分类中,此函数计算子集精度:为样本预测的标签集必须完全匹配y_true(实际标签)中相应的标签集。
参数
y_true : 一维数组,或标签指示符 / 稀疏矩阵,实际(正确的)标签.
y_pred : 一维数组,或标签指示符 / 稀疏矩阵,分类器返回的预测标签.
normalize : 布尔值, 可选的(默认为True). 如果为False,返回分类正确的样本数量,否则,返回正 确分类的得分.
sample_weight : 形状为[样本数量]的数组,可选. 样本权重.

返回值 score : 浮点型
如果normalize为True,返回正确分类的得分(浮点型),否则返回分类正确的样本数量(整型).
当normalize为True时,最好的表现是score为1,当normalize为False时,最好的表现是score未样本数量.

代码的输出我已经写在注释中了,需要注意的是最后一行代码中,y_true为[0111],,y_pred为[1111],矩阵的行表示样本,列表示标签(样本具有两个标签,标签0和1共同确定样本类别),那么这时实际上只有一个样本是预测正确的,因此准确率为1/2 ,即0.5。
另外,因为准确率的缺陷比较明显,所以在多分类问题中一般不直接使用整体的分类准确率,而是使用每个类别下的样本准确率的算术平均作为模型的评估指标。

精确率

精确率指模型预测为正的样本中实际也为正的样本占被预测为正的样本的比例。计算公式为:
在这里插入图片描述
sklearn中的函数接口precision_score的描述如下:

计算精确率

精确率是 tp / (tp + fp)的比例,其中tp是真正性的数量,fp是假正性的数量.
精确率直观地可以说是分类器不将负样本标记为正样本的能力.
精确率最好的值是1,最差的值是0.

参数
y_true : 一维数组,或标签指示符 / 稀疏矩阵,实际(正确的)标签.
y_pred : 一维数组,或标签指示符 / 稀疏矩阵,分类器返回的预测标签.
labels : 列表,可选值. 当average != binary时被包含的标签集合,如果average是None的话还包含它们的顺序.在数据中存在的标签可以被排除,比如计算一个忽略多数负类的多类平均值时,数据中没有出现的标签会导致宏平均值(marco average)含有0个组件. 对于多标签的目标,标签是列索引. 默认情况下,y_true和y_pred中的所有标签按照排序后的顺序使用.
pos_label : 字符串或整型,默认为1. 如果average = binary并且数据是二进制时需要被报告的类. 如果数据是多类的或者多标签的,这将被忽略;设置labels=[pos_label]和average !=binary就只会报告设置的特定标签的分数.
average : 字符串,可选值为[None, ‘binary’ (默认), ‘micro’, ‘macro’, ‘samples’, ‘weighted’]. 多类或 者多标签目标需要这个参数.如果为None,每个类别的分数将会返回. 否则,它决定了数据的平均值类型.
‘binary’: 仅报告由pos_label指定的类的结果. 这仅适用于目标(y_{true, pred})是二进制的情况.
> ‘micro’: 通过计算总的真正性、假负性和假正性来全局计算指标.
‘macro’: 为每个标签计算指标,找到它们未加权的均值. 它不考虑标签数量不平衡的情况.
‘weighted’:为每个标签计算指标,并通过各类占比找到它们的加权均值(每个标签的正例数).它解决了’macro’的标签不平衡问题;它可以产生不在精确率和召回率之间的F-score.

‘samples’: 为每个实例计算指标,找到它们的均值(只在多标签分类的时候有意义,并且和函数accuracy_score不同).
sample_weight : 形状为[样本数量]的数组,可选参数. 样本权重. 返回值 precision :浮点数(如果average不是None) 或浮点数数组, shape =[唯一标签的数量]
二分类中正类的精确率或者在多分类任务中每个类的精确率的加权平均.

from sklearn.metrics import precision_score

y_true = [0, 1, 2, 0, 1, 2]
y_pred = [0, 2, 1, 0, 0, 1]
print(precision_score(y_true, y_pred, average='macro'))  # 0.2222222222222222
print(precision_score(y_true, y_pred, average='micro'))  # 0.3333333333333333
print(precision_score(y_true, y_pred, average='weighted'))  # 0.2222222222222222
print(precision_score(y_true, y_pred, average=None))  # [0.66666667 0.         0.        ]

直接看函数接口和示例代码还是让人有点云里雾里的,我们这里先介绍两个与多分类相关的概念,再说说上面的代码是如何计算的。

  • Macro Average 宏平均是指在计算均值时使每个类别具有相同的权重,最后结果是每个类别的指标的算术平均值。
  • Micro Average 微平均是指计算多分类指标时赋予所有类别的每个样本相同的权重,将所有样本合在一起计算各个指标。

根据precision_score接口的解释,我们可以知道,当average参数为None时,得到的结果是每个类别的precision。上面的y_true有3个类别,分别为类0、类1、类2。我们将每个类别的TP、FP、FN列在下表中。
在这里插入图片描述
那么每个类别的precision也就得到了,如下所示:

在这里插入图片描述
虽然,我们是主要讲精确率的,但是宏平均和微平均的概念也很重要,这里顺便对比一下。

  • 如果每个类别的样本数量差不多,那么宏平均和微平均没有太大差异
  • 如果每个类别的样本数量差异很大,那么注重样本量多的类时使用微平均,注重样本量少的类时使用宏平均
  • 如果微平均大大低于宏平均,那么检查样本量多的类来确定指标表现差的原因
  • 如果宏平均大大低于微平均,那么检查样本量少的类来确定指标表现差的原因

召回率

召回率指实际为正的样本中被预测为正的样本所占实际为正的样本的比例。
在这里插入图片描述

sklearn中recall_score方法和precision_score方法的参数说明都是一样的,所以这里不再重复,只是把函数和返回值说明贴在下面:

计算召回率

召回率是比率tp / (tp + fn),其中tp是真正性的数量,fn是假负性的数量.
召回率直观地说是分类器找到所有正样本的能力. 召回率最好的值是1,最差的值是0.
返回值
recall :浮点数(如果average不是None) 或者浮点数数组,shape = [唯一标签的数量]
二分类中正类的召回率或者多分类任务中每个类别召回率的加权平均值.

from sklearn.metrics import recall_score

y_true = [0, 1, 2, 0, 1, 2]
y_pred = [0, 2, 1, 0, 0, 1]
print(recall_score(y_true, y_pred, average='macro'))  # 0.3333333333333333
print(recall_score(y_true, y_pred, average='micro'))  # 0.3333333333333333
print(recall_score(y_true, y_pred, average='weighted'))  # 0.3333333333333333
print(recall_score(y_true, y_pred, average=None))  # [1. 0. 0.]

P-R曲线

评价一个模型的好坏,不能仅靠精确率或者召回率,最好构建多组精确率和召回率,绘制出模型的P-R曲线。
下面说一下P-R曲线的绘制方法。P-R曲线的横轴是召回率,纵轴是精确率。P-R曲线上的一个点代表着,在某一阈值下,模型将大于该阈值的结果判定为正样本,小于该阈值的结果判定为负样本,此时返回结果对应的召回率和精确率。整条P-R曲线是通过将阈值从高到低移动而生成的。原点附近代表当阈值最大时模型的精确率和召回率。

ROC曲线

参考:https://blog.csdn.net/hfutdog/article/details/88079934

F1 score

F1 score是精确率和召回率的调和平均值,计算公式为:
在这里插入图片描述

Precision体现了模型对负样本的区分能力,Precision越高,模型对负样本的区分能力越强;Recall体现了模型对正样本的识别能力,Recall越高,模型对正样本的识别能力越强。F1 score是两者的综合,F1 score越高,说明模型越稳健。

sklearn中f1_score方法和precision_score方法、recall_score方法的参数说明都是一样的,所以这里不再重复,只是把函数和返回值说明贴在下面:

计算F1 score,它也被叫做F-score或F-measure.
F1 score可以解释为精确率和召回率的加权平均值.
F1 score的最好值为1,最差值为0. 精确率和召回率对F1 score的相对贡献是相等的. F1 score的计算公式为:
F1 = 2 * (precision * recall) / (precision + recall)
在多类别或者多标签的情况下,这是权重取决于average参数的对于每个类别的F1 score的加权平均值.
返回值
f1_score : 浮点数或者是浮点数数组,shape=[唯一标签的数量]
二分类中的正类的F1 score或者是多分类任务中每个类别F1 score的加权平均.

from sklearn.metrics import f1_score

y_true = [0, 1, 2, 0, 1, 2]
y_pred = [0, 2, 1, 0, 0, 1]
print(f1_score(y_true, y_pred, average='macro'))  # 0.26666666666666666
print(f1_score(y_true, y_pred, average='micro'))  # 0.3333333333333333
print(f1_score(y_true, y_pred, average='weighted'))  # 0.26666666666666666
print(f1_score(y_true, y_pred, average=None))  # [0.8 0.  0. ]

PRF值-微平均(Micro Average)

**"Micro"是通过先计算总体的TP, FP和FN的数量,然后计算PRF。**即先将多个混淆矩阵的TP,FP,TN,FN对应的位置求和,然后按照PRF值公式及逆行计算。公式如下:
在这里插入图片描述
下面通过一个简单的例子来理解,假设是三个类别的分类模型:

y_true=[1,2,3]

y_pred=[1,1,3]

(1)如下,将第一个类别设置为True(1),非第一个类别设置为False(0),

y_true=[1,0,0]
y_pred=[1,1,0]

由此我们统计得到第一个类别的混淆矩阵:

在这里插入图片描述
(2)如下,将第二个类别设置为True(1),非第二个类别设置为False(0),

y_true=[0,1,0]
y_pred=[0,0,0]

由此我们统计得到第二个类别的混淆矩阵:

在这里插入图片描述
(3)如下,将第三个类别设置为True(1),非第三个类别设置为False(0),

y_true=[0,0,1]
y_pred=[0,0,1]

由此我们统计得到第三个类别的混淆矩阵:
在这里插入图片描述
(4)根据微平均算法公式我们得到最终的混淆矩阵,如下:

在这里插入图片描述
在这里插入图片描述
其实可以参考上面介绍精确率时提到的方法,将每一类的TP,FP,FN,TN分别计算出来,再按照类别进行求和,然后按照公式计算。如下:

在这里插入图片描述

PRF值-宏平均(Macro Average)

“Macro”是分别计算每个类别的PRF,然后分别求平均得到PRF。 即对多个混淆矩阵求PRF,然后求PRF的算术平均。公式如下:
在这里插入图片描述
同样借助上面例子,假设是三个类别的分类模型:(若除法过程中,分子分母同时为0,则结果也为0)

y_true=[1,2,3]

y_pred=[1,1,3]

(1)如下,将第一个类别设置为True(1),非第一个类别设置为False(0),

y_true=[1,0,0]
y_pred=[1,1,0]

由此我们统计得到第一个类别的混淆矩阵:

在这里插入图片描述
在这里插入图片描述
(2)如下,将第二个类别设置为True(1),非第二个类别设置为False(0),

y_true=[0,1,0]
y_pred=[0,0,0]

由此我们统计得到第二个类别的混淆矩阵:

在这里插入图片描述
在这里插入图片描述
(3)如下,将第三个类别设置为True(1),非第三个类别设置为False(0),

y_true=[0,0,1]
y_pred=[0,0,1]

由此我们统计得到第三个类别的混淆矩阵:
在这里插入图片描述
(4)对P1, P2, P3取平均得到P, 对R1, R2, R3取平均得到R, 对F1_1, F1_2, F1_3求平均得到F1:
在这里插入图片描述
一般macro-f1和micro-f1都高的分类器性能好

PRF值-权重(Weighted)

weighted计算方法就是对于macro中的每一类的PRF给予不同的权重
从计算的角度讲,先对每个类求值,再取平均得到Macro Average会比较容易.但是当数据集中存在严重类别不平衡的问题时,就不适宜单纯使用Macro Average.此时可以采取weighted average. 具体来说当我们计算Macro Average时候我们给每个类赋予相同的权重,但是当样本不平衡时,不适宜给每个类赋予同样的权重,我们可以根据每个类的样本量,给每个类赋予不同的权重,这就是weighted average的计算方法.

参考资料

sklearn计算准确率、精确率、召回率、F1 score
sklearn ROC曲线使用
多分类的评价指标PRF(Macro-F1/MicroF1/weighted)详解
二分类和多分类问题的评价指标总结
sklearn之分类模型混淆矩阵和分类报告

  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值