Migrating from 0.31 to 0.32¶
0.32 is mostly the detection-metrics layer: one-call evaluation
(evaluate_detections, evaluate_heatmaps, evaluate_segmentation), object
tables in (match_detections), IoU sweeps, COCO 101-point AP, and one
bootstrap engine for any Statistic. The breaking changes are a higher polars
floor, a smaller to_per_image() frame, and metric values that were wrong
before and are now computed as documented. This page lists what to check
coming from 0.31; the changelog has the full list.
Requirements¶
- polars
>=1.44.2(was>=1.43.2). On 1.43.2 a cached lazy frame read under different projections returned wrong rows, which the bootstrap intervals now rely on.
Results that change¶
Multi-class matching no longer duplicates detections. BBoxMatcher and
ContourMatcher attached class_id to detections by image_id alone, so on
an image with k classes every detection appeared k times. Per-class AP,
mAP and FROC from any multi-class evaluation change, and are now correct.
Single-class results are unchanged.
All-points AP integrates the step rule. Σ (Rₖ − Rₖ₋₁)·P̂ₖ, as Pascal
VOC 2010+ and COCO do, where it used to average neighbouring precisions (a
trapezoid). The two agree when scores are distinct. When a block of equal
scores mixes TPs and FPs, AP is now lower: TP@0.9 then {TP, FP, FP}@0.5
against 2 GTs read 0.875 and is now 0.75. Heatmap-derived scores tie often.
The 11-point grid is i · 0.1 (the VOC devkit's), not i / 10. A recall
landing exactly on 0.3, 0.6 or 0.7 can compare differently.
Precision-recall metrics are weighted. precision_recall_curve,
average_precision, mean_average_precision, the *_at_threshold
functions, confusion_at_threshold and average_precision_ci_lazy now read
image_metadata.weight, as FROC and LROC already did. Unit weights give the
same values as before. ConfusionResult.precision/recall/f1 read the
weighted counts; the raw tp/fp/fn are unchanged.
Bootstrap intervals.
- Multi-class and grouped tables drew wrongly: an image positive for one class and negative for another had two draw chances per replicate, and a grouped draw brought the image's other groups' rows. Intervals for those tables change. Single-class, ungrouped intervals are unchanged.
- The resample is stratified on weight cells. A group in which one weight
cell holds a single image (a continuous weight, or a one-image group) now
reports null
ci_lower/ci_upper, keeping its point estimate, where it used to report a zero-width interval.
.contour.boundary_distances(frame=) is continuous at the frame. A
sample just inside the frame is now measured to the other side's whole
boundary. It used to be measured across the region, so annotations drawn a
pixel inside the image edge read about 30 px instead of 1 px in the reported
case. mean_*, hd and hd95 near the frame drop to their true values.
DetectionTable.to_per_image()'s top_is_tp breaks a tie for the top
score by the lowest det_idx (the matcher's ranking). It used to depend on
input order, and so did LROC's top_scoring variant.
Changed shapes¶
DetectionTable.to_per_image()returnsmax_score,top_is_tpandbest_tp_score, and no longer thedetectionslist of structs. Read those columns instead of unpacking the list.BBoxMatchertables no longer hold a null-score row for an image without predictions. The image stays inimage_metadata, so the denominators are unchanged.PrecisionRecallResult.curvegainscum_weighted_tpandcum_weighted_fp;PrecisionRecallResultgainsweighted_gts;ConfusionResultgainsweighted_tp/weighted_fp/weighted_fn.
Newly refused¶
- A sweep pooled across thresholds. A table matched at several IoU
thresholds (
iou_threshold=[...]) refuses any evaluation that would count each ground truth once per threshold. Group byiou_threshold, average over it (mean_ap()), or select one with.at_iou_threshold(t). - An instance mask with several regions (
match_detectionswith a mask geometry) now fails with apolars.exceptions.ComputeErrorraised by the plugin (.contour.single), where it used to be aValueErrorfrom a Python UDF. Catch the new type if you relied on the old one. - A repeated
image_idinmatch_detections(images=...)withweight=orgroup=fails the query. It used to repeat that image's detections and ground truth.