Recall@K and Median Rank Together
Problem Statement
Image-text retrieval papers report a bundle of metrics: R@1, R@5, R@10 and the median rank. Compute all four from the ranked-id lists in a single pass over the queries.
Background
For each query with a single correct item, its rank is the 1-based position of that item in the ranked list (or len(list) + 1 if absent). Then:
- R@K is the fraction of queries whose rank <= K, reported as a percentage rounded to 2 decimals.
- The median rank is the median of all per-query ranks (lower is better). For an even number of queries use the average of the two middle values.
Your Task
Implement:
def retrieval_report(rankings, relevant, ks=(1, 5, 10)):
Return a dict:
- "recall": dict mapping each K to its R@K percentage (2 decimals).
- "median_rank": the median rank (a float; use .0 for integers, halves for even counts).
Input Format
- rankings: list of ranked-id lists.
- relevant: list of correct ids.
- ks: tuple of cutoffs.
Output Format
- A dict with "recall" and "median_rank".
Sample
print(retrieval_report([[1, 2, 3], [4, 5, 6], [9, 8, 7]], [1, 6, 7]))
Output:
{'recall': {1: 33.33, 5: 100.0, 10: 100.0}, 'median_rank': 3.0}
Example
print(retrieval_report([[1, 2, 3], [4, 5, 6], [9, 8, 7]], [1, 6, 7]))
{'recall': {1: 33.33, 5: 100.0, 10: 100.0}, 'median_rank': 3.0}Ranks are 1, 3, 3. R@1 = 1/3 = 33.33%. R@5 and R@10 catch all three = 100%. Median of [1,3,3] is 3.0.
Constraints
len(rankings) == len(relevant),1 <= Q <= 5000.- Rank is 1-based; a missing item ranks
len(list) + 1. - R@K is a percentage rounded to 2 decimals; median uses the two-middle average for even Q.