信息检索实验2- Ranked retrieval model

实验要求

实验内容

– 在Experiment1的基础上实现最基本的Ranked retrieval model

• Input:a query (like Ron Weasley birthday)

• Output: Return the top K (e.g., K = 100) relevant tweets.

• 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

• 改进Inverted index

• 在Dictionary中存储每个term的DF

• 在posting list中存储term在每个doc中的TF with pairs (docID, tf) • 选做

• 支持所有的SMART Notations

实验目的

实现基本的排名检索模型

实验环境

Windows10、Spyder(Anaconda3)

基本知识及实验原理详解

实验原理分析:

1.对tf-idf的详细理解

TF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术。TF是词频(Term Frequency),IDF是逆文本频率指数(Inverse Document Frequency)。TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。
figure
figure

n i,j 表示的是第i个词在文档j中出现的总次数,分母表示在文档j中其它的所有的词数。
使用上面的公式我们就可以计算出词频。

figure
figure

使用如上公式可以计算出逆文档频率idf,所谓tf-idf=tf*idf。对tf和idf有了一定的理解后,开始进行实验,选择python语言。

需要注意的是罕见词项比常见词所蕴含的信息更多,因此它的权重会更大。

2.排序检索模型

现在回到题目实现排序检索中去,为什么要使用排序检索呢。因为在排序检索模型中,

•系统根据文档与query的相关性排序返回文档集合中的文档,而不是简单地返回所有满足query描述的文档集合

• 自由文本查询:用户query是自然语言的一个或多个词语而不是由查询语言构造的表达式

• 总体上,排序检索模型中有布尔查询和自由文本查询两种方式,但是实际中排序检索模型总是与自由文本查询联系在一起,反之亦然

排序检索的基本——评分

• 我们希望根据文档对查询者的有用性大小顺序将文档返回给查询者

• 怎样根据一个query对文档进行排序?

• 给每个“查询-文档对”进行评分,在[0,1]之间

• 这个评分值衡量文档与query的匹配程度

Jaccard 系数:一种常用的衡量两个集合重叠度的方法,Jaccard(A,B) = |A ∩ B| / |A ∪ B|,Jaccard(A,A) = 1, Jaccard(A,B) = 0 if A ∩ B = 0, 集合A和B不需要具有同样的规模, Jaccard(A,B)的取值在[0,1]。在这里用它来计算terms之间的相似度得分。但是jaccard有一定的缺陷。

最后我们要对最终得分做归一化处理。
figure

3.相关示例

引用课堂里的PPT页面,首先根据cos方法计算最后得分的时候,我们可以看到相关的情况如下图
figure
其中一个例子tf-idf example: lnc.ltc
figure

实验结果图

figure

数据集处理

• 在Dictionary中存储每个term的DF

• 在posting list中存储term在每个doc中的TF with pairs (docID, tf)

代码重要部分解释

相似度得分计算部分

def similarity_NLP(query):
    global score_tid
    t_num={}
    for te in query:
        if te in t_num:
            t_num[te]+=1
        else:
            t_num[te]=1
    for te in t_num.keys():
        if te in postings:
            d_fre=len(postings[te])
        else:
            d_fre=doc_nums
        t_num[te]=(math.log(t_num[te])+1)*math.log(doc_nums/d_fre)
    for te in query:
        if te in postings:
            for tid in postings[te]:
                if tid in score_tid.keys():
                    score_tid[tid]+=postings[te][tid]*t_num[te]
                else:
                    score_tid[tid]=postings[te][tid]*t_num[te]
    similarity=sorted(score_tid.items(),key=lambda x:x[1],reverse=True)  #降序排序,文档匹配度高的优先
    return similarity

归一化处理

就是指消除某些特征造成的过大的影响,核心思想就是
n o r = 1 ∑ d n u m [ t e r m s ] nor=\frac{1}{ \sqrt{∑dnum[terms]}} nor=dnum[terms] 1

 #归一化
        #normalized() 
        nor=0
        for te in d_num.keys():
            nor=nor+d_num[te]
        nor=1.0/math.sqrt(nor)
        for te in d_num.keys():
            d_num[te]=d_num[te]*nor 

Code

# -*- coding: utf-8 -*-
"""
Created on Fri Oct 16 08:02:19 2020

@author: bad-kids
"""
import sys
import math
from functools import reduce  
from textblob import TextBlob
from textblob import Word
from collections import defaultdict

uselessTerm = ["username", "text", "tweetid"]
postings = defaultdict(dict)     #记录df
doc_nums = 0
d_num=defaultdict(int)#文档数
t_num=defaultdict(int)#词数
score_tid=defaultdict(dict)

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 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 get_postings():
    global postings,doc_nums
    f = open(r"E:\myClass2\data-mining\expriment\lab1\tweets.txt")
    lines = f.readlines()  # 读取全部内容
    for line in lines:
        doc_nums+=1
        line = tokenize_tweet(line)
        tweetid = line[0]  # 这里记录一下tweetid,就弹出
        line.pop(0)
        d_num={}
        for te in line:
            if te in d_num.keys():
                d_num[te]+=1
            else:
                d_num[te]=1
        for te in d_num.keys():
            d_num[te]=math.log(d_num[te])+1
        #归一化
        #normalized() 
        nor=0
        for te in d_num.keys():
            nor=nor+d_num[te]
        nor=1.0/math.sqrt(nor)
        for te in d_num.keys():
            d_num[te]=d_num[te]*nor 
    # 按字典序对postings进行升序排序,返回的是列表
        unique_terms=set(line)
        for te in unique_terms:
            if te in postings.keys():
                postings[te][tweetid]=d_num[te]
            else:
                postings[te][tweetid]=d_num[te]

def do_search():
    query = token(input("please input search query >> "))
    result = []  # 返回对于query的所有tweetid排序后的列表
    if query == []:
        sys.exit()
    unique_query = set(query)
    relevant_tweetids = Union([set(postings[term].keys()) for term in unique_query])
    print ("score(NLP): Tweeetid")
    print("NLP一共有"+str(len(relevant_tweetids))+"条相关tweet!")
    if not relevant_tweetids:
        print("No tweets matched any query terms for")
        print(query)
    else:
        # NLP文本分类
        print("the top 50 tweets are:")#调用sorted函数对score进行排序
        scores=similarity_NLP(query)
        i = 1
        for (id, score) in scores:
            if i<=50:#返回前n条查询到的信息
                result.append(id)
                print(str(score) + ": " + id)
                i = i + 1
            else:
                break
        print("finished")
#计算相似度得分
def similarity_NLP(query):
    global score_tid
    t_num={}
    for te in query:
        if te in t_num:
            t_num[te]+=1
        else:
            t_num[te]=1
    for te in t_num.keys():
        if te in postings:
            d_fre=len(postings[te])
        else:
            d_fre=doc_nums
        t_num[te]=(math.log(t_num[te])+1)*math.log(doc_nums/d_fre)
    for te in query:
        if te in postings:
            for tid in postings[te]:
                if tid in score_tid.keys():
                    score_tid[tid]+=postings[te][tid]*t_num[te]
                else:
                    score_tid[tid]=postings[te][tid]*t_num[te]
    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 main():
    get_postings()
    while True:
        do_search()
        
if __name__ == "__main__":
    main()

实验数据

实验数据tweet

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值