Precision-Recall Curve Feature Addition (#1107)
* initial commit * Update general.py Indent update * Update general.py refactor duplicate code * 200 dpi
This commit is contained in:
1 parent
9eae82e3a3
commit
5fac5ad165
3 files changed
+33
-31
No files matched your search
+21
-16
@@ -245,14 +245,16 @@ def clip_coords(boxes, img_shape):
|
||||
boxes[:, 3].clamp_(0, img_shape[0]) # y2
|
||||
|
||||
|
||||
def ap_per_class(tp, conf, pred_cls, target_cls):
|
||||
def ap_per_class(tp, conf, pred_cls, target_cls, plot=False, fname='precision-recall_curve.png'):
|
||||
""" 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).
|
||||
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).
|
||||
pred_cls: Predicted object classes (nparray).
|
||||
target_cls: True object classes (nparray).
|
||||
plot: Plot precision-recall curve at mAP@0.5
|
||||
fname: Plot filename
|
||||
# Returns
|
||||
The average precision as computed in py-faster-rcnn.
|
||||
"""
|
||||
@@ -265,6 +267,7 @@ def ap_per_class(tp, conf, pred_cls, target_cls):
|
||||
unique_classes = np.unique(target_cls)
|
||||
|
||||
# Create Precision-Recall curve and compute AP for each class
|
||||
px, py = np.linspace(0, 1, 1000), [] # for plotting
|
||||
pr_score = 0.1 # score to evaluate P and R https://github.com/ultralytics/yolov3/issues/898
|
||||
s = [unique_classes.shape[0], tp.shape[1]] # number class, number iou thresholds (i.e. 10 for mAP0.5...0.95)
|
||||
ap, p, r = np.zeros(s), np.zeros(s), np.zeros(s)
|
||||
@@ -289,22 +292,26 @@ def ap_per_class(tp, conf, pred_cls, target_cls):
|
||||
p[ci] = np.interp(-pr_score, -conf[i], precision[:, 0]) # p at pr_score
|
||||
|
||||
# AP from recall-precision curve
|
||||
py.append(np.interp(px, recall[:, 0], precision[:, 0])) # precision at mAP@0.5
|
||||
for j in range(tp.shape[1]):
|
||||
ap[ci, j] = compute_ap(recall[:, j], precision[:, j])
|
||||
|
||||
# Plot
|
||||
# fig, ax = plt.subplots(1, 1, figsize=(5, 5))
|
||||
# ax.plot(recall, precision)
|
||||
# ax.set_xlabel('Recall')
|
||||
# ax.set_ylabel('Precision')
|
||||
# ax.set_xlim(0, 1.01)
|
||||
# ax.set_ylim(0, 1.01)
|
||||
# fig.tight_layout()
|
||||
# fig.savefig('PR_curve.png', dpi=300)
|
||||
|
||||
# Compute F1 score (harmonic mean of precision and recall)
|
||||
f1 = 2 * p * r / (p + r + 1e-16)
|
||||
|
||||
if plot:
|
||||
py = np.stack(py, axis=1)
|
||||
fig, ax = plt.subplots(1, 1, figsize=(5, 5))
|
||||
ax.plot(px, py, linewidth=0.5, color='grey') # plot(recall, precision)
|
||||
ax.plot(px, py.mean(1), linewidth=2, color='blue', label='all classes')
|
||||
ax.set_xlabel('Recall')
|
||||
ax.set_ylabel('Precision')
|
||||
ax.set_xlim(0, 1)
|
||||
ax.set_ylim(0, 1)
|
||||
plt.legend()
|
||||
fig.tight_layout()
|
||||
fig.savefig(fname, dpi=200)
|
||||
|
||||
return p, r, ap, f1, unique_classes.astype('int32')
|
||||
|
||||
|
||||
@@ -1011,8 +1018,6 @@ def plot_wh_methods(): # from utils.general import *; plot_wh_methods()
|
||||
def plot_images(images, targets, paths=None, fname='images.jpg', names=None, max_size=640, max_subplots=16):
|
||||
tl = 3 # line thickness
|
||||
tf = max(tl - 1, 1) # font thickness
|
||||
if os.path.isfile(fname): # do not overwrite
|
||||
return None
|
||||
|
||||
if isinstance(images, torch.Tensor):
|
||||
images = images.cpu().float().numpy()
|
||||
|
||||
Reference in new issue
Block a user