其他分享
首页 > 其他分享> > 信息检索实验1-Inverted index and Boolean Retrieval Model

信息检索实验1-Inverted index and Boolean Retrieval Model

作者:互联网

实验题目 :Inverted index and Boolean Retrieval Model

实验内容:– 使用我们介绍的方法,在tweets数据集上构建inverted index;

– 实现Boolean Retrieval Model,使用TREC 2014 test topics 进行测试;

– Boolean Retrieval Model:

• Input:a query (like Ron and Weasley)

• Output: print the qualified tweets.

• 支持and, or ,not;查询优化可以选做。

实验目的:实现布尔检索模型

实验环境:Windows10、Spyder(Anaconda3)

实验原理分析
1.针对布尔查询,其实就是查询(Queries)被表示为关键词的布尔组合,用“and、or、not”连接起来,并用括弧指示优先次序.

2.词项关联矩阵:就是将对应文档里出现的terms标记为0 1并且用矩阵的形式表示出来的方法。

figure

由上图的布尔表达式为 Brutus AND Caesar AND NOT Calpurnia,即为查询莎士比亚剧本的哪一部是包含Brutus和凯撒但是不包含Calpurnia的。最简单的检索方式就是枚举,说白了,就是检索他所有的剧本,这种方法带来的后果就是会花费大量的时间,所有后面需要构建倒排索引,有了索引对结果的排序等有很大的好处。

3.倒排索引的应用:倒排索引是实现“单词-文档矩阵”的一种具体存储形式,通过倒排索引,可以根据单词快速获取包含这个单词的文档列表。倒排索引主要由两个部分组成:“单词词典”和“倒排文件”。
按照docId排序后:
figure
索引构建:
figure
索引构建具体过程:

第一步是收集构建索引的文档集,将检索所需要的检索文档收集起来。

第二步,将文本转化为词条,即词条序列,我们从文档中读出<词条,docID>二元组。

第三步,令牌化并排序,就是将单词的其他形式复原,然后再排序,按词项排序,然后每个词项按docID排序。

第四步,构建倒排索引表,是词典和倒排记录表,某个词项在单篇文档中的多次出现会被合并,拆分成词典和倒排记录表两部分,每个词项出现的文档数目(doc.frequency, DF)会被加入

数据处理

取tweet前5行数据举例分析

{“userName”: “Mariah Peoples”, “clusterNo”: 82, “text”: "House may kill Arizona-style immigration bill, Rep. Rick Rand says: The House is unlikely to pass the “Ari… http://tinyurl.com/4jrjcdz”, “timeStr”: “Sun Jan 23 00:02:37 +0000 2011”, “tweetId”: “28965792812892160”, “errorCode”: “200”, “textCleaned”: " ", “relevance”: 2}
{“userName”: “servando”, “clusterNo”: 35, “text”: “Mourners recall Sarge Shriver’s charity, idealism \n (AP): AP - R. Sargent Shriver was always an optimist, pio… http://bit.ly/gqMcdG”, “timeStr”: “Sun Jan 23 00:07:48 +0000 2011”, “tweetId”: “28967095878287360”, “errorCode”: “200”, “textCleaned”: " ", “relevance”: 1}
{“userName”: “Heide Eversoll”, “clusterNo”: 60, “text”: “Bass Fishing Techniques: 2 Fantastic Tips To Improve Your Casting Skills”, “timeStr”: “Sun Jan 23 00:10:05 +0000 2011”, “tweetId”: “28967672074993664”, “errorCode”: “200”, “textCleaned”: " ", “relevance”: 2}
{“userName”: “Ailsa Hung”, “clusterNo”: 97, “text”: “#Financial Aid | Proper Method Of Getting Financial Aid For Education http://ping.fm/BK0R3 #applying-for-financial-aid financial-aid-essay #”, “timeStr”: “Sun Jan 23 00:11:03 +0000 2011”, “tweetId”: “28967914417688576”, “errorCode”: “200”, “textCleaned”: " ", “relevance”: 2}
{“userName”: “Brothy”, “clusterNo”: 89, “text”: “Supreme Court: NASA’s intrusive background checks OK http://bit.ly/h2jgy9”, “timeStr”: “Sun Jan 23 00:13:18 +0000 2011”, “tweetId”: “28968479176531969”, “errorCode”: “200”, “textCleaned”: " ", “relevance”: 2}

由tweets里面数据所反映的情况来看,它并不是严格地按照表格形式来存储每一个数据的,所以我们在搜索过程中才会出现各种各样的问题。所以我们引入一个函数库textblob(TextBlob 是一款 Pythonic 的文本处理工具,用于处理文本数据,它提供了一个简单的 API,用于潜入常见的自然语言处理(NLP)任务,如词性标注、名词短语提取、情感分析、分类、翻译等)。

实验的过程其实就是要在文档的基础上建立索引,通过观察数据,我们发现"username",“clusterno”,“text”,“timestr”,“tweetid”,“errorcode”……这几个属性,唯一能标识对应文档的就是tweetID,所以选取它为主键,进行数据检索,并在最终的结果里将答案输出。而对于这五行数据,我们也发现,它所对应的是一个文档,所以在编程过程中,我们按行处理数据,并将其进行转化。

以下代码是对文本文档进行处理,就是将所有的单词进行统计,将大写字母全部还原为小写,单词改变后的形式也全部还原,便于检索。对应索引构建的第二步第三步的过程,将文本转化为词条的形式,并且按docID排序,这种格式化的处理对信息提取等也很重要。

def tokenize_tweet(document):    #文件的属性
    document=document.lower()   #将所有大写字母返回小写字母并返回字符串
    a=document.index("username")     #返回指定的索引名称
    b=document.index("clusterno")
    c=document.rindex("tweetid") - 1
    d=document.rindex("errorcode")
    e=document.index("text")
    f=document.index("timestr") - 3 #获取时间戳
    #提取twwetid,username,tweet内容三部分主要信息
    document=document[c:d] + document[a:b] + document[e:f]
    terms=TextBlob(document).words.singularize()  #词干提取,单词名词变单数,含特殊处理
    result=[]
    for word in terms:
        expected_str=Word(word)
        expected_str=expected_str.lemmatize("v")     #lemmatize() 方法  对单词进行词形还原,名词找单数,动词找原型
        if expected_str not in uselessTerm:
            result.append(expected_str)
    return result

实验结果截图

1.and操作:figure

2.not操作:
figure

3.or操作:
figure
Codes

# -*- coding: utf-8 -*-
"""
lab-1
author:bad-kids
"""
import sys
from collections import defaultdict
from textblob import TextBlob        #导入文本处理工具
from textblob import Word
uselessTerm=["username","text","tweetid"]
postings=defaultdict(dict)        #inverted
def tokenize_tweet(document):    #文件的属性
    document=document.lower()   #将所有大写字母返回小写字母并返回字符串
    a=document.index("username")     #返回指定的索引名称
    b=document.index("clusterno")
    c=document.rindex("tweetid") - 1
    d=document.rindex("errorcode")
    e=document.index("text")
    f=document.index("timestr") - 3 #获取时间戳
    #提取twwetid,username,tweet内容三部分主要信息
    document=document[c:d] + document[a:b] + document[e:f]
    
    terms=TextBlob(document).words.singularize()  #词干提取,单词名词变单数,含特殊处理
    result=[]
    for word in terms:
        expected_str=Word(word)
        expected_str=expected_str.lemmatize("v")     #lemmatize() 方法  对单词进行词形还原,名词找单数,动词找原型
        if expected_str not in uselessTerm:
            result.append(expected_str)
    return result
#读取文档
def get_postings():
    global postings
    f=open(r"E:\myClass2\data-mining\expriment\lab1\tweets.txt")  #打开document文件
    lines=f.readlines()
    for line in lines:
        line=tokenize_tweet(line)  #令牌化,解析一行数据
        
        tweetid=line[0] 
        line.pop(0)
        unique_terms=set(line)
        for te in unique_terms:
            if te in postings.keys():
                postings[te].append(tweetid)
            else:
                postings[te]=[tweetid]
def op_and(term1,term2):      #and与操作
    global postings       #全局变量
    answer=[]
    if(term1 not in postings) or (term2 not in postings):
        return answer
    else:
        i=len(postings[term1])       #获取词长度
        j=len(postings[term2])
        x=0
        y=0
        while x<i and y<j:
            if postings[term1][x]==postings[term2][y]:
                answer.append(postings[term1][x])
                x+=1
                y+=1
            elif postings[term1][x]<postings[term2][y]:
                x+=1
            else:
                y+=1
        return answer
def op_or(term1,term2):     #或操作
    answer=[]
    if(term1 not in postings) and (term2 not in postings):
        answer=[]
    elif term2 not in postings:
        answer=postings[term1]
    elif term1 not in postings:
        answer=postings[term2]
    else:
        answer=postings[term1]
        for item in postings[term2]:
            if item not in answer:
                answer.append(item)
    return answer
def op_not(term1,term2):      #非操作
    answer=[]
    if term1 not in postings:
        return answer
    elif term2 not in postings:
        answer=postings[term1]
        return answer
    else:
        answer=postings[term1]
        ANS=[]
        for ter in answer:
            if ter not in postings[term2]:
                ANS.append(ter)
        return ANS
def do_rankSearch(terms):      #倒排索引
    Answer=defaultdict(dict)
    for item in terms:
        if item in postings:
            for tweetid in postings[item]:
                if tweetid in Answer:
                    Answer[tweetid]+=1
                else:
                    Answer[tweetid]=1
    Answer=sorted(Answer.items(),key=lambda asd: asd[1],reverse=True)
    return Answer
def token(doc):
    doc=doc.lower()
    terms=TextBlob(doc).words.singularize()
    result=[]
    for word in terms:
        expected_str=Word(word)
        expected_str=expected_str.lemmatize("v")
        result.append(expected_str)
    return result

def do_search():       #查询
    terms=token(input("input your search query >> "))
    if terms==[]:
        sys.exit()
    if len(terms)==3:
        if terms[1]=="and":
            answer=op_and(terms[0],terms[2])
            print(answer)
        elif terms[1]=="or":
            answer=op_or(terms[0],terms[2])
            print(answer)
        elif terms[1]=="not":
            answer=op_not(terms[0],terms[2])
            print(answer)
        else:
            print("there is a syntax error!")
    else:
        leng=len(terms)
        answer=do_rankSearch(terms)
        print("[Rank_Score: Tweetid]")
        for(tweetid,score) in answer:
            print(str(score/leng)+ ": " + tweetid)
def main():
    get_postings()
    while True:
        do_search()
        
if __name__ == "__main__":
    main()

标签:index,terms,Inverted,索引,Boolean,str,document,postings
来源: https://blog.csdn.net/qq_43738932/article/details/112648411