信息检索与数据挖掘 | 【实验】检索评价指标MAP、MRR、NDCG

news2024/12/25 12:28:38

文章目录

  • 📚实验内容
  • 📚知识梳理
  • 📚实验步骤
    • 🐇前情提要
    • 🐇MAP评价指标函数
    • 🐇MRR 评价指标函数
    • 🐇NDCG评价指标函数
    • 🐇调试结果

📚实验内容

  • 实现以下指标评价,并对Experiment2的检索结果进行评价
    • Mean Average Precision (MAP)
    • Mean Reciprocal Rank (MRR)
    • Normalized Discounted Cumulative Gain (NDCG)

📚知识梳理

  • MAP(Mean Average Precision):平均准确率,是衡量检索结果排序质量的指标。
    • 计算方式是对于每个查询,计算被正确检索的文档的平均精确率,再对所有查询的平均值取均值。
    • 存在意义是衡量对于一个查询,检索结果的平均精确率,适用于评估排序结果精确度的情况。

  • MRR(Mean Reciprocal Rank):平均倒数排名,是衡量检索结果排序质量的指标。
    • 计算方式是对于每个查询,计算被正确检索的文档的最高排名的倒数的平均值,再对所有查询的平均值取均值。
    • 存在意义是衡量对于一个查询,检索结果的排名,适用于评估检索结果排序效果好坏的情况。

  • NDCG(Normalized Discounted Cumulative Gain):归一化折损累积增益,是衡量检索结果排序质量的指标。
    • 计算方式是对于每个查询,对每个被检索到的结果计算其相对于理想排序的增益值,然后对这些相对增益值进行加权求和,再除以理想排序的增益值
    • 存在意义是衡量对于一个查询,检索结果的绝对和相对排序质量,适用于评估排序结果的质量与排名准确度的情况。

  • 这三个指标各有侧重,根据不同的评估需要和数据特征选择合适的指标。例如,对于特定领域的文档检索,可能更关注排名准确度和检索结果的可靠度,因此MRR和NDCG可能比较适合。对于广泛领域的文档检索,可能更关注精确度,因此MAP比较适合。

📚实验步骤

🐇前情提要

  • 本次实验是补充式实验,先给出了qrels_dicttest_dict
  • 构建qrels_dict,根据 qrel.txt 中的 query_id 和对应库中真正相关的 doc_id 的信息构建 qrels_dict={query_id:{doc_id:gain,doc_id:gain,……}}。 遍历文件中的每一行,完成遍历后,返回 qrels_dict:
    • 使用 split(’ ') 将行按空格分隔成列表 ele。
    • 检查 ele[0](query_id)是否已经在 qrels_dict 中。如果不在,将其作为新的查询ID键添加到 qrels_dict 中,并将其对应的值设置为空字典。
    • 检查 ele[3](gain)是否大于0。如果是,将 ele[2](doc_id)作为新的相关文档ID键添加到查询ID键对应的值中,并将其对应的值设置为 ele[3] 的整数形式。
    def generate_tweetid_gain(file_name):
        qrels_dict = {}
        with open(file_name, 'r', errors='ignore') as f:
            for line in f:
                # 按空格划分
                ele = line.strip().split(' ')
                # ele[0]中存放的是query_id
                if ele[0] not in qrels_dict:
                    qrels_dict[ele[0]] = {}
                # ele[3]存放的是gain,ele[2]存放的是doc_id
                # 将gain大于0的存入
                if int(ele[3]) > 0:
                    qrels_dict[ele[0]][ele[2]] = int(ele[3])
        return qrels_dict
    
  • 构建test_dict,根据 result.txt 文档中 query 和对应的检索到的 doc 文档对应信息构建 test_dict={query_id:{doc_id,doc_id,……}}。遍历文件中的每一行,完成遍历后,返回 test_dict:
    • 使用 split(’ ') 将行按空格分隔成列表 ele。
    • 检查 ele[0](query_id)是否已经在 test_dict 中。如果不在,将其作为新的查询ID键添加到 test_dict 中,并将其对应的值设置为一个空列表。
    • ele[1](doc_id)添加到查询ID键对应的列表中。
    def read_tweetid_test(file_name):
        # 输入格式为:query_id doc_id
        test_dict = {}
        with open(file_name, 'r', errors='ignore') as f:
            for line in f:
                # 按空格划分
                ele = line.strip().split(' ')
                # 这里的ele[0]是query_id,ele[1]是doc_id
                if ele[0] not in test_dict:
                    test_dict[ele[0]] = []
                test_dict[ele[0]].append(ele[1])
        return test_dict
    

🐇MAP评价指标函数

  1. 获取检索到的(test_dict)相关文档信息

  2. 获取库中(qrels_dict)所有相关文档的信息

  3. 进行 P@K评估计算

    在这里插入图片描述
    在这里插入图片描述

  4. 进行 AP 评估计算
    在这里插入图片描述

  5. 进行 MAP 均值评估计算。
    在这里插入图片描述

    在这里插入图片描述


def MAP_eval(qrels_dict, test_dict, k = 100):
    # MAP是对AP评价结果进行平均,AP基于P(Precision@K)评估
    AP_result = [] 
    for query in qrels_dict:
        # 获取相关信息
        test_result = test_dict[query]              # 检索文档
        true_list = set(qrels_dict[query].keys())   # 相关文档
        use_length = min(k, len(test_result))       # 用不超过100条文档计算
        if use_length <= 0:
            print('query:', query, '未找到')
            return []
        # 声明变量
        P_result = [] 
        total = 0    
        the_true = 0  
        # P@K 评估
        for doc_id in test_result[0: use_length]:
            total += 1
            if doc_id in true_list:
                # 如果是相关的
                the_true += 1
                P_result.append(the_true / total)
        # AP评估
        if P_result:
            AP = np.sum(P_result) / len(true_list)
            # print('query:', query, '的AP评估结果:', AP)
            AP_result.append(AP)
        else:
            print('query:', query, ' 就没有相关的┭┮﹏┭┮')
            AP_result.append(0)
    # MAP就是AP的平均值
    return np.mean(AP_result)

🐇MRR 评价指标函数

  1. 获取检索到的(test_dict)相关文档信息

  2. 获取库中(qrels_dict)所有相关文档的信息

  3. 计算排序倒数(第一个相关结果的位置倒数)
    在这里插入图片描述

  4. 进行 RR 评估计算
    在这里插入图片描述

  5. 进行 MRR 均值评估计算。
    在这里插入图片描述
    在这里插入图片描述


def MRR_eval(qrels_dict, test_dict, k = 100):
    # MRR是对RR评价结果进行平均,RR基于排序倒数
    RR_result = []
    for query in qrels_dict:
        # 获取相关信息
        test_result = test_dict[query]              # 检索文档
        true_list = set(qrels_dict[query].keys())   # 相关文档
        use_length = min(k, len(test_result))       # 用不超过100条文档计算
        if use_length <= 0:
            print('query:', query, '未找到')
            return []
        # 声明变量
        R_result = []
        rank = 0
        # 计算排序倒数
        for doc_id in test_result[0: use_length]:
            rank += 1
            if doc_id in true_list:
                R_result.append(1 / rank)
                break
        # RR评估
        if R_result:
            RR = np.sum(R_result)/1.0
            # print('query:', query, '的RR评估结果:', RR)
            RR_result.append(RR)
        else:
            print('query:', query, ' 就没有相关的┭┮﹏┭┮') 
            RR_result.append(0)
    # MRR就是RR的平均值
    return np.mean(RR_result)

🐇NDCG评价指标函数

  1. 获取检索到的(test_dict)相关文档信息
  2. 获取库中(qrels_dict)所有相关文档的gain(也就是下边的rel)信息
  3. 按gain(rel)倒序排列(理想化,用于计算IDCG)
  4. 先计算出 DCGIDCG,二者相除得到NDCG,取均值后返回。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

def NDCG_eval(qrels_dict, test_dict, k = 100):
    # NDCG@K = DCG@K / IDCG@K
    # DCG = rel(1) + sum(rel(i)/log(i))
    # IDCG就是按rel排序之后的DCG
    NDCG_result = []
    for query in qrels_dict:
        # 获取相关信息                                          
        test_result = test_dict[query]                       # 检索文档
        true_list = list(qrels_dict[query].values())         # 相关文档的gain列表
        true_list = sorted(true_list, reverse=True)          # 按gain(rel)倒序排列
        use_length = min(k, len(test_result),len(true_list)) # 用不超过100条文档计算
        if use_length <= 0:
            print('query:', query, '未找到')
            return []
        # 声明变量
        i = 1
        DCG = 0.0 
        IDCG = 0.0
        # 计算DCG和IDCG
        rel1 = qrels_dict[query].get(test_result[0], 0)
        DCG += rel1
        for doc_id in test_result[1: use_length]:
            i += 1
            rel = qrels_dict[query].get(doc_id, 0)
            DCG += rel / math.log(i, 2)
            IDCG += true_list[i - 2] / math.log(i, 2)
        NDCG = DCG / IDCG
        # print('query:', query, '的NDCG评估结果:', NDCG)
        NDCG_result.append(NDCG)
    # 取平均值后返回
    return np.mean(NDCG_result)

🐇调试结果

在这里插入图片描述


参考博客:信息检索实验3- IR Evaluation

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1209057.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Maven介绍及配置

目录 一.Maven 1.介绍 坐标 仓库 1&#xff09;中央仓库 2&#xff09;本地仓库 3&#xff09;私服 配置国内源 配置过程 二.Maven功能 2.项目构建 3.依赖管理 Maven Help插件 安装 ​使用 一.Maven 1.介绍 坐标 唯一的&#xff0c;通过以下代码的三个键值对确…

C++:OJ练习(每日练习!)

编程题&#xff1a; 题一&#xff1a;计算日期到天数的转换 计算日期到天数转换_牛客题霸_牛客网 (nowcoder.com) 示例1 输入&#xff1a; 2012 12 31 输出&#xff1a; 366 思路一&#xff1a; 第一步&#xff1a;创建年&#xff0c;月&#xff0c;日的变量&#xff0c;并按…

十年软件测试老程序告诉你性能测试的左移右移到底能干嘛

常规的性能测试一般都是在测试阶段集成测试时候才开始介入&#xff0c;很容易测试时间不够&#xff0c;可不可以借鉴测试左移右移的思路&#xff0c;更早的介入和发现性能风险&#xff0c;然后在测试阶段更专注于分析优化&#xff1f; 借着这个问题&#xff0c;结合自己的实践…

数据结构:反射

基本概念 反射中的四个类 Class类 Java文件在被编译之后&#xff0c;生成了.class文件&#xff0c;JVM此时解读.class文件&#xff0c;将其解析为java.lang.Class 对象&#xff0c;在程序运行时每个java文件就最终变成了Class类对象的一个实例。通过反射机制应用这个 实例就…

黑马点评回顾 redis实现共享session

文章目录 传统session缺点整体访问流程代码实现生成验证码登录 问题具体思路 传统session缺点 传统单体项目一般是把session存入tomcat&#xff0c;但是每个tomcat中都有一份属于自己的session,假设用户第一次访问第一台tomcat&#xff0c;并且把自己的信息存放到第一台服务器…

基于Vue+SpringBoot的天然气工程运维系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目详细录屏 二、功能模块2.1 系统角色分类2.2 核心功能2.2.1 流程 12.2.2 流程 22.3 各角色功能2.3.1 系统管理员功能2.3.2 用户服务部功能2.3.3 分公司&#xff08;施工单位&#xff09;功能2.3.3.1 技术员角色功能2.3.3.2 材料员角色功能 2.3…

计算机网络原理 谢希仁(第8版)第四章习题答案

4-01 网络层向上提供的服务有哪两种&#xff1f;试比较其优缺点。 面向连接的和无连接。 面向连接优点&#xff1a; 通过虚电路发送分组&#xff0c;分组只用填写虚电路编号&#xff0c;分组开销较小&#xff1b;分组按序达到终点。 面向连接缺点&#xff1a; 一个节点出故障&a…

【电源专题】低功耗设备如何解决POE协议要求的PD最小功耗?

要让PD正常工作起来除了需要与PSE握手协商外,还要求PD有一个最小功耗输出。 其原因是如果PD没有在一定时间内给出一个最小功耗,那么PSE将会认为PD设备断开而自动关闭,将功率分配给其他网口。对于不同的类别PD,其要求也不一样。如下所示为Type 1/2/2/4最小电流的要求:如类…

队列与二值信号量

一、队列简介&#xff1a;队列也称为消息队列&#xff0c;是一种用于消息间进行通信的数据结构&#xff0c;队列可以用于任务与任务之间、中断与任务之间传递消息&#xff0c;队列通常采用先进先出&#xff08;FIFO&#xff09;的数据缓冲机制。 二、队列常见的API函数 1.创建…

MySQL主主复制

主1 192.168.66.15 主2 192.168.66.16 主1&#xff1a; roottest2 ~]# hostname master1 [roottest2 ~]# bash [rootmaster1 ~]# vim /etc/my.cnf server-id11 log-binmysql-bin auto_increment_increment2 auto_increment_offset1 replicate-do-dbdemo_db …

STM32笔记—USART

课外知识插入&#xff1a;STM32单片机extern全局变量_stm32全局变量-CSDN博客 如果你把temple定义在A中&#xff0c;然后让A.h和B.h包含在includes.h中&#xff0c;然后把includes.h放在A.c和B.c中单个编译是没有问题的&#xff0c;但是链接的时候会出现问题&#xff0c; “S…

振南技术干货集:深入浅出的Bootloader(4)

注解目录 1、烧录方式的更新迭代 1.1 古老的烧录方式 (怀旧一下&#xff0c;单片机高压烧录器。) 1.2 ISP 与ICP 烧录方式 (还记得当年我们玩过的 AT89S51?) 1.3 更方便的 ISP 烧录方式 1.3.1串口 ISP &#xff08;是 STC 单片机成就了我们&#xff0c;还是我们成就了…

【开源】基于Vue.js的快递管理系统的设计和实现

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 数据中心模块2.2 快递类型模块2.3 快递区域模块2.4 快递货架模块2.5 快递档案模块 三、界面展示3.1 登录注册3.2 快递类型3.3 快递区域3.4 快递货架3.5 快递档案3.6 系统基础模块 四、免责说明 一、摘要 1.1 项目介绍 …

ARMday06(总线、串口、RCC章节分析)

总线 总线是完成各个部件之间传输的一种媒介 串行/并行总线 串行总线&#xff0c; 在同一时刻&#xff0c;根据时钟线的变化&#xff0c;只可以收发一位数据 优点&#xff1a;占用引脚资源少 缺点&#xff1a;传输速度比较慢 并行总线&#xff0c; 在同一时刻&#xff…

软件工程分析报告05体系结构说明书——基于Paddle的肝脏CT影像分割

基于Paddle的肝脏CT影像分割系统的体系结构说明书 目录 HIPO图 H图 Ipo图 软件结构图 面向数据流的体系结构设计图 程序流程图 S图 用PDL语言描述的伪代码 HIPO图 H图 Ipo图 软件结构图 面向数据流的体系结构设计图 程序流程图 S图 PAD图 用PDL语言描述的伪代码 (1)…

ubuntu20.04.6安装Intel AX211网卡驱动

前言 环境&#xff1a; ThinkBook16 2023 款网卡Intel AX211 Wi-Fi6ubuntu版本20.04.6&#xff08;最后一位小数很重要&#xff09;系统内核 Linux wzy 5.15.0-67-generic #74~20.04.1-Ubuntu SMP Wed Feb 22 14:52:34 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux 方法&#x…

【数据结构】树与二叉树(十五):二叉树的基础操作:查找结点(算法Find)

文章目录 5.2.1 二叉树二叉树性质引理5.1&#xff1a;二叉树中层数为i的结点至多有 2 i 2^i 2i个&#xff0c;其中 i ≥ 0 i \geq 0 i≥0。引理5.2&#xff1a;高度为k的二叉树中至多有 2 k 1 − 1 2^{k1}-1 2k1−1个结点&#xff0c;其中 k ≥ 0 k \geq 0 k≥0。引理5.3&…

AVL树的插入和删除

一.AVL树的四种旋转方式 以上是AVL树插入和删除时需要用到的四种旋转方式。为什么要旋转&#xff1f;因为树不平衡了,通过旋转使其再次平衡。 但是上面的四副图在旋转前就是平衡的&#xff0c;所以这样的旋转是没有意义的&#xff0c;重点在于理解旋转的方法。下面的插入和删除…

修改Openwrt软路由的web端口

如何修改openwrt路由器的web访问端口号&#xff1f; 在OpenWrt路由器上&#xff0c;如何修改Web访问端口号&#xff0c;通常涉及到修改HTTP服务器的配置文件。默认情况下&#xff0c;OpenWrt使用的HTTP服务器是uHTTPd。 以下是修改Web访问端口号的步骤&#xff1a; 一、通过…