谷歌拥有数以万亿计的网页,它是如何高效地为搜索相关网页而不需要页面URL的呢?信息检索系统允许基于文档的有意义信息高效地搜索文档。正如所知,两个句子可能结构完全不同,使用的词汇也不同,但它们可能具有相同的含义。在NLP中,目标是捕获句子的含义,通过使用各种NLP概念,将在本文中详细探讨。
执行基于上下文含义的信息检索系统。
执行信息检索有多种方法。但使用词嵌入是一种既简单又高效的方法。词嵌入考虑了上下文含义,而不管句子结构如何。
信息检索系统的应用包括文档检索、段落检索、搜索引擎和问答系统。
已经写过一篇关于各种特征提取技术的文章,包括词嵌入的实现,如果还没有阅读,可以通过查看。词嵌入能够理解句子的含义,不管词汇结构如何。例如,“喜欢他”和“爱他”在使用词嵌入时几乎具有相同的含义。
将使用Python实现信息检索系统。在实现过程中,需要遵循以下步骤:
创建了自己的数据集,包含4个文档,为了更好地理解,将使用一个小数据集。
Doc1 = ["""浪费自然资源是一个非常严重的问题,因为都知道自然资源是有限的,但仍然没有感觉到。使用它超过需要的,政府也鼓励人们节约自然资源。"""]
Doc2 = ["""机器学习是现在非常流行的研究领域,正在进行持续的研究,机器学习是关于数学的。分析模式解决问题。"""]
Doc3 = ["""现在书籍正在失去它的魅力,因为手机和智能设备已经取代了旧时代,书籍现在以数字方式印刷,这节省了纸张,最终节省了成千上万的树木。"""]
Doc4 = ["""站在门后的男子是MS DHONI,他快速的手在门后是印度的一大优势,但Pant现在正在继承DHONI的遗产,但他没有那么快。"""]
这里有4个文档,数据集将是一个由逗号分隔的文档列表。
将一次性导入所有将被使用到的依赖。
import numpy as np
import nltk
import itertools
from nltk.corpus import stopwords
from nltk.tokenize import sent_tokenize, word_tokenize
import scipy
from scipy import spatial
import re
tokenizer = ToktokTokenizer()
stopword_list = nltk.corpus.stopwords.words('english')
在NLP中,数据清洗总是概括训练并承诺更好的结果。加载数据后进行数据清洗始终是一个好习惯。
def remove_stopwords(text, is_lower_case=False):
pattern = r'[^a-zA-z0-9s]'
text = re.sub(pattern," ",''.join(text))
tokens = tokenizer.tokenize(text)
tokens = [tok.strip() for tok in tokens]
if is_lower_case:
cleaned_token = [tok for tok in tokens if tok not in stopword_list]
else:
cleaned_tokens = [tok for tok in tokens if tok.lower() not in stopword_list]
filtered_text = ' '.join(cleaned_tokens)
return filtered_text
函数remove_stopwords逐个处理文档,并返回清洗后的文档。首先使用正则表达式移除所有不必要的字符。移除不必要的字符后,对过滤后的单词进行标记化,并使用stopword_list过滤掉所有停用词。
将使用预训练的300维词向量。可以使用这个下载词向量。建议在Kaggle上创建一个笔记本,如果不想下载大文件的世界向量。
glove_vectors = dict()
file = open('../input/glove6b/glove.6B.300d.txt', encoding = 'utf-8')
for line in file:
values = line.split()
word = values[0]
vectors = np.asarray(values[1:])
glove_vectors[word] = vectors
file.close()
glove_vectors是一个字典,包含单词作为键和特征向量作为值。glove.6B.300d这个词嵌入是在60亿个单词上训练的,特征向量长度为300。如果一个单词不在词向量字典中,它将返回一个长度为300的零向量。
一个文档包含许多句子,一个句子根据句子中出现的单词数量有许多向量。要总结文档的含义,需要平均文档中所有句子的含义。在NLP的语言中,平均文档中所有句子的特征向量。
out_dict = {}
for sen in fin:
average_vector = (np.mean(np.array([get_embedding(x) for x in nltk.word_tokenize(remove_stopwords(sen))]), axis=0))
dict = { sen : (average_vector) }
out_dict.update(dict)
字典out_dict包含文档作为键和它们的平均特征向量作为相应的值。平均特征向量将文档的含义编码为向量。
到目前为止,已经拥有每个文档的特征向量,需要构建一个函数,可以根据它们的含义比较特征向量。两个词的相似性可以通过它们的特征向量之间的余弦距离来计算。
def get_sim(query_embedding, average_vector_doc):
sim = [(1 - scipy.spatial.distance.cosine(query_embedding, average_vector_doc))]
return sim
函数get_sim接受查询的特征向量和所有文档的特征向量,并返回查询和文档之间的相似性。如果相似性sim更高,接近1,可以认为它几乎具有相同的含义。如果相似性sim更接近0,可以认为它们的含义不同。
def Ranked_documents(query):
query_word_vectors = (np.mean(np.array([get_embedding(x) for x in nltk.word_tokenize(query.lower())],dtype=float), axis=0))
rank = []
for k,v in out_dict.items():
rank.append((k, get_sim(query_word_vectors, v)))
rank = sorted(rank,key=lambda t: t[1], reverse=True)
print('Ranked Documents :')
return rank[0]