使用自定义的类别和数据集训练了MMDetection的目标检测模型,需要汇报模型的precision, recall等等各项指标。在MMDetection的官网文档里只找到了生成混淆矩阵的代码,但似乎并不支持直接给出其他常见的评价指标(见Github项目的issue#6212issue#8791。搜索一番后发现CSDN博客上有人分享了如何通过在tools/analysis_tools/confusion_matrix.pymain()函数末尾添加代码,从而得到precision, recall, F1, AP, AR。然而实际运行后发现其实有bug,并且原理上也有一些问题,所以进行了适当修改。

总体思路是,先从混淆矩阵中计算出每个分类的真阳性样本量FP、假阳性样本量TP、假阴性样本量FN,然后按照公式计算各分类标签的precision和recall。

需要注意的是,precisionrecall的长度其实比分类数量多1。这是因为前面生成confusion matrix的时候,在已有分类的后边还加了一个“background”的标签。precisionrecall的最后一位其实就是“background”的精确率和召回率,并且总是为零。从混淆矩阵里面也可以看出,background的真阳性比例一定是0%。在计算平均precision和recall的时候,我们不需要考虑这一个额外的分类。

normalized confusion matrix, from MMDetection documents
MMDetection官方文档里的normalized confusion matrix,"background"分类的真阳性比例一定是0%

需要在main()函数末尾添加的代码为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
TP = np.diag(confusion_matrix)
FP = np.sum(confusion_matrix, axis=0) - TP
FN = np.sum(confusion_matrix, axis=1) - TP

precision = TP / (TP + FP)
recall = TP / (TP + FN)
average_precision = np.mean(precision[:-1])
average_recall = np.mean(recall[:-1])
f1 = 2* (average_precision * average_recall) / (average_precision + average_recall)

print('\n===Averaging all classes===')
print('AP:', average_precision)
print('AR:', average_recall)
print('F1:', f1)
print('Classes', dataset.metainfo['classes'] + ('background', ))
print('Precision', precision)
print('Recall', recall)

然后按照官方文档的说明,正常运行代码就可以输出结果了。

1
python tools/analysis_tools/confusion_matrix.py ${CONFIG}  ${DETECTION_RESULTS}  ${SAVE_DIR} --show

打印内容形如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
loading annotations into memory...
Done (t=0.02s)
creating index...
index created!
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>] 14/14, 62.8 task/s, elapsed: 0s, ETA:     0s
===Averaging all classes===
AP: 0.95018367938121
AR: 0.664406462586606
F1: 0.7820042508816204
Classes ('label1', 'label2', 'label3', 'label4', 'background')
Precision [0.92405063 0.97506925 0.96411483 0.9375     0.        ]
Recall [0.65765766 0.80182232 0.79019608 0.40794979 0.        ]