编程环境:
anaconda + Spyder
Win10 + python3.6
完整代码及数据已经更新至GitHub,欢迎fork~GitHub链接
声明:创作不易,未经授权不得复制转载
statement:No reprinting without authorization
内容概述:
任务:
在tweets数据集上构建inverted index;
实现Boolean Retrieval Model,使用TREC 2014 test topics进行测试;
Boolean Retrieval Model:
Input:a query (like Ron Weasley birthday)
Output: print a list of top k relevant tweets.
支持and, or ,not;查询优化可以选做;
注意:
对于tweets与queries使用相同的预处理;
一、对推特数据的处理
打开推特的文本数据发现数据具有较好的结构性,信息主要有userName、clusterNo、text、timeStr、tweetId、errorCode、textCleaned、relevance这些部分的信息,但是除了红色标注的,对于我们的检索任务而言,其它的都是冗余的,我们首先需要集中提取出红色的三部分信息来建立inverted index的postings。
按行读取每条tweet后调用tokenize_tweet方法对其进行处理,并进行分词后对单词的统一变小写、单复数和动词形式统一等处理,使用TextBlob工具包,处理后的推特如下所示:
然后进行分词等处理后的推特如下:
最后再构建postings,采用字典结构,其中将每个单词作为键值,后面跟着包含该单词的tweet的tweetid列表。
二、对查询的输入进行处理
注意需要对查询进行和tweet同样的分词等处理,保持一致性,主要代码如下所示:
terms=TextBlob(document).words.singularize()
result=[]
for word in terms:
expected_str = Word(word)
expected_str = expected_str.lemmatize("v")
if expected_str not in uselessTerm:
result.append(expected_str)
return result
主要是对输入的查询进行语义逻辑的识别,判断是什么样的布尔查询,在本次实验中,针对单个and、or、not(A and B、A or B、A not B)三种布尔查询进行了实现,并在此基础上对双层逻辑的如A and B and C、A or B or C、(A and B) or C、(A or B) and C的实现,并作为功能拓展实现了对一般输入语句进行的排序查询,可以返回排序最靠前的若干个结果。如下所示:(用查询的单词在该文档中出现的个数/总数作为简单的排序分数)
def do_search():
terms = token(input("Search query >> "))
if terms == []:
sys.exit()
#搜索的结果答案
if len(terms)==3:
#A and B
if terms[1]=="and":
answer = merge2_and(terms[0],terms[2])
#A or B
elif terms[1]=="or":
answer = merge2_or(terms[0],terms[2])
#A not B
elif terms[1]=="not":
answer = merge2_not(terms[0],terms[2])
#输入的三个词格式不对
else:
print("input wrong!")
elif len(terms)==5:
#A and B and C
if (terms[1]=="and") and (terms[3]=="and"):
answer = merge3_and(terms[0],terms[2],terms[4])
print(answer)
#A or B or C
elif (terms[1]=="or") and (terms[3]=="or"):
answer = merge3_or(terms[0],terms[2],terms[4])
print(answer)
#(A and B) or C
elif (terms[1]=="and") and (terms[3]=="or"):
answer = merge3_and_or(terms[0],terms[2],terms[4])
print(answer)
#(A or B) and C
elif (terms[1]=="or") and (terms[3]=="and"):
answer = merge3_or_and(terms[0],terms[2],terms[4])
print(answer)
else:
print("More format is not supported now!")
#进行自然语言的排序查询,返回按相似度排序的最靠前的若干个结果
else:
leng = len(terms)
answer = do_rankSearch(terms)
print ("[Rank_Score: Tweetid]")
for (tweetid,score) in answer:
print (str(score/leng)+": "+tweetid)
其中merge合并列表时采用同时遍历的方法,降低复杂度为O(x+y),如下merge2_and所示:
def merge2_and(term1,term2):
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
三、查询测试展示
1、A and B、A or B、A not B:
2、A and B and C、A or B or C、(A and B) or C、(A or B) and C:
3、一般的语句查询:
小结:
根据inverted index的模型完成了布尔的查询的要求,复杂的布尔查询也可以在基本的and、or、not逻辑基础实现上嵌套实现,最后通过用查询的单词在该文档中出现的个数/总数作为简单的排序检索比较简陋,结果需要进一步评估,在本次inverted index模型中没有考虑TF、IDF和文档长度等信息,还需要进一步完善来满足更高级的应用需求。
声明:创作不易,未经授权不得复制转载
statement:No reprinting without authorization