valor-lite 0.33.0__py3-none-any.whl → 0.33.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of valor-lite might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  from .annotation import Bitmask, BoundingBox, Detection
2
2
  from .computation import (
3
- compute_detailed_pr_curve,
3
+ compute_detailed_counts,
4
4
  compute_iou,
5
5
  compute_metrics,
6
6
  compute_ranked_pairs,
@@ -14,8 +14,7 @@ from .metric import (
14
14
  APAveragedOverIOUs,
15
15
  ARAveragedOverScores,
16
16
  Counts,
17
- DetailedPrecisionRecallCurve,
18
- DetailedPrecisionRecallPoint,
17
+ DetailedCounts,
19
18
  MetricType,
20
19
  Precision,
21
20
  PrecisionRecallCurve,
@@ -45,12 +44,11 @@ __all__ = [
45
44
  "ARAveragedOverScores",
46
45
  "mARAveragedOverScores",
47
46
  "PrecisionRecallCurve",
48
- "DetailedPrecisionRecallPoint",
49
- "DetailedPrecisionRecallCurve",
47
+ "DetailedCounts",
50
48
  "compute_iou",
51
49
  "compute_ranked_pairs",
52
50
  "compute_metrics",
53
- "compute_detailed_pr_curve",
51
+ "compute_detailed_counts",
54
52
  "DataLoader",
55
53
  "Evaluator",
56
54
  ]
@@ -49,7 +49,7 @@ def compute_iou(data: NDArray[np.floating]) -> NDArray[np.floating]:
49
49
 
50
50
  def _compute_ranked_pairs_for_datum(
51
51
  data: np.ndarray,
52
- label_counts: np.ndarray,
52
+ label_metadata: np.ndarray,
53
53
  ) -> np.ndarray:
54
54
  """
55
55
  Computes ranked pairs for a datum.
@@ -58,6 +58,12 @@ def _compute_ranked_pairs_for_datum(
58
58
  # remove null predictions
59
59
  data = data[data[:, 2] >= 0.0]
60
60
 
61
+ # find best fits for prediction
62
+ mask_label_match = data[:, 4] == data[:, 5]
63
+ matched_predicitons = np.unique(data[mask_label_match, 2].astype(int))
64
+ mask_unmatched_predictions = ~np.isin(data[:, 2], matched_predicitons)
65
+ data = data[mask_label_match | mask_unmatched_predictions]
66
+
61
67
  # sort by gt_id, iou, score
62
68
  indices = np.lexsort(
63
69
  (
@@ -69,7 +75,7 @@ def _compute_ranked_pairs_for_datum(
69
75
  data = data[indices]
70
76
 
71
77
  # remove ignored predictions
72
- for label_idx, count in enumerate(label_counts[:, 0]):
78
+ for label_idx, count in enumerate(label_metadata[:, 0]):
73
79
  if count > 0:
74
80
  continue
75
81
  data = data[data[:, 5] != label_idx]
@@ -85,13 +91,13 @@ def _compute_ranked_pairs_for_datum(
85
91
 
86
92
  def compute_ranked_pairs(
87
93
  data: list[NDArray[np.floating]],
88
- label_counts: NDArray[np.integer],
94
+ label_metadata: NDArray[np.integer],
89
95
  ) -> NDArray[np.floating]:
90
96
  pairs = np.concatenate(
91
97
  [
92
98
  _compute_ranked_pairs_for_datum(
93
99
  datum,
94
- label_counts=label_counts,
100
+ label_metadata=label_metadata,
95
101
  )
96
102
  for datum in data
97
103
  ],
@@ -108,7 +114,7 @@ def compute_ranked_pairs(
108
114
 
109
115
  def compute_metrics(
110
116
  data: np.ndarray,
111
- label_counts: np.ndarray,
117
+ label_metadata: np.ndarray,
112
118
  iou_thresholds: np.ndarray,
113
119
  score_thresholds: np.ndarray,
114
120
  ) -> tuple[
@@ -143,7 +149,7 @@ def compute_metrics(
143
149
  """
144
150
 
145
151
  n_rows = data.shape[0]
146
- n_labels = label_counts.shape[0]
152
+ n_labels = label_metadata.shape[0]
147
153
  n_ious = iou_thresholds.shape[0]
148
154
  n_scores = score_thresholds.shape[0]
149
155
 
@@ -153,7 +159,7 @@ def compute_metrics(
153
159
 
154
160
  pd_labels = data[:, 5].astype(int)
155
161
  unique_pd_labels = np.unique(pd_labels)
156
- gt_count = label_counts[:, 0]
162
+ gt_count = label_metadata[:, 0]
157
163
  running_total_count = np.zeros(
158
164
  (n_ious, n_rows),
159
165
  dtype=np.float64,
@@ -313,8 +319,8 @@ def compute_metrics(
313
319
  average_recall /= n_ious
314
320
 
315
321
  # calculate mAP and mAR
316
- label_key_mapping = label_counts[unique_pd_labels, 2]
317
- label_keys = np.unique(label_counts[:, 2])
322
+ label_key_mapping = label_metadata[unique_pd_labels, 2]
323
+ label_keys = np.unique(label_metadata[:, 2])
318
324
  mAP = np.ones((n_ious, label_keys.shape[0])) * -1.0
319
325
  mAR = np.ones((n_scores, label_keys.shape[0])) * -1.0
320
326
  for key in np.unique(label_key_mapping):
@@ -352,9 +358,9 @@ def compute_metrics(
352
358
  )
353
359
 
354
360
 
355
- def compute_detailed_pr_curve(
361
+ def compute_detailed_counts(
356
362
  data: np.ndarray,
357
- label_counts: np.ndarray,
363
+ label_metadata: np.ndarray,
358
364
  iou_thresholds: np.ndarray,
359
365
  score_thresholds: np.ndarray,
360
366
  n_samples: int,
@@ -368,9 +374,10 @@ def compute_detailed_pr_curve(
368
374
  3 fp - 2
369
375
  4 fn - misclassification
370
376
  5 fn - hallucination
377
+ 6 tn
371
378
  """
372
379
 
373
- n_labels = label_counts.shape[0]
380
+ n_labels = label_metadata.shape[0]
374
381
  n_ious = iou_thresholds.shape[0]
375
382
  n_scores = score_thresholds.shape[0]
376
383
  n_metrics = 5 * (n_samples + 1)
@@ -386,46 +393,97 @@ def compute_detailed_pr_curve(
386
393
  mask_gt_exists = data[:, 1] > -0.5
387
394
  mask_pd_exists = data[:, 2] > -0.5
388
395
  mask_label_match = np.isclose(data[:, 4], data[:, 5])
396
+ mask_score_nonzero = data[:, 6] > 1e-9
397
+ mask_iou_nonzero = data[:, 3] > 1e-9
389
398
 
390
399
  mask_gt_pd_exists = mask_gt_exists & mask_pd_exists
391
400
  mask_gt_pd_match = mask_gt_pd_exists & mask_label_match
392
401
  mask_gt_pd_mismatch = mask_gt_pd_exists & ~mask_label_match
393
402
 
403
+ groundtruths = data[:, [0, 1]].astype(int)
404
+ predictions = data[:, [0, 2]].astype(int)
394
405
  for iou_idx in range(n_ious):
395
- mask_iou = data[:, 3] >= iou_thresholds[iou_idx]
396
- mask_gt_pd_match_iou = mask_gt_pd_match & mask_iou
397
- mask_gt_pd_mismatch_iou = mask_gt_pd_mismatch & mask_iou
406
+ mask_iou_threshold = data[:, 3] >= iou_thresholds[iou_idx]
407
+ mask_iou = mask_iou_nonzero & mask_iou_threshold
408
+
409
+ groundtruths_with_pairs = np.unique(groundtruths[mask_iou], axis=0)
410
+ mask_groundtruths_with_passing_ious = (
411
+ groundtruths.reshape(-1, 1, 2)
412
+ == groundtruths_with_pairs.reshape(1, -1, 2)
413
+ ).all(axis=2)
414
+ mask_groundtruths_with_passing_ious = (
415
+ mask_groundtruths_with_passing_ious.any(axis=1)
416
+ )
417
+ mask_groundtruths_without_passing_ious = (
418
+ ~mask_groundtruths_with_passing_ious & mask_gt_exists
419
+ )
420
+
421
+ predictions_with_passing_ious = np.unique(
422
+ predictions[mask_iou], axis=0
423
+ )
424
+ mask_predictions_with_passing_ious = (
425
+ predictions.reshape(-1, 1, 2)
426
+ == predictions_with_passing_ious.reshape(1, -1, 2)
427
+ ).all(axis=2)
428
+ mask_predictions_with_passing_ious = (
429
+ mask_predictions_with_passing_ious.any(axis=1)
430
+ )
431
+ mask_predictions_without_passing_ious = (
432
+ ~mask_predictions_with_passing_ious & mask_pd_exists
433
+ )
434
+
398
435
  for score_idx in range(n_scores):
399
- mask_score = data[:, 6] >= score_thresholds[score_idx]
400
- mask_tp = mask_gt_pd_match_iou & mask_score
401
- mask_fp_misclf = mask_gt_pd_mismatch_iou & mask_score
402
- mask_fn_misclf = mask_gt_pd_match_iou & ~mask_score
403
- mask_halluc_missing = ~(
404
- mask_gt_pd_match_iou | (mask_gt_pd_mismatch & mask_score)
405
- )
406
- mask_fp_halluc = mask_halluc_missing & mask_pd_exists
407
- mask_fn_misprd = mask_halluc_missing & mask_gt_exists
436
+ mask_score_threshold = data[:, 6] >= score_thresholds[score_idx]
437
+ mask_score = mask_score_nonzero & mask_score_threshold
408
438
 
409
- tp_slice = data[mask_tp]
410
- fp_misclf_slice = data[mask_fp_misclf]
411
- fp_halluc_slice = data[mask_fp_halluc]
412
- fn_misclf_slice = data[mask_fn_misclf]
413
- fn_misprd_slice = data[mask_fn_misprd]
439
+ groundtruths_with_passing_score = np.unique(
440
+ groundtruths[mask_iou & mask_score], axis=0
441
+ )
442
+ mask_groundtruths_with_passing_score = (
443
+ groundtruths.reshape(-1, 1, 2)
444
+ == groundtruths_with_passing_score.reshape(1, -1, 2)
445
+ ).all(axis=2)
446
+ mask_groundtruths_with_passing_score = (
447
+ mask_groundtruths_with_passing_score.any(axis=1)
448
+ )
449
+ mask_groundtruths_without_passing_score = (
450
+ ~mask_groundtruths_with_passing_score & mask_gt_exists
451
+ )
414
452
 
415
- tp_count = np.bincount(
416
- tp_slice[:, 5].astype(int), minlength=n_labels
453
+ mask_tp = mask_score & mask_iou & mask_gt_pd_match
454
+ mask_fp_misclf = mask_score & mask_iou & mask_gt_pd_mismatch
455
+ mask_fn_misclf = mask_iou & (
456
+ (
457
+ ~mask_score
458
+ & mask_gt_pd_match
459
+ & mask_groundtruths_with_passing_score
460
+ )
461
+ | (mask_score & mask_gt_pd_mismatch)
462
+ )
463
+ mask_fp_halluc = mask_score & mask_predictions_without_passing_ious
464
+ mask_fn_misprd = (
465
+ mask_groundtruths_without_passing_ious
466
+ | mask_groundtruths_without_passing_score
417
467
  )
468
+
469
+ tp = np.unique(data[mask_tp][:, [0, 2, 5]], axis=0)
470
+ fp_misclf = np.unique(data[mask_fp_misclf][:, [0, 2, 5]], axis=0)
471
+ fp_halluc = np.unique(data[mask_fp_halluc][:, [0, 2, 5]], axis=0)
472
+ fn_misclf = np.unique(data[mask_fn_misclf][:, [0, 1, 4]], axis=0)
473
+ fn_misprd = np.unique(data[mask_fn_misprd][:, [0, 1, 4]], axis=0)
474
+
475
+ tp_count = np.bincount(tp[:, 2].astype(int), minlength=n_labels)
418
476
  fp_misclf_count = np.bincount(
419
- fp_misclf_slice[:, 5].astype(int), minlength=n_labels
477
+ fp_misclf[:, 2].astype(int), minlength=n_labels
420
478
  )
421
479
  fp_halluc_count = np.bincount(
422
- fp_halluc_slice[:, 5].astype(int), minlength=n_labels
480
+ fp_halluc[:, 2].astype(int), minlength=n_labels
423
481
  )
424
482
  fn_misclf_count = np.bincount(
425
- fn_misclf_slice[:, 4].astype(int), minlength=n_labels
483
+ fn_misclf[:, 2].astype(int), minlength=n_labels
426
484
  )
427
485
  fn_misprd_count = np.bincount(
428
- fn_misprd_slice[:, 4].astype(int), minlength=n_labels
486
+ fn_misprd[:, 2].astype(int), minlength=n_labels
429
487
  )
430
488
 
431
489
  detailed_pr_curve[iou_idx, score_idx, :, tp_idx] = tp_count
@@ -444,20 +502,20 @@ def compute_detailed_pr_curve(
444
502
 
445
503
  if n_samples > 0:
446
504
  for label_idx in range(n_labels):
447
- tp_examples = tp_slice[
448
- tp_slice[:, 5].astype(int) == label_idx
449
- ][:n_samples, 0]
450
- fp_misclf_examples = fp_misclf_slice[
451
- fp_misclf_slice[:, 5].astype(int) == label_idx
505
+ tp_examples = tp[tp[:, 2].astype(int) == label_idx][
506
+ :n_samples, 0
507
+ ]
508
+ fp_misclf_examples = fp_misclf[
509
+ fp_misclf[:, 2].astype(int) == label_idx
452
510
  ][:n_samples, 0]
453
- fp_halluc_examples = fp_halluc_slice[
454
- fp_halluc_slice[:, 5].astype(int) == label_idx
511
+ fp_halluc_examples = fp_halluc[
512
+ fp_halluc[:, 2].astype(int) == label_idx
455
513
  ][:n_samples, 0]
456
- fn_misclf_examples = fn_misclf_slice[
457
- fn_misclf_slice[:, 4].astype(int) == label_idx
514
+ fn_misclf_examples = fn_misclf[
515
+ fn_misclf[:, 2].astype(int) == label_idx
458
516
  ][:n_samples, 0]
459
- fn_misprd_examples = fn_misprd_slice[
460
- fn_misprd_slice[:, 4].astype(int) == label_idx
517
+ fn_misprd_examples = fn_misprd[
518
+ fn_misprd[:, 2].astype(int) == label_idx
461
519
  ][:n_samples, 0]
462
520
 
463
521
  detailed_pr_curve[
@@ -6,7 +6,7 @@ from numpy.typing import NDArray
6
6
  from tqdm import tqdm
7
7
  from valor_lite.detection.annotation import Detection
8
8
  from valor_lite.detection.computation import (
9
- compute_detailed_pr_curve,
9
+ compute_detailed_counts,
10
10
  compute_iou,
11
11
  compute_metrics,
12
12
  compute_ranked_pairs,
@@ -19,8 +19,7 @@ from valor_lite.detection.metric import (
19
19
  APAveragedOverIOUs,
20
20
  ARAveragedOverScores,
21
21
  Counts,
22
- DetailedPrecisionRecallCurve,
23
- DetailedPrecisionRecallPoint,
22
+ DetailedCounts,
24
23
  MetricType,
25
24
  Precision,
26
25
  PrecisionRecallCurve,
@@ -35,12 +34,12 @@ from valor_lite.detection.metric import (
35
34
  Usage
36
35
  -----
37
36
 
38
- manager = DataLoader()
39
- manager.add_data(
37
+ loader = DataLoader()
38
+ loader.add_data(
40
39
  groundtruths=groundtruths,
41
40
  predictions=predictions,
42
41
  )
43
- evaluator = manager.finalize()
42
+ evaluator = loader.finalize()
44
43
 
45
44
  metrics = evaluator.evaluate(iou_thresholds=[0.5])
46
45
 
@@ -120,7 +119,7 @@ class Evaluator:
120
119
  label_keys: list[str] | NDArray[np.int32] | None = None,
121
120
  ) -> Filter:
122
121
  """
123
- Creates a boolean mask that can be passed to an evaluation.
122
+ Creates a filter that can be passed to an evaluation.
124
123
 
125
124
  Parameters
126
125
  ----------
@@ -208,9 +207,6 @@ class Evaluator:
208
207
  return Filter(
209
208
  indices=np.where(mask_pairs)[0],
210
209
  label_metadata=label_metadata,
211
- # uids=datum_uids,
212
- # labels=labels,
213
- # label_keys=label_keys,
214
210
  )
215
211
 
216
212
  def evaluate(
@@ -255,7 +251,7 @@ class Evaluator:
255
251
  pr_curves,
256
252
  ) = compute_metrics(
257
253
  data=data,
258
- label_counts=label_metadata,
254
+ label_metadata=label_metadata,
259
255
  iou_thresholds=np.array(iou_thresholds),
260
256
  score_thresholds=np.array(score_thresholds),
261
257
  )
@@ -265,7 +261,7 @@ class Evaluator:
265
261
  metrics[MetricType.AP] = [
266
262
  AP(
267
263
  value=average_precision[iou_idx][label_idx],
268
- iou=iou_thresholds[iou_idx],
264
+ iou_threshold=iou_thresholds[iou_idx],
269
265
  label=self.index_to_label[label_idx],
270
266
  )
271
267
  for iou_idx in range(average_precision.shape[0])
@@ -276,7 +272,7 @@ class Evaluator:
276
272
  metrics[MetricType.mAP] = [
277
273
  mAP(
278
274
  value=mean_average_precision[iou_idx][label_key_idx],
279
- iou=iou_thresholds[iou_idx],
275
+ iou_threshold=iou_thresholds[iou_idx],
280
276
  label_key=self.index_to_label_key[label_key_idx],
281
277
  )
282
278
  for iou_idx in range(mean_average_precision.shape[0])
@@ -286,7 +282,7 @@ class Evaluator:
286
282
  metrics[MetricType.APAveragedOverIOUs] = [
287
283
  APAveragedOverIOUs(
288
284
  value=average_precision_average_over_ious[label_idx],
289
- ious=iou_thresholds,
285
+ iou_thresholds=iou_thresholds,
290
286
  label=self.index_to_label[label_idx],
291
287
  )
292
288
  for label_idx in range(self.n_labels)
@@ -296,7 +292,7 @@ class Evaluator:
296
292
  metrics[MetricType.mAPAveragedOverIOUs] = [
297
293
  mAPAveragedOverIOUs(
298
294
  value=mean_average_precision_average_over_ious[label_key_idx],
299
- ious=iou_thresholds,
295
+ iou_thresholds=iou_thresholds,
300
296
  label_key=self.index_to_label_key[label_key_idx],
301
297
  )
302
298
  for label_key_idx in range(
@@ -307,8 +303,8 @@ class Evaluator:
307
303
  metrics[MetricType.AR] = [
308
304
  AR(
309
305
  value=average_recall[score_idx][label_idx],
310
- ious=iou_thresholds,
311
- score=score_thresholds[score_idx],
306
+ iou_thresholds=iou_thresholds,
307
+ score_threshold=score_thresholds[score_idx],
312
308
  label=self.index_to_label[label_idx],
313
309
  )
314
310
  for score_idx in range(average_recall.shape[0])
@@ -319,8 +315,8 @@ class Evaluator:
319
315
  metrics[MetricType.mAR] = [
320
316
  mAR(
321
317
  value=mean_average_recall[score_idx][label_key_idx],
322
- ious=iou_thresholds,
323
- score=score_thresholds[score_idx],
318
+ iou_thresholds=iou_thresholds,
319
+ score_threshold=score_thresholds[score_idx],
324
320
  label_key=self.index_to_label_key[label_key_idx],
325
321
  )
326
322
  for score_idx in range(mean_average_recall.shape[0])
@@ -330,8 +326,8 @@ class Evaluator:
330
326
  metrics[MetricType.ARAveragedOverScores] = [
331
327
  ARAveragedOverScores(
332
328
  value=average_recall_averaged_over_scores[label_idx],
333
- scores=score_thresholds,
334
- ious=iou_thresholds,
329
+ score_thresholds=score_thresholds,
330
+ iou_thresholds=iou_thresholds,
335
331
  label=self.index_to_label[label_idx],
336
332
  )
337
333
  for label_idx in range(self.n_labels)
@@ -341,8 +337,8 @@ class Evaluator:
341
337
  metrics[MetricType.mARAveragedOverScores] = [
342
338
  mARAveragedOverScores(
343
339
  value=mean_average_recall_averaged_over_scores[label_key_idx],
344
- scores=score_thresholds,
345
- ious=iou_thresholds,
340
+ score_thresholds=score_thresholds,
341
+ iou_thresholds=iou_thresholds,
346
342
  label_key=self.index_to_label_key[label_key_idx],
347
343
  )
348
344
  for label_key_idx in range(
@@ -353,7 +349,7 @@ class Evaluator:
353
349
  metrics[MetricType.PrecisionRecallCurve] = [
354
350
  PrecisionRecallCurve(
355
351
  precision=list(pr_curves[iou_idx][label_idx]),
356
- iou=iou_threshold,
352
+ iou_threshold=iou_threshold,
357
353
  label=label,
358
354
  )
359
355
  for iou_idx, iou_threshold in enumerate(iou_thresholds)
@@ -361,14 +357,14 @@ class Evaluator:
361
357
  if int(label_metadata[label_idx][0]) > 0
362
358
  ]
363
359
 
364
- for iou_idx, iou_threshold in enumerate(iou_thresholds):
360
+ for label_idx, label in self.index_to_label.items():
365
361
  for score_idx, score_threshold in enumerate(score_thresholds):
366
- for label_idx, label in self.index_to_label.items():
362
+ for iou_idx, iou_threshold in enumerate(iou_thresholds):
367
363
  row = precision_recall[iou_idx][score_idx][label_idx]
368
364
  kwargs = {
369
365
  "label": label,
370
- "iou": iou_threshold,
371
- "score": score_threshold,
366
+ "iou_threshold": iou_threshold,
367
+ "score_threshold": score_threshold,
372
368
  }
373
369
  metrics[MetricType.Counts].append(
374
370
  Counts(
@@ -405,21 +401,38 @@ class Evaluator:
405
401
 
406
402
  return metrics
407
403
 
408
- def compute_detailed_pr_curve(
404
+ def compute_detailed_counts(
409
405
  self,
410
406
  iou_thresholds: list[float] = [0.5],
411
407
  score_thresholds: list[float] = [
412
408
  score / 10.0 for score in range(1, 11)
413
409
  ],
414
410
  n_samples: int = 0,
415
- ) -> list[DetailedPrecisionRecallCurve]:
411
+ ) -> list[list[DetailedCounts]]:
412
+ """
413
+ Computes detailed counting metrics.
414
+
415
+ Parameters
416
+ ----------
417
+ iou_thresholds : list[float], default=[0.5]
418
+ List of IoU thresholds to compute metrics for.
419
+ score_thresholds : list[float], default=[0.1,0.2,...,1.0]
420
+ List of confidence thresholds to compute metrics for.
421
+ n_samples : int, default=0
422
+ Number of datum samples to return per metric.
423
+
424
+ Returns
425
+ -------
426
+ list[list[DetailedCounts]]
427
+ Outer list is indexed by label, inner list is by IoU.
428
+ """
416
429
 
417
430
  if self._detailed_pairs.size == 0:
418
431
  return list()
419
432
 
420
- metrics = compute_detailed_pr_curve(
433
+ metrics = compute_detailed_counts(
421
434
  self._detailed_pairs,
422
- label_counts=self._label_metadata,
435
+ label_metadata=self._label_metadata,
423
436
  iou_thresholds=np.array(iou_thresholds),
424
437
  score_thresholds=np.array(score_thresholds),
425
438
  n_samples=n_samples,
@@ -431,71 +444,91 @@ class Evaluator:
431
444
  fn_misclf_idx = fp_halluc_idx + n_samples + 1
432
445
  fn_misprd_idx = fn_misclf_idx + n_samples + 1
433
446
 
434
- results = list()
435
- for label_idx in range(len(metrics)):
436
- n_ious, n_scores, _, _ = metrics.shape
437
- for iou_idx in range(n_ious):
438
- curve = DetailedPrecisionRecallCurve(
439
- iou=iou_thresholds[iou_idx],
440
- value=list(),
447
+ n_ious, n_scores, n_labels, _ = metrics.shape
448
+ return [
449
+ [
450
+ DetailedCounts(
451
+ iou_threshold=iou_thresholds[iou_idx],
441
452
  label=self.index_to_label[label_idx],
442
- )
443
- for score_idx in range(n_scores):
444
- curve.value.append(
445
- DetailedPrecisionRecallPoint(
446
- score=score_thresholds[score_idx],
447
- tp=metrics[iou_idx][score_idx][label_idx][tp_idx],
448
- tp_examples=[
449
- self.index_to_uid[int(datum_idx)]
450
- for datum_idx in metrics[iou_idx][score_idx][
451
- label_idx
452
- ][tp_idx + 1 : fp_misclf_idx]
453
- if int(datum_idx) >= 0
454
- ],
455
- fp_misclassification=metrics[iou_idx][score_idx][
453
+ score_thresholds=score_thresholds,
454
+ tp=metrics[iou_idx, :, label_idx, tp_idx]
455
+ .astype(int)
456
+ .tolist(),
457
+ tp_examples=[
458
+ [
459
+ self.index_to_uid[int(datum_idx)]
460
+ for datum_idx in metrics[iou_idx][score_idx][
456
461
  label_idx
457
- ][fp_misclf_idx],
458
- fp_misclassification_examples=[
459
- self.index_to_uid[int(datum_idx)]
460
- for datum_idx in metrics[iou_idx][score_idx][
461
- label_idx
462
- ][fp_misclf_idx + 1 : fp_halluc_idx]
463
- if int(datum_idx) >= 0
464
- ],
465
- fp_hallucination=metrics[iou_idx][score_idx][
462
+ ][tp_idx + 1 : fp_misclf_idx]
463
+ if int(datum_idx) >= 0
464
+ ]
465
+ for score_idx in range(n_scores)
466
+ ],
467
+ fp_misclassification=metrics[
468
+ iou_idx, :, label_idx, fp_misclf_idx
469
+ ]
470
+ .astype(int)
471
+ .tolist(),
472
+ fp_misclassification_examples=[
473
+ [
474
+ self.index_to_uid[int(datum_idx)]
475
+ for datum_idx in metrics[iou_idx][score_idx][
466
476
  label_idx
467
- ][fp_halluc_idx],
468
- fp_hallucination_examples=[
469
- self.index_to_uid[int(datum_idx)]
470
- for datum_idx in metrics[iou_idx][score_idx][
471
- label_idx
472
- ][fp_halluc_idx + 1 : fn_misclf_idx]
473
- if int(datum_idx) >= 0
474
- ],
475
- fn_misclassification=metrics[iou_idx][score_idx][
477
+ ][fp_misclf_idx + 1 : fp_halluc_idx]
478
+ if int(datum_idx) >= 0
479
+ ]
480
+ for score_idx in range(n_scores)
481
+ ],
482
+ fp_hallucination=metrics[
483
+ iou_idx, :, label_idx, fp_halluc_idx
484
+ ]
485
+ .astype(int)
486
+ .tolist(),
487
+ fp_hallucination_examples=[
488
+ [
489
+ self.index_to_uid[int(datum_idx)]
490
+ for datum_idx in metrics[iou_idx][score_idx][
476
491
  label_idx
477
- ][fn_misclf_idx],
478
- fn_misclassification_examples=[
479
- self.index_to_uid[int(datum_idx)]
480
- for datum_idx in metrics[iou_idx][score_idx][
481
- label_idx
482
- ][fn_misclf_idx + 1 : fn_misprd_idx]
483
- if int(datum_idx) >= 0
484
- ],
485
- fn_missing_prediction=metrics[iou_idx][score_idx][
492
+ ][fp_halluc_idx + 1 : fn_misclf_idx]
493
+ if int(datum_idx) >= 0
494
+ ]
495
+ for score_idx in range(n_scores)
496
+ ],
497
+ fn_misclassification=metrics[
498
+ iou_idx, :, label_idx, fn_misclf_idx
499
+ ]
500
+ .astype(int)
501
+ .tolist(),
502
+ fn_misclassification_examples=[
503
+ [
504
+ self.index_to_uid[int(datum_idx)]
505
+ for datum_idx in metrics[iou_idx][score_idx][
486
506
  label_idx
487
- ][fn_misprd_idx],
488
- fn_missing_prediction_examples=[
489
- self.index_to_uid[int(datum_idx)]
490
- for datum_idx in metrics[iou_idx][score_idx][
491
- label_idx
492
- ][fn_misprd_idx + 1 :]
493
- if int(datum_idx) >= 0
494
- ],
495
- )
496
- )
497
- results.append(curve)
498
- return results
507
+ ][fn_misclf_idx + 1 : fn_misprd_idx]
508
+ if int(datum_idx) >= 0
509
+ ]
510
+ for score_idx in range(n_scores)
511
+ ],
512
+ fn_missing_prediction=metrics[
513
+ iou_idx, :, label_idx, fn_misprd_idx
514
+ ]
515
+ .astype(int)
516
+ .tolist(),
517
+ fn_missing_prediction_examples=[
518
+ [
519
+ self.index_to_uid[int(datum_idx)]
520
+ for datum_idx in metrics[iou_idx][score_idx][
521
+ label_idx
522
+ ][fn_misprd_idx + 1 :]
523
+ if int(datum_idx) >= 0
524
+ ]
525
+ for score_idx in range(n_scores)
526
+ ],
527
+ )
528
+ for iou_idx in range(n_ious)
529
+ ]
530
+ for label_idx in range(n_labels)
531
+ ]
499
532
 
500
533
 
501
534
  class DataLoader:
@@ -839,7 +872,7 @@ class DataLoader:
839
872
 
840
873
  self._evaluator._ranked_pairs = compute_ranked_pairs(
841
874
  self.pairs,
842
- label_counts=self._evaluator._label_metadata,
875
+ label_metadata=self._evaluator._label_metadata,
843
876
  )
844
877
 
845
878
  return self._evaluator
@@ -19,7 +19,7 @@ class MetricType(str, Enum):
19
19
  ARAveragedOverScores = "ARAveragedOverScores"
20
20
  mARAveragedOverScores = "mARAveragedOverScores"
21
21
  PrecisionRecallCurve = "PrecisionRecallCurve"
22
- DetailedPrecisionRecallCurve = "DetailedPrecisionRecallCurve"
22
+ DetailedCounts = "DetailedCounts"
23
23
 
24
24
 
25
25
  @dataclass
@@ -28,8 +28,8 @@ class Counts:
28
28
  fp: int
29
29
  fn: int
30
30
  label: tuple[str, str]
31
- iou: float
32
- score: float
31
+ iou_threshold: float
32
+ score_threshold: float
33
33
 
34
34
  @property
35
35
  def metric(self) -> Metric:
@@ -41,8 +41,8 @@ class Counts:
41
41
  "fn": self.fn,
42
42
  },
43
43
  parameters={
44
- "iou": self.iou,
45
- "score": self.score,
44
+ "iou_threshold": self.iou_threshold,
45
+ "score_threshold": self.score_threshold,
46
46
  "label": {
47
47
  "key": self.label[0],
48
48
  "value": self.label[1],
@@ -58,8 +58,8 @@ class Counts:
58
58
  class ClassMetric:
59
59
  value: float
60
60
  label: tuple[str, str]
61
- iou: float
62
- score: float
61
+ iou_threshold: float
62
+ score_threshold: float
63
63
 
64
64
  @property
65
65
  def metric(self) -> Metric:
@@ -67,8 +67,8 @@ class ClassMetric:
67
67
  type=type(self).__name__,
68
68
  value=self.value,
69
69
  parameters={
70
- "iou": self.iou,
71
- "score": self.score,
70
+ "iou_threshold": self.iou_threshold,
71
+ "score_threshold": self.score_threshold,
72
72
  "label": {
73
73
  "key": self.label[0],
74
74
  "value": self.label[1],
@@ -99,7 +99,7 @@ class F1(ClassMetric):
99
99
  @dataclass
100
100
  class AP:
101
101
  value: float
102
- iou: float
102
+ iou_threshold: float
103
103
  label: tuple[str, str]
104
104
 
105
105
  @property
@@ -108,7 +108,7 @@ class AP:
108
108
  type=type(self).__name__,
109
109
  value=self.value,
110
110
  parameters={
111
- "iou": self.iou,
111
+ "iou_threshold": self.iou_threshold,
112
112
  "label": {
113
113
  "key": self.label[0],
114
114
  "value": self.label[1],
@@ -123,7 +123,7 @@ class AP:
123
123
  @dataclass
124
124
  class mAP:
125
125
  value: float
126
- iou: float
126
+ iou_threshold: float
127
127
  label_key: str
128
128
 
129
129
  @property
@@ -132,7 +132,7 @@ class mAP:
132
132
  type=type(self).__name__,
133
133
  value=self.value,
134
134
  parameters={
135
- "iou": self.iou,
135
+ "iou_threshold": self.iou_threshold,
136
136
  "label_key": self.label_key,
137
137
  },
138
138
  )
@@ -144,7 +144,7 @@ class mAP:
144
144
  @dataclass
145
145
  class APAveragedOverIOUs:
146
146
  value: float
147
- ious: list[float]
147
+ iou_thresholds: list[float]
148
148
  label: tuple[str, str]
149
149
 
150
150
  @property
@@ -153,7 +153,7 @@ class APAveragedOverIOUs:
153
153
  type=type(self).__name__,
154
154
  value=self.value,
155
155
  parameters={
156
- "ious": self.ious,
156
+ "iou_thresholds": self.iou_thresholds,
157
157
  "label": {
158
158
  "key": self.label[0],
159
159
  "value": self.label[1],
@@ -168,7 +168,7 @@ class APAveragedOverIOUs:
168
168
  @dataclass
169
169
  class mAPAveragedOverIOUs:
170
170
  value: float
171
- ious: list[float]
171
+ iou_thresholds: list[float]
172
172
  label_key: str
173
173
 
174
174
  @property
@@ -177,7 +177,7 @@ class mAPAveragedOverIOUs:
177
177
  type=type(self).__name__,
178
178
  value=self.value,
179
179
  parameters={
180
- "ious": self.ious,
180
+ "iou_thresholds": self.iou_thresholds,
181
181
  "label_key": self.label_key,
182
182
  },
183
183
  )
@@ -189,8 +189,8 @@ class mAPAveragedOverIOUs:
189
189
  @dataclass
190
190
  class AR:
191
191
  value: float
192
- score: float
193
- ious: list[float]
192
+ score_threshold: float
193
+ iou_thresholds: list[float]
194
194
  label: tuple[str, str]
195
195
 
196
196
  @property
@@ -199,8 +199,8 @@ class AR:
199
199
  type=type(self).__name__,
200
200
  value=self.value,
201
201
  parameters={
202
- "score": self.score,
203
- "ious": self.ious,
202
+ "score_threshold": self.score_threshold,
203
+ "iou_thresholds": self.iou_thresholds,
204
204
  "label": {
205
205
  "key": self.label[0],
206
206
  "value": self.label[1],
@@ -215,8 +215,8 @@ class AR:
215
215
  @dataclass
216
216
  class mAR:
217
217
  value: float
218
- score: float
219
- ious: list[float]
218
+ score_threshold: float
219
+ iou_thresholds: list[float]
220
220
  label_key: str
221
221
 
222
222
  @property
@@ -225,8 +225,8 @@ class mAR:
225
225
  type=type(self).__name__,
226
226
  value=self.value,
227
227
  parameters={
228
- "score": self.score,
229
- "ious": self.ious,
228
+ "score_threshold": self.score_threshold,
229
+ "iou_thresholds": self.iou_thresholds,
230
230
  "label_key": self.label_key,
231
231
  },
232
232
  )
@@ -238,8 +238,8 @@ class mAR:
238
238
  @dataclass
239
239
  class ARAveragedOverScores:
240
240
  value: float
241
- scores: list[float]
242
- ious: list[float]
241
+ score_thresholds: list[float]
242
+ iou_thresholds: list[float]
243
243
  label: tuple[str, str]
244
244
 
245
245
  @property
@@ -248,8 +248,8 @@ class ARAveragedOverScores:
248
248
  type=type(self).__name__,
249
249
  value=self.value,
250
250
  parameters={
251
- "scores": self.scores,
252
- "ious": self.ious,
251
+ "score_thresholds": self.score_thresholds,
252
+ "iou_thresholds": self.iou_thresholds,
253
253
  "label": {
254
254
  "key": self.label[0],
255
255
  "value": self.label[1],
@@ -264,8 +264,8 @@ class ARAveragedOverScores:
264
264
  @dataclass
265
265
  class mARAveragedOverScores:
266
266
  value: float
267
- scores: list[float]
268
- ious: list[float]
267
+ score_thresholds: list[float]
268
+ iou_thresholds: list[float]
269
269
  label_key: str
270
270
 
271
271
  @property
@@ -274,8 +274,8 @@ class mARAveragedOverScores:
274
274
  type=type(self).__name__,
275
275
  value=self.value,
276
276
  parameters={
277
- "scores": self.scores,
278
- "ious": self.ious,
277
+ "score_thresholds": self.score_thresholds,
278
+ "iou_thresholds": self.iou_thresholds,
279
279
  "label_key": self.label_key,
280
280
  },
281
281
  )
@@ -291,7 +291,7 @@ class PrecisionRecallCurve:
291
291
  """
292
292
 
293
293
  precision: list[float]
294
- iou: float
294
+ iou_threshold: float
295
295
  label: tuple[str, str]
296
296
 
297
297
  @property
@@ -300,7 +300,7 @@ class PrecisionRecallCurve:
300
300
  type=type(self).__name__,
301
301
  value=self.precision,
302
302
  parameters={
303
- "iou": self.iou,
303
+ "iou_threshold": self.iou_threshold,
304
304
  "label": {"key": self.label[0], "value": self.label[1]},
305
305
  },
306
306
  )
@@ -310,48 +310,48 @@ class PrecisionRecallCurve:
310
310
 
311
311
 
312
312
  @dataclass
313
- class DetailedPrecisionRecallPoint:
314
- score: float
315
- tp: int
316
- fp_misclassification: int
317
- fp_hallucination: int
318
- fn_misclassification: int
319
- fn_missing_prediction: int
320
- tp_examples: list[str]
321
- fp_misclassification_examples: list[str]
322
- fp_hallucination_examples: list[str]
323
- fn_misclassification_examples: list[str]
324
- fn_missing_prediction_examples: list[str]
325
-
326
- def to_dict(self) -> dict:
327
- return {
328
- "score": self.score,
329
- "tp": self.tp,
330
- "fp_misclassification": self.fp_misclassification,
331
- "fp_hallucination": self.fp_hallucination,
332
- "fn_misclassification": self.fn_misclassification,
333
- "fn_missing_prediction": self.fn_missing_prediction,
334
- "tp_examples": self.tp_examples,
335
- "fp_misclassification_examples": self.fp_misclassification_examples,
336
- "fp_hallucination_examples": self.fp_hallucination_examples,
337
- "fn_misclassification_examples": self.fn_misclassification_examples,
338
- "fn_missing_prediction_examples": self.fn_missing_prediction_examples,
339
- }
340
-
341
-
342
- @dataclass
343
- class DetailedPrecisionRecallCurve:
344
- iou: float
345
- value: list[DetailedPrecisionRecallPoint]
313
+ class DetailedCounts:
314
+ tp: list[int]
315
+ fp_misclassification: list[int]
316
+ fp_hallucination: list[int]
317
+ fn_misclassification: list[int]
318
+ fn_missing_prediction: list[int]
319
+ tp_examples: list[list[str]]
320
+ fp_misclassification_examples: list[list[str]]
321
+ fp_hallucination_examples: list[list[str]]
322
+ fn_misclassification_examples: list[list[str]]
323
+ fn_missing_prediction_examples: list[list[str]]
324
+ score_thresholds: list[float]
325
+ iou_threshold: float
346
326
  label: tuple[str, str]
347
327
 
348
- def to_dict(self) -> dict:
349
- return {
350
- "value": [pt.to_dict() for pt in self.value],
351
- "iou": self.iou,
352
- "label": {
353
- "key": self.label[0],
354
- "value": self.label[1],
328
+ @property
329
+ def metric(self) -> Metric:
330
+ return Metric(
331
+ type=type(self).__name__,
332
+ value={
333
+ "tp": self.tp,
334
+ "fp_misclassification": self.fp_misclassification,
335
+ "fp_hallucination": self.fp_hallucination,
336
+ "fn_misclassification": self.fn_misclassification,
337
+ "fn_missing_prediction": self.fn_missing_prediction,
338
+ "tn": None,
339
+ "tp_examples": self.tp_examples,
340
+ "fp_misclassification_examples": self.fp_misclassification_examples,
341
+ "fp_hallucination_examples": self.fp_hallucination_examples,
342
+ "fn_misclassification_examples": self.fn_misclassification_examples,
343
+ "fn_missing_prediction_examples": self.fn_missing_prediction_examples,
344
+ "tn_examples": None,
355
345
  },
356
- "type": "DetailedPrecisionRecallCurve",
357
- }
346
+ parameters={
347
+ "score_thresholds": self.score_thresholds,
348
+ "iou_threshold": self.iou_threshold,
349
+ "label": {
350
+ "key": self.label[0],
351
+ "value": self.label[1],
352
+ },
353
+ },
354
+ )
355
+
356
+ def to_dict(self) -> dict:
357
+ return self.metric.to_dict()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: valor-lite
3
- Version: 0.33.0
3
+ Version: 0.33.1
4
4
  Summary: Compute valor metrics directly in your client.
5
5
  License: MIT License
6
6
 
@@ -0,0 +1,12 @@
1
+ valor_lite/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ valor_lite/schemas.py,sha256=r4cC10w1xYsA785KmGE4ePeOX3wzEs846vT7QAiVg_I,293
3
+ valor_lite/detection/__init__.py,sha256=WHLHwHoKzXTBjkjC6E1_lhqB7gRWkiGWVWPqkKn-yK8,997
4
+ valor_lite/detection/annotation.py,sha256=ON9iVa33pxysUmZVTCb0wNz-eFX6MDOqDhGDz-ouymc,1466
5
+ valor_lite/detection/computation.py,sha256=2FnVw6_dcAOvwCqpU9bIkeD7gPqDzfW48WSARnvKeOg,18873
6
+ valor_lite/detection/manager.py,sha256=HyODoIkmj92Kfspnpojp1pUY7noAw3FuCgQ36r6vMa4,32356
7
+ valor_lite/detection/metric.py,sha256=hHqClS7c71ztoUnfoaW3T7RmGYaVNU1SlM6vUs1P08I,8809
8
+ valor_lite-0.33.1.dist-info/LICENSE,sha256=M0L53VuwfEEqezhHb7NPeYcO_glw7-k4DMLZQ3eRN64,1068
9
+ valor_lite-0.33.1.dist-info/METADATA,sha256=W36vWkCaas8e0H5RqfGwwlh5FritdeNO7bBj8r-lf6s,1842
10
+ valor_lite-0.33.1.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
11
+ valor_lite-0.33.1.dist-info/top_level.txt,sha256=9ujykxSwpl2Hu0_R95UQTR_l07k9UUTSdrpiqmq6zc4,11
12
+ valor_lite-0.33.1.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- valor_lite/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- valor_lite/schemas.py,sha256=r4cC10w1xYsA785KmGE4ePeOX3wzEs846vT7QAiVg_I,293
3
- valor_lite/detection/__init__.py,sha256=vkV907Sjx09tgOHpDaLyR_-aFGfu2c1Kpb7hg220vBY,1099
4
- valor_lite/detection/annotation.py,sha256=ON9iVa33pxysUmZVTCb0wNz-eFX6MDOqDhGDz-ouymc,1466
5
- valor_lite/detection/computation.py,sha256=VIYZUeBd3KpwCPDBQCKCa0cY0hVb4mq_yGtY2ZP9gGE,16512
6
- valor_lite/detection/manager.py,sha256=i-C72aQfuakeYFWsERQX-KoOGdGsDMrKMVQsqN82TnY,31527
7
- valor_lite/detection/metric.py,sha256=wn9JAZMNbUIXUvH2C79jNKJswca1QEyXrCfs7isi1hU,8144
8
- valor_lite-0.33.0.dist-info/LICENSE,sha256=M0L53VuwfEEqezhHb7NPeYcO_glw7-k4DMLZQ3eRN64,1068
9
- valor_lite-0.33.0.dist-info/METADATA,sha256=1JyXg3OdEhmSTMWnzQqm2FBOlrpmex3TuizlnkLvdeE,1842
10
- valor_lite-0.33.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
11
- valor_lite-0.33.0.dist-info/top_level.txt,sha256=9ujykxSwpl2Hu0_R95UQTR_l07k9UUTSdrpiqmq6zc4,11
12
- valor_lite-0.33.0.dist-info/RECORD,,