valor-lite 0.33.13__py3-none-any.whl → 0.33.14__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.

@@ -0,0 +1,222 @@
1
+ from collections import defaultdict
2
+
3
+ import numpy as np
4
+ from numpy.typing import NDArray
5
+ from valor_lite.classification.metric import Metric, MetricType
6
+
7
+
8
+ def unpack_precision_recall_rocauc_into_metric_lists(
9
+ results: tuple[
10
+ NDArray[np.int32],
11
+ NDArray[np.float64],
12
+ NDArray[np.float64],
13
+ NDArray[np.float64],
14
+ NDArray[np.float64],
15
+ NDArray[np.float64],
16
+ float,
17
+ ],
18
+ score_thresholds: list[float],
19
+ hardmax: bool,
20
+ label_metadata: NDArray[np.int32],
21
+ index_to_label: dict[int, str],
22
+ ) -> dict[MetricType, list[Metric]]:
23
+ (
24
+ counts,
25
+ precision,
26
+ recall,
27
+ accuracy,
28
+ f1_score,
29
+ rocauc,
30
+ mean_rocauc,
31
+ ) = results
32
+
33
+ metrics = defaultdict(list)
34
+
35
+ metrics[MetricType.ROCAUC] = [
36
+ Metric.roc_auc(
37
+ value=float(rocauc[label_idx]),
38
+ label=label,
39
+ )
40
+ for label_idx, label in index_to_label.items()
41
+ if label_metadata[label_idx, 0] > 0
42
+ ]
43
+
44
+ metrics[MetricType.mROCAUC] = [
45
+ Metric.mean_roc_auc(
46
+ value=float(mean_rocauc),
47
+ )
48
+ ]
49
+
50
+ metrics[MetricType.Accuracy] = [
51
+ Metric.accuracy(
52
+ value=float(accuracy[score_idx]),
53
+ score_threshold=score_threshold,
54
+ hardmax=hardmax,
55
+ )
56
+ for score_idx, score_threshold in enumerate(score_thresholds)
57
+ ]
58
+
59
+ for label_idx, label in index_to_label.items():
60
+ for score_idx, score_threshold in enumerate(score_thresholds):
61
+
62
+ kwargs = {
63
+ "label": label,
64
+ "hardmax": hardmax,
65
+ "score_threshold": score_threshold,
66
+ }
67
+ row = counts[:, label_idx]
68
+ metrics[MetricType.Counts].append(
69
+ Metric.counts(
70
+ tp=int(row[score_idx, 0]),
71
+ fp=int(row[score_idx, 1]),
72
+ fn=int(row[score_idx, 2]),
73
+ tn=int(row[score_idx, 3]),
74
+ **kwargs,
75
+ )
76
+ )
77
+
78
+ # if no groundtruths exists for a label, skip it.
79
+ if label_metadata[label_idx, 0] == 0:
80
+ continue
81
+
82
+ metrics[MetricType.Precision].append(
83
+ Metric.precision(
84
+ value=float(precision[score_idx, label_idx]),
85
+ **kwargs,
86
+ )
87
+ )
88
+ metrics[MetricType.Recall].append(
89
+ Metric.recall(
90
+ value=float(recall[score_idx, label_idx]),
91
+ **kwargs,
92
+ )
93
+ )
94
+ metrics[MetricType.F1].append(
95
+ Metric.f1_score(
96
+ value=float(f1_score[score_idx, label_idx]),
97
+ **kwargs,
98
+ )
99
+ )
100
+ return metrics
101
+
102
+
103
+ def _unpack_confusion_matrix_value(
104
+ confusion_matrix: NDArray[np.float64],
105
+ number_of_labels: int,
106
+ number_of_examples: int,
107
+ index_to_uid: dict[int, str],
108
+ index_to_label: dict[int, str],
109
+ ) -> dict[str, dict[str, dict[str, int | list[dict[str, str | float]]]]]:
110
+ """
111
+ Unpacks a numpy array of confusion matrix counts and examples.
112
+ """
113
+
114
+ datum_idx = lambda gt_label_idx, pd_label_idx, example_idx: int( # noqa: E731 - lambda fn
115
+ confusion_matrix[
116
+ gt_label_idx,
117
+ pd_label_idx,
118
+ example_idx * 2 + 1,
119
+ ]
120
+ )
121
+
122
+ score_idx = lambda gt_label_idx, pd_label_idx, example_idx: float( # noqa: E731 - lambda fn
123
+ confusion_matrix[
124
+ gt_label_idx,
125
+ pd_label_idx,
126
+ example_idx * 2 + 2,
127
+ ]
128
+ )
129
+
130
+ return {
131
+ index_to_label[gt_label_idx]: {
132
+ index_to_label[pd_label_idx]: {
133
+ "count": max(
134
+ int(confusion_matrix[gt_label_idx, pd_label_idx, 0]),
135
+ 0,
136
+ ),
137
+ "examples": [
138
+ {
139
+ "datum": index_to_uid[
140
+ datum_idx(gt_label_idx, pd_label_idx, example_idx)
141
+ ],
142
+ "score": score_idx(
143
+ gt_label_idx, pd_label_idx, example_idx
144
+ ),
145
+ }
146
+ for example_idx in range(number_of_examples)
147
+ if datum_idx(gt_label_idx, pd_label_idx, example_idx) >= 0
148
+ ],
149
+ }
150
+ for pd_label_idx in range(number_of_labels)
151
+ }
152
+ for gt_label_idx in range(number_of_labels)
153
+ }
154
+
155
+
156
+ def _unpack_missing_predictions_value(
157
+ missing_predictions: NDArray[np.int32],
158
+ number_of_labels: int,
159
+ number_of_examples: int,
160
+ index_to_uid: dict[int, str],
161
+ index_to_label: dict[int, str],
162
+ ) -> dict[str, dict[str, int | list[dict[str, str]]]]:
163
+ """
164
+ Unpacks a numpy array of missing prediction counts and examples.
165
+ """
166
+
167
+ datum_idx = (
168
+ lambda gt_label_idx, example_idx: int( # noqa: E731 - lambda fn
169
+ missing_predictions[
170
+ gt_label_idx,
171
+ example_idx + 1,
172
+ ]
173
+ )
174
+ )
175
+
176
+ return {
177
+ index_to_label[gt_label_idx]: {
178
+ "count": max(
179
+ int(missing_predictions[gt_label_idx, 0]),
180
+ 0,
181
+ ),
182
+ "examples": [
183
+ {"datum": index_to_uid[datum_idx(gt_label_idx, example_idx)]}
184
+ for example_idx in range(number_of_examples)
185
+ if datum_idx(gt_label_idx, example_idx) >= 0
186
+ ],
187
+ }
188
+ for gt_label_idx in range(number_of_labels)
189
+ }
190
+
191
+
192
+ def unpack_confusion_matrix_into_metric_list(
193
+ results: tuple[NDArray[np.float64], NDArray[np.int32]],
194
+ score_thresholds: list[float],
195
+ number_of_examples: int,
196
+ index_to_uid: dict[int, str],
197
+ index_to_label: dict[int, str],
198
+ ) -> list[Metric]:
199
+
200
+ (confusion_matrix, missing_predictions) = results
201
+ n_scores, n_labels, _, _ = confusion_matrix.shape
202
+ return [
203
+ Metric.confusion_matrix(
204
+ score_threshold=score_threshold,
205
+ maximum_number_of_examples=number_of_examples,
206
+ confusion_matrix=_unpack_confusion_matrix_value(
207
+ confusion_matrix=confusion_matrix[score_idx, :, :, :],
208
+ number_of_labels=n_labels,
209
+ number_of_examples=number_of_examples,
210
+ index_to_label=index_to_label,
211
+ index_to_uid=index_to_uid,
212
+ ),
213
+ missing_predictions=_unpack_missing_predictions_value(
214
+ missing_predictions=missing_predictions[score_idx, :, :],
215
+ number_of_labels=n_labels,
216
+ number_of_examples=number_of_examples,
217
+ index_to_label=index_to_label,
218
+ index_to_uid=index_to_uid,
219
+ ),
220
+ )
221
+ for score_idx, score_threshold in enumerate(score_thresholds)
222
+ ]
@@ -3,56 +3,25 @@ from .computation import (
3
3
  compute_bbox_iou,
4
4
  compute_bitmask_iou,
5
5
  compute_confusion_matrix,
6
- compute_metrics,
7
6
  compute_polygon_iou,
7
+ compute_precion_recall,
8
8
  compute_ranked_pairs,
9
9
  )
10
10
  from .manager import DataLoader, Evaluator
11
- from .metric import (
12
- AP,
13
- AR,
14
- F1,
15
- Accuracy,
16
- APAveragedOverIOUs,
17
- ARAveragedOverScores,
18
- ConfusionMatrix,
19
- Counts,
20
- MetricType,
21
- Precision,
22
- PrecisionRecallCurve,
23
- Recall,
24
- mAP,
25
- mAPAveragedOverIOUs,
26
- mAR,
27
- mARAveragedOverScores,
28
- )
11
+ from .metric import Metric, MetricType
29
12
 
30
13
  __all__ = [
31
14
  "Bitmask",
32
15
  "BoundingBox",
33
16
  "Detection",
34
17
  "Polygon",
18
+ "Metric",
35
19
  "MetricType",
36
- "Counts",
37
- "Precision",
38
- "Recall",
39
- "Accuracy",
40
- "F1",
41
- "AP",
42
- "mAP",
43
- "AR",
44
- "mAR",
45
- "APAveragedOverIOUs",
46
- "mAPAveragedOverIOUs",
47
- "ARAveragedOverScores",
48
- "mARAveragedOverScores",
49
- "PrecisionRecallCurve",
50
- "ConfusionMatrix",
51
20
  "compute_bbox_iou",
52
21
  "compute_bitmask_iou",
53
22
  "compute_polygon_iou",
54
23
  "compute_ranked_pairs",
55
- "compute_metrics",
24
+ "compute_precion_recall",
56
25
  "compute_confusion_matrix",
57
26
  "DataLoader",
58
27
  "Evaluator",
@@ -5,7 +5,7 @@ from numpy.typing import NDArray
5
5
 
6
6
  def compute_bbox_iou(data: NDArray[np.float64]) -> NDArray[np.float64]:
7
7
  """
8
- Computes intersection-over-union (IoU) for axis-aligned bounding boxes.
8
+ Computes intersection-over-union (IOU) for axis-aligned bounding boxes.
9
9
 
10
10
  Takes data with shape (N, 8):
11
11
 
@@ -20,7 +20,7 @@ def compute_bbox_iou(data: NDArray[np.float64]) -> NDArray[np.float64]:
20
20
 
21
21
  Returns data with shape (N, 1):
22
22
 
23
- Index 0 - IoU
23
+ Index 0 - IOU
24
24
 
25
25
  Parameters
26
26
  ----------
@@ -30,7 +30,7 @@ def compute_bbox_iou(data: NDArray[np.float64]) -> NDArray[np.float64]:
30
30
  Returns
31
31
  -------
32
32
  NDArray[np.float64]
33
- Computed IoU's.
33
+ Computed IOU's.
34
34
  """
35
35
  if data.size == 0:
36
36
  return np.array([], dtype=np.float64)
@@ -76,7 +76,7 @@ def compute_bbox_iou(data: NDArray[np.float64]) -> NDArray[np.float64]:
76
76
 
77
77
  def compute_bitmask_iou(data: NDArray[np.bool_]) -> NDArray[np.float64]:
78
78
  """
79
- Computes intersection-over-union (IoU) for bitmasks.
79
+ Computes intersection-over-union (IOU) for bitmasks.
80
80
 
81
81
  Takes data with shape (N, 2):
82
82
 
@@ -85,7 +85,7 @@ def compute_bitmask_iou(data: NDArray[np.bool_]) -> NDArray[np.float64]:
85
85
 
86
86
  Returns data with shape (N, 1):
87
87
 
88
- Index 0 - IoU
88
+ Index 0 - IOU
89
89
 
90
90
  Parameters
91
91
  ----------
@@ -95,7 +95,7 @@ def compute_bitmask_iou(data: NDArray[np.bool_]) -> NDArray[np.float64]:
95
95
  Returns
96
96
  -------
97
97
  NDArray[np.float64]
98
- Computed IoU's.
98
+ Computed IOU's.
99
99
  """
100
100
 
101
101
  if data.size == 0:
@@ -125,7 +125,7 @@ def compute_polygon_iou(
125
125
  data: NDArray[np.float64],
126
126
  ) -> NDArray[np.float64]:
127
127
  """
128
- Computes intersection-over-union (IoU) for shapely polygons.
128
+ Computes intersection-over-union (IOU) for shapely polygons.
129
129
 
130
130
  Takes data with shape (N, 2):
131
131
 
@@ -134,7 +134,7 @@ def compute_polygon_iou(
134
134
 
135
135
  Returns data with shape (N, 1):
136
136
 
137
- Index 0 - IoU
137
+ Index 0 - IOU
138
138
 
139
139
  Parameters
140
140
  ----------
@@ -144,7 +144,7 @@ def compute_polygon_iou(
144
144
  Returns
145
145
  -------
146
146
  NDArray[np.float64]
147
- Computed IoU's.
147
+ Computed IOU's.
148
148
  """
149
149
 
150
150
  if data.size == 0:
@@ -225,7 +225,7 @@ def compute_ranked_pairs(
225
225
  Index 0 - Datum Index
226
226
  Index 1 - GroundTruth Index
227
227
  Index 2 - Prediction Index
228
- Index 3 - IoU
228
+ Index 3 - IOU
229
229
  Index 4 - GroundTruth Label Index
230
230
  Index 5 - Prediction Label Index
231
231
  Index 6 - Score
@@ -262,7 +262,7 @@ def compute_ranked_pairs(
262
262
  return ranked_pairs[indices]
263
263
 
264
264
 
265
- def compute_metrics(
265
+ def compute_precion_recall(
266
266
  data: NDArray[np.float64],
267
267
  label_metadata: NDArray[np.int32],
268
268
  iou_thresholds: NDArray[np.float64],
@@ -292,7 +292,7 @@ def compute_metrics(
292
292
  Index 0 - Datum Index
293
293
  Index 1 - GroundTruth Index
294
294
  Index 2 - Prediction Index
295
- Index 3 - IoU
295
+ Index 3 - IOU
296
296
  Index 4 - GroundTruth Label Index
297
297
  Index 5 - Prediction Label Index
298
298
  Index 6 - Score
@@ -304,7 +304,7 @@ def compute_metrics(
304
304
  label_metadata : NDArray[np.int32]
305
305
  An array containing metadata related to labels.
306
306
  iou_thresholds : NDArray[np.float64]
307
- A 1-D array containing IoU thresholds.
307
+ A 1-D array containing IOU thresholds.
308
308
  score_thresholds : NDArray[np.float64]
309
309
  A 1-D array containing score thresholds.
310
310
 
@@ -328,7 +328,7 @@ def compute_metrics(
328
328
  n_scores = score_thresholds.shape[0]
329
329
 
330
330
  if n_ious == 0:
331
- raise ValueError("At least one IoU threshold must be passed.")
331
+ raise ValueError("At least one IOU threshold must be passed.")
332
332
  elif n_scores == 0:
333
333
  raise ValueError("At least one score threshold must be passed.")
334
334
 
@@ -532,18 +532,18 @@ def compute_metrics(
532
532
  mAR = np.zeros(n_scores, dtype=np.float64)
533
533
 
534
534
  # calculate AR and AR averaged over thresholds
535
- APAveragedOverIoUs = average_precision.mean(axis=0)
535
+ APAveragedOverIOUs = average_precision.mean(axis=0)
536
536
  ARAveragedOverScores = average_recall.mean(axis=0)
537
537
 
538
538
  # calculate mAP and mAR averaged over thresholds
539
- mAPAveragedOverIoUs = mAP.mean(axis=0)
539
+ mAPAveragedOverIOUs = mAP.mean(axis=0)
540
540
  mARAveragedOverScores = mAR.mean(axis=0)
541
541
 
542
542
  ap_results = (
543
543
  average_precision,
544
544
  mAP,
545
- APAveragedOverIoUs,
546
- mAPAveragedOverIoUs,
545
+ APAveragedOverIOUs,
546
+ mAPAveragedOverIOUs,
547
547
  )
548
548
  ar_results = (
549
549
  average_recall,
@@ -643,7 +643,7 @@ def compute_confusion_matrix(
643
643
  Index 0 - Datum Index
644
644
  Index 1 - GroundTruth Index
645
645
  Index 2 - Prediction Index
646
- Index 3 - IoU
646
+ Index 3 - IOU
647
647
  Index 4 - GroundTruth Label Index
648
648
  Index 5 - Prediction Label Index
649
649
  Index 6 - Score
@@ -655,7 +655,7 @@ def compute_confusion_matrix(
655
655
  label_metadata : NDArray[np.int32]
656
656
  An array containing metadata related to labels.
657
657
  iou_thresholds : NDArray[np.float64]
658
- A 1-D array containing IoU thresholds.
658
+ A 1-D array containing IOU thresholds.
659
659
  score_thresholds : NDArray[np.float64]
660
660
  A 1-D array containing score thresholds.
661
661
  n_examples : int