今天早上动力满满,早起先写个博客!
话说前两个月,运行了Faster RCNN的源码,效果不错,但是没有把Precision-recall曲线可视化出来。
本教程主要参考:1.Faster RCNN画PR曲线
2.https://github.com/rbgirshick/py-faster-rcnn/issues/670
AP衡量的是学出来的模型在每个类别上的好坏,mAP衡量的是学出的模型在所有的类别上的好坏,得到AP后 mAP的计算就变得很简单,即取所有AP的平均值。
参考:Precision/Recall、ROC/AUC、AP/MAP等概念区分
PR曲线的横轴Recall也就是TPR,反映了分类器对正例的覆盖能力,而纵轴Precision反映了分类器预测正例的准确程度。那么Precision-recall曲线反映了分类器对正例的识别准确程度和对正例的覆盖能力之间的权衡。
AP就是PR曲线与X轴围成的图形面积。
回归正题,怎么画PR曲线呢?
首先,我参考的Faster RCNN源码是:https://github.com/smallcorgi/Faster-RCNN_TF
感觉这份源码挺好的,能成功训练自己的数据集。
修改/lib/datasets/pascal_voc.py:
在文件头部加入:
import matplotlib.pyplot as plt
import pylab as pl
from sklearn.metrics import precision_recall_curve
from itertools import cycle
修改_do_python_eval()函数
在aps += [ap]
后加入:
pl.plot(rec, prec, lw=2,
label='{} (AP = {:.4f})'
''.format(cls, ap))
这句最重要,就是用来画图的。
再加入:
pl.xlabel('Recall')
pl.ylabel('Precision')
plt.grid(True)
pl.ylim([0.0, 1.05])
pl.xlim([0.0, 1.0])
pl.title('Precision-Recall')
pl.legend(loc="upper left")
plt.show()
修改完后的整个函数如下所示:
def _do_python_eval(self, output_dir = 'output'):
annopath = os.path.join(
self._devkit_path,
'VOC' + self._year,
'Annotations',
'{:s}.xml')
imagesetfile = os.path.join(
self._devkit_path,
'VOC' + self._year,
'ImageSets',
'Main',
self._image_set + '.txt')
cachedir = os.path.join(self._devkit_path, 'annotations_cache')
aps = []
# The PASCAL VOC metric changed in 2010
use_07_metric = True if int(self._year) < 2010 else False
print 'VOC07 metric? ' + ('Yes' if use_07_metric else 'No')
if not os.path.isdir(output_dir):
os.mkdir(output_dir)
for i, cls in enumerate(self._classes):
if cls == '__background__':
continue
filename = self._get_voc_results_file_template().format(cls)
rec, prec, ap = voc_eval(
filename, annopath, imagesetfile, cls, cachedir, ovthresh=0.5,
use_07_metric=use_07_metric)
aps += [ap]
pl.plot(rec, prec, lw=2,
label='{} (AP = {:.4f})'
''.format(cls, ap))
print('AP for {} = {:.4f}'.format(cls, ap))
with open(os.path.join(output_dir, cls + '_pr.pkl'), 'w') as f:
cPickle.dump({'rec': rec, 'prec': prec, 'ap': ap}, f)
pl.xlabel('Recall')
pl.ylabel('Precision')
plt.grid(True)
pl.ylim([0.0, 1.05])
pl.xlim([0.0, 1.0])
pl.title('Precision-Recall')
pl.legend(loc="upper left")
plt.show()
pl.savefig('test_1.jpg')
print('Mean AP = {:.4f}'.format(np.mean(aps)))
print('~~~~~~~~')
print('Results:')
for ap in aps:
print('{:.3f}'.format(ap))
print('{:.3f}'.format(np.mean(aps)))
print('~~~~~~~~')
print('')
print('--------------------------------------------------------------')
print('Results computed with the **unofficial** Python eval code.')
print('Results should be very close to the official MATLAB eval code.')
print('Recompute with `./tools/reval.py --matlab ...` for your paper.')
print('-- Thanks, The Management')
print('--------------------------------------------------------------')
解释:这段代码不是根据日志信息输出的,而是在测试过程中输出的。
我得到的图如下所示:
这是我自己的一个数据集,所以AP比较高。。。其实图里面我的标识标错了 应该是:AP=
但是上面的代码已经修正了。
总结:上面只是举了个例子 怎么画AP曲线,其实也适用于其他的代码,亲测有效。
你只需找到你的代码是在哪里算mAP的,一般都有个eval函数,每测试一张图片都有个AP值,用plot函数画出来就好。
所以关键就是这行代码啦:
pl.plot(rec, prec, lw=2, label='{} (AP = {:.4f})' ''.format(cls, ap))
有问题请留言~~~~~
接下来,想将多种方法的mAP用曲线可视化。