Overview
Evaluation metrics for classification, segmentation, detection and instance segmentation.
Modules:
-
classificationβClassification metrics of a confusion matrix: the matrix itself and the accuracy.
-
detectionβ3D box detection metrics: per-batch box matches and their average precision.
-
instance_segmentationβPoint-mask instance-segmentation metrics: per-scene instance matches and their average precision.
-
kittiβThe KITTI 3D object detection protocol: per-class AP at the official IoU thresholds.
-
nuscenesβThe nuScenes detection metrics: center-distance average precision, true-positive errors and the NDS.
-
segmentationβSemantic- and part-segmentation metrics: intersection over union of a confusion matrix, or per sample.
Functions:
-
accuracyβAccuracy of a confusion matrix.
-
confusion_matrixβCompute the confusion matrix.
-
box_average_precisionβ3D detection average precision (AP) of matched box predictions.
-
box_matchesβMatch one batch of box predictions to its ground truth, the record scored by
box_average_precision. -
instance_average_precisionβPoint-mask instance-segmentation average precision (AP) of matched instance predictions.
-
instance_matchesβReduce one scene's instance predictions to the compact match record scored by
instance_average_precision. -
kitti_average_precisionβThe KITTI 3D detection metrics: per-class AP at the official IoU thresholds, and their mean.
-
nuscenes_detection_metricsβThe nuScenes detection metrics: per-class AP, mAP, the five TP errors and the NDS.
-
intersection_over_unionβIntersection over Union (IoU, the Jaccard index) of a confusion matrix.
-
part_intersection_over_unionβPer-shape IoU averaged over the parts of the shape's category (the ShapeNetPart protocol).
-
part_mean_intersection_over_unionβMean IoU of per-shape IoUs (the ShapeNetPart instance and class mIoU).
accuracy [source] ΒΆ
accuracy(
cm: Tensor,
*,
average: Literal["micro", "macro"] = ...,
ignore_index: Union[int, Sequence[int], None] = ...,
zero_division: float = ...,
class_names: Optional[Sequence[str]] = ...,
) -> float
accuracy(
cm: Tensor,
*,
average: Literal["micro", "macro", "none"] = "micro",
ignore_index: Union[int, Sequence[int], None] = None,
zero_division: float = 0.0,
class_names: Optional[Sequence[str]] = None,
) -> Union[float, Tensor, Dict[str, float]]
Accuracy of a confusion matrix.
Confusion matrices add up, so the matrix may describe one batch or the sum of confusion_matrix over a whole split.
Parameters:
-
cm(Tensor) βConfusion matrix with true classes as rows, shape \((C, C)\) (see
confusion_matrix). -
average(Literal['micro', 'macro', 'none'], default:'micro') β"micro"returns the overall accuracy (the fraction of points on the diagonal);"macro"returns the mean class accuracy (the mean of the per-class recalls);"none"returns the per-class accuracy. -
ignore_index(Union[int, Sequence[int], None], default:None) βClass index, or indices, to ignore: points whose true class is ignored are dropped, and the ignored classes are left out of the mean. Indices outside \([0, C)\) have no effect.
-
zero_division(float, default:0.0) βAccuracy given to a class without any point (and to an empty matrix with
"micro"). -
class_names(Optional[Sequence[str]], default:None) βName of each class index; with
average="none"the per-class accuracy comes back as a{name: accuracy}dict instead of a tensor.
Returns:
-
Union[float, Tensor, Dict[str, float]]βThe accuracy as a float with
average="micro"or"macro", or the per-class accuracy, shape \((C,)\), -
Union[float, Tensor, Dict[str, float]]βwith
average="none"(a{name: accuracy}dict whenclass_namesis given).
Shape
- cm: \((C, C)\)
- output: scalar, or \((C,)\) with
average="none"
Example
>>> cm = confusion_matrix(torch.tensor([0, 1, 1, 1]), torch.tensor([0, 1, 0, 1]), num_classes=2)
>>> accuracy(cm), accuracy(cm, average="macro")
(0.75, 0.75)
>>> accuracy(cm, average="none")
tensor([0.5000, 1.0000])
>>> accuracy(cm, average="none", class_names=["wall", "floor"])
{'wall': 0.5, 'floor': 1.0}
confusion_matrix [source] ΒΆ
confusion_matrix(
preds: Tensor,
target: Tensor,
num_classes: int,
ignore_index: Union[int, Sequence[int], None] = None,
) -> Tensor
Compute the confusion matrix.
Parameters:
-
preds(Tensor) βPredicted class indices, shape \((N,)\).
-
target(Tensor) βGround truth class indices, shape \((N,)\).
-
num_classes(int) βTotal number of classes.
-
ignore_index(Union[int, Sequence[int], None], default:None) βClass index, or indices, whose points are excluded from the matrix.
Returns:
-
TensorβConfusion matrix of shape \((\text{num\_classes}, \text{num\_classes})\) where
-
Tensorβcm[i, j]is the number of points with true classi -
Tensorβpredicted as class
j.
box_average_precision [source] ΒΆ
box_average_precision(
matches: Sequence[BoxMatches],
*,
iou_threshold: Union[float, Mapping[int, float]] = ...,
average: Literal["macro"] = ...,
num_classes: Optional[int] = ...,
class_names: Optional[Sequence[str]] = ...,
interpolation: Interpolation = ...,
) -> float
box_average_precision(
matches: Sequence[BoxMatches],
*,
iou_threshold: Union[float, Mapping[int, float]] = ...,
average: Literal["none"],
num_classes: Optional[int] = ...,
class_names: None = ...,
interpolation: Interpolation = ...,
) -> Tensor
box_average_precision(
matches: Sequence[BoxMatches],
*,
iou_threshold: Union[float, Mapping[int, float]] = ...,
average: Literal["none"],
num_classes: Optional[int] = ...,
class_names: Sequence[str],
interpolation: Interpolation = ...,
) -> Dict[str, float]
box_average_precision(
matches: Sequence[BoxMatches],
*,
iou_threshold: Union[float, Mapping[int, float]] = 0.5,
average: Literal["macro", "none"] = "macro",
num_classes: Optional[int] = None,
class_names: Optional[Sequence[str]] = None,
interpolation: Interpolation = "all",
) -> Union[float, Tensor, Dict[str, float]]
3D detection average precision (AP) of matched box predictions.
Dataset- and model-agnostic: box_matches reduces any detector's packed (boxes, scores, labels, batch) output to the same record, one per batch, and the records of a whole split are scored together. Within a class, predictions claim their best ground-truth box in descending score order: the first one above the IoU threshold is a true positive, the others are false positives, and the AP is the area under the resulting precision-recall curve.
With one iou_threshold for every class, the classes that have ground truth are scored. With one per class index, exactly those classes are scored, and one without ground truth scores \(0\) (its predictions are all false positives).
Parameters:
-
matches(Sequence[BoxMatches]) βThe
box_matchesrecord of every evaluated batch. -
iou_threshold(Union[float, Mapping[int, float]], default:0.5) βIoU a match must exceed: one value for every class (e.g.
0.25), or one per class index (e.g. KITTI's{0: 0.7, 1: 0.5, 2: 0.5}). -
average(Literal['macro', 'none'], default:'macro') β"macro"returns the mean AP (mAP) over the scored classes;"none"returns the per-class AP. -
num_classes(Optional[int], default:None) βNumber of classes, i.e. the length of the
average="none"output; defaults to the number ofclass_names, else to the largest class index met plus one. -
class_names(Optional[Sequence[str]], default:None) βName of each class index; with
average="none"the per-class AP comes back as a{name: ap}dict instead of a tensor. -
interpolation(Interpolation, default:'all') βAP interpolation:
"all"integrates the full precision-recall curve;"r11"/"r40"sample the KITTI 11- / 40-point recall grids.
Returns:
-
Union[float, Tensor, Dict[str, float]]βThe mAP as a float with
average="macro"(\(0\) when no class is scored), or the per-class AP, shape -
Union[float, Tensor, Dict[str, float]]β\((C,)\) float64, with
average="none"(a{name: ap}dict whenclass_namesis given), holding NaN for -
Union[float, Tensor, Dict[str, float]]βthe classes that are not scored.
Shape
- output: scalar, or \((C,)\) with
average="none"
Example
>>> boxes = torch.tensor([[0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 0.0], [9.0, 9.0, 9.0, 1.0, 1.0, 1.0, 0.0]])
>>> labels, batch = torch.tensor([0, 1]), torch.tensor([0, 0])
>>> preds = {"boxes": boxes, "scores": torch.tensor([0.9, 0.4]), "labels": labels, "batch": batch}
>>> matches = [box_matches(preds, {"boxes": boxes[:1], "labels": labels[:1], "batch": batch[:1]})]
>>> box_average_precision(matches, iou_threshold=0.25)
1.0
>>> box_average_precision(matches, iou_threshold={0: 0.7, 1: 0.5}, average="none")
tensor([1., 0.], dtype=torch.float64)
>>> box_average_precision(matches, average="none", class_names=["Car", "Cyclist"])
{'Car': 1.0, 'Cyclist': nan}
box_matches [source] ΒΆ
box_matches(
preds: Detection3D, target: Boxes3D
) -> BoxMatches
Match one batch of box predictions to its ground truth, the record scored by box_average_precision.
Which ground-truth box a prediction overlaps most, and by how much, depends on neither the IoU threshold nor on what the other predictions matched. The oriented IoU is therefore paid here, once per batch and on the device of the inputs, and nothing box-sized outlives the call: a whole validation split accumulates as a few flat tensors per batch, so keep one record per batch in a list and score the list.
Target boxes flagged by ignore_mask (see Boxes3D) are ignore regions rather than ground truth; their labels entry names the class they excuse. Predictions flagged by their own ignore_mask are left out of the record, so they can neither match a box nor count as a false positive (the KITTI min-height rule).
Parameters:
-
preds(Detection3D) βPacked predictions (one
decodeoutput),{"boxes", "scores", "labels", "batch"}with an optionalignore_mask. -
target(Boxes3D) βPacked ground truth aligned to
preds,{"boxes", "labels", "batch"}with an optionalignore_mask.
Returns:
-
BoxMatchesβThe
BoxMatchesrecord of the batch, as CPU tensors.
Shape
- preds["boxes"]: \((P, 7)\)
- target["boxes"]: \((G, 7)\)
- output: six tensors of shape \((P',)\) or \((G',)\), the predictions and boxes left after the ignore masks
Example
>>> boxes = torch.tensor([[0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 0.0], [9.0, 9.0, 9.0, 1.0, 1.0, 1.0, 0.0]])
>>> index = torch.zeros(2, dtype=torch.long)
>>> preds = {"boxes": boxes, "scores": torch.tensor([0.9, 0.4]), "labels": index, "batch": index}
>>> match = box_matches(preds, {"boxes": boxes[:1], "labels": index[:1], "batch": index[:1]})
>>> match["pred_iou"].tolist(), match["pred_gt"].tolist()
([1.0, 0.0], [0, 0])
>>> box_average_precision([match], iou_threshold=0.5)
1.0
instance_average_precision [source] ΒΆ
instance_average_precision(
matches: Sequence[InstanceMatches],
*,
iou_threshold: Union[float, Sequence[float]] = ...,
average: Literal["macro"] = ...,
num_classes: Optional[int] = ...,
class_names: Optional[Sequence[str]] = ...,
min_points: int = ...,
) -> float
instance_average_precision(
matches: Sequence[InstanceMatches],
*,
iou_threshold: Union[float, Sequence[float]] = ...,
average: Literal["none"],
num_classes: Optional[int] = ...,
class_names: None = ...,
min_points: int = ...,
) -> Tensor
instance_average_precision(
matches: Sequence[InstanceMatches],
*,
iou_threshold: Union[float, Sequence[float]] = ...,
average: Literal["none"],
num_classes: Optional[int] = ...,
class_names: Sequence[str],
min_points: int = ...,
) -> Dict[str, float]
instance_average_precision(
matches: Sequence[InstanceMatches],
*,
iou_threshold: Union[float, Sequence[float]] = (
0.5,
0.55,
0.6,
0.65,
0.7,
0.75,
0.8,
0.85,
0.9,
),
average: Literal["macro", "none"] = "macro",
num_classes: Optional[int] = None,
class_names: Optional[Sequence[str]] = None,
min_points: int = 100,
) -> Union[float, Tensor, Dict[str, float]]
Point-mask instance-segmentation average precision (AP) of matched instance predictions.
Follows the standard indoor instance-segmentation protocol (the ScanNet benchmark): per class and IoU threshold, ground-truth instances greedily consume overlapping predicted masks above the threshold, duplicates on a matched instance count as false positives with the lower score, and an unmatched prediction whose void / small-instance point fraction exceeds the threshold is excused. The AP integrates the score-swept precision-recall curve with centered recall steps, and is averaged over the IoU thresholds: the default sweep \(0.5, 0.55, \ldots, 0.9\) is the benchmark's headline AP, iou_threshold=0.5 and 0.25 its AP50 and AP25. A class is scored when it has ground truth.
Parameters:
-
matches(Sequence[InstanceMatches]) βThe
instance_matchesrecord of every evaluated scene. -
iou_threshold(Union[float, Sequence[float]], default:(0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9)) βIoU a match must exceed, or a sequence of them to average the AP over.
-
average(Literal['macro', 'none'], default:'macro') β"macro"returns the mean AP (mAP) over the scored classes;"none"returns the per-class AP. -
num_classes(Optional[int], default:None) βNumber of instance classes, i.e. the length of the
average="none"output; defaults to the number ofclass_names, else to the largest class index met plus one. -
class_names(Optional[Sequence[str]], default:None) βName of each class index; with
average="none"the per-class AP comes back as a{name: ap}dict instead of a tensor. -
min_points(int, default:100) βMinimum point count for a prediction or ground-truth instance to be scored; smaller ground-truth instances count as ignore regions.
Returns:
-
Union[float, Tensor, Dict[str, float]]βThe mAP as a float with
average="macro"(\(0\) when no class is scored), or the per-class AP, shape -
Union[float, Tensor, Dict[str, float]]β\((C,)\) float64, with
average="none"(a{name: ap}dict whenclass_namesis given), holding NaN -
Union[float, Tensor, Dict[str, float]]βfor the classes without ground truth.
Shape
- output: scalar, or \((C,)\) with
average="none"
Example
>>> masks = torch.tensor([[True, True, True, False], [False, False, False, True]])
>>> match = instance_matches(
... masks,
... torch.tensor([0, 1]),
... torch.tensor([0.9, 0.8]),
... torch.tensor([0, 0, 0, 1]),
... torch.tensor([0, 0, 0, 1]),
... )
>>> instance_average_precision([match], min_points=1)
1.0
>>> instance_average_precision([match], iou_threshold=0.5, average="none", class_names=["chair", "table"], min_points=1)
{'chair': 1.0, 'table': 1.0}
instance_matches [source] ΒΆ
instance_matches(
pred_masks: Tensor,
pred_labels: Tensor,
pred_scores: Tensor,
gt_instance: Tensor,
gt_label: Tensor,
*,
ignore_index: int = -1,
) -> InstanceMatches
Reduce one scene's instance predictions to the compact match record scored by instance_average_precision.
Predicted masks are dense \((K, N)\) booleans: a few hundred masks over a \(\sim 50\text{k}\)-point scene is only tens of MB and intersections reduce to bincounts, while index lists would be ragged and no smaller. The returned record holds per-instance counts and pairwise intersections only, so nothing mask-sized outlives the call and a whole validation split can be accumulated scene by scene.
Ground truth instances are the unique gt_instance ids among points with a non-negative id and a valid semantic label; points whose gt_label equals ignore_index are void, and predictions overlapping them are excused accordingly during scoring. Each instance must carry a single semantic label. Intersections are recorded for same-class (prediction, instance) pairs only.
Parameters:
-
pred_masks(Tensor) βPer-instance point masks, shape \((K, N)\) bool.
-
pred_labels(Tensor) βPer-instance class indices, shape \((K,)\).
-
pred_scores(Tensor) βPer-instance confidences, shape \((K,)\).
-
gt_instance(Tensor) βPer-point ground-truth instance ids, shape \((N,)\); negative marks no instance.
-
gt_label(Tensor) βPer-point semantic labels in the instance-class space, shape \((N,)\).
-
ignore_index(int, default:-1) βSemantic label marking void points.
Returns:
-
InstanceMatchesβThe
InstanceMatchesrecord of the scene, as CPU tensors.
Example
>>> masks = torch.tensor([[True, True, True, True]])
>>> match = instance_matches(
... masks, torch.tensor([0]), torch.tensor([0.9]), torch.tensor([0, 0, 1, -1]), torch.tensor([0, 0, 0, -1])
... )
>>> match["gt_counts"].tolist(), match["pair_inter"].tolist(), match["pred_void"].tolist()
([2, 1], [2, 1], [1])
kitti_average_precision [source] ΒΆ
kitti_average_precision(
matches: Sequence[BoxMatches],
class_names: Sequence[str] = (
"Car",
"Pedestrian",
"Cyclist",
),
) -> Dict[str, float]
The KITTI 3D detection metrics: per-class AP at the official IoU thresholds, and their mean.
Each class is matched at its KITTI IoU threshold (Car at \(0.7\), Pedestrian and Cyclist at \(0.5\)), and AP interpolates precision at the 11 recall points \(0.0, 0.1, \ldots, 1.0\) of the KITTI benchmark. mAP averages the per-class APs.
Parameters:
-
matches(Sequence[BoxMatches]) βThe
box_matchesrecords of every evaluated scene, with labels indexingclass_names. -
class_names(Sequence[str], default:('Car', 'Pedestrian', 'Cyclist')) βClass name per label index, each one of
Car,PedestrianandCyclist.
Returns:
-
Dict[str, float]βAP/<class>for every class, andmAP.
Example
>>> import torch
>>> from torch_pointcloud.metrics import box_matches, kitti_average_precision
>>> zero = torch.tensor([0])
>>> boxes = torch.tensor([[0.0, 0.0, 0.0, 4.0, 2.0, 1.5, 0.0]])
>>> preds = {"boxes": boxes, "scores": torch.tensor([0.9]), "labels": zero, "batch": zero}
>>> target = {"boxes": boxes, "labels": zero, "batch": zero}
>>> metrics = kitti_average_precision([box_matches(preds, target)])
>>> sorted(metrics)
['AP/Car', 'AP/Cyclist', 'AP/Pedestrian', 'mAP']
nuscenes_detection_metrics [source] ΒΆ
nuscenes_detection_metrics(
preds: Detection3D,
target: Boxes3D,
*,
class_names: Sequence[str],
gt_num_points: Optional[Tensor] = None,
pred_attributes: Optional[Tensor] = None,
gt_attributes: Optional[Tensor] = None,
class_ranges: Optional[Mapping[str, float]] = None,
dist_thresholds: Sequence[float] = (0.5, 1.0, 2.0, 4.0),
tp_threshold: float = 2.0,
max_boxes_per_sample: int = 500,
min_recall: float = 0.1,
min_precision: float = 0.1,
) -> Dict[str, float]
The nuScenes detection metrics: per-class AP, mAP, the five TP errors and the NDS.
Follows the official protocol of the nuScenes benchmark (nuScenes: A Multimodal Dataset for Autonomous Driving). Predictions are matched per sample and class by BEV center distance: in descending score order each prediction greedily takes the closest still-unmatched ground-truth box strictly below the threshold. AP interpolates precision at 101 recall points \(0.00, 0.01, \ldots, 1.00\), drops recalls up to min_recall, subtracts min_precision, clamps at \(0\), averages and rescales by the remaining precision span; mAP averages over class_names and dist_thresholds. The TP errors ATE (BEV center distance), ASE ($1 - $ IoU of center- and yaw-aligned boxes), AOE (absolute yaw difference, modulo \(\pi\) for barrier), AVE (L2 xy-velocity difference) and AAE ($1 - $ attribute accuracy) average the cumulative-mean error curve of the tp_threshold matches from min_recall to the highest achieved recall; a class without matches scores the full error of \(1\). The officially excluded pairs (traffic_cone: AOE/AVE/AAE, barrier: AVE/AAE) are left out of the per-metric means, and \(\text{NDS} = (5 \cdot \text{mAP} + \sum_\text{tp} (1 - \min(1, \text{err}))) / 10\).
Boxes are filtered before scoring: each sample keeps its max_boxes_per_sample highest-scoring predictions, boxes farther from the sensor origin (BEV) than their class range are dropped on both sides, and ground-truth boxes with gt_num_points == 0 are removed. When velocity columns or attributes are absent (on either side), AVE / AAE fall back to the full penalty of \(1.0\) per class.
Parameters:
-
preds(Detection3D) βPredicted
boxes\((M, 7)\) of \((c_x, c_y, c_z, d_x, d_y, d_z, \theta)\), or \((M, 9)\) with \((v_x, v_y)\) velocity columns appended, with theirscores,labels(class index intoclass_names) andbatch(sample index), each \((M,)\). -
target(Boxes3D) βGround-truth
boxes\((K, 7)\) or \((K, 9)\), like the predictions, with theirlabelsandbatch, each \((K,)\). -
class_names(Sequence[str]) βClass name per label index;
barrierandtraffic_coneget their official special handling by name. -
gt_num_points(Optional[Tensor], default:None) βOptional per-box point count, shape \((K,)\); boxes with exactly \(0\) points are removed (unknown counts of \(-1\) are kept).
-
pred_attributes(Optional[Tensor], default:None) βOptional per-box attribute id, shape \((M,)\). Without it AAE is \(1.0\).
-
gt_attributes(Optional[Tensor], default:None) βOptional per-box attribute id, shape \((K,)\); a negative id marks a box without an attribute, which is skipped in the AAE mean. Without it AAE is \(1.0\).
-
class_ranges(Optional[Mapping[str, float]], default:None) βMaximum BEV evaluation range per class name; defaults to the official ranges (50 m car/truck/bus/trailer/construction_vehicle, 40 m pedestrian/motorcycle/bicycle, 30 m traffic_cone/barrier). A name missing from the mapping is not range-filtered.
-
dist_thresholds(Sequence[float], default:(0.5, 1.0, 2.0, 4.0)) βMatching thresholds in meters the AP is averaged over.
-
tp_threshold(float, default:2.0) βMatching threshold in meters of the TP-error metrics.
-
max_boxes_per_sample(int, default:500) βPer-sample cap on scored predictions (highest scores kept).
-
min_recall(float, default:0.1) βRecall up to which the AP and TP-error curves are clipped.
-
min_precision(float, default:0.1) βPrecision subtracted before the AP mean.
Returns:
-
Dict[str, float]βA flat dict with
AP/<class>(averaged overdist_thresholds),mAP,mATE,mASE,mAOE, -
Dict[str, float]βmAVE,mAAEandNDS.
Example
>>> zero = torch.tensor([0])
>>> preds = {
... "boxes": torch.tensor([[0.25, 0.0, 0.0, 4.0, 2.0, 1.5, 0.0]]),
... "scores": torch.tensor([0.9]),
... "labels": zero,
... "batch": zero,
... }
>>> target = {"boxes": torch.tensor([[0.0, 0.0, 0.0, 4.0, 2.0, 1.5, 0.0]]), "labels": zero, "batch": zero}
>>> metrics = nuscenes_detection_metrics(preds, target, class_names=["car"])
>>> f"{metrics['AP/car']:.2f} {metrics['mATE']:.2f} {metrics['NDS']:.3f}"
'1.00 0.25 0.775'
intersection_over_union [source] ΒΆ
intersection_over_union(
cm: Tensor,
*,
average: Literal["macro"] = ...,
ignore_index: Union[int, Sequence[int], None] = ...,
zero_division: float = ...,
class_names: Optional[Sequence[str]] = ...,
) -> float
intersection_over_union(
cm: Tensor,
*,
average: Literal["macro", "none"] = "macro",
ignore_index: Union[int, Sequence[int], None] = None,
zero_division: float = 0.0,
class_names: Optional[Sequence[str]] = None,
) -> Union[float, Tensor, Dict[str, float]]
Intersection over Union (IoU, the Jaccard index) of a confusion matrix.
Confusion matrices add up, so the matrix may describe one batch or the sum of confusion_matrix over a whole split. With average="macro" a class absent from the whole matrix (zero union) counts as zero_division, matching sklearn's jaccard_score(zero_division=0); toolboxes that average only over present classes report a higher value on splits missing a class, so compare published numbers accordingly.
Parameters:
-
cm(Tensor) βConfusion matrix with true classes as rows, shape \((C, C)\) (see
confusion_matrix). -
average(Literal['macro', 'none'], default:'macro') β"macro"returns the mean IoU (mIoU) over the classes;"none"returns the per-class IoU. -
ignore_index(Union[int, Sequence[int], None], default:None) βClass index, or indices, to ignore: points whose true class is ignored are dropped, and the ignored classes are left out of the mean. Indices outside \([0, C)\) have no effect.
-
zero_division(float, default:0.0) βIoU given to a class with zero union (and to the ignored classes with
average="none"). -
class_names(Optional[Sequence[str]], default:None) βName of each class index; with
average="none"the per-class IoU comes back as a{name: iou}dict instead of a tensor.
Returns:
-
Union[float, Tensor, Dict[str, float]]βThe mean IoU as a float with
average="macro", or the per-class IoU, shape \((C,)\), withaverage="none" -
Union[float, Tensor, Dict[str, float]]β(a
{name: iou}dict whenclass_namesis given).
Shape
- cm: \((C, C)\)
- output: scalar, or \((C,)\) with
average="none"
part_intersection_over_union [source] ΒΆ
part_intersection_over_union(
preds: Tensor,
target: Tensor,
part_ids: Sequence[Sequence[int]],
category: Tensor,
batch: Optional[Tensor] = None,
) -> Tensor
Per-shape IoU averaged over the parts of the shape's category (the ShapeNetPart protocol).
Each shape is scored only over the part labels its category owns (e.g. ShapeNetPart's Airplane owns parts \([0, 1, 2, 3]\)); a part absent from both the prediction and the target counts as IoU \(1\).
Parameters:
-
preds(Tensor) βPredicted part indices, shape \((N,)\).
-
target(Tensor) βGround truth part indices, shape \((N,)\).
-
part_ids(Sequence[Sequence[int]]) βPart labels owned by each category, e.g.
ShapeNetPart.seg_ids.values(). -
category(Tensor) βPer-shape category index into
part_ids, shape \((B,)\). -
batch(Optional[Tensor], default:None) βOptional per-point shape index, shape \((N,)\); when omitted, all the points belong to one shape.
Returns:
-
TensorβPer-shape IoU tensor of shape \((B,)\).
Shape
- preds, target, batch: \((N,)\)
- category: \((B,)\)
- output: \((B,)\)
part_mean_intersection_over_union [source] ΒΆ
part_mean_intersection_over_union(
ious: Tensor,
category: Tensor,
*,
average: Literal["micro", "macro"] = ...,
num_classes: Optional[int] = ...,
class_names: Optional[Sequence[str]] = ...,
) -> float
part_mean_intersection_over_union(
ious: Tensor,
category: Tensor,
*,
average: Literal["micro", "macro", "none"] = "micro",
num_classes: Optional[int] = None,
class_names: Optional[Sequence[str]] = None,
) -> Union[float, Tensor, Dict[str, float]]
Mean IoU of per-shape IoUs (the ShapeNetPart instance and class mIoU).
A shape's IoU does not depend on the other shapes of its batch, so the IoUs may come from one batch or be the part_intersection_over_union of every batch of a split, concatenated.
Parameters:
-
ious(Tensor) βPer-shape IoUs (see
part_intersection_over_union), shape \((B,)\). -
category(Tensor) βPer-shape category index, shape \((B,)\).
-
average(Literal['micro', 'macro', 'none'], default:'micro') β"micro"returns the instance mIoU (the mean over all shapes);"macro"returns the class mIoU (the mean, over the categories that have a shape, of their per-category means);"none"returns the per-category mean IoU. -
num_classes(Optional[int], default:None) βNumber of categories, i.e. the length of the
average="none"output; defaults to the number ofclass_names, else to the largest category index met plus one. -
class_names(Optional[Sequence[str]], default:None) βName of each category index; with
average="none"the per-category mean IoU comes back as a{name: iou}dict instead of a tensor.
Returns:
-
Union[float, Tensor, Dict[str, float]]βThe mIoU as a float with
average="micro"or"macro"(NaN without any shape), or the per-category mean -
Union[float, Tensor, Dict[str, float]]βIoU, shape \((C,)\), with
average="none"(a{name: iou}dict whenclass_namesis given), holding NaN -
Union[float, Tensor, Dict[str, float]]βfor the categories without any shape.
Shape
- ious: \((B,)\)
- category: \((B,)\)
- output: scalar, or \((C,)\) with
average="none"
Example
>>> ious, category = torch.tensor([1.0, 0.5, 0.0]), torch.tensor([0, 0, 1])
>>> part_mean_intersection_over_union(ious, category)
0.5
>>> part_mean_intersection_over_union(ious, category, average="macro")
0.375
>>> part_mean_intersection_over_union(ious, category, average="none", class_names=["Airplane", "Bag"])
{'Airplane': 0.75, 'Bag': 0.0}