evaluma 0.2.0__tar.gz → 0.3.0__tar.gz

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.
Files changed (73) hide show
  1. {evaluma-0.2.0 → evaluma-0.3.0}/.github/workflows/ci.yml +1 -13
  2. {evaluma-0.2.0 → evaluma-0.3.0}/PKG-INFO +69 -9
  3. {evaluma-0.2.0 → evaluma-0.3.0}/README.md +68 -8
  4. {evaluma-0.2.0 → evaluma-0.3.0}/docs/overview.md +59 -4
  5. {evaluma-0.2.0 → evaluma-0.3.0}/docs/references.md +27 -0
  6. evaluma-0.3.0/docs/tutorials/improvability.md +313 -0
  7. {evaluma-0.2.0 → evaluma-0.3.0}/docs/tutorials/index.md +1 -0
  8. {evaluma-0.2.0 → evaluma-0.3.0}/docs/tutorials/rank_sensitivity.md +7 -5
  9. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma/__init__.py +6 -3
  10. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma/_version.py +3 -3
  11. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma/benchmark.py +203 -9
  12. evaluma-0.3.0/evaluma/methods/improvability.py +88 -0
  13. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma/methods/rank_sensitivity.py +77 -17
  14. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma/metric_registry.py +65 -0
  15. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma/plot.py +39 -4
  16. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma/results.py +39 -3
  17. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma.egg-info/PKG-INFO +69 -9
  18. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma.egg-info/SOURCES.txt +5 -0
  19. evaluma-0.3.0/evaluma.egg-info/scm_file_list.json +65 -0
  20. evaluma-0.3.0/evaluma.egg-info/scm_version.json +8 -0
  21. {evaluma-0.2.0 → evaluma-0.3.0}/tests/test_elo.py +4 -2
  22. evaluma-0.3.0/tests/test_improvability.py +281 -0
  23. evaluma-0.3.0/tests/test_metric_registry.py +129 -0
  24. {evaluma-0.2.0 → evaluma-0.3.0}/tests/test_rank_sensitivity.py +187 -1
  25. evaluma-0.2.0/tests/test_metric_registry.py +0 -63
  26. {evaluma-0.2.0 → evaluma-0.3.0}/.gitignore +0 -0
  27. {evaluma-0.2.0 → evaluma-0.3.0}/.readthedocs.yaml +0 -0
  28. {evaluma-0.2.0 → evaluma-0.3.0}/LICENSE +0 -0
  29. {evaluma-0.2.0 → evaluma-0.3.0}/Makefile +0 -0
  30. {evaluma-0.2.0 → evaluma-0.3.0}/docs/_static/logo.png +0 -0
  31. {evaluma-0.2.0 → evaluma-0.3.0}/docs/conf.py +0 -0
  32. {evaluma-0.2.0 → evaluma-0.3.0}/docs/configuration.md +0 -0
  33. {evaluma-0.2.0 → evaluma-0.3.0}/docs/contributing.md +0 -0
  34. {evaluma-0.2.0 → evaluma-0.3.0}/docs/index.md +0 -0
  35. {evaluma-0.2.0 → evaluma-0.3.0}/docs/tutorials/bayesian_comparison.md +0 -0
  36. {evaluma-0.2.0 → evaluma-0.3.0}/docs/tutorials/elo_ranking.md +0 -0
  37. {evaluma-0.2.0 → evaluma-0.3.0}/docs/tutorials/frequentist_comparison.md +0 -0
  38. {evaluma-0.2.0 → evaluma-0.3.0}/docs/tutorials/frequentist_vs_bayesian.md +0 -0
  39. {evaluma-0.2.0 → evaluma-0.3.0}/docs/tutorials/iqm_ranking.md +0 -0
  40. {evaluma-0.2.0 → evaluma-0.3.0}/docs/tutorials/performance_profiles.md +0 -0
  41. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma/cli.py +0 -0
  42. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma/methods/__init__.py +0 -0
  43. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma/methods/aggregate.py +0 -0
  44. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma/methods/bayesian.py +0 -0
  45. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma/methods/elo.py +0 -0
  46. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma/methods/frequentist.py +0 -0
  47. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma/methods/iqm.py +0 -0
  48. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma/methods/profiles.py +0 -0
  49. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma/normalize.py +0 -0
  50. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma.egg-info/dependency_links.txt +0 -0
  51. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma.egg-info/entry_points.txt +0 -0
  52. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma.egg-info/requires.txt +0 -0
  53. {evaluma-0.2.0 → evaluma-0.3.0}/evaluma.egg-info/top_level.txt +0 -0
  54. {evaluma-0.2.0 → evaluma-0.3.0}/pyproject.toml +0 -0
  55. {evaluma-0.2.0 → evaluma-0.3.0}/results_and_parameters.csv +0 -0
  56. {evaluma-0.2.0 → evaluma-0.3.0}/setup.cfg +0 -0
  57. {evaluma-0.2.0 → evaluma-0.3.0}/tests/conftest.py +0 -0
  58. {evaluma-0.2.0 → evaluma-0.3.0}/tests/fixtures/geobench_subset.csv +0 -0
  59. {evaluma-0.2.0 → evaluma-0.3.0}/tests/fixtures/score_df.csv +0 -0
  60. {evaluma-0.2.0 → evaluma-0.3.0}/tests/fixtures/score_df_lowerisbetter.csv +0 -0
  61. {evaluma-0.2.0 → evaluma-0.3.0}/tests/fixtures/score_df_missing.csv +0 -0
  62. {evaluma-0.2.0 → evaluma-0.3.0}/tests/fixtures/score_df_seeded.csv +0 -0
  63. {evaluma-0.2.0 → evaluma-0.3.0}/tests/test_aggregate.py +0 -0
  64. {evaluma-0.2.0 → evaluma-0.3.0}/tests/test_bayesian.py +0 -0
  65. {evaluma-0.2.0 → evaluma-0.3.0}/tests/test_benchmark.py +0 -0
  66. {evaluma-0.2.0 → evaluma-0.3.0}/tests/test_cli.py +0 -0
  67. {evaluma-0.2.0 → evaluma-0.3.0}/tests/test_frequentist.py +0 -0
  68. {evaluma-0.2.0 → evaluma-0.3.0}/tests/test_integration.py +0 -0
  69. {evaluma-0.2.0 → evaluma-0.3.0}/tests/test_iqm.py +0 -0
  70. {evaluma-0.2.0 → evaluma-0.3.0}/tests/test_load_df.py +0 -0
  71. {evaluma-0.2.0 → evaluma-0.3.0}/tests/test_load_metric_type_bounds.py +0 -0
  72. {evaluma-0.2.0 → evaluma-0.3.0}/tests/test_normalize.py +0 -0
  73. {evaluma-0.2.0 → evaluma-0.3.0}/tests/test_profiles.py +0 -0
@@ -34,21 +34,9 @@ jobs:
34
34
  - run: ruff format --check .
35
35
  - run: ty check
36
36
 
37
- docs:
38
- runs-on: ubuntu-latest
39
- env:
40
- IPYTHONDIR: /tmp/ipython
41
- steps:
42
- - uses: actions/checkout@v4
43
- - uses: actions/setup-python@v5
44
- with:
45
- python-version: "3.11"
46
- - run: pip install -e ".[docs]"
47
- - run: sphinx-build -W -b html docs docs/_build/html
48
-
49
37
  publish:
50
38
  if: startsWith(github.ref, 'refs/tags/v')
51
- needs: [test, lint, docs]
39
+ needs: [test, lint]
52
40
  runs-on: ubuntu-latest
53
41
  environment: pypi
54
42
  permissions:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: evaluma
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: ML benchmark ranking tools — IQM, Bayesian pairwise, and Dolan-Moré performance profiles
5
5
  Author-email: Nils Lehmann <nils.lehmann24@gmail.com>
6
6
  License: Apache 2.0
@@ -58,11 +58,16 @@ Dynamic: license-file
58
58
 
59
59
  # evaluma
60
60
 
61
- A small Python package for comparing machine learning models across benchmark suites. Given a CSV of per-model, per-dataset scores, evaluma can compute three complementary views of the results:
61
+ A small Python package for comparing machine learning models across benchmark suites. Given a CSV of per-model, per-dataset scores, evaluma computes eight complementary views of the results:
62
62
 
63
+ - **Aggregate ranking** — point-estimate ranking via trimmed mean, mean, or median
63
64
  - **IQM ranking** — interquartile mean with bootstrapped confidence intervals, following [Agarwal et al. (2021)](https://arxiv.org/abs/2108.13264)
65
+ - **ELO ranking** — MLE ELO ratings from pairwise head-to-head battles with bootstrap CIs and a win-rate matrix, following [Erickson et al. (2025)](https://arxiv.org/abs/2506.16791)
66
+ - **Improvability ranking** — mean percent error reduction each model needs to match the per-dataset best, in raw error space, following [TabArena](https://arxiv.org/abs/2506.16791) / [BeyondArena](https://arxiv.org/abs/2606.30410)
64
67
  - **Bayesian pairwise comparison** — posterior probabilities that model A beats model B (or is practically equivalent), via [baycomp](https://github.com/janezd/baycomp)
65
- - **Dolan-Moré performance profiles** — cumulative distribution of performance ratios and area-under-profile scores
68
+ - **Frequentist comparison** — Friedman + Nemenyi (all-pairs) or Wilcoxon + Holm (reference model), following [Demšar (2006)](https://jmlr.org/papers/v7/demsar06a.html)
69
+ - **Dolan-Moré performance profiles** — cumulative distribution of performance ratios and area-under-profile scores, following [Dolan & Moré (2002)](https://doi.org/10.1007/s101070100263)
70
+ - **Rank sensitivity** — Kendall τ-b with bootstrap CI measuring whether rankings hold across two experimental conditions, following [Kendall (1945)](https://doi.org/10.1093/biomet/33.3.239)
66
71
 
67
72
 
68
73
  ## Documentation
@@ -99,36 +104,62 @@ bench = evaluma.load_df(
99
104
  score="score",
100
105
  )
101
106
 
102
- # IQM ranking with 95% bootstrap CI
107
+ # Point-estimate aggregate ranking (trimmed mean)
108
+ agg = bench.aggregate_ranking()
109
+ print(agg.table)
110
+
111
+ # IQM ranking with 95% bootstrap CI (requires seed column)
103
112
  iqm = bench.iqm_ranking()
104
113
  print(iqm.table)
105
114
  fig = iqm.plot()
106
115
  fig.savefig("iqm.png")
107
116
 
117
+ # ELO ranking with win-rate matrix
118
+ elo = bench.elo_ranking()
119
+ print(elo.table)
120
+ fig = elo.plot_winrate()
121
+
122
+ # Improvability ranking (mean % error reduction needed to match the best)
123
+ imp = bench.improvability_ranking()
124
+ print(imp.table)
125
+ fig = imp.plot()
126
+
108
127
  # Bayesian pairwise probabilities
109
128
  bayes = bench.bayesian_comparison()
110
129
  print(bayes.table)
111
130
 
131
+ # Frequentist comparison (Friedman + Nemenyi)
132
+ freq = bench.frequentist_comparison()
133
+ print(freq.table)
134
+
112
135
  # Dolan-Moré performance profiles
113
136
  profiles = bench.performance_profiles()
114
137
  fig = profiles.plot()
138
+
139
+ # Rank sensitivity across two conditions
140
+ bench_b = evaluma.load_df("results_b.csv", model="model", dataset="dataset",
141
+ metric="metric", score="score")
142
+ sens = bench.rank_sensitivity(bench_b, cond_a="condA", cond_b="condB")
143
+ print(f"Kendall τ = {sens.tau:.3f}, 95% CI = {sens.tau_ci}")
115
144
  ```
116
145
 
117
146
  ### CLI
118
147
 
119
148
  ```bash
120
- # Run all three analyses and write six output files
149
+ # Run aggregate, Bayesian, frequentist, and performance-profile analyses
121
150
  evaluma report results.csv \
122
151
  --model model --dataset dataset --metric metric --score score \
123
152
  --output results/
124
153
 
125
154
  # Individual subcommands
126
- evaluma rank results.csv --model model --dataset dataset --metric metric --score score --output results/
127
- evaluma compare results.csv --model model --dataset dataset --metric metric --score score --output results/
128
- evaluma profiles results.csv --model model --dataset dataset --metric metric --score score --output results/
155
+ evaluma aggregate results.csv --model model --dataset dataset --metric metric --score score --output results/
156
+ evaluma rank results.csv --model model --dataset dataset --metric metric --score score --seed seed --output results/
157
+ evaluma compare results.csv --model model --dataset dataset --metric metric --score score --output results/
158
+ evaluma frequentist results.csv --model model --dataset dataset --metric metric --score score --output results/
159
+ evaluma profiles results.csv --model model --dataset dataset --metric metric --score score --output results/
129
160
  ```
130
161
 
131
- Each subcommand writes a `.csv` table and a `.png` figure to `--output`.
162
+ Each subcommand writes a `.csv` table and a `.png` figure to `--output`. ELO ranking and rank sensitivity are available via the Python API only.
132
163
 
133
164
  ### Column mapping
134
165
 
@@ -238,6 +269,15 @@ also cite the works of the underlying methods and frameworks used:
238
269
  year = {2021},
239
270
  }
240
271
 
272
+ @inproceedings{erickson2025tabarena,
273
+ title = {{TabArena}: A Living Benchmark for Machine Learning on Tabular Data},
274
+ author = {Erickson, Nick and Purucker, Lennart and Tschalzev, Andrej
275
+ and Holzm{\"u}ller, David and Mutalik Desai, Prabhant
276
+ and Salinas, David and Hutter, Frank},
277
+ booktitle = {Advances in Neural Information Processing Systems},
278
+ year = {2025},
279
+ }
280
+
241
281
  @article{benavoli2017time,
242
282
  title = {Time for a Change: a Tutorial for Comparing Multiple Classifiers
243
283
  Through Bayesian Analysis},
@@ -250,6 +290,15 @@ also cite the works of the underlying methods and frameworks used:
250
290
  year = {2017},
251
291
  }
252
292
 
293
+ @article{demsar2006statistical,
294
+ title = {Statistical Comparisons of Classifiers over Multiple Data Sets},
295
+ author = {Dem{\v{s}}ar, Janez},
296
+ journal = {Journal of Machine Learning Research},
297
+ volume = {7},
298
+ pages = {1--30},
299
+ year = {2006},
300
+ }
301
+
253
302
  @article{dolan2002benchmarking,
254
303
  title = {Benchmarking Optimization Software with Performance Profiles},
255
304
  author = {Dolan, Elizabeth D. and Mor{\'e}, Jorge J.},
@@ -258,4 +307,15 @@ also cite the works of the underlying methods and frameworks used:
258
307
  pages = {201--213},
259
308
  year = {2002},
260
309
  }
310
+
311
+ @article{kendall1945treatment,
312
+ title = {The Treatment of Ties in Ranking Problems},
313
+ author = {Kendall, Maurice G.},
314
+ journal = {Biometrika},
315
+ volume = {33},
316
+ number = {3},
317
+ pages = {239--251},
318
+ year = {1945},
319
+ doi = {10.1093/biomet/33.3.239},
320
+ }
261
321
  ```
@@ -13,11 +13,16 @@
13
13
 
14
14
  # evaluma
15
15
 
16
- A small Python package for comparing machine learning models across benchmark suites. Given a CSV of per-model, per-dataset scores, evaluma can compute three complementary views of the results:
16
+ A small Python package for comparing machine learning models across benchmark suites. Given a CSV of per-model, per-dataset scores, evaluma computes eight complementary views of the results:
17
17
 
18
+ - **Aggregate ranking** — point-estimate ranking via trimmed mean, mean, or median
18
19
  - **IQM ranking** — interquartile mean with bootstrapped confidence intervals, following [Agarwal et al. (2021)](https://arxiv.org/abs/2108.13264)
20
+ - **ELO ranking** — MLE ELO ratings from pairwise head-to-head battles with bootstrap CIs and a win-rate matrix, following [Erickson et al. (2025)](https://arxiv.org/abs/2506.16791)
21
+ - **Improvability ranking** — mean percent error reduction each model needs to match the per-dataset best, in raw error space, following [TabArena](https://arxiv.org/abs/2506.16791) / [BeyondArena](https://arxiv.org/abs/2606.30410)
19
22
  - **Bayesian pairwise comparison** — posterior probabilities that model A beats model B (or is practically equivalent), via [baycomp](https://github.com/janezd/baycomp)
20
- - **Dolan-Moré performance profiles** — cumulative distribution of performance ratios and area-under-profile scores
23
+ - **Frequentist comparison** — Friedman + Nemenyi (all-pairs) or Wilcoxon + Holm (reference model), following [Demšar (2006)](https://jmlr.org/papers/v7/demsar06a.html)
24
+ - **Dolan-Moré performance profiles** — cumulative distribution of performance ratios and area-under-profile scores, following [Dolan & Moré (2002)](https://doi.org/10.1007/s101070100263)
25
+ - **Rank sensitivity** — Kendall τ-b with bootstrap CI measuring whether rankings hold across two experimental conditions, following [Kendall (1945)](https://doi.org/10.1093/biomet/33.3.239)
21
26
 
22
27
 
23
28
  ## Documentation
@@ -54,36 +59,62 @@ bench = evaluma.load_df(
54
59
  score="score",
55
60
  )
56
61
 
57
- # IQM ranking with 95% bootstrap CI
62
+ # Point-estimate aggregate ranking (trimmed mean)
63
+ agg = bench.aggregate_ranking()
64
+ print(agg.table)
65
+
66
+ # IQM ranking with 95% bootstrap CI (requires seed column)
58
67
  iqm = bench.iqm_ranking()
59
68
  print(iqm.table)
60
69
  fig = iqm.plot()
61
70
  fig.savefig("iqm.png")
62
71
 
72
+ # ELO ranking with win-rate matrix
73
+ elo = bench.elo_ranking()
74
+ print(elo.table)
75
+ fig = elo.plot_winrate()
76
+
77
+ # Improvability ranking (mean % error reduction needed to match the best)
78
+ imp = bench.improvability_ranking()
79
+ print(imp.table)
80
+ fig = imp.plot()
81
+
63
82
  # Bayesian pairwise probabilities
64
83
  bayes = bench.bayesian_comparison()
65
84
  print(bayes.table)
66
85
 
86
+ # Frequentist comparison (Friedman + Nemenyi)
87
+ freq = bench.frequentist_comparison()
88
+ print(freq.table)
89
+
67
90
  # Dolan-Moré performance profiles
68
91
  profiles = bench.performance_profiles()
69
92
  fig = profiles.plot()
93
+
94
+ # Rank sensitivity across two conditions
95
+ bench_b = evaluma.load_df("results_b.csv", model="model", dataset="dataset",
96
+ metric="metric", score="score")
97
+ sens = bench.rank_sensitivity(bench_b, cond_a="condA", cond_b="condB")
98
+ print(f"Kendall τ = {sens.tau:.3f}, 95% CI = {sens.tau_ci}")
70
99
  ```
71
100
 
72
101
  ### CLI
73
102
 
74
103
  ```bash
75
- # Run all three analyses and write six output files
104
+ # Run aggregate, Bayesian, frequentist, and performance-profile analyses
76
105
  evaluma report results.csv \
77
106
  --model model --dataset dataset --metric metric --score score \
78
107
  --output results/
79
108
 
80
109
  # Individual subcommands
81
- evaluma rank results.csv --model model --dataset dataset --metric metric --score score --output results/
82
- evaluma compare results.csv --model model --dataset dataset --metric metric --score score --output results/
83
- evaluma profiles results.csv --model model --dataset dataset --metric metric --score score --output results/
110
+ evaluma aggregate results.csv --model model --dataset dataset --metric metric --score score --output results/
111
+ evaluma rank results.csv --model model --dataset dataset --metric metric --score score --seed seed --output results/
112
+ evaluma compare results.csv --model model --dataset dataset --metric metric --score score --output results/
113
+ evaluma frequentist results.csv --model model --dataset dataset --metric metric --score score --output results/
114
+ evaluma profiles results.csv --model model --dataset dataset --metric metric --score score --output results/
84
115
  ```
85
116
 
86
- Each subcommand writes a `.csv` table and a `.png` figure to `--output`.
117
+ Each subcommand writes a `.csv` table and a `.png` figure to `--output`. ELO ranking and rank sensitivity are available via the Python API only.
87
118
 
88
119
  ### Column mapping
89
120
 
@@ -193,6 +224,15 @@ also cite the works of the underlying methods and frameworks used:
193
224
  year = {2021},
194
225
  }
195
226
 
227
+ @inproceedings{erickson2025tabarena,
228
+ title = {{TabArena}: A Living Benchmark for Machine Learning on Tabular Data},
229
+ author = {Erickson, Nick and Purucker, Lennart and Tschalzev, Andrej
230
+ and Holzm{\"u}ller, David and Mutalik Desai, Prabhant
231
+ and Salinas, David and Hutter, Frank},
232
+ booktitle = {Advances in Neural Information Processing Systems},
233
+ year = {2025},
234
+ }
235
+
196
236
  @article{benavoli2017time,
197
237
  title = {Time for a Change: a Tutorial for Comparing Multiple Classifiers
198
238
  Through Bayesian Analysis},
@@ -205,6 +245,15 @@ also cite the works of the underlying methods and frameworks used:
205
245
  year = {2017},
206
246
  }
207
247
 
248
+ @article{demsar2006statistical,
249
+ title = {Statistical Comparisons of Classifiers over Multiple Data Sets},
250
+ author = {Dem{\v{s}}ar, Janez},
251
+ journal = {Journal of Machine Learning Research},
252
+ volume = {7},
253
+ pages = {1--30},
254
+ year = {2006},
255
+ }
256
+
208
257
  @article{dolan2002benchmarking,
209
258
  title = {Benchmarking Optimization Software with Performance Profiles},
210
259
  author = {Dolan, Elizabeth D. and Mor{\'e}, Jorge J.},
@@ -213,4 +262,15 @@ also cite the works of the underlying methods and frameworks used:
213
262
  pages = {201--213},
214
263
  year = {2002},
215
264
  }
265
+
266
+ @article{kendall1945treatment,
267
+ title = {The Treatment of Ties in Ranking Problems},
268
+ author = {Kendall, Maurice G.},
269
+ journal = {Biometrika},
270
+ volume = {33},
271
+ number = {3},
272
+ pages = {239--251},
273
+ year = {1945},
274
+ doi = {10.1093/biomet/33.3.239},
275
+ }
216
276
  ```
@@ -1,11 +1,14 @@
1
1
  # Overview
2
2
 
3
- Given a collection of models evaluated on multiple datasets, the question "which model is best?" is harder than it sounds. Simple averages obscure robustness, ignore statistical uncertainty, and make it difficult to compare methods across papers. However, several works in the literature and different competition benchmarks have explored various schemas to come up with informative rankings. **evaluma** is designed to be an accessible entry point to build such rankings for your benchmark evaluations providing four complementary analyses from a single input format:
3
+ Given a collection of models evaluated on multiple datasets, the question "which model is best?" is harder than it sounds. Simple averages obscure robustness, ignore statistical uncertainty, and make it difficult to compare methods across papers. However, several works in the literature and different competition benchmarks have explored various schemas to come up with informative rankings. **evaluma** is designed to be an accessible entry point to build such rankings for your benchmark evaluations providing six complementary analyses from a single input format:
4
4
 
5
5
  - **Aggregate ranking** — point-estimate ranking via trimmed mean, mean, or median
6
6
  - **IQM ranking** — robust central tendency with bootstrap confidence intervals (requires multiple seeds per model/dataset)
7
+ - **ELO ranking** — MLE ELO ratings from pairwise head-to-head battles with bootstrap CIs and a win-rate matrix
7
8
  - **Bayesian comparison** — probability that one model outperforms another
9
+ - **Frequentist comparison** — Friedman + Nemenyi (all-pairs) or Wilcoxon + Holm (reference model) significance tests
8
10
  - **Performance profiles** — cumulative distribution showing how often each model comes within a factor of the best
11
+ - **Rank sensitivity** — Kendall τ-b measuring whether rankings hold across two experimental conditions
9
12
 
10
13
  This page walks through installing the package, preparing your results CSV, and running the analyses.
11
14
 
@@ -65,7 +68,7 @@ bench = evaluma.load_csv(
65
68
  )
66
69
  ```
67
70
 
68
- The `Benchmark` object holds your data and provides four analysis methods. Each returns a result object with a `.table` (pandas DataFrame) and a `.plot()` method:
71
+ The `Benchmark` object holds your data and provides analysis methods. Each returns a result object with a `.table` (pandas DataFrame) and a `.plot()` method:
69
72
 
70
73
  ### Aggregate ranking
71
74
 
@@ -91,6 +94,19 @@ iqm.plot()
91
94
 
92
95
  The IQM discards the top and bottom 25% of per-dataset scores before averaging, making it resistant to outliers. The bootstrap CIs are stratified — seeds are resampled independently within each dataset. **Requires multiple seeds** — pass `seed="seed_column"` to `load_csv()` when loading. Use `aggregate_ranking()` for single-run data. See the [IQM Tutorial](./tutorials/iqm_ranking.md) for a more in-depth example.
93
96
 
97
+ ### ELO ranking
98
+
99
+ Compute MLE ELO ratings from pairwise head-to-head battles across datasets:
100
+
101
+ ```python
102
+ elo = bench.elo_ranking()
103
+ print(elo.table) # model, ELO, CI_low, CI_high
104
+ elo.plot() # horizontal bar chart with 95% CI
105
+ elo.plot_winrate() # M×M win-rate heatmap
106
+ ```
107
+
108
+ Each dataset contributes equally via sample weighting. Bootstrap CIs resample battles within each dataset. `tie_threshold` treats near-equal scores as draws; `calibration_model` anchors one model to ELO 1000. See the [ELO Ranking Tutorial](./tutorials/elo_ranking.md) for a more in-depth example.
109
+
94
110
  ### Bayesian pairwise comparison
95
111
 
96
112
  Compute posterior probabilities for every model pair:
@@ -103,6 +119,22 @@ bayes.plot()
103
119
 
104
120
  For each pair (A, B), the output gives `p_a_better`, `p_equiv`, and `p_b_better` — the probabilities that A is better, equivalent (within a practical equivalence region), or worse than B. See the [Bayesian Comparison](./tutorials/bayesian_comparison.md) for a more in-depth example.
105
121
 
122
+ ### Frequentist comparison
123
+
124
+ Run Friedman + Nemenyi (all-pairs) or Wilcoxon + Holm (reference model) significance tests:
125
+
126
+ ```python
127
+ # All-pairs: Friedman omnibus then Nemenyi post-hoc
128
+ freq = bench.frequentist_comparison()
129
+ print(freq.table)
130
+ freq.plot() # critical-difference diagram
131
+
132
+ # Reference mode: Wilcoxon + Holm against one baseline
133
+ freq_ref = bench.frequentist_comparison(reference="ModelA")
134
+ ```
135
+
136
+ Requires at least 5 datasets. See the [Frequentist Comparison Tutorial](./tutorials/frequentist_comparison.md) for a more in-depth example.
137
+
106
138
  ### Performance profiles
107
139
 
108
140
  Plot how often each model achieves near-best performance across datasets:
@@ -115,6 +147,24 @@ profiles.plot()
115
147
 
116
148
  The profile curve shows, for each performance ratio τ ≥ 1, the fraction of datasets where a model's score is within τ of the best. A curve that rises faster means the model is closer to best more often. See the [Performance Profile Tutorial](./tutorials/performance_profiles.md) for a more in-depth example.
117
149
 
150
+ ### Rank sensitivity
151
+
152
+ Measure whether model rankings hold when you change an experimental condition (e.g. optimizer, augmentation policy, normalization choice):
153
+
154
+ ```python
155
+ from evaluma import load_csv
156
+
157
+ # Load two conditions separately, or use condition_col to split a single DataFrame
158
+ bench_b = load_csv("results_b.csv", model="model", dataset="dataset",
159
+ metric="metric", score="score")
160
+ sens = bench.rank_sensitivity(bench_b, cond_a="condA", cond_b="condB")
161
+ print(f"Kendall τ = {sens.tau:.3f}, 95% CI = {sens.tau_ci}")
162
+ print(sens.table) # per-model delta_rank, sorted by |delta_rank|
163
+ sens.plot() # rank scatter with identity line
164
+ ```
165
+
166
+ Alternatively, pass `condition_col=` to `load_df` to get a `BenchmarkGroup` and call `.rank_sensitivity("condA", "condB")` directly. See the [Rank Sensitivity Tutorial](./tutorials/rank_sensitivity.md) for a more in-depth example.
167
+
118
168
  ## Column mapping
119
169
 
120
170
  If your CSV uses different column names, pass them explicitly:
@@ -131,7 +181,7 @@ bench = evaluma.load_csv(
131
181
 
132
182
  ## CLI quickstart
133
183
 
134
- Run all three point-estimate analyses and write CSV and PNG outputs to the current directory:
184
+ Run aggregate, Bayesian, frequentist, and performance-profile analyses, writing CSV and PNG outputs:
135
185
 
136
186
  ```bash
137
187
  evaluma report results.csv
@@ -149,10 +199,15 @@ Save outputs to a specific directory:
149
199
  evaluma report results.csv --output ./results/
150
200
  ```
151
201
 
152
- Individual subcommands are also available: `evaluma rank` (IQM with seeds), `evaluma aggregate`, `evaluma compare`, and `evaluma profiles`. The CLI supports the same column mapping with `--model`, `--dataset`, `--metric`, and `--score` flags, or via a YAML config file passed with `--config`.
202
+ Individual subcommands are also available: `evaluma aggregate`, `evaluma rank` (IQM, requires `--seed`), `evaluma compare` (Bayesian), `evaluma frequentist`, and `evaluma profiles`. The CLI supports the same column mapping with `--model`, `--dataset`, `--metric`, and `--score` flags, or via a YAML config file passed with `--config`.
203
+
204
+ ELO ranking and rank sensitivity are available via the Python API only.
153
205
 
154
206
  ## Next steps
155
207
 
156
208
  - [IQM Ranking tutorial](tutorials/iqm_ranking) — deeper dive with worked examples
209
+ - [ELO Ranking tutorial](tutorials/elo_ranking) — head-to-head battles, win-rate matrix, and calibration
157
210
  - [Bayesian Comparison tutorial](tutorials/bayesian_comparison) — interpreting posterior probabilities
211
+ - [Frequentist Comparison tutorial](tutorials/frequentist_comparison) — Friedman, Nemenyi, Wilcoxon, and CD diagrams
158
212
  - [Performance Profiles tutorial](tutorials/performance_profiles) — understanding the Dolan-Moré framework
213
+ - [Rank Sensitivity tutorial](tutorials/rank_sensitivity) — measuring ranking stability across conditions
@@ -11,6 +11,15 @@ Deep Reinforcement Learning at the Edge of the Statistical Precipice.
11
11
 
12
12
  ---
13
13
 
14
+ **ELO Ranking**
15
+
16
+ Erickson, N., Purucker, L., Tschalzev, A., Holzmüller, D., Mutalik Desai, P., Salinas, D., & Hutter, F. (2025).
17
+ TabArena: A Living Benchmark for Machine Learning on Tabular Data.
18
+ *Advances in Neural Information Processing Systems* (Datasets and Benchmarks, Spotlight).
19
+ <https://arxiv.org/abs/2506.16791>
20
+
21
+ ---
22
+
14
23
  **Bayesian Pairwise Comparison**
15
24
 
16
25
  Benavoli, A., Corani, G., Demšar, J., & Zaffalon, M. (2017).
@@ -20,6 +29,15 @@ Time for a Change: a Tutorial for Comparing Multiple Classifiers Through Bayesia
20
29
 
21
30
  ---
22
31
 
32
+ **Frequentist Comparison**
33
+
34
+ Demšar, J. (2006).
35
+ Statistical Comparisons of Classifiers over Multiple Data Sets.
36
+ *Journal of Machine Learning Research*, 7, 1–30.
37
+ <https://jmlr.org/papers/v7/demsar06a.html>
38
+
39
+ ---
40
+
23
41
  **Dolan-Moré Performance Profiles**
24
42
 
25
43
  Dolan, E. D., & Moré, J. J. (2002).
@@ -29,6 +47,15 @@ Benchmarking Optimization Software with Performance Profiles.
29
47
 
30
48
  ---
31
49
 
50
+ **Rank Sensitivity**
51
+
52
+ Kendall, M. G. (1945).
53
+ The Treatment of Ties in Ranking Problems.
54
+ *Biometrika*, 33(3), 239–251.
55
+ <https://doi.org/10.1093/biomet/33.3.239>
56
+
57
+ ---
58
+
32
59
  ## Libraries
33
60
 
34
61
  **baycomp**