Evaluators¶
Evaluation happens at four levels — sample, sensor, timestep, and
scenario — matching the benchmark protocol. Each evaluator is a streaming
accumulator: call update() once per batch, then compute() at the
end for the aggregated metrics. See Evaluating your model for a guided tour with
code examples.
Every evaluator identifies data by scenario_id (the filesystem path to the
scenario directory) and — below the scenario level — timestep_id (an
integer timestep number). The path must follow the on-disk layout, e.g.
.../test/anomaly/{town}/{anomaly_type}/... or
.../test/normal/{town}/...: evaluators read it both to locate label files
and to parse the anomaly type and town for per-type breakdowns.
Sample level¶
Per-pixel (camera) and per-point (LiDAR) scores. Every evaluated sample in
the split — from anomalous timesteps, anomaly-free timesteps, and normal
scenarios alike — is pooled into a single binary problem, instead of averaging
per-timestep scores over anomaly-containing timesteps. This removes the
selection bias that lets a detector score a whole class (e.g. traffic lights)
high without separating anomalous instances from normal ones. Metrics use
bounded-memory streaming histograms; compute() returns global pooled
AUROC/AUPR/AP/FPR95 plus a per-anomaly-type breakdown and a per-scenario
macro-average diagnostic.
- class carlanomaly.PixelEvaluator(sensor, num_workers=32, max_inflight=32, *, n_bins=65536, scenario_bins=4096, score_transform=None, score_range=None)[source]¶
Bases:
_SampleLevelEvaluatorSample-level metrics over per-pixel scores of one camera, pooled over the split.
Loads ground-truth masks from
{scenario_id}/anomaly-{sensor}/{timestep_id:06d}.png(any non-zero pixel is anomalous); a missing mask counts as all-negative.- Parameters:
sensor – Camera direction (
"front","left","right","rear").num_workers – Worker threads that decode masks and bin scores off the main loop.
max_inflight – Maximum timesteps queued at once; bounds retained host and GPU memory.
n_bins – Bins for the global and per-type score histograms.
scenario_bins – Bins for the per-scenario histograms; must divide
n_bins.score_transform – Strictly monotonic map applied to scores before binning; defaults to
asinh, which handles unbounded scores without tuning.score_range –
(lo, hi)covered by the histogram afterscore_transform.
- Parameters:
- update(pixel_scores, scenario_ids, timestep_ids)[source]¶
Accumulate one batch of per-pixel scores.
Scores stay on their source device (the model’s GPU); each timestep’s mask decode + GPU metric computation is handed to a worker thread. Each timestep’s score slice is cloned so the full batch tensor can be freed immediately, bounding retained GPU memory to
max_inflighttimesteps.- Parameters:
pixel_scores –
FloatTensor (B, H, W)of per-pixel anomaly scores.scenario_ids – length-B sequence of scenario path strings (see module docstring).
timestep_ids – length-B sequence of integer timestep numbers.
- Return type:
- Parameters:
- class carlanomaly.PointEvaluator(num_workers=32, max_inflight=32, *, n_bins=65536, scenario_bins=4096, score_transform=None, score_range=None)[source]¶
Bases:
_SampleLevelEvaluatorSample-level metrics over per-point LiDAR scores, pooled over the split.
Loads ground-truth labels from
{scenario_id}/anomaly-lidar/{timestep_id:06d}.feather(anomalycolumn) and handles variable-length point clouds. Constructor parameters (num_workers,max_inflight,n_bins,scenario_bins,score_transform,score_range) matchPixelEvaluator; this evaluator takes nosensorargument.- Parameters:
- update(point_scores, scenario_ids, timestep_ids)[source]¶
Accumulate one batch of per-point scores.
- Parameters:
point_scores – length-B sequence of
FloatTensor (N_i,)per-point scores.scenario_ids – length-B sequence of scenario path strings (see module docstring).
timestep_ids – length-B sequence of integer timestep numbers.
- Return type:
- Parameters:
Sensor level¶
One score per sensor reading (one sensor at one timestep), evaluated against labels that mark whether the anomaly is visible in that specific sensor.
- class carlanomaly.SensorEvaluator(sensor)[source]¶
Bases:
_PerTimestepEvaluatorSensor-level AUROC: one score per sensor reading, against sensor-specific labels.
A sensor reading (this sensor at one timestep) is positive only if the anomaly is visible in this specific sensor. Labels come from
{scenario_id}/anomaly-{sensor}/sensor.feather.- Parameters:
sensor – Any sensor name (
"front","left","right","rear","lidar").- Parameters:
sensor (str)
- max_per_scenario()¶
Reduce accumulated timestep scores to one max score per scenario.
- update(scores, scenario_ids, timestep_ids)¶
Accumulate one batch of scalar per-timestep scores.
Timestep level¶
One score per timestep, treating all synchronized sensor readings as one multimodal observation. This is where fused multi-sensor scores are evaluated.
- class carlanomaly.TimestepEvaluator[source]¶
Bases:
_PerTimestepEvaluatorTimestep-level AUROC against timestep-level labels.
The timestep label marks whether the scene is anomalous at a given timestep — all synchronized sensor readings treated as one multimodal observation, independent of any single sensor. It can fire when an anomaly is visible to one or more sensors, when the sensors disagree, or for purely semantic anomalies that no sensor localises (e.g. anomalous weather). Labels are stored on disk as
{scenario_id}/anomaly-observation.feather. Accepts fused multi-sensor scores; a scenario with 30 timesteps contributes 30 scores.- max_per_scenario()¶
Reduce accumulated timestep scores to one max score per scenario.
- update(scores, scenario_ids, timestep_ids)¶
Accumulate one batch of scalar per-timestep scores.
Scenario level¶
One score per scenario; the label is inferred from the scenario path.
- class carlanomaly.ScenarioEvaluator[source]¶
Bases:
objectScenario-level AUROC: one score per scenario.
The label is inferred from the scenario path (
/test/anomaly/is positive,/test/normal/is negative). Eachupdate()takes one scalar score for the whole scenario; how that score is produced is up to the caller and need not involve timestep-level evaluation (e.g. a max over timestep scores, or a model that scores whole scenarios directly).