信息检索P@10、MAP、NDCG,及同一指标计算的差别

      问题源于我在重现一篇信息检索方面顶会论文实验的时候,始终计算不出与论文中相同的实验结果。论文的实验用到了P@10,MAP,NDCG@10三种指标。我先是用了Galago提供的计算工具,发现除P@10一项指标结果一致外,MAP,NDCG@10两项都有很大的不同。经过观察发现虽然实验结果的数据不同,但是实验结果的趋势是相同的(实验是对几种排名算法进行评比,尽管得到了不同的数据,但是用这些数据对算法进行排名,算法的好坏同样能比较出来)。有趣的是,

       我同样使用了Galago提供的MAP,NDCG计算工具,对这篇论文引用的另外一篇论文同样的复现了一下实验,结果是完全一致。因此我认为虽然使用了同一种,但是对这种指标的计算存在的一些差别,哪怕同样是同一领域顶级会议的两篇论文,计算方式也不尽相同。接着我就开始自己编写计算MAP,NDCG的代码,不断的去修改尝试,终于试出了差别在哪了。

1、P@10

       在说同一指标计算的差别之前,我先顺带说一下信息检索的几个常用评价指标。
       P@10意思是:返回前10个结果的精确度。P英文为 Precision。直接看下图例子。
      准确的说,这里演示的是P@5。一次查询中返回了上图所示的5个答案,其中第1、3、5个答案是正确的,第2、4个答案是错误的,因此这次查询的P@5=0.6。
      对于一个系统而言,评价它的精确度,常用多个不同种类的查询进行测试,对每个查询分别计算P@10,取这些查询P@10的平均值作为系统的P@10。这个计算比较固定,没有什么歧义,所以各个论文中对于P@10的计算方式我看到的都是一样的。

2、MAP

      MAP因为为Mean Average Precision,就是说对一个叫Average Precision(AP)的东西取平均值。检测一个系统的性能,常用多个不同种类的查询对它进行测试,每个查询的结果都能计算出一个AP值,把所有AP取平均值就是系统的MAP。
      那么问题就变成了如何对一次查询结果计算AP值。AP值其实是对P@n的一个扩展。上述的P@10是吧n固定为10,而AP的计算是平均P@1,P@2......P@n所有的值。
       感谢网友提醒,之前对AP平均的对象说明不严谨。AP是对  每个相关文档出现时的 精度  做平均,而不是对从1到n每个精度求和算平均。查阅了论文有如下定义:
     

        上图中的公式,r是每个相关文档的排名,R是相关文档的总数,P@r 是前r个检索到的相关文档的精度。

        这里再对分母R做一个说明,R又可分为两种,一种是整个文档集合中所有相关文档的总数,包括了未出现再返回的Top-N结果内的所有相关文档,这种方式考虑到了召回率。另一种是R只算了返回的Top-N个结果内的相关文档的总数。

      下面展示一个例子:

        上图为对一个系统的两次查询。对于结果1,AP@10=(1.0+0.67+0.75+0.8+0.83+0.6)/6=0.78,对于结果2,AP@10=(0.5+0.4+0.5+0.57+0.56+0.6)/6=0.52

       对于一次查询,AP值可以判断优劣,但是如果涉及到一个系统整体的效果,就需要用到MAP(Mean Average Precision),简单的说,MAP的计算的是搜索查询结果AP值的均值。如上图如果表示的MAP = (0.78+0.52)/2。

不同论文中计算需要注意的区别

        MAP的计算也是很简单的,但是需要注意的就是AP@n这个n的取值。MAP不像P@10这样明确的表达了要用返回结果的前10个进行计算,多数论文都没有具体写明要取前多少个计算MAP。我遇到的论文就是,实验结果得到了前1000个答案,但是它只选了前100个进行计算MAP值,虽然简单,但是没注意到的话还是会让人摸不着头脑的答案不一致。

3、NDCG@n

          NDCG可以拆解为四个部分,分别是N(Normalization)标准化、D(D iscounted)折减、C(C umulative)累积、G(G ain)增益。四个部分通过下式表示NDCG。
                                                           
         其中x表示一个查询,n表示用返回的前n个答案计算本次查询的NDCG,i表示第几个答案。
         G可以理解为一个返回的答案对于本次查询质量的加分。G的大小与i无关,只取决于这个答案的质量。
         D可以理解为对于一个加分的适当减分。因为越靠前的答案应该加分越多,越靠后的答案加分越少,加分G是与答案的位置前后无关的,所以需要通过D来控制加分大小。所以D是一个随答案位置i增大而增大的量。
         C是对1到n个位置的G/D进行累加,得到这次查询的质量得分。
         N是对得分进行归一化处理,可以理解为N是理想情况下的得分,及能够取得的最高得分。

计算NDCG存在的差异

        NDCG相对于前两种指标公式会更复杂,所以计算方式存在差异的可能性更大。除了C是进行累加没有什么争议以外,N、D、G三项计算都可能存在差别
        G的差别比较大,有的是直接取相关度得分rel作为G的值,有的是取2^rel-1作为G的值,当然还存在有其他的表达方式。相同的是相关度得分都是rel = {0,1,2......}。
        对于D相同的都是以log(i)的形式取值,显然i=1时D=0,不可作为分母。因此发现有两种不同的方式。第一种,当i=1时,D取1,其余的取log(i)。第二种D=log(1+i)。
        对于N也发现了两种计算方式。相同的是都使用了相同的DCG方式计算,不同的在于取哪些值计算。
        第一种,取当前返回结果的前n的最优排序计算DCG作为N的值。例如,一组NDCG@5的相关度为X={1,0,2,2,1},将其变化成X={2,2,1,1,0}计算DCG的值作为N。也就是说集合X的取值一定出现在答案中。但是假设返回的前n个的相关度得分都是0,N也变成了0,那么答案将出错。网络上的计算方式大多是这种。
       第二种,是将整个搜索空间中的最优n个答案形成集合X,从高到低排列后计算DCG作为N的值。集合X的值不要求出现在系统返回的答案中。我在论文中遇到的是这种。
  • 17
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
由于MRR、MAPNDCG都是评估指标,需要根据具体的任务和数据集进行实现。以下是一些常见任务的评估指标实现示例: 1. 信息检索任务中的MRR实现: ```python def mean_reciprocal_rank(results, relevant_docs): for i, r in enumerate(results): if r in relevant_docs: return 1.0 / (i + 1) return 0.0 # 示例 relevant_docs = [1, 3, 5] results = [3, 4, 2, 1, 5] print(mean_reciprocal_rank(results, relevant_docs)) # 输出 0.3333 ``` 2. 信息检索任务中的MAP实现: ```python def average_precision(results, relevant_docs): precision = 0.0 num_relevant = 0 for i, r in enumerate(results): if r in relevant_docs: num_relevant += 1 precision += num_relevant / (i + 1) return precision / len(relevant_docs) def mean_average_precision(results_list, relevant_docs_list): map_score = 0.0 for results, relevant_docs in zip(results_list, relevant_docs_list): map_score += average_precision(results, relevant_docs) return map_score / len(results_list) # 示例 relevant_docs_list = [[1, 3, 5], [2, 4, 6], [3, 5, 7]] results_list = [[3, 4, 2, 1, 5], [3, 2, 4, 5, 1], [7, 6, 5, 4, 3]] print(mean_average_precision(results_list, relevant_docs_list)) # 输出 0.5 ``` 3. 推荐系统任务中的NDCG实现: ```python import numpy as np def ndcg(recommended_items, relevant_items, k): dcg = 0.0 idcg = np.sum(1.0 / np.log2(np.arange(2, k + 2))) for i, r in enumerate(recommended_items[:k]): if r in relevant_items: dcg += 1.0 / np.log2(i + 2) return dcg / idcg # 示例 recommended_items = [1, 2, 3, 4, 5] relevant_items = [1, 3, 5] print(ndcg(recommended_items, relevant_items, 5)) # 输出 0.6244 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值