glenn-jocher commited on
Commit
ed85038
·
unverified ·
1 Parent(s): 7fe4a6b

Precision-Recall Curve feature update (#1206)

Browse files

* Precision-Recall Curve feature update

* sentinel value update

Files changed (1) hide show
  1. 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, [min(recall[-1] + 1E-3, 1.)]))
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, 101) # 101-point interp (COCO)
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