Mean Reciprocal Rank (MRR)

Mean reciprocal rank scores a ranked result list by one question: how far down the list is the first relevant item? It suits tasks where a single good hit is enough, such as finding the one passage that answers a factual question or the one correct file in a lookup.

Definition

For a query \(i\), let \(\mathrm{rank}_i\) be the position, counted from 1, of the first relevant result. The reciprocal rank is \(1/\mathrm{rank}_i\), or 0 if no relevant result appears (in the whole list, or in the top \(k\) for MRR@\(k\)). MRR is the average over the \(Q\) queries:

\[ \mathrm{MRR}=\frac{1}{Q}\sum_{i=1}^{Q}\frac{1}{\mathrm{rank}_i}. \]

The score is 1 when every query has a relevant result first, and it drops to 0.5 for a first hit at rank 2, 0.333 at rank 3, and so on.

A worked example

Four hypothetical queries return ranked lists in which a 1 marks a relevant result at that position.

runs={"q1":[0,0,1,0,0],"q2":[1,0,0,0,0],"q3":[0,0,0,0,0],"q4":[0,1,1,0,0]}
rr=lambda r:next((1/(i+1) for i,x in enumerate(r) if x),0)
for q,r in runs.items(): print(q,round(rr(r),3))
print("MRR",round(sum(rr(r) for r in runs.values())/len(runs),4))

Output:

q1 0.333
q2 1.0
q3 0
q4 0.5
MRR 0.4583

Query q1 has its first relevant result at rank 3, q2 at rank 1, q3 has none, and q4 has its first at rank 2 (the second relevant item at rank 3 is ignored). The mean is \((0.333+1+0+0.5)/4=0.4583\).

Properties worth knowing

Only the first relevant item counts. The program below compares system A, which places one relevant document first and then nothing relevant in positions 2 to 6, with system B, which places five relevant documents at positions 2 to 6.

A=[1,0,0,0,0,0]; B=[0,1,1,1,1,1]
print("MRR A",rr(A),"B",rr(B),"; relevant in top6 A",sum(A),"B",sum(B))
MRR A 1.0 B 0.5 ; relevant in top6 A 1 B 5

A has reciprocal rank 1.0 and B has 0.5, although A returns one relevant document in the top six and B returns five. If the application needs several relevant documents, for example to assemble evidence for an answer that draws on multiple passages, MRR hides the difference. Recall@\(k\) or nDCG measures it.

The weighting is steep at the top. Moving the first hit from rank 1 to rank 2 costs 0.5, while moving it from rank 9 to rank 10 costs 0.011. This matches users who read only the first result, and it understates the difference between a result at 10 and one at 50 when a reranker or a language model reads the entire top-\(k\).

It is an average of ratios, not of ranks. A query whose first hit is at rank 100 and one at rank 1000 both contribute almost nothing, so MRR is insensitive to how bad the bad cases are, and a mean of 0.5 can come from half the queries at rank 1 and half missing entirely, or from every query at rank 2. Look at the distribution of reciprocal ranks, or the fraction with a hit in the top \(k\), next to the mean.

It depends on the judgments. A relevant document that was never labeled counts as a non-hit, so an improved system can lose MRR. See Relevance Judgments and Pooling.

Report uncertainty. MRR is an average over queries, so with a few dozen queries it is noisy; compare two systems with a paired bootstrap over per-query reciprocal ranks.

Neighboring metrics

  • Recall@\(k\): the fraction of relevant documents appearing in the top \(k\). It ignores order within \(k\).
  • nDCG@\(k\): handles graded relevance and several relevant items, with a logarithmic position discount.
  • Hit rate or success@\(k\): whether any relevant result appears in the top \(k\). MRR@\(k\) refines it by rewarding earlier hits.

Discover more from Insightful Data Lab

Subscribe to get the latest posts sent to your email.

Similar Posts

Questions, corrections, or additional insights?

This site uses Akismet to reduce spam. Learn how your comment data is processed.