信息检索与数据挖掘 | 【实验】排名检索模型

文章目录

  • 📚实验内容
  • 📚相关概念
  • 📚实验步骤
    • 🐇分词预处理
    • 🐇构建倒排索引表
    • 🐇计算query和各个文档的相似度
    • 🐇queries预处理及检索函数
      • 🔥对输入的文本进行词法分析和标准化处理
      • 🔥检索函数
    • 🐇调试结果

📚实验内容

  1. 在Experiment1的基础上实现最基本的Ranked retrieval model
    • Input:a query (like Ron Weasley birthday)
    • Output: Return the top K (e.g., K = 100) relevant tweets.
  2. Use SMART notation: lnc.ltn
    • Document: logarithmic tf (l as first character), no idf and cosine normalization
    • Query: logarithmic tf (l in leftmost column), idf (t in second column), no normalization
  3. 改进Inverted index
    • 在Dictionary中存储每个term的DF
    • 在posting list中存储term在每个doc中的TF with pairs (docID, tf)

📚相关概念

  • 信息检索与数据挖掘 | (五)文档评分、词项权重计算及向量空间模型
  • 词项频率(term frequencey):t在文档中的出现次数。
  • 文档集频率(collection frequency):词项在文档集中出现的次数。
  • 文档频率(document frequency):出现t的所有文档的数目。
  • 逆文档频率
    在这里插入图片描述
  • t f − i d f t , d tf-idf_{t,d} tfidft,d计算
    在这里插入图片描述
    在这里插入图片描述
  • 相似度计算
    在这里插入图片描述
  • 查询权重机制
    在这里插入图片描述

📚实验步骤

🐇分词预处理

  1. 将输入的推特文档转换为小写,这里统一处理,使得后续查询不区分大小写。

  2. 根据特定标记在推特文档中查找并确定关键部分信息的位置索引,并提取出推特文档中的tweetid和tweet内容。

  3. 对提取出的文本内容进行分词处理,并将单词转换为其单数形式。

  4. 对分词后的词列表进行词形还原,主要针对动词的还原操作。同时,筛去[“text”, “tweetid”]

  5. 将筛选出的有效词添加到最终结果列表中,并返回。

    #分词预处理
    def tokenize_tweet(document):
        # 统一处理使查询不区分大小写
        document = document.lower()
        # 根据特定标记在推特文档中查找并确定关键部分信息的位置索引
        # 这里的减1减3是对引号逗号切入与否的调整
        a = document.index("tweetid") - 1
        b = document.index("errorcode") - 1
        c = document.index("text") - 1
        d = document.index("timestr") - 3
        # 将推特文档中的tweetid和text内容主要信息提取出来
        document = document[a:b] + document[c:d]
        # 分词处理,并将单词转换为其单数形式
        terms = TextBlob(document).words.singularize()
        # 将分词后的词列表进行词形还原,并筛选出不属于无用词的有效词
        result = []
        for word in terms:
            # 将当前词转换为Word对象
            expected_str = Word(word)
            # 动词的还原操作
            expected_str = expected_str.lemmatize("v")
            if expected_str not in uselessTerm:
                # 筛去["text", "tweetid"],添加到result中
                result.append(expected_str)
        return result
    

🐇构建倒排索引表

  • 存储term在每个doc中的TF with pairs (docID, tf)。
    在这里插入图片描述
  1. 首先明确,在该过程计算文档词项的对应权重,采用lnc规则,即 logarithmic tf (l as first character), no idf and cosine normalization。
  2. 具体流程如下:
    • 读取内容。文件中每行都代表一条推特。将每一行推特文本分解为单词(词条化),并存储在一个列表line中
    • 利用一个全局变量N记录读取的推特文档数量。
    • 从line中提取tweetid,并从line中删除。
    • 创建一个空字典tf用于统计每个词在当前文档中的出现次数。遍历line中的每个词,通过判断词是否已经在tf字典的键中存在来更新词的出现次数。
    • 对tf字典中的每个词项频率进行logarithmic tf的计算,即将出现次数加1并取对数。(对应logarithmic tf (l as first character))
    • 归一化(对应cosine normalization,遍历tf字典的键(即词项),得到归一化因子。最后,代码再次遍历tf字典的键,并将每个词项的频率乘以归一化因子。得到最后的对应tf权重。
    • 将line转换为集合unique_terms并遍历其中的每个词。
      • 如果该词已经在postings字典的键中存在,则更新该词对应的字典项,将tweetid和权重加入其中。
      • 如果该词不存在于postings字典的键中,则创建该键,并将tweetid和权重加入其中。

  • 统计词频频率
    # 统计词项频率,记录每个词在当前文档中的出现次数
    tf = {}
     for word in line:
         if word in tf.keys():
             tf[word] += 1
         else:
             tf[word] = 1
    
  • 1 + l o g ( t f t , d ) 1+log(tf_{t,d}) 1+log(tft,d)
     # logarithmic tf
     for word in tf.keys():
         tf[word] = 1 + math.log(tf[word])
    
  • 1 w 1 2 + w 2 2 + . . . + w m 2 \frac{1}{\sqrt{{w_1}^2+{w_2}^2+...+{w_m}^2}} w12+w22+...+wm2 1
     # 归一化,cosine normalization
     cosine = 0
     for word in tf.keys():
         cosine = cosine + tf[word] * tf[word]
     cosine = 1.0 / math.sqrt(cosine)
     for word in tf.keys():
         tf[word] = tf[word] * cosine
    

🐇计算query和各个文档的相似度

  1. 首先明确,该过程分为两个步骤,首先计算query词项的对应权重,然后求相似度(也即对应词项两个权重相乘并求和)并降序排序。Query权重采用ltn规则,即 logarithmic tf (l in leftmost column), idf (t in second column), no normalization
  2. 具体流程如下:
    • 遍历查询词列表query​,对每个词进行词项频率统计,将结果存储在tf中。
    • 遍历tf字典的键(即查询词),根据每个词在postings中的文档频率(文档出现的次数)计算文档频率df​。若一个词不在postings​中,则将文档频率设置为全局变量 N(表示总的文档数量)。
    • 计算权重tf[word] = (math.log(tf[word]) + 1) * math.log(N / df),对应ltn(logarithmic tf, idf, no normalization)
    • 对于每个查询词,检查它是否postings字典中存在。若存在,则遍历该查询词的倒排索引(文档编号及对应的词项权重),根据每个文档的词项权重和查询词的tf-idf值计算相似度得分
    • 存储得分并进行降序排序,得到一个按照相似度排名的列表,并将其返回作为结果。
    def similarity(query):
        global score_tid
        tf = {}
        # 统计词项频率
        for word in query:
            if word in tf:
                tf[word] += 1
            else:
                tf[word] = 1
        # 统计文档频率
        for word in tf.keys():
            if word in postings:
                df = len(postings[word])
            else:
                df = N
            # 对应ltn,logarithmic tf (l in leftmost column), idf (t in second column), no normalization
            tf[word] = (math.log(tf[word]) + 1) * math.log(N / df)
        # 计算相似度
        for word in query:
            if word in postings:
                for tid in postings[word]:
                    if tid in score_tid.keys():
                        score_tid[tid] += postings[word][tid] * tf[word]
                    else:
                        score_tid[tid] = postings[word][tid] * tf[word]
        # 按照得分(相似度)进行降序排序
        similarity = sorted(score_tid.items(), key=lambda x: x[1], reverse=True)
        return similarity
    

🐇queries预处理及检索函数

🔥对输入的文本进行词法分析和标准化处理

def token(doc):
    # 将输入文本转换为小写字母,以便统一处理。
    doc = doc.lower()
    # 将文本拆分为单个词项,并尝试将词项转换为单数形式
    terms = TextBlob(doc).words.singularize()
    # 将分词后的词列表进行词形还原,返回结果列表result
    result = []
    for word in terms:
        expected_str = Word(word)
        expected_str = expected_str.lemmatize("v")
        result.append(expected_str)
    return result

🔥检索函数

def Union(sets):
    return reduce(set.union, [s for s in sets])

def do_search():
    query = token(input("please input search query >> "))
    result = []
    if query == []:
        sys.exit()
    # set()去除查询词列表中的重复项
    unique_query = set(query)
    # 生成一个包含每个查询词对应的tweet的id集合的列表,并且利用Union()函数将这些集合取并集
    relevant_tweetids = Union([set(postings[term].keys()) for term in unique_query])
    print("一共有" + str(len(relevant_tweetids)) + "条相关tweet!")
    if not relevant_tweetids:
        print("No tweets matched any query terms for")
        print(query)
    else:
        print("the top 100 tweets are:")
        scores = similarity(query)
        i = 1
        for (id, score) in scores:
            if i <= 100:  # 返回前n条查询到的信息
                result.append(id)
                print(str(score) + ": " + id)
                i = i + 1
            else:
                break
        print("finished")

🐇调试结果

在这里插入图片描述


最终代码

import sys
from collections import defaultdict
from textblob import TextBlob
from textblob import Word
import math
from functools import reduce

uselessTerm = ["text", "tweetid"]
# 构建倒排索引表,存储term在每个doc中的TF with pairs (docID, tf)
postings = defaultdict(dict)
# 文档数目N
N = 0
# 最终权值
score_tid = defaultdict(dict)

#分词预处理
def tokenize_tweet(document):
    # 统一处理使查询不区分大小写
    document = document.lower()
    # 根据特定标记在推特文档中查找并确定关键部分信息的位置索引
    # 这里的减1减3是对引号逗号切入与否的调整
    a = document.index("tweetid") - 1
    b = document.index("errorcode") - 1
    c = document.index("text") - 1
    d = document.index("timestr") - 3
    # 将推特文档中的tweetid和text内容主要信息提取出来
    document = document[a:b] + document[c:d]
    # 分词处理,并将单词转换为其单数形式
    terms = TextBlob(document).words.singularize()
    # 将分词后的词列表进行词形还原,并筛选出不属于无用词的有效词
    result = []
    for word in terms:
        # 将当前词转换为Word对象
        expected_str = Word(word)
        # 动词的还原操作
        expected_str = expected_str.lemmatize("v")
        if expected_str not in uselessTerm:
            # 筛去["text", "tweetid"],添加到result中
            result.append(expected_str)
    return result

# 构建倒排索引表,存储term在每个doc中的TF with pairs (docID, tf)
# lnc:logarithmic tf, no idf and cosine normalization
def get_postings():
    global postings, N
    content = open(r"Tweets.txt")
    # 内容读取,每一条推特作为一个元素存储在lines中
    lines = content.readlines()
    for line in lines:
        N += 1
        # 预处理
        line = tokenize_tweet(line)
        # 提取处理后的词列表中的第一个元素,即推特文档的tweetid
        tweetid = line[0]
        # 提取后删除,不作为有效词
        line.pop(0)

        # 统计词项频率,记录每个词在当前文档中的出现次数
        tf = {}
        for word in line:
            if word in tf.keys():
                tf[word] += 1
            else:
                tf[word] = 1
        # logarithmic tf
        for word in tf.keys():
            tf[word] = 1 + math.log(tf[word])
        # 归一化,cosine normalization
        cosine = 0
        for word in tf.keys():
            cosine = cosine + tf[word] * tf[word]
        cosine = 1.0 / math.sqrt(cosine)
        for word in tf.keys():
            tf[word] = tf[word] * cosine

        # 将处理后的词列表转换为集合,获取其中的唯一词
        unique_terms = set(line)
        for key_word in unique_terms:
            if key_word in postings.keys():
                postings[key_word][tweetid] = tf[key_word]
            else:
                postings[key_word][tweetid] = tf[key_word]

# query标准化处理
def token(doc):
    # 将输入文本转换为小写字母,以便统一处理。
    doc = doc.lower()
    # 将文本拆分为单个词项,并尝试将词项转换为单数形式
    terms = TextBlob(doc).words.singularize()
    # 将分词后的词列表进行词形还原,返回结果列表result
    result = []
    for word in terms:
        expected_str = Word(word)
        expected_str = expected_str.lemmatize("v")
        result.append(expected_str)
    return result

# 计算query和各个文档的相似度
def similarity(query):
    global score_tid
    tf = {}
    # 统计词项频率
    for word in query:
        if word in tf:
            tf[word] += 1
        else:
            tf[word] = 1
    # 统计文档频率
    for word in tf.keys():
        if word in postings:
            df = len(postings[word])
        else:
            df = N
        # 对应ltn,logarithmic tf (l in leftmost column), idf (t in second column), no normalization
        tf[word] = (math.log(tf[word]) + 1) * math.log(N / df)
    # 计算相似度
    for word in query:
        if word in postings:
            for tid in postings[word]:
                if tid in score_tid.keys():
                    score_tid[tid] += postings[word][tid] * tf[word]
                else:
                    score_tid[tid] = postings[word][tid] * tf[word]
    # 按照得分(相似度)进行降序排序
    similarity = sorted(score_tid.items(), key=lambda x: x[1], reverse=True)
    return similarity


def Union(sets):
    return reduce(set.union, [s for s in sets])

def do_search():
    query = token(input("please input search query >> "))
    result = []
    if query == []:
        sys.exit()
    # set()去除查询词列表中的重复项
    unique_query = set(query)
    # 生成一个包含每个查询词对应的tweet的id集合的列表,并且利用Union()函数将这些集合取并集
    relevant_tweetids = Union([set(postings[term].keys()) for term in unique_query])
    print("一共有" + str(len(relevant_tweetids)) + "条相关tweet!")
    if not relevant_tweetids:
        print("No tweets matched any query terms for")
        print(query)
    else:
        print("the top 100 tweets are:")
        scores = similarity(query)
        i = 1
        for (id, score) in scores:
            if i <= 100:  # 返回前n条查询到的信息
                result.append(id)
                print(str(score) + ": " + id)
                i = i + 1
            else:
                break
        print("finished")

def main():
    get_postings()
    while True:
        do_search()

if __name__ == "__main__":
    main()

参考博客:信息检索实验2- Ranked retrieval model

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从0开始在Vscode中搭建Vue2/3项目详细步骤

1.安装node.js:Node.js下载安装及环境配置教程【超详细】_nodejs下载_WHF__的博客-CSDN博客 node.js自带npm&#xff0c;无需单独安装。 验证&#xff1a; node -v npm -v 2.先简单创建一个空文件夹&#xff0c;vscode进入该文件夹&#xff0c;并打开终端。 3.安装cnpm&…

【Gensim概念】03/3 NLP玩转 word2vec

第三部分 对象函数 八 word2vec对象函数 该对象本质上包含单词和嵌入之间的映射。训练后&#xff0c;可以直接使用它以各种方式查询这些嵌入。有关示例&#xff0c;请参阅模块级别文档字符串。 类型 KeyedVectors 1&#xff09; add_lifecycle_event(event_name, log_level2…

OpenCV视频车流量识别详解与实践

视频车流量识别基本思想是使用背景消去算法将运动物体从图片中提取出来&#xff0c;消除噪声识别运动物体轮廓&#xff0c;最后&#xff0c;在固定区域统计筛选出来符合条件的轮廓。 基于统计背景模型的视频运动目标检测技术&#xff1a; 背景获取&#xff1a;需要在场景存在…

React 框架

1、React 框架简介 1.1、介绍 CS 与 BS结合&#xff1a;像 React&#xff0c;Vue 此类框架&#xff0c;转移了部分服务器的功能到客户端。将CS 和 BS 加以结合。客户端只用请求一次服务器&#xff0c;服务器就将所有js代码返回给客户端&#xff0c;所有交互类操作都不再依赖服…

禁止拷贝文件到U盘的解决办法

禁止拷贝文件到U盘的解决办法 安企神U盘管理系统下载使用 说到这问题&#xff0c;大多情况下是企业的需求&#xff0c;很多公司电脑中都保存着极为重要的数据&#xff0c;这些数据往往是不能传播的&#xff0c;所以此时就需要禁止拷贝文件到U盘来防止公司数据被泄密。 禁止拷…

python造测试数据存到excel

代码&#xff1a; from ExcelHandler import ExcelHandler from faker import Faker # 导入faker库的Faker方法 # ↓默认为en_US&#xff0c;只有使用了相关语言才能生成相对应的随机数据 fkFaker(locale"zh_CN")def create_date():m int(input(请输入要造的数据条…

自动驾驶的商业应用和市场前景

自动驾驶技术已经成为了交通运输领域的一项重要创新。它不仅在改善交通安全性和效率方面具有巨大潜力&#xff0c;还为各种商业应用提供了新的机会。本文将探讨自动驾驶在交通运输中的潜力&#xff0c;自动驾驶汽车的制造商和技术公司&#xff0c;以及自动驾驶的商业模式和市场…

基于OpenCV批量分片高像素影像

基于OpenCV批量分片高像素影像 为了更加精确的诊断和治疗&#xff0c;医疗影像往往是大像素&#xff08;1920x1080&#xff09;或超大像素图像&#xff08;4k图像4096x2160&#xff09;。这类图像的尺寸与深度学习实验数据常见尺寸&#xff08;227x227&#xff0c;或32x32&…

OpenCV实现物体尺寸的测量

一 &#xff0c;项目分析 物体尺寸测量的思路是找一个确定尺寸的物体作为参照物&#xff0c;根据已知的计算未知物体尺寸。 如下图所示&#xff0c;绿色的板子尺寸为220*300&#xff08;单位&#xff1a;毫米&#xff09;&#xff0c;通过程序计算白色纸片的长度。 主要是通过…

我国有多少个港口?

港口是什么&#xff1f; 港口是海洋运输中不可或缺的重要设施之一&#xff0c;是连接陆路和水路运输的重要节点。港口通常是指位于沿海地区的水陆交通枢纽&#xff0c;是船舶停靠、装卸货物、储存物资和维修船只的场所。港口一般由码头、泊位、仓库、货场、客运站等设施组成&a…

数据结构和算法概述

什么是数据结构&#xff1f; 官方解释&#xff1a; 数据结构是一门研究非数值计算的程序设计问题中的操作对象&#xff0c;以及他们之间的关系和操作等相关问题的学科。 大白话&#xff1a; 数据结构就是把数据元素按照一定的关系组织起来的集合&#xff0c;用来组织和存储…

【网安大模型专题10.19】※论文5:ChatGPT+漏洞定位+补丁生成+补丁验证+APR方法+ChatRepair+不同修复场景+修复效果(韦恩图展示)

Keep the Conversation Going: Fixing 162 out of 337 bugs for $0.42 each using ChatGPT 写在最前面背景介绍自动程序修复流程Process of APR (automated program repair)1、漏洞程序2、漏洞定位模块3、补丁生成4、补丁验证 &#xff08;可以学习的PPT设计&#xff09;经典的…

Spring Cloud之服务熔断与降级(Hystrix)

目录 Hystrix 概念 作用 服务降级 简介 使用场景 接口降级 服务端服务降级 1.添加依赖 2.定义接口 3.实现接口 4.Controller类使用 5.启动类添加注释 6.浏览器访问 客户端服务降级 1.添加依赖 2.application.yml 中添加配置 3.定义接口 4.Controller类使用 …

解读意大利葡萄酒分类系统

由于该国众多的产区和复杂的品种&#xff0c;要想真正掌握意大利葡萄酒是相当困难的。仅仅是试图从复杂混乱的葡萄酒标签中辨别信息的想法就足以让许多人焦虑不安。 位于托斯卡纳的基安蒂酒地区&#xff0c;Il Ciliegio生产的葡萄酒标签上包含以下名称之一:基安蒂酒科利塞内西…

通过IP地址可以做什么

通过IP地址可以做很多事情&#xff0c;因为它是互联网通信的基础之一。本文将探讨IP地址的定义、用途以及一些可能的应用。 IP地址的用途 1. 设备标识&#xff1a;IP地址用于标识互联网上的每个设备&#xff0c;这包括计算机、服务器、路由器、智能手机等。它类似于我们日常生…

unity 一键替换 UI上所有字体,批量替换字体(包括:Text和Text (TMP))

前言&#xff1a;在开发中会遇到这种情况&#xff0c;开发完了&#xff0c;发现UI字体没有替换&#xff0c;特别是需要发布到WebGL端的同学&#xff0c;突然发现无法显示汉字了。下面一个非常方便的方法完美解决。 1.解压出来的脚本放在Edit文件下&#xff0c;没有的创建一个 2…

Linux 基于sysfs的GPIO读写操作

https://bbs.huaweicloud.com/blogs/297252 前言 最近接触到Linux系统中的GPIO开发&#xff0c;这里做个小总结&#xff0c;也分享一下&#xff1b;本文会介绍GPIO的读写&#xff0c;介绍基本原理&#xff0c;以及不同读写方式的性能。 一、GPIO sysfs interface 基本原理 …

计算机视觉中的数据预处理与模型训练技巧总结

计算机视觉主要问题有图像分类、目标检测和图像分割等。针对图像分类任务&#xff0c;提升准确率的方法路线有两条&#xff0c;一个是模型的修改&#xff0c;另一个是各种数据处理和训练的技巧(tricks)。图像分类中的各种技巧对于目标检测、图像分割等任务也有很好的作用&#…

Http长连接同一个socket多个请求和响应如何保证一一对应?

HTTP/2引入二进制数据帧和流的概念&#xff0c;其中帧对数据进行顺序标识&#xff0c;如下图所示&#xff0c;这样浏览器收到数据之后&#xff0c;就可以按照序列对数据进行合并&#xff0c;而不会出现合并后数据错乱的情况。同样是因为有了序列&#xff0c;服务器就可以并行的…

从REST到GraphQL:升级你的Apollo体验

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…