在Embedding模型评测中常用的这四个以@10为后缀的指标。这些指标主要用于评估模型在检索(Retrieval)任务中的性能,例如:给定一个查询(Query),模型需要从一个大文档库中找出最相关的文档(Document)。@10 表明我们只关心模型返回的前10个最相关的结果(Top-10)。
我们用一个具体场景贯穿所有指标的例子:
场景: 文档检索系统。
查询(Query): "量子纠缠的基本原理"
相关文档(Ground Truth Documents):
- Doc_A:详细介绍量子纠缠的物理原理和实验验证。Doc_B:讨论量子纠缠在量子通信中的应用(原理部分较少)。Doc_C:科普文章,解释量子纠缠概念和爱因斯坦的质疑。(核心概念有覆盖)
假设模型返回的Top-10结果(Ranked List):
- Doc_X (完全不相关:关于经典力学)Doc_A (高度相关:详细原理)Doc_Y (不太相关:量子计算硬件)Doc_B (相关,但侧重点不同)Doc_C (相关:核心概念)Doc_Z (完全不相关)Doc_D (相关但非最优:简单提及纠缠)Doc_E (完全不相关)Doc_F (完全不相关)Doc_G (完全不相关)
现在我们看各个指标如何评估这个结果列表:
MRR@10 (Mean Reciprocal Rank at 10)
含义: 平均倒数排名。它衡量系统找到第一个正确答案的能力。计算方式:对于每个查询,找出模型返回的Top-10结果中,排名最高的那个相关文档的位置(Rank),然后取这个位置的倒数(Reciprocal Rank)。将所有查询的倒数排名求平均,即得到MRR。
公式: MRR = (1 / |Q|) * Σ(1 / rank_i)。其中 |Q| 是查询总数,rank_i 是查询 i 的最相关文档在结果列表中的排名(如果在Top-K之外,则忽略该查询或设为0)。
关键点:
- 只关心第一个相关文档出现的位置。位置越靠前 (Rank越小),倒数越大,贡献越大。位置大于10则该项得0。对找到第一个正确答案的速度非常敏感。
本例计算:
- 相关文档在Top-10中首次出现的位置: Doc_A 在 Rank=2。倒数排名 (Reciprocal Rank) = 1 / 2 = 0.5(假设只有一个查询,则 MRR@10 = 0.5。真实场景需对多个查询平均)
优点: 简单直观,对首个正确答案的位置敏感。
缺点: 只关心第一个答案,完全不考虑后续的相关文档数量或排名。
Recall@10 (Recall at 10)
含义: 召回率。它衡量系统在Top-10结果中找出了总相关文档集合中的多少个。
公式: Recall@K = (Number of relevant documents retrieved in Top-K) / (Total number of relevant documents)。K=10。
关键点:
- 关注覆盖度:Top-10结果中捞到了多少相关文档。分子是在Top-10中找到的相关文档数量。分母是查询对应的所有相关文档(即标准答案集合)的总数量。结果范围在 [0, 1] 之间,越大越好。
本例计算:
- 所有相关文档总数 = 3 (Doc_A, Doc_B, Doc_C)在Top-10中找到的相关文档数 = 3 (Doc_A(2), Doc_B(4), Doc_C(5))Recall@10 = 3 / 3 = 1.0
优点: 直观反映系统找到所有正确答案的能力(限定在Top-K内)。
缺点: 不关心结果的排序。把Doc_A, Doc_B, Doc_C排在1、2、3名和排在第8、9、10名,Recall@10都是1.0。也没有考虑不同文档的相关性程度差异(所有相关文档被视为同等重要)。分母是总相关文档数,如果总相关文档数量庞大(如某个Query有100个相关文档),Recall@10即使为1.0也几乎不可能(因为只能返回10个),所以Recall@10值本身的大小需要结合问题理解。
Recall_cap@10 (Recall capped at 10)
含义: 截断召回率。它本质上是为了缓解标准召回率分母过大问题的变体。计算公式与Recall@10不同!
公式: Recall_cap@K = (Number of relevant documents retrieved in Top-K) / (min(K, Total number of relevant documents))。K=10。
关键点:
- 分母不再是总相关文档数,而是
K 和 总相关文档数 两者中的较小者。这种定义的直觉是:系统最多只能返回K个结果,理论上最多能找到的相关文档数就是 min(K, TotalRelevant)。Recall_cap@K 衡量的是系统相对于“最多能返回的相关文档数”的表现。本例计算:
- 所有相关文档总数 = 3 (Doc_A, Doc_B, Doc_C)min(K=10, TotalRelevant=3) = min(10, 3) = 3在Top-10中找到的相关文档数 = 3Recall_cap@10 = 3 / 3 = 1.0
另一个重要例子: 假设某个Query只有1个相关文档DocRel。
- Scenario 1:DocRel排在第1名。Recall@10 = 1 / 1 = 1.0;Recall_cap@10 = 1 / min(10,1) = 1/1 = 1.0Scenario 2:DocRel排在第15名(Top-10之外)。Recall@10 = 0 / 1 = 0.0;Recall_cap@10 = 0 / min(10,1) = 0 / 1 = 0.0结果相同。
关键区分例子: 假设某个Query有20个相关文档。
- Scenario 1:系统在Top-10中返回了10个相关文档(正好是它能返回的最大数量)。Recall@10 = 10 / 20 = 0.5;Recall_cap@10 = 10 / min(10,20) = 10 / 10 = 1.0Scenario 2:系统在Top-10中返回了5个相关文档。Recall@10 = 5 / 20 = 0.25;Recall_cap@10 = 5 / 10 = 0.5
优点:
- 当总相关文档数远大于K时,Recall_cap@K的值更容易解释,1.0 表示系统最大程度地返回了相关文档(即使总相关文档很多)。当总相关文档数少于K时,与Recall@K一致。
缺点: 也不关心排序。同样假设所有相关文档等价。
nDCG@10 (Normalized Discounted Cumulative Gain at 10)
含义: 归一化折损累计增益。这是衡量排序质量的经典指标,既考虑结果中相关文档的数量,也精细地考虑了相关文档的相关程度(Relevance Level)和出现的位置(Rank)。高相关性的文档排在前面能获得更高的分数。
核心组件理解(单查询):
Gain (G): 表示一个文档的相关性得分。通常相关度分级(如:5非常相关,4相关,3一般,2不太相关,1不相关)。假设我们定义相关性:
- Doc_A: 相关性 5 (高度相关)Doc_B: 相关性 4 (相关)Doc_C: 相关性 4 (相关)
Discounted Gain (DG): 对Gain根据其位置进行折损。位置越靠后折损越大。折损公式常用 Gain / log2(rank + 1)。排名第1的不折损。对Rank=2及以下开始折损。
Cumulative Discounted Gain (DCG@K): 将Top-K中每个位置的Discounted Gain累加起来。DCG@K = Σ (rel_i / log2(i + 1)) for i = 1 to K。rel_i是第i个位置的文档的真实相关性得分。
Ideal DCG (IDCG@K): 对当前查询,将所有相关文档按其相关性从高到低排序(理想排序),然后计算该理想排序列表的DCG@K。这个值表示在该查询下,Top-K能达到的最大可能DCG。
nDCG@K: nDCG@K = DCG@K / IDCG@K。将其归一化到[0, 1]之间。1表示排序结果与理想排序一致。
本例计算 (nDCG@10):
好的,我们用一个更简单、更详细的例子来彻底讲清楚 nDCG@10 的计算过程和逻辑。这次我们用 蛋糕店推荐 的场景。
场景: 你输入查询 “生日蛋糕推荐”,系统要返回10家最相关的蛋糕店。相关性的判定:
- 5分 (Perfect Match): 专业生日蛋糕定制店,评价极好,主营生日蛋糕。4分 (Excellent): 优质烘焙店,生日蛋糕是主力产品之一,评价很好。3分 (Good): 普通面包蛋糕店,卖生日蛋糕但选择不多或评价一般。2分 (Fair): 咖啡店或简餐店,也卖少量几款基础生日蛋糕。1分 (Irrelevant): 与生日蛋糕基本无关(比如主打面包、饼干或不卖任何蛋糕的店)。
真实的相关蛋糕店(Ground Truth):
- 店A: 专业生日蛋糕定制 (相关性 5)店B: 高端烘焙坊,生日蛋糕招牌 (相关性 5)店C: 连锁蛋糕店,种类丰富 (相关性 4)店D: 社区面包店,有几款生日蛋糕 (相关性 3)店E: 网红甜品站,主推小蛋糕 (相关性 3) (用户明确想找生日蛋糕,这个只能算边缘相关)店F: 法式甜点屋,有精致生日蛋糕 (相关性 4) (假设我们后面发现漏标了这个相关店)
假设模型返回的 Top-10 结果及标注的 真实相关性 得分:
- 店P:只卖面包 (相关性 1)店F: 法式甜点屋 (相关性 4) (注:位置1后面出现)店Q:咖啡馆兼售基础蛋糕 (相关性 2)店A: 专业生日蛋糕定制 (相关性 5)店R:饼干专卖店 (相关性 1)店E: 网红甜品站,小蛋糕为主 (相关性 3)店D: 社区面包店 (相关性 3)店S:冰淇淋店 (相关性 1)店B: 高端烘焙坊 (相关性 5)店C: 连锁蛋糕店 (相关性 4)
注意:
- 相关店 店A、B、C、D、E、F 都被系统找出来了,但排序混乱。店F 相关性为4,排在位置2。店A 相关性为5,本该最靠前,却只排在位置4。店B 相关性为5,却被排到很后的位置9。不相关的店(P,Q,R,S)占据了位置1,3,5,8。
计算 nDCG@10 步骤:
1. 计算 DCG@10 (Discounted Cumulative Gain at 10)
目的: 累加 Top-10 中每家店的 折损后相关性增益。
公式: DCG@K = Σ[ (相关性分值_i) / log2(位次_i + 1) ] (i 从 1 到 K, K=10)
log2(i+1) 的作用: 这就是 折损 (Discount)!位置越靠后,log2(i+1) 越大,分子(相关性得分)被除得越小,贡献就越低。位置1 (i=1) 的 log2(1+1)=log2(2)=1,不折损;位置2 log2(3)≈1.585,位置10 log2(11)≈3.459。
计算过程 (逐位计算):
- 位置1 (i=1): Rel=1 / log2(1+1) = 1 / 1 = 1.000位置2 (i=2): Rel=4 / log2(2+1) ≈ 4 / 1.585 ≈ 2.524位置3 (i=3): Rel=2 / log2(3+1) = 2 / 2 = 1.000位置4 (i=4): Rel=5 / log2(4+1) ≈ 5 / 2.322 ≈ 2.152位置5 (i=5): Rel=1 / log2(5+1) ≈ 1 / 2.585 ≈ 0.387位置6 (i=6): Rel=3 / log2(6+1) ≈ 3 / 2.807 ≈ 1.069位置7 (i=7): Rel=3 / log2(7+1) = 3 / 3 = 1.000位置8 (i=8): Rel=1 / log2(8+1) ≈ 1 / 3.170 ≈ 0.315位置9 (i=9): Rel=5 / log2(9+1) ≈ 5 / 3.322 ≈ 1.505位置10 (i=10): Rel=4 / log2(10+1) ≈ 4 / 3.459 ≈ 1.156
DCG@10 = 1.000 + 2.524 + 1.000 + 2.152 + 0.387 + 1.069 + 1.000 + 0.315 + 1.505 + 1.156 ≈ 12.108
2. 计算 IDCG@10 (Ideal DCG at 10)
目的: 计算在 完美排序 (所有相关店按 相关性降序排列 排在最前面) 情况下的最大可能 DCG,作为基准。
步骤:
收集 所有 真实相关的店:店A(5), 店B(5), 店F(4), 店C(4), 店D(3), 店E(3)。
按 相关性分数降序排序:
店A (5)
店B (5)
店F (4)
店C (4)
店D (3)
店E (3)
(排到第6个了。Top-10只有6个相关店,后面4位假设是不相关的,相关性为0)
计算这个完美列表的 DCG@10 (只算前10个,这里只有前6个有贡献,后4个为0不计入):
位置1 (i=1): Rel=5 (店A) / log2(1+1) = 5 / 1 = 5.000
位置2 (i=2): Rel=5 (店B) / log2(2+1) ≈ 5 / 1.585 ≈ 3.154
位置3 (i=3): Rel=4 (店F) / log2(3+1) = 4 / 2 = 2.000
位置4 (i=4): Rel=4 (店C) / log2(4+1) ≈ 4 / 2.322 ≈ 1.722
位置5 (i=5): Rel=3 (店D) / log2(5+1) ≈ 3 / 2.585 ≈ 1.160
位置6 (i=6): Rel=3 (店E) / log2(6+1) ≈ 3 / 2.807 ≈ 1.069
位置7 (i=7): Rel=0 / ... = 0
位置8 (i=8): Rel=0 / ... = 0
位置9 (i=9): Rel=0 / ... = 0
位置10 (i=10): Rel=0 / ... = 0
IDCG@10 = 5.000 + 3.154 + 2.000 + 1.722 + 1.160 + 1.069 + 0 + 0 + 0 + 0 ≈ 14.105
3. 计算 nDCG@10 (Normalized DCG at 10)
- 目的: 归一化!将实际获得的
DCG@10 除以理想的 IDCG@10。这样就把值压缩到 [0, 1] 之间,方便比较不同查询或不同系统的结果。公式: nDCG@K = DCG@K / IDCG@K计算:nDCG@10 = DCG@10 / IDCG@10 ≈ 12.108 / 14.105 ≈ 0.858结果解释 (nDCG@10 ≈ 0.858):
这个值表示:当前模型返回的 Top-10 结果的质量,达到了在完美排序下能获得的最高质量的 85.8%。
为什么不到 1.0 (100%)? 因为模型排序 不够理想:
- 两个应该排在最前面的一流店(店A-Rel5和店B-Rel5)分别被排在了第4和第9位,位置过于靠后,导致它们的高分被严重折损(贡献只有2.152和1.505),远低于它们在完美位置能贡献的值(5.000和3.154)。相关性只有4分的店F 反而被排在了非常高的第2位(贡献了2.524)。不相关的店(P, Q, R, S)占据了宝贵的前排位置(1,3,5,8)。
但为什么比想象中高 (85.8%,而不是比如0.5)? 因为:
- Recall_cap@10=1.0: 系统把 所有 6个相关店都找出来了(店A,B,F,C,D,E都出现在了Top-10里)!
nDCG 也部分反映了高召回率。店F(Rel4)和店C(Rel4)出现在了相对靠前的位置(2和10,店C贡献1.156),也有不小的贡献。总结表格:
| 指标 | 核心关注点 | 关键特性 | 是否考虑排序 | 是否考虑相关性程度 | 本例值(示例场景) |
|---|---|---|---|---|---|
| MRR@10 | 第一个正确答案的位置 | 只关心排名最高的相关文档位置,取倒数,然后平均 | 间接(位置) | 否 | ~0.5 |
| Recall@10 | Top-10中包含的相关文档比例 | 覆盖度,数量导向 | 否 | 否(二值相关) | 1.0 |
| Recall_cap@10 | Top-10中找到的相关文档占比 | 分母是 K 和总相关文档数的较小者 | 否 | 否(二值相关) | 1.0 |
| nDCG@10 | Top-10中相关文档的排序质量 | 考虑相关性等级,对位置折损,归一化到理想排序 | 是 | 是 | ~0.674 |
如何选择:
- 如果你关心系统是否能尽快提供第一个正确答案 -> MRR@10如果你关心系统在限定结果数(前10个)内尽可能多的找到所有相关文档(不论顺序),并且总相关文档数量不大 -> Recall@10如果你关心系统在限定结果数(前10个)内尽可能多的找到所有相关文档(不论顺序),特别是当总相关文档数量可能很大或变化时 -> Recall_cap@10 (近年来更常用)如果你既关心找到多少相关文档,也关心这些文档的相关程度以及它们是否被排在了前面 -> nDCG@10 (通常认为是最具信息量的指标之一)
在实践中,尤其在Embedding模型评测(如MTEB基准测试)中,nDCG@10 和 Recall_cap@10 是非常常用且能提供丰富信息的核心指标。报告多个指标通常比仅报告一个更好。
