随着人工智能如火如荼的发展,无论是学界的模型创新,还是业界的模型应用,如何去评价模型的优劣都是十分重要的工作。每年业界或学术界都会举办很多AI方面的比赛,而作为量化所有参赛者的成绩则是运用他们的模型在给定的测试集下计算出对应的
指标
。
我给大家深入分析下CV场景下评测指标的含义。无论您是作为开发工程师,还是算法工程师,希望这篇文章能够让你弄清楚这些指标的含义。
1、图像分类指标
分类模型的指标主要有准确率(accuracy),精确率/查准率(precision),召回率/查全率(recall), PR曲线,混淆矩阵(confusion-matrix),F-score。
精确率、召回率、混淆矩阵
精确率(Precision), 召回率(Recall)
精确率和召回率主要用于二分类问题
,结合混淆矩阵有:
精确率Precision和召回率Recall的定义为:
精
确
率
(
P
r
e
c
i
s
i
o
n
)
=
T
P
T
P
+
F
P
精确率(Precision)=\frac{TP}{TP+FP}
精
确
率
(
P
r
e
c
i
s
i
o
n
)
=
T
P
+
F
P
T
P
召
回
率
(
R
e
c
a
l
l
)
=
T
P
T
P
+
F
N
召回率(Recall)=\frac{TP}{TP+FN}
召
回
率
(
R
e
c
a
l
l
)
=
T
P
+
F
N
T
P
上述计算公式中的Positive与Negative表示预测标签,True与False代表预测正误;
这里需要重点介绍一下TP,FP,TN,FN,这是计算整个指标体系的基石:
TP: True Positive,表示预测结果为正例,实际结果也为正例,即预测正确的正例;
FP: False Positive,表示预测结果为正例,实际结果为负例,即预测错误的正例,没有预测到的负例;
TN: True Negative,表示预测结果为负例,实际结果也为负例,即预测正确的负例;
FN: False Negative,表示预测结果为负例,实际结果为正例,即预测错误的负例,没有预测到的正例;
需要注意的是,精确率和召回率是二分类指标,并不不适用于多分类,由此得到P-R曲线也是二分类评估指标,
因此如果需要计算多分类的Precision和Recall,我们需要指定某一类别标签作为Positive,而其他的类别则均为Negative,从而将问题转化为二分类问题,然后计算出相应类别的Precision和Recall.
理想情况下,精确率和召回率两者都越高越好。**然而事实上这两者在某些情况下是矛盾的,精确率高时,召回率低;精确率低时,召回率高;**关于这个性质通过观察PR曲线不难观察出来。比如在搜索网页时,如果只返回最相关的一个网页,那精确率就是100%,而召回率就很低;如果返回全部网页,那召回率为100%,精确率就很低。因此在不同场合需要根据实际需求判断哪个指标跟重要。
混淆矩阵(Confusion Matrix)
混淆矩阵
表示的是模型在测试集上所有预测结果的统计,对角线上的数值表示的是该类别预测正确的样本数:
labe1 | label2 | label3 | label4 | |
---|---|---|---|---|
label1 | 12 | 2 | 1 | 2 |
label2 | 0 | 34 | 4 | 2 |
label3 | 2 | 5 | 31 | 0 |
label4 | 1 | 4 | 1 | 45 |
行表示预测结果,列表示实际结果。因此label1的Precision和Recall为:
R
e
c
a
l
l
(
l
a
b
e
l
1
)
=
12
12
+
0
+
2
+
1
Recall(label1)=\frac{12}{12+0+2+1}
R
e
c
a
l
l
(
l
a
b
e
l
1
)
=
1
2
+
0
+
2
+
1
1
2
P
r
e
c
i
s
i
o
n
(
l
a
b
e
l
1
)
=
12
12
+
2
+
1
+
2
Precision(label1)=\frac{12}{12+2+1+2}
P
r
e
c
i
s
i
o
n
(
l
a
b
e
l
1
)
=
1
2
+
2
+
1
+
2
1
2
准确率、F-score
准确率(Accuracy)
准确率(accuracy)是一个全局指标
,既适用于二分类评估,也适用于多分类评估。其计算方式为将所有预测正确的样本数除以所有的样本数.
- 二分类评估公式如下:
准
确
率
(
A
c
c
u
r
a
c
y
)
=
T
P
+
T
N
T
P
+
F
P
+
T
N
+
F
N
准确率(Accuracy)=\frac{TP+TN}{TP+FP+TN+FN}
准
确
率
(
A
c
c
u
r
a
c
y
)
=
T
P
+
F
P
+
T
N
+
F
N
T
P
+
T
N
- 多分类评估公式如下:
准
确
率
(
A
c
c
u
r
a
c
y
)
=
1
n
∑
i
=
1
n
I
(
f
(
x
i
)
=
y
i
)
n
=
t
e
s
t
S
e
t
N
u
m
b
e
r
准确率(Accuracy)=\frac{1}{n}\sum_{i=1}^{n}{I(f(x_i)=y_i)}\ \ \ \ \ n=testSetNumber
准
确
率
(
A
c
c
u
r
a
c
y
)
=
n
1
i
=
1
∑
n
I
(
f
(
x
i
)
=
y
i
)
n
=
t
e
s
t
S
e
t
N
u
m
b
e
r
F-score
-
F-score
是关于精确率(Precision)和Recall(Recall)的一个评估指标,是对精确率和召回率赋不同权值进行加权调和:
F
−
s
c
o
r
e
=
(
1
+
α
2
)
∗
P
r
e
c
i
s
o
n
∗
R
e
c
a
l
l
α
2
∗
P
r
e
c
i
s
i
o
n
+
R
e
c
a
l
l
F-score=\frac{(1+\alpha^2)*Precison*Recall}{\alpha^2*Precision+Recall}
F
−
s
c
o
r
e
=
α
2
∗
P
r
e
c
i
s
i
o
n
+
R
e
c
a
l
l
(
1
+
α
2
)
∗
P
r
e
c
i
s
o
n
∗
R
e
c
a
l
l
-
F1-score
是精确率和召回率的调和均值,即
F
1
−
s
c
o
r
e
=
2
∗
P
r
e
c
i
s
o
n
∗
R
e
c
a
l
l
P
r
e
c
i
s
i
o
n
+
R
e
c
a
l
l
α
=
1
F1-score=\frac{2*Precison*Recall}{Precision+Recall}\ \ \ \ \ \ \ \ \alpha=1
F
1
−
s
c
o
r
e
=
P
r
e
c
i
s
i
o
n
+
R
e
c
a
l
l
2
∗
P
r
e
c
i
s
o
n
∗
R
e
c
a
l
l
α
=
1
-
macro-F1
是多分类模型中的全局指标
m
a
c
r
o
−
p
r
e
c
i
s
i
o
n
=
1
n
∑
i
=
1
n
P
i
macro-precision=\frac{1}{n}\sum_{i=1}^{n}{P_i}
m
a
c
r
o
−
p
r
e
c
i
s
i
o
n
=
n
1
i
=
1
∑
n
P
i
m
a
c
r
o
−
r
e
c
a
l
l
=
1
n
∑
i
=
1
n
R
i
macro-recall=\frac{1}{n}\sum_{i=1}^{n}{R_i}
m
a
c
r
o
−
r
e
c
a
l
l
=
n
1
i
=
1
∑
n
R
i
m
a
c
r
o
−
F
1
=
2
∗
m
a
c
r
o
−
p
r
e
c
i
s
i
o
n
∗
m
a
c
r
o
−
r
e
c
a
l
l
m
a
c
r
o
−
p
r
e
c
i
s
i
o
n
+
m
a
c
r
o
−
r
e
c
a
l
l
macro-F1=\frac{2*macro-precision*macro-recall}{macro-precision+macro-recall}
m
a
c
r
o
−
F
1
=
m
a
c
r
o
−
p
r
e
c
i
s
i
o
n
+
m
a
c
r
o
−
r
e
c
a
l
l
2
∗
m
a
c
r
o
−
p
r
e
c
i
s
i
o
n
∗
m
a
c
r
o
−
r
e
c
a
l
l
-
micro-F1
是跟
macro-F1
相对应的一个指标
设有n个类别,计算出每个类别的TP,FP,TN, 再计算precision、recall,F1
m
i
c
r
o
−
p
r
e
c
i
s
i
o
n
=
∑
i
=
1
n
T
P
i
∑
i
=
1
n
T
P
i
+
∑
i
=
1
n
F
P
i
micro-precision=\frac{\sum_{i=1}^n{TP_i}}{\sum_{i=1}^n{TP_i}+\sum_{i=1}^n{FP_i}}
m
i
c
r
o
−
p
r
e
c
i
s
i
o
n
=
∑
i
=
1
n
T
P
i
+
∑
i
=
1
n
F
P
i
∑
i
=
1
n
T
P
i
m
i
c
r
o
−
r
e
c
a
l
l
=
∑
i
=
1
n
T
P
i
∑
i
=
1
n
T
P
i
+
∑
i
=
1
n
T
N
i
micro-recall=\frac{\sum_{i=1}^n{TP_i}}{\sum_{i=1}^n{TP_i}+\sum_{i=1}^n{TN_i}}
m
i
c
r
o
−
r
e
c
a
l
l
=
∑
i
=
1
n
T
P
i
+
∑
i
=
1
n
T
N
i
∑
i
=
1
n
T
P
i
m
i
c
r
o
−
F
1
=
2
∗
m
i
c
r
o
−
p
r
e
c
i
s
i
o
n
∗
m
i
c
r
o
−
r
e
c
a
l
l
m
i
c
r
o
−
p
r
e
c
i
s
i
o
n
+
m
i
c
r
o
−
r
e
c
a
l
l
micro-F1=\frac{2*micro-precision*micro-recall}{micro-precision+micro-recall}
m
i
c
r
o
−
F
1
=
m
i
c
r
o
−
p
r
e
c
i
s
i
o
n
+
m
i
c
r
o
−
r
e
c
a
l
l
2
∗
m
i
c
r
o
−
p
r
e
c
i
s
i
o
n
∗
m
i
c
r
o
−
r
e
c
a
l
l
PR曲线
PR曲线是一个二分类模型的指标,其计算方式目前主流的方法:
根据给定测试集的预测结果以及ground truth结果,按照预测分数score将所有的测试集进行降序排列,然后从大到小逐个选择样本score作为阈值,大于此阈值的样本都属于正例,反之均属于负例,再对比ground truth的结果从而算出TP,FP计算出此阈值对应的Precision和Recall,遍历所有样本,从而算出PR曲线包含的所有(precision,recall)。
上述方法是业界计算PR曲线的标准方法,除此方法外,本文还使用了另外一种计算PR曲线的方法。
将阈值从1到0均等划分为n个点,构成一个集合{1,…,0},然后从1遍历到0,依次选择阈值,大于此阈值的样本都属于正例,反之均属于负例,再对比ground truth的结果从而算出TP,FP计算出此阈值对应的Precision和Recall,从而算出PR曲线包含的所有(precision,recall)。
两种方法的本质区别在于如何选择阈值,第一种方法的阈值是由样本的score组成的,而第二种方法的阈值则是根据PR曲线所对应的precision,recall数值的长度生成的。
以上便是计算PR曲线的两种方法,但均是对于二分类问题而言的。
对于多分类问题的PR曲线,也需要指定类别作为Positive, 其余类别作为Negative,从而根据上述方法算出PR曲线对应的Precision list 和 Recall List。
Image_name | Prediction | Ground Truth |
---|---|---|
Name1 |
A: 0.84 , B: 0.12, C: 0.04 |
A |
Name2 |
A: 0.77 , B: 0.18, C: 0.05 |
A |
Name3 |
A: 0.17, B: 0.81 , C: 0.02 |
A |
Name4 |
A: 0.06, B: 0.06, C: 0.88 |
A |
Name5 |
A: 0.01, B: 0.90 , C: 0.09 |
B |
Name6 |
A: 0.21, B: 0.67 , C: 0.12 |
B |
Name7 |
A: 0.15, B: 0.08, C: 0.78 |
B |
Name8 |
A: 0.32, B: 0.65 , C: 0.03 |
C |
Name9 |
A: 0.08, B: 0.10, C: 0.82 |
C |
上表是一个三分类问题的测试结果,这里我们分别使用上述的两种方法来计算类别A的PR曲线。
第一种方法:
首先将A的预测结果进行排序得到下表
Image_name | Prediction | Ground Truth |
---|---|---|
Name1 |
A: 0.84 , B: 0.12, C: 0.04 |
A |
Name2 |
A: 0.77 , B: 0.18, C: 0.05 |
A |
Name3 |
A: 0.32 , B: 0.65, C: 0.03 |
C |
Name4 |
A: 0.21 , B: 0.67, C: 0.12 |
B |
Name5 |
A: 0.17 , B: 0.81, C: 0.02 |
A |
Name6 |
A: 0.15 , B: 0.08, C: 0.78 |
B |
Name7 |
A: 0.08 , B: 0.10, C: 0.82 |
C |
Name8 |
A: 0.06 , B: 0.06, C: 0.88 |
A |
Name9 |
A: 0.01 , B: 0.90, C: 0.09 |
B |
这里可以看到阈值集合为{0.84, 0.77, 0.32, 0.21, 0.17, 0.15, 0.08, 0.06, 0.01},接下来依次计算这些阈值所对应的Precision和Recall:
阈值 | TP/FP/TP+FN | Precision/Recall |
---|---|---|
0.84 | 0/0/4 | 0.0/0.0 |
0.77 | 1/0/4 | 1.0/0.25 |
0.32 | 2/0/4 | 1.0/0.5 |
0.21 | 2/1/4 | 0.67/0.5 |
0.17 | 2/2/4 | 0.5/0.25 |
0.15 | 3/2/4 | 0.6/0.75 |
0.08 | 3/3/4 | 0.5/0.75 |
0.06 | 3/4/4 | 0.43/0.75 |
0.01 | 4/4/4 | 0.5/1.0 |
第二种方法
我们将阈值等分为11个点,每个点的间隔为0.1,其计算结果如下表所示:
阈值 | TP/FP/TP+FN | Precision/Recall |
---|---|---|
1.0 | 0/0/4 | 0.0/0.0 |
0.9 | 0/0/4 | 0.0/0.0 |
0.8 | 1/0/4 | 1.0/0.25 |
0.7 | 2/0/4 | 1.0/0.5 |
0.6 | 2/0/4 | 1.0/0.5 |
0.5 | 2/0/4 | 1.0/0.5 |
0.4 | 2/0/4 | 1.0/0.5 |
0.3 | 2/1/4 | 0.67/0.5 |
0.2 | 2/2/4 | 0.5/0.5 |
0.1 | 3/3/4 | 0.5/0.75 |
0.0 | 4/5/4 | 0.44/1.0 |
2. 目标检测指标
介绍检测指标之前,我先介绍下目标检测问题:给定一个图像,找到它所包含的物体,找到它们的位置并对它们进行分类。目标检测模型通常是在一组特定的类集合上进行训练的,所以模型只会定位和分类图像中的那些类。另外,对象的位置通常采用矩形边界框表示。因此,
目标检测涉及图像中物体的定位和分类
。
检测指标目前常用的主要有Precision/Recall,mAP, AP,PR曲线。
目标检测任务的预测结果包括:
- 物体位置坐标(bndbox),通常是一个四个元素的数组,即[Xmin,Ymin,Xmax,Ymax]
- 物体的类别
- 预测结果的置信度
IoU
在计算检测指标之前,需要介绍一个名词:
IoU
IoU是预测框与ground truth的交集和并集的比值。这个量也被称为Jaccard指数,20世纪初由Paul Jaccard首次提出。为了得到交集和并集,我们首先将预测框与ground truth放在一起,如图2所示。
对于每个类,预测框和ground truth重叠的区域是交集,而横跨的总区域就是并集。IoU可以如下计算:
如果想深入了解IoU,可以参考
Intersection over Union (IoU) for object detection
精确率(Precision), 召回率(Recall)
为了正确鉴别检测结果并计算精确率(Precision)和召回率(Recall),根据precision和recall的计算公式可知,我们需要计算出
True Positive
(真正例)、
False Positive
(假正例)。
为了获得
True Positives
和
False Positives
,我们需要使用IoU。
计算IoU,我们从而确定一个检测结果(Positive)是正确的(True)还是错误的(False)。最常用的阈值是0.5,即如果IoU> 0.5,则认为它是True Positive,否则认为是False Positive。阈值可以根据业务需要进行选择,本文仅讨论阈值为0.5的情况。
这里我用一张图片作为例子,多张图片道理一样。假设一张图片有N个需要检测的目标,分别是object1,object2,object3共分为三类,使用检测器得到了M个Bounding Box(bndbox),每个bndbox里包含bndbox所在的位置以及object1,object2,object3对应的分数confidence。
我把计算目标检测评价指标归为一下2步:
-
遍历M个bndbox中每一个bndbox,计算其与N个GroundTruth(GT)的IoU值,且取其中的最大值MaxIoU。设定一个阈值thresh,一般设置thresh为0.5。
当MaxIoU < thresh: 记录其类别label,分数confidence以及fp = 1。
当MaxIoU>=thresh, 分为以下俩种情况:
当MaxIoU对应的GT类别与给定的bndbox类别相同,记录其类别label,分数confidence以及tp = 1。
当MaxIoU对应的GT类别与给定的bndbox类别不同,记录其类别label,分数confidence以及fp = 1。 -
由步骤1我们可以得到M个分数与tp/fp的元祖,形如(label,confidence,tp或者fp),以label为key,将这M个元组分成三份,遍历每个label, 对从属于此label的所有元组按照confidence进行排序。
通过上述方式,然后在所有的测试集上进行计算就可以得到所有label的TP与FP,以及对应的confidence。
另外通过解析ground truth中的所有样例,就可以计算出每个label的真实数目,记作:gt_num
因此我们可以计算
每个label的Precision跟Recall
P
r
e
c
i
s
i
o
n
(
l
a
b
e
l
)
=
∑
T
P
(
l
a
b
e
l
)
∑
T
P
(
l
a
b
e
l
)
+
∑
F
P
(
l
a
b
e
l
)
Precision(label)=\frac{\sum{TP(label)}}{\sum{TP(label)}+\sum{FP(label)}}
P
r
e
c
i
s
i
o
n
(
l
a
b
e
l
)
=
∑
T
P
(
l
a
b
e
l
)
+
∑
F
P
(
l
a
b
e
l
)
∑
T
P
(
l
a
b
e
l
)
R
e
c
a
l
l
(
l
a
b
e
l
)
=
∑
T
P
(
l
a
b
e
l
)
∑
g
t
_
n
u
m
(
l
a
b
e
l
)
Recall(label)=\frac{\sum{TP(label)}}{\sum{gt\_num(label)}}
R
e
c
a
l
l
(
l
a
b
e
l
)
=
∑
g
t
_
n
u
m
(
l
a
b
e
l
)
∑
T
P
(
l
a
b
e
l
)
全局的Precision跟Recall
P
r
e
c
i
s
i
o
n
=
∑
l
a
b
e
l
∈
l
a
b
e
l
s
∑
T
P
(
l
a
b
e
l
)
∑
T
P
(
l
a
b
e
l
)
+
∑
F
P
(
l
a
b
e
l
)
Precision=\sum_{label\in labels}\frac{\sum{TP(label)}}{\sum{TP(label)}+\sum{FP(label)}}
P
r
e
c
i
s
i
o
n
=
l
a
b
e
l
∈
l
a
b
e
l
s
∑
∑
T
P
(
l
a
b
e
l
)
+
∑
F
P
(
l
a
b
e
l
)
∑
T
P
(
l
a
b
e
l
)
R
e
c
a
l
l
=
∑
l
a
b
e
l
∈
l
a
b
e
l
s
∑
T
P
(
l
a
b
e
l
)
∑
g
t
_
n
u
m
(
l
a
b
e
l
)
Recall=\sum_{label\in labels}\frac{\sum{TP(label)}}{\sum{gt\_num(label)}}
R
e
c
a
l
l
=
l
a
b
e
l
∈
l
a
b
e
l
s
∑
∑
g
t
_
n
u
m
(
l
a
b
e
l
)
∑
T
P
(
l
a
b
e
l
)
PR曲线
在计算Precision和Recall时,计算出了TP,FP,以及对应的confidence。在计算PR曲线时,跟分类模型类似,这里还是需要选取阈值集合,根据选取的阈值集合生成PR曲线。这里只介绍业界通用的选取方式。
分label的PR曲线
按照标签label,对相应的confidence进行降序排序,然后从大到小依次选取对应的confidence作为阈值,大于此阈值的均为预测正例,从而计算出TP,FP,然后计算出该阈值下的Precision跟Recall。
全局PR曲线
不区分label, 将所有的confidence进行降序排序,然后从大到小依次选取对应的confidence作为阈值,大于此阈值的bndbox以及label均为预测正例,从而计算出全局的TP,FP,然后计算出该阈值下的Precision跟Recall。
计算PR曲线核心代码
def compute_PRs(tp, fp, scores, gt_num):
"""
cal precisions and recalls according to the tp, fp and scores(confidence)
:param tp: np.array(), the item is 0 or 1
:param fp: np.array(), the item is 0 or 1
:param scores: np.array(), the scores(confidence)
:param gt_num: int, the ground truth number
:return:
precisions: np.array
recalls: np.array
thresholds. np.array
"""
if gt_num == 0:
logging.error('gt_num is equal to zero')
sorted_indices = np.argsort(scores)
sorted_indices = sorted_indices[::-1]
true_positive_labels = tp[sorted_indices]
false_positive_labels = fp[sorted_indices]
cum_true_positives = np.cumsum(true_positive_labels)
cum_false_positives = np.cumsum(false_positive_labels)
precisons = cum_true_positives.astype(float) / np.maximum(
cum_true_positives + cum_false_positives, np.finfo(np.float64).eps)
recalls = cum_true_positives.astype(float) / np.maximum(gt_num, np.finfo(np.float64).eps)
thresholds = scores[sorted_indices]
return precisons, recalls, thresholds
AP, mAP
AP
AP, Average Precision, 相比较PR曲线而言,是将其图形化的指标进行了量化,能够帮助开发者直观的观察模型的性能。它的公式如下:
∫
0
1
p
(
r
)
d
r
\int_0^1p(r)dr
∫
0
1
p
(
r
)
d
r
p®表示PR曲线,通过公式可以看到AP其实就是PR曲线所围成的面积。计算PR曲线的积分无疑是十分繁琐的,PR曲线本身都不是连续函数,微积分那一套东西根本不适合。
目前业界有两种计算AP的方法:
-
Approximated Average Precision,近似算法,这跟原始的定义法求积分的思路是一样的。
具体计算方法:对每一种阈值分别求(Precision值)乘以(Recall值的变化情况),再把所有阈值下求得的乘积值进行累加。公式如下:
AP
=
∑
k
=
1
N
P
(
k
)
Δ
r
(
k
)
AP=\sum_{k=1}^{N}P(k)\Delta r(k)
A
P
=
k
=
1
∑
N
P
(
k
)
Δ
r
(
k
)
公式中的N表示所有的样本数,P(k)表示在能识别出k个图片的时候Precision的值,而 Delta r(k) 则表示识别图片个数从k-1变化到k时(通过调整阈值)Recall值的变化情况。 -
Interpolated Average Precision,插值法
为了得到precision-recall曲线,首先要对模型预测结果进行排序(ranked output,按照各个预测值置信度降序排列)。那么给定一个rank,Recall和Precision仅在高于该rank值的预测结果中计算,改变rank值会改变recall值。这里共选择11个不同的recall([0, 0.1, …, 0.9, 1.0]),可以认为是选择了11个rank,由于按照置信度排序,所以实际上等于选择了11个不同的置信度阈值。那么,AP就定义为在这11个recall下precision的平均值,其可以表征整个precision-recall曲线(曲线下面积)。
AP
=
1
11
∑
r
∈
0
,
0.01
,
.
.
.
,
1.0
P
i
n
t
e
r
p
(
r
)
AP=\frac{1}{11}\sum_{r\in {0,0.01,…,1.0}}P_{interp}(r)
A
P
=
1
1
1
r
∈
0
,
0
.
0
1
,
.
.
.
,
1
.
0
∑
P
i
n
t
e
r
p
(
r
)
计算Precision时采用插值法,求出大于等于给定rec所对应的最大Precision作为计算结果。
Pi
n
e
r
p
=
max
r
:
r
≥
r
e
c
(
r
)
P_{inerp}=\max_{r:r\geq rec}(r)
P
i
n
e
r
p
=
r
:
r
≥
r
e
c
max
(
r
)
Code 2007:
ap = 0. for t in np.arange(0., 1.1, 0.1): if np.sum(recalls >= t) == 0: p = 0 else: p = np.max(precisions[recalls >= t]) ap = ap + p / 11.
这是VOC在2007年提出的方法,只采用的11个点进行计算,而在2010年以后使用了所有数据集来计算AP。
Code 2010:
# correct AP calculation # first append sentinel values at the end mrec = np.concatenate(([0.], recalls, [1.])) mpre = np.concatenate(([0.], precisions, [0.])) # compute precision integration ladder for i in range(mpre.size - 1, 0, -1): mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i]) # to calculate area under PR curve, look for points # where X axis (recall) changes value i = np.where(mrec[1:] != mrec[:-1])[0] # and sum (\Delta recall) * prec ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])
通过定义我们可以发现, Approximated Average Precision与精度曲线挨的很近,而使用Interpolated Average Precision算出的Average Precision值明显要比Approximated Average Precision的方法算出的要高。通过观察上图,也验证我们的结论。
至于选择哪种计算方法,大家可以根据自己的需求进行选择,本文使用的是VOC 2010年之后的插值法 Approximated Average Precision。
mAP
在目标检测中,mAP(mean average precision)的定义首先出现在PASCAL Visual Objects Classes(VOC)竞赛中,mAP通常是在整个数据集上计算得到的,它是一个全局指标,其计算方式非常简单,就是将所有标签的AP计算出来取其算术平均值即可。
m
A
P
=
1
N
l
a
b
e
l
s
∑
l
a
b
e
l
∈
l
a
b
e
l
s
A
P
(
l
a
b
e
l
)
mAP=\frac{1}{N_{labels}}\sum_{label\in labels}AP(label)
m
A
P
=
N
l
a
b
e
l
s
1
l
a
b
e
l
∈
l
a
b
e
l
s
∑
A
P
(
l
a
b
e
l
)
上述公式中的Nlabels表示label的数目。
3. 识别指标
本文介绍的识别是指图像识别跟文字识别(OCR),识别问题是指在给定的图像中识别出感兴趣的内容,目前应用比较广泛的便是OCR。
识别指标主要有编辑距离率(ned_accuracy),精确率(precision),召回率(recall), PR曲线。
精确率(Precision), 召回率(Recall)
精确率,召回率的定义已经在前面详细介绍过了,关键在于TP,FP的计算。识别模型中,预测结果为关注区域的内容,计算TP,FP时比较预测内容跟实际内容是否完全相同,如果相同,则TP为1,否则FP为1.
给定一个样本,预测结果为N个内容,ground truth有M个内容,依次遍历预测结果中每个内容,跟ground truth中的结果进行比较,如果相同则TP=1,不相同则FP=1,记录其score跟内容,然后将此内容从ground truth中去除。这样可以得到N个元组(score, TP/FP)。最后遍历整个样本计算出所有的TP/FP。再根据格式计算出Precision和Recall。
编辑距离率(ned_accuracy)
编辑距离
首先介绍下编辑距离。
编辑距离(Minimum Edit Distance,MED),由俄罗斯科学家 Vladimir Levenshtein 在1965年提出,也因此而得名 Levenshtein Distance。
在信息论、语言学和计算机科学领域,Levenshtein Distance 是用来度量两个序列相似程度的指标。通俗地来讲,编辑距离指的是在两个单词(w1,w2)之间,由其中一个单词 w1 转换为另一个单词 w2 所需要的最少
单字符编辑操作
次数。
在这里定义的单字符编辑操作有且仅有三种:
- 插入(Insertion)
- 删除(Deletion)
- 替换(Substitution)
譬如,“kitten” 和 “sitting” 这两个单词,由 “kitten” 转换为 “sitting” 需要的最少单字符编辑操作有:
1.kitten → sitten (substitution of “s” for “k”)
2.sitten → sittin (substitution of “i” for “e”)
3.sittin → sitting (insertion of “g” at the end)
因此,“kitten” 和 “sitting” 这两个单词之间的编辑距离为 3 。
编辑距离率
给定两个字符串string1跟string2,假设它们的编辑距离为med(string1,string2),那么编辑距离率为:
n
e
d
_
a
c
c
u
r
a
c
y
(
s
t
r
i
n
g
1
,
s
t
r
i
n
g
2
)
=
1
−
m
e
d
(
s
t
r
i
n
g
1
,
s
t
r
i
n
g
2
)
m
a
x
(
l
e
n
(
s
t
r
i
n
g
1
)
,
l
e
n
(
s
t
r
i
n
g
2
)
)
ned\_accuracy(string1,string2)=1-\frac{med(string1,string2)}{max(len(string1),len(string2))}
n
e
d
_
a
c
c
u
r
a
c
y
(
s
t
r
i
n
g
1
,
s
t
r
i
n
g
2
)
=
1
−
m
a
x
(
l
e
n
(
s
t
r
i
n
g
1
)
,
l
e
n
(
s
t
r
i
n
g
2
)
)
m
e
d
(
s
t
r
i
n
g
1
,
s
t
r
i
n
g
2
)
从公式可以看出,若string1跟string2完全相同,则它们的编辑距离率为1,若string1不为空,string2为空字符串,则它们的编辑距离率为0。因此当string1跟string2的编辑距离越小,则它们的编辑距离率越大。
那么整个样本的编辑距离率怎么计算呢?
还是以一个样本为例。给定一个样本,预测结果为N个内容,ground truth有M个内容,依次遍历预测结果中每个内容,计算其与ground truth中每个内容的编辑距离率,取最大的作为其结果,然后将最大结果对应的内容从ground truth中去除。这样可以得到N个编辑距离率。最后遍历整个样本计算出所有的编辑距离率,将它们进行求和除以所有的编辑距离率的数目,这样得到了便是整个样本的编辑距离率。
n
e
d
_
a
c
c
u
r
a
c
y
=
∑
i
=
1
n
∑
j
=
1
N
i
n
e
d
_
a
c
c
u
r
a
c
y
(
j
)
∑
i
n
N
i
ned\_accuracy=\frac{\sum_{i=1}^{n}{\sum_{j=1}^{N_i}ned\_accuracy(j)}}{\sum_{i}^{n}N_i}
n
e
d
_
a
c
c
u
r
a
c
y
=
∑
i
n
N
i
∑
i
=
1
n
∑
j
=
1
N
i
n
e
d
_
a
c
c
u
r
a
c
y
(
j
)
Ni表示第i个样本中的预测内容的数量,n表示样本个数。
PR曲线
根据前面生成的TP,FP以及score, 计算方式跟分类模型类似,这里就不详细叙述了。