MENU

准确率、精确率、召回率、F1-score

February 26, 2020 • Read: 371 • 数据挖掘与机器学习

分类是机器学习中比较常见的任务,对于分类任务常见的评价指标有准确率(Accuracy)、精确率(Precision)、召回率(Recall)、F1 score、ROC曲线(Receiver Operating Characteristic Curve)等

这篇文章将结合sklearn对准确率、精确率、召回率、F1-score进行讲解

混淆矩阵

如上图所示,要了解各个评价指标,首先需要知道混淆矩阵,混淆矩阵中的P表示Positive,即正例或者阳性,N表示Negative,即负例或者阴性。你也可以把P和N分别理解为二分类中的1-0

  • TP:实际为正,预测为正的样本数量
  • FP:实际为负,预测为正的样本数量
  • FN:实际为正,预测为负的样本数量
  • TN:实际为负,预测为负的样本数量

另外

  • TP+FP:表示所有预测为正的样本数量
  • TN+FN:表示所有预测为负的样本数量
  • TP+FN:表示实际为正的样本数量
  • TN+FP:表示实际为负的样本数量

准确率

准确率是分类正确的样本占总样本个数,即

$$ accuracy = \frac{n_{correct}}{n_{total}} $$

其中,$n_{correct}$表示被正确分类的样本个数,$n_{total}$表示样本总数

综合上面的混淆矩阵,公式还可以这样写

$$ accuracy=\frac{TP+TN}{TP+TN+FP+FN} $$

准确率是分类问题中最简单最直观的评价指标,但存在明显的缺陷。比如正负样本的比例不均衡,假设样本中正样本占90%,负样本占10%,那分类器只需要一直预测为正,就可以得到90%的准确率,但其实际性能是非常低下的

下面看一下sklearn中计算准确率的示例

import numpy as np
from sklearn.metrics import accuracy_score as accu

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

print(accu(y_true, y_pred)) # 0.5
print(accu(y_true, y_pred, normalize=False)) # 2
# normalize=False 返回分类正确的样本数量

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

对于最后两行代码

$$ y_{true}=\begin{bmatrix} {0}&{1}\\ {1}&{1} \end{bmatrix},\ \ \ y_{pred}=\begin{bmatrix} {1}&{1}\\ {1}&{1} \end{bmatrix} $$

矩阵的每一行表示一个样本,列表示标签(每个样本具有两个标签,这两个标签共同确定样本类别)。对于这种情况,此时实际上只有一个样本是预测正确的,因此准确率为0.5

精确率

精确率指模型预测为正的样本中实际也为正的样本 占 被预测为正的样本的比例。计算公式为

$$ precision=\frac{TP}{TP+FP} $$

代码如下

from sklearn.metrics import precision_score as ps

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

print(ps(y_true, y_pred, average="macro"))    # 0.22222
print(ps(y_true, y_pred, average="micro"))    # 0.33333
print(ps(y_true, y_pred, average="weighted")) # 0.22222
print(ps(y_true, y_pred, average=None)) # [0.6666 0. 0.]

average的参数可选值有None, binary(默认), micro, macro, samples, weighted

上面的$y_{true}$有3个类别,分别为类0,类1,类2。我们将每个类别的TP、FP、FN列在下表中

类别TPFPFN
0210
1022
2011

那么每个类别的precision也就得到了

$$ \begin{align*} P_0&=\frac{2}{1+2}=\frac{2}{3}\approx 0.667\\ P_1&=\frac{0}{0+2}=0\\ P_2&=\frac{0}{0+1}=0 \end{align*} $$

于是Macro Precision也就知道了,就是$\frac{P_0+P_1+P_2}{3}\approx 0.222$

Micro Precision的计算要从每个样本考虑,所有样本中预测正确的有两个,那么TP就是2,剩下的4个预测结果都可以看作FP,于是Micro Precision就是$\frac{2}{2+4}=\frac{1}{3}\approx 0.333$

最后还有一个weighted,因为这里每个类别的数量恰好占比都是1/3,所以结果是

$$ P_w=\frac{1}{3}*P_0+\frac{1}{3}*P_1+\frac{1}{3}*P_2\approx 0.222 $$

  • 如果每个类别的样本数量不多,那么Macro和Micro没有太大差异
  • 如果每个类别的样本数量差异很大,那么注重样本量多的类时用Micro,注重样本量少的类时用Macro
  • 如果Macro>>Micro的值,那么检查样本量多的类来确定指标表现差的原因
  • 如果Micro>>Macro的值,那么检查样本量少的类来确定指标表现差的原因

召回率

召回率指实际为正的样本中,预测也为正的样本 占 实际为正的样本的比例。计算公式为

$$ recall=\frac{TP}{TP+FN} $$

代码如下

from sklearn.metrics import recall_score as rs

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

print(rs(y_true, y_pred, average="macro")) # 0.3333
print(rs(y_true, y_pred, average="micro")) # 0.3333
print(rs(y_true, y_pred, average="weighted")) # 0.3333
print(rs(y_true, y_pred, average=None)) # [1. 0. 0.]

Recall和Precision只有计算公式不同,它们average参数的计算方式都是相同的,这里不再赘述

F1-score

F1-score是精确率和召回率的加权平均值,计算公式为

$$ F1-score=\frac{2*precision*recall}{precision+revall} $$

Precision体现了模型对负样本的区分能力,Precision越高,模型对负样本的区分能力越强

Recall体现了模型对正样本的识别能力,Recall越高,模型对正样本的识别能力越强

F1-score是两者的综合,F1-score越高,说明模型越稳健

代码如下

from sklearn.metrics import f1_score as fs

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

print(fs(y_true, y_pred, average="macro")) # 0.2666
print(fs(y_true, y_pred, average="micro")) # 0.3333
print(fs(y_true, y_pred, average="weighted")) # 0.2666
print(fs(y_true, y_pred, averge=None)) # [0.8 0. 0.]

Worked Example

对于正常的邮件

$$ \begin{align*} precision&=\frac{16}{16+2}=\frac{8}{9}\\ Recall&=\frac{16}{16+4}=\frac{4}{5}\\ F1-score&=\frac{2*\frac{8}{9}*0.8}{\frac{8}{9}+0.8} = a \end{align*} $$

对于垃圾邮件

$$ \begin{align*} precision&=\frac{3}{3+4}=\frac{3}{7}\\ Recall&=\frac{3}{3+2}=\frac{3}{5}\\ F1-score&=\frac{2*\frac{3}{7}*0.6}{\frac{3}{7}+0.6} = b \end{align*} $$

对于整体的所有邮件

$$ \begin{align*} P &= \frac{\frac{8}{9}+\frac{3}{7}}{2} \\ R &= \frac{0.8+0.6}{2}\\ F1 &= \frac{a+b}{2} \end{align*} $$

Archives Tip
QR Code for this page
Tipping QR Code