PR-curve(precision-recall curve)object detection

本文针对目标检测中的PR曲线进行了深入探讨,并纠正了网上普遍存在的绘制错误。正确的PR曲线应以召回率为x轴,精确率为y轴,并展示了如何使用Python及matplotlib正确绘制PR曲线。

最近在对目标检测中的PR曲线做程序实现,发现网上有很多的版本,而且引用https://www.zhihu.com/question/53405779中的一些内容,网上很多的程序在绘制PR曲线中存在一些问题。

使用python+matplotlib 绘制PR曲线的代码应该如下:(其中出现争议的部分是ax.plot(x,y))根据PR曲线,x轴为Recall, y轴为Precision。网上有些代码是反过来的。从matplotlib的源码中很容易可以发现是错误的。

import matplotlib.pyplot as plt
        
fig, ax = plt.subplots(1, 1, figsize=(5, 5))
ax.plot(recall, precision,color='red')
ax.plot(recall_b, precision_b)
ax.set_xlabel('Recall')
ax.set_ylabel('Precision')
ax.set_xlim(0, 1.01)
ax.set_ylim(0, 1.01)

plt.legend(('a', 'b'), loc='upper right')
fig.tight_layout()
fig.show()

理想的PR曲线两端应该是收敛到1的。从开始的部分精度为1,到结束的部分recall为1.但是可能出现的问题是:有的模型存在一种问题就是(1,信息检索中一定有某几条相关内容(Ground Truth)没有检索出来;2,目标检测中一定有某几个目标(Ground Truth)没有检测出来),即FN不为0.这样带来的问题就是PR曲线在Recall端无法收敛为0.

def ap_per_class(tp, conf, pred_cls, target_cls, plot=False, save_dir='.', names=()): """ Compute the average precision, given the recall and precision curves. Source: https://github.com/rafaelpadilla/Object-Detection-Metrics. # Arguments tp: True positives (nparray, nx1 or nx10). conf: Objectness value from 0-1 (nparray). pred_cls: Predicted object classes (nparray). target_cls: True object classes (nparray). plot: Plot precision-recall curve at mAP@0.5 save_dir: Plot save directory # Returns The average precision as computed in py-faster-rcnn. """ # Sort by objectness i = np.argsort(-conf) tp, conf, pred_cls = tp[i], conf[i], pred_cls[i] # Find unique classes unique_classes = np.unique(target_cls) nc = unique_classes.shape[0] # number of classes, number of detections # Create Precision-Recall curve and compute AP for each class px, py = np.linspace(0, 1, 1000), [] # for plotting ap, p, r = np.zeros((nc, tp.shape[1])), np.zeros((nc, 1000)), np.zeros((nc, 1000)) for ci, c in enumerate(unique_classes): i = pred_cls == c n_l = (target_cls == c).sum() # number of labels n_p = i.sum() # number of predictions if n_p == 0 or n_l == 0: continue else: # Accumulate FPs and TPs fpc = (1 - tp[i]).cumsum(0) tpc = tp[i].cumsum(0) # Recall recall = tpc / (n_l + 1e-16) # recall curve r[ci] = np.interp(-px, -conf[i], recall[:, 0], left=0) # negative x, xp because xp decreases # Precision precision = tpc / (tpc + fpc) # precision curve p[ci] = np.interp(-px, -conf[i], precision[:, 0], left=1) # p at pr_score # AP from recall-precision curve for j in range(tp.shape[1]): ap[ci, j], mpre, mrec = compute_ap(recall[:, j], precision[:, j]) if plot and j == 0: py.append(np.interp(px, mrec, mpre)) # precision at mAP@0.5 # Compute F1 (harmonic mean of precision and recall) f1 = 2 * p * r / (p + r + 1e-16) if plot: plot_pr_curve(px, py, ap, Path(save_dir) / 'PR_curve.png', names) plot_mc_curve(px, f1, Path(save_dir) / 'F1_curve.png', names, ylabel='F1') plot_mc_curve(px, p, Path(save_dir) / 'P_curve.png', names, ylabel='Precision') plot_mc_curve(px, r, Path(save_dir) / 'R_curve.png', names, ylabel='Recall') i = f1.mean(0).argmax() # max F1 index return p[:, i], r[:, i], ap, f1[:, i], unique_classes.astype('int32')
最新发布
03-26
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值