Precision-Recall Curve feature update (#1206)
Browse files* Precision-Recall Curve feature update
* sentinel value update
- utils/general.py +10 -8
utils/general.py
CHANGED
@@ -293,9 +293,10 @@ def ap_per_class(tp, conf, pred_cls, target_cls, plot=False, fname='precision-re
|
|
293 |
p[ci] = np.interp(-pr_score, -conf[i], precision[:, 0]) # p at pr_score
|
294 |
|
295 |
# AP from recall-precision curve
|
296 |
-
py.append(np.interp(px, recall[:, 0], precision[:, 0])) # precision at [email protected]
|
297 |
for j in range(tp.shape[1]):
|
298 |
-
ap[ci, j] = compute_ap(recall[:, j], precision[:, j])
|
|
|
|
|
299 |
|
300 |
# Compute F1 score (harmonic mean of precision and recall)
|
301 |
f1 = 2 * p * r / (p + r + 1e-16)
|
@@ -304,7 +305,7 @@ def ap_per_class(tp, conf, pred_cls, target_cls, plot=False, fname='precision-re
|
|
304 |
py = np.stack(py, axis=1)
|
305 |
fig, ax = plt.subplots(1, 1, figsize=(5, 5))
|
306 |
ax.plot(px, py, linewidth=0.5, color='grey') # plot(recall, precision)
|
307 |
-
ax.plot(px, py.mean(1), linewidth=2, color='blue', label='all classes')
|
308 |
ax.set_xlabel('Recall')
|
309 |
ax.set_ylabel('Precision')
|
310 |
ax.set_xlim(0, 1)
|
@@ -327,8 +328,8 @@ def compute_ap(recall, precision):
|
|
327 |
"""
|
328 |
|
329 |
# Append sentinel values to beginning and end
|
330 |
-
mrec = np.concatenate(([0.], recall, [
|
331 |
-
mpre = np.concatenate(([0.], precision, [0.]))
|
332 |
|
333 |
# Compute the precision envelope
|
334 |
mpre = np.flip(np.maximum.accumulate(np.flip(mpre)))
|
@@ -336,13 +337,13 @@ def compute_ap(recall, precision):
|
|
336 |
# Integrate area under curve
|
337 |
method = 'interp' # methods: 'continuous', 'interp'
|
338 |
if method == 'interp':
|
339 |
-
x = np.linspace(0, 1,
|
340 |
ap = np.trapz(np.interp(x, mrec, mpre), x) # integrate
|
341 |
else: # 'continuous'
|
342 |
i = np.where(mrec[1:] != mrec[:-1])[0] # points where x axis (recall) changes
|
343 |
ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1]) # area under curve
|
344 |
|
345 |
-
return ap
|
346 |
|
347 |
|
348 |
def bbox_iou(box1, box2, x1y1x2y2=True, GIoU=False, DIoU=False, CIoU=False, eps=1e-9):
|
@@ -1259,7 +1260,7 @@ def plot_results_overlay(start=0, stop=0): # from utils.general import *; plot_
|
|
1259 |
|
1260 |
|
1261 |
def plot_results(start=0, stop=0, bucket='', id=(), labels=(), save_dir=''):
|
1262 |
-
# from utils.general import *; plot_results()
|
1263 |
# Plot training 'results*.txt' as seen in https://github.com/ultralytics/yolov5#reproduce-our-training
|
1264 |
fig, ax = plt.subplots(2, 5, figsize=(12, 6))
|
1265 |
ax = ax.ravel()
|
@@ -1273,6 +1274,7 @@ def plot_results(start=0, stop=0, bucket='', id=(), labels=(), save_dir=''):
|
|
1273 |
os.system(c)
|
1274 |
else:
|
1275 |
files = glob.glob(str(Path(save_dir) / 'results*.txt')) + glob.glob('../../Downloads/results*.txt')
|
|
|
1276 |
for fi, f in enumerate(files):
|
1277 |
try:
|
1278 |
results = np.loadtxt(f, usecols=[2, 3, 4, 8, 9, 12, 13, 14, 10, 11], ndmin=2).T
|
|
|
293 |
p[ci] = np.interp(-pr_score, -conf[i], precision[:, 0]) # p at pr_score
|
294 |
|
295 |
# AP from recall-precision curve
|
|
|
296 |
for j in range(tp.shape[1]):
|
297 |
+
ap[ci, j], mpre, mrec = compute_ap(recall[:, j], precision[:, j])
|
298 |
+
if j == 0:
|
299 |
+
py.append(np.interp(px, mrec, mpre)) # precision at [email protected]
|
300 |
|
301 |
# Compute F1 score (harmonic mean of precision and recall)
|
302 |
f1 = 2 * p * r / (p + r + 1e-16)
|
|
|
305 |
py = np.stack(py, axis=1)
|
306 |
fig, ax = plt.subplots(1, 1, figsize=(5, 5))
|
307 |
ax.plot(px, py, linewidth=0.5, color='grey') # plot(recall, precision)
|
308 |
+
ax.plot(px, py.mean(1), linewidth=2, color='blue', label='all classes %.3f [email protected]' % ap[:, 0].mean())
|
309 |
ax.set_xlabel('Recall')
|
310 |
ax.set_ylabel('Precision')
|
311 |
ax.set_xlim(0, 1)
|
|
|
328 |
"""
|
329 |
|
330 |
# Append sentinel values to beginning and end
|
331 |
+
mrec = recall # np.concatenate(([0.], recall, [recall[-1] + 1E-3]))
|
332 |
+
mpre = precision # np.concatenate(([0.], precision, [0.]))
|
333 |
|
334 |
# Compute the precision envelope
|
335 |
mpre = np.flip(np.maximum.accumulate(np.flip(mpre)))
|
|
|
337 |
# Integrate area under curve
|
338 |
method = 'interp' # methods: 'continuous', 'interp'
|
339 |
if method == 'interp':
|
340 |
+
x = np.linspace(0, 1, 1001) # 101-point interp (COCO)
|
341 |
ap = np.trapz(np.interp(x, mrec, mpre), x) # integrate
|
342 |
else: # 'continuous'
|
343 |
i = np.where(mrec[1:] != mrec[:-1])[0] # points where x axis (recall) changes
|
344 |
ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1]) # area under curve
|
345 |
|
346 |
+
return ap, mpre, mrec
|
347 |
|
348 |
|
349 |
def bbox_iou(box1, box2, x1y1x2y2=True, GIoU=False, DIoU=False, CIoU=False, eps=1e-9):
|
|
|
1260 |
|
1261 |
|
1262 |
def plot_results(start=0, stop=0, bucket='', id=(), labels=(), save_dir=''):
|
1263 |
+
# from utils.general import *; plot_results(save_dir='runs/exp0')
|
1264 |
# Plot training 'results*.txt' as seen in https://github.com/ultralytics/yolov5#reproduce-our-training
|
1265 |
fig, ax = plt.subplots(2, 5, figsize=(12, 6))
|
1266 |
ax = ax.ravel()
|
|
|
1274 |
os.system(c)
|
1275 |
else:
|
1276 |
files = glob.glob(str(Path(save_dir) / 'results*.txt')) + glob.glob('../../Downloads/results*.txt')
|
1277 |
+
assert len(files), 'No results.txt files found in %s, nothing to plot.' % os.path.abspath(save_dir)
|
1278 |
for fi, f in enumerate(files):
|
1279 |
try:
|
1280 |
results = np.loadtxt(f, usecols=[2, 3, 4, 8, 9, 12, 13, 14, 10, 11], ndmin=2).T
|