​​MRR@10​、​​Recall@10​​、​​Recall_cap@10​​、​​nDCG@10​​指标的含义

518 阅读13分钟

在Embedding模型评测中常用的这四个以@10为后缀的指标。这些指标主要用于评估模型在​​检索(Retrieval)任务​​中的性能,例如:给定一个查询(Query),模型需要从一个大文档库中找出最相关的文档(Document)。@10 表明我们只关心模型返回的​​前10个最相关的结果​​(Top-10)。

我们用一个具体场景贯穿所有指标的例子:

  • ​场景:​​ 文档检索系统。

  • ​查询(Query):​​ "量子纠缠的基本原理"

  • ​相关文档(Ground Truth Documents):​

    • Doc_A:详细介绍量子纠缠的物理原理和实验验证。
    • Doc_B:讨论量子纠缠在量子通信中的应用(原理部分较少)。
    • Doc_C:科普文章,解释量子纠缠概念和爱因斯坦的质疑。(核心概念有覆盖)
  • ​假设模型返回的Top-10结果(Ranked List):​

    1. Doc_X (完全不相关:关于经典力学)
    2. ​Doc_A​​ (高度相关:详细原理)
    3. Doc_Y (不太相关:量子计算硬件)
    4. ​Doc_B​​ (相关,但侧重点不同)
    5. ​Doc_C​​ (相关:核心概念)
    6. Doc_Z (完全不相关)
    7. Doc_D (相关但非最优:简单提及纠缠)
    8. Doc_E (完全不相关)
    9. Doc_F (完全不相关)
    10. Doc_G (完全不相关)

现在我们看各个指标如何评估这个结果列表:

  1. ​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。真实场景需对多个查询平均)
    • ​优点:​​ 简单直观,对首个正确答案的位置敏感。

    • ​缺点:​​ 只关心第一个答案,完全不考虑后续的相关文档数量或排名。

  2. ​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值本身的大小需要结合问题理解。

  3. ​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中找到的相关文档数 = 3
      • Recall_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.0
      • Scenario 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.0​
      • Scenario 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一致。
    • ​缺点:​​ 也不关心排序。同样假设所有相关文档等价。

  4. ​nDCG@10 (Normalized Discounted Cumulative Gain at 10)​

    • ​含义:​​ ​​归一化折损累计增益​​。这是衡量​​排序质量​​的经典指标,既考虑结果中相关文档的数量,也​​精细地考虑了相关文档的相关程度(Relevance Level)和出现的位置(Rank)​​。高相关性的文档排在前面能获得更高的分数。

    • ​核心组件理解(单查询):​

      1. ​Gain (G):​​ 表示一个文档的相关性得分。通常相关度分级(如:5非常相关,4相关,3一般,2不太相关,1不相关)。假设我们定义相关性:

        • Doc_A: 相关性 5 (高度相关)
        • Doc_B: 相关性 4 (相关)
        • Doc_C: 相关性 4 (相关)
      2. ​Discounted Gain (DG):​​ 对Gain根据其位置进行折损。位置越靠后折损越大。折损公式常用 Gain / log2(rank + 1)。排名第1的不折损。对Rank=2及以下开始折损。

      3. ​Cumulative Discounted Gain (DCG@K):​​ 将Top-K中每个位置的Discounted Gain累加起来。DCG@K = Σ (rel_i / log2(i + 1)) for i = 1 to Krel_i是第i个位置的文档的真实相关性得分。

      4. ​Ideal DCG (IDCG@K):​​ 对当前查询,将所有相关文档按其相关性​​从高到低​​排序(理想排序),然后计算该理想排序列表的DCG@K。这个值表示在该查询下,Top-K能达到的最大可能DCG。

      5. ​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):​

      1. ​店A:​​ 专业生日蛋糕定制 (相关性 ​​5​​)
      2. ​店B:​​ 高端烘焙坊,生日蛋糕招牌 (相关性 ​​5​​)
      3. ​店C:​​ 连锁蛋糕店,种类丰富 (相关性 ​​4​​)
      4. ​店D:​​ 社区面包店,有几款生日蛋糕 (相关性 ​​3​​)
      5. ​店E:​​ 网红甜品站,主推小蛋糕 (相关性 ​​3​​) (用户明确想找生日蛋糕,这个只能算边缘相关)
      6. ​店F:​​ 法式甜点屋,有精致生日蛋糕 (相关性 ​​4​​) (假设我们后面发现漏标了这个相关店)

      ​假设模型返回的 Top-10 结果及标注的 真实相关性 得分:​

      1. 店P:只卖面包 (相关性 ​​1​​)
      2. ​店F:​​ 法式甜点屋 (相关性 ​​4​​) (注:位置1后面出现)
      3. 店Q:咖啡馆兼售基础蛋糕 (相关性 ​​2​​)
      4. ​店A:​​ 专业生日蛋糕定制 (相关性 ​​5​​)
      5. 店R:饼干专卖店 (相关性 ​​1​​)
      6. ​店E:​​ 网红甜品站,小蛋糕为主 (相关性 ​​3​​)
      7. ​店D:​​ 社区面包店 (相关性 ​​3​​)
      8. 店S:冰淇淋店 (相关性 ​​1​​)
      9. ​店B:​​ 高端烘焙坊 (相关性 ​​5​​)
      10. ​店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,作为基准。

      • ​步骤:​

        1. 收集 所有 真实相关的店:​​店A(5), 店B(5), 店F(4), 店C(4), 店D(3), 店E(3)​​。

        2. 按 ​​相关性分数降序排序​​:

          • 店A (5)

          • 店B (5)

          • 店F (4)

          • 店C (4)

          • 店D (3)

          • 店E (3)
            (排到第6个了。Top-10只有6个相关店,后面4位假设是不相关的,相关性为0)

      1. 计算这个完美列表的 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​​ 是非常常用且能提供丰富信息的核心指标。报告多个指标通常比仅报告一个更好。