-
Notifications
You must be signed in to change notification settings - Fork 0
Metrics Reference
All metric functions live in dfbench.benchmark.metrics. They are organised into three tiers:
- Per-run — operate on a single run's loss/time arrays
- Aggregation — combine per-run scalars into statistics
- Multi-run — inherently need data from all runs (diversity, top-k)
Plus time-slicing utilities used to evaluate metrics at arbitrary wall-clock cutoffs.
These take a single run's arrays and return a scalar.
Minimum loss achieved in the run. Returns inf if the loss array is empty.
Whether any loss value falls below threshold. This is a binary indicator, not a count.
The iteration index at which the loss first drops below threshold. Returns None if no success occurred. (Internal helper, typically not called directly.)
Wall-clock time of first success. Looks up the time_steps entry at the index returned by run_first_success_idx.
Area under the loss curve, computed via trapezoidal integration over wall-clock time.
Parameters:
| Parameter | Default | Description |
|---|---|---|
losses |
required | Loss values per evaluation |
time_steps |
required | Elapsed time per evaluation |
floor |
None |
Shift losses by subtracting floor, then clamp to 0. Typically set to success_loss so the AUC measures "excess loss above success" |
baseline_loss |
None |
Expected loss of a random guess. If provided with max_time, normalizes the result |
max_time |
None |
Required if baseline_loss is set |
Normalization:
When both baseline_loss and max_time are given:
where
Interpretation:
- Positive → better than random
- 0 → equal to random
- Negative → worse than random
-
inf→ perfect (zero AUC)
These combine lists of per-run scalars into summary statistics.
Mean and standard deviation using jnp.nanmean / jnp.nanstd to handle NaN values gracefully.
Global minimum across all runs. Returns inf for empty input.
Fraction of True entries. E.g., fraction of runs that achieved success.
Mean and std of non-None values. Returns (fallback, 0.0) if all values are None. Used for metrics like "time to success" where failed runs contribute None.
These inherently require data from all runs.
Mean pairwise Euclidean distance between all successful solutions, normalized to
Normalization procedure:
- Each parameter dimension is scaled to
$[0, 1]$ by bounds:$(x - \text{lb}) / (\text{ub} - \text{lb})$ - Euclidean distance is divided by
$\sqrt{n_\text{params}}$ so the maximum possible distance is 1
Returns (0.0, 0.0) if fewer than 2 successful solutions exist.
Why this metric? It measures whether independent runs converge to the same optimum or spread across multiple local minima. High diversity suggests the loss landscape has many viable solutions.
Mean nearest-neighbor distance instead of mean pairwise distance. Same normalization as above.
Why both? Overall diversity is dominated by far-apart clusters; NN diversity captures local packing density. A landscape with two tight clusters far apart will have high overall diversity but low NN diversity.
AUC statistics for the top k% runs by final minimum loss.
- Sort runs by
min_loss - Select the best
max(1, n_runs × k_fraction)runs - Return mean and std of their AUC values
Why? Average AUC is dragged down by failed runs. Top-k AUC measures how well the algorithm performs when it works.
compute_performance_profile(run_min_losses, loss_thresholds) → (thresholds, success_rates, normalized_auc)
Empirical CDF of final losses: for each threshold min_loss < τ.
Default thresholds: jnp.linspace(-1.0, 5.0, 601) — loss values on log scale for typical Differometor problems.
Returns:
| Value | Shape | Description |
|---|---|---|
thresholds |
(n_thresholds,) |
Loss threshold values |
success_rates |
(n_thresholds,) |
Fraction of runs below each threshold |
normalized_auc |
scalar | Area under the curve divided by threshold range |
Interpretation: A higher normalized_auc means the algorithm consistently achieves low losses. Similar to an ROC curve but for optimization performance.
These functions enable evaluating metrics at arbitrary wall-clock cutoffs.
Returns the last index time_steps[i] ≤ t. Returns -1 if t is before the first evaluation.
Returns history[:idx+1] where idx = get_index_at_time(time_steps, t). Returns [] if no evaluations occurred by time t.
Returns the single value history[idx] at time t, or default if no data exists.
Why three functions? Different callers need different things:
-
slice_history_at_time→ computing metrics on the prefix (AUC, min loss) -
get_value_at_time→ reading best params at a given time -
get_index_at_time→ low-level, used by the other two
For each time sample
losses_at_t = slice_history_at_time(run.loss_history, run.time_steps, t)
time_at_t = slice_history_at_time(run.time_steps, run.time_steps, t)
per_run_min_loss[r] = run_min_loss(losses_at_t)
per_run_has_success[r] = run_has_success(losses_at_t, success_loss)
per_run_first_success[r] = run_first_success_time(losses_at_t, time_at_t, success_loss)
per_run_auc[r] = run_auc(losses_at_t, time_at_t, ...)
Then aggregated:
fraction_of_success[t] = agg_fraction_true(per_run_has_success)
min_loss[t] = agg_min(per_run_min_loss)
avg_loss[t] = agg_mean_std(per_run_min_loss)
time_to_success[t] = agg_mean_std_filtered(per_run_first_success)
auc_top_1[t] = per_run_auc[best_run]
auc_top_10[t] = multi_auc_top_k(per_run_min_loss, per_run_auc)
performance_profile_auc[t] = compute_performance_profile(per_run_min_loss)[2]
Additionally, for diversity, only the parameters of successful runs at time
successful_params = [get_value_at_time(run.params, ..., t) for run if has_success]
diversity_overall[t] = multi_solution_diversity_overall(successful_params, bounds)
diversity_nn[t] = multi_solution_diversity_nn(successful_params, bounds)
Artificial Scientist Lab | Website |University of Tübingen
Department of Computer Science
| Read our Documentation | Contact: laurin.sefa@student.uni-tuebingen.de, mario.krenn@uni-tuebingen.de, soham.basu@uni-tuebingen.de
Getting Started
Core API
Benchmarking
Contributing
Reference