ranklens.metrics¶
ranklens.metrics
¶
Ranking metrics, the registry of built-in metrics and evaluation of a run.
What has which shape, and why there is no base class to inherit:
- a metric is any callable
(ranked, judgements, k) -> float(ranklens.core.Metric, a Protocol). A plain function is a metric; - metrics with parameters are frozen dataclasses (
NDCG,AP,RR,ERR,RBP): the parameters are then visible, comparable and validated once, at construction; dcg,gain_functionand friends inbaseare functions: they are pieces of formulas, not metrics, and are not registered;rbois a function as well — it compares two rankings, not a ranking with judgements.
ERR
dataclass
¶
ERR@k = sum over ranks r <= k of (1/r) * R_r * prod_{i<r} (1 - R_i).
R = (2rel - 1) / 2max_rel is the probability that the user is satisfied by
the document and stops (Chapelle et al., 2009). max_rel is the top grade of the
relevance scale, not of the query; the default 4 is that of TREC gdeval.
Relevance above max_rel counts as max_rel, non-positive as 0.
Source code in src/ranklens/metrics/err_rbp.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | |
RBP
dataclass
¶
RBP@k = (1 - p) * sum over ranks r <= k of rel_r * p**(r - 1).
The user moves to the next document with probability p (Moffat & Zobel, 2008);
p = 0.8 by default, 0.5 is impatient, 0.95 patient. Relevance is binary (rel >= 1)
unless max_rel is given: then it is graded as min(rel, max_rel) / max_rel,
which keeps RBP within [0, 1]. RBP@k is the lower bound: the unseen tail is ignored.
Source code in src/ranklens/metrics/err_rbp.py
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | |
Judged
dataclass
¶
Share of the top k documents that have a judgement (of any grade, 0 included).
The denominator is the number of documents actually in the top k — a ranking
shorter than k is not penalized for documents it did not return. An empty
ranking gives 0.
Source code in src/ranklens/metrics/judged.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | |
AP
dataclass
¶
AP@k = (sum of P@i over relevant documents at ranks i <= k) / R.
A document is relevant when its relevance is >= rel. R counts all relevant
judged documents of the query, as trec_eval does, so AP@k < 1 whenever R > k.
The mean over queries is MAP. No relevant documents: 0.
Source code in src/ranklens/metrics/map_mrr.py
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | |
RR
dataclass
¶
RR@k = 1 / rank of the first relevant document within k, else 0.
A document is relevant when its relevance is >= rel. The mean over queries is MRR.
Source code in src/ranklens/metrics/map_mrr.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | |
NDCG
dataclass
¶
NDCG@k = DCG@k / IDCG@k.
IDCG is the DCG of the ideal order of all judged documents of the query,
not only the retrieved ones, cut at k. No relevant documents: 0 (as trec_eval).
gain="linear" matches trec_eval; gain="exp" matches LTR libraries.
Source code in src/ranklens/metrics/ndcg.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
resolve
¶
resolve(spec: str | MetricSpec) -> BoundMetric
Resolve a spec such as ndcg@10 against the built-in metrics.
Source code in src/ranklens/metrics/builtin.py
22 23 24 | |
evaluate
¶
evaluate(
runs: Iterable[RankedList],
qrels: Qrels,
metrics: Sequence[str | BoundMetric],
*,
registry: Registry = builtin_registry,
strict: bool = False,
batch_size: int = 1024,
) -> Evaluation
Compute every metric for every query of runs that has judgements.
runs is consumed once, so a streaming reader works. A query of the run without
judgements is skipped and counted (strict: MissingQrelsError).
Metric specs are resolved with registry (built-in metrics by default) before
the first query is read, so a typo fails fast.
Queries are scored in batches of batch_size: metrics implementing
BatchMetric share one relevance matrix per
batch, the others are called query by query. Memory holds one batch, not the run;
a batch is cut earlier when its matrices would exceed BATCH_CELLS.
Source code in src/ranklens/metrics/evaluation.py
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |