BM25算法评估文本检索结果的详细步骤如下:
- 数据准备:收集文本数据集,包括标题、作者和内容等信息。
- 文本预处理:对文本进行预处理操作以便进行后续计算。常见的预处理包括分词、去除停用词(如一些常见的虚词、标点符号等)、词干化(将词汇还原为其原始形式)等。可以使用自然语言处理(NLP)库如NLTK、spaCy等进行预处理操作。
- 构建倒排索引:将预处理后的文本构建成倒排索引,以加速检索。倒排索引是一个词项到文档的映射,每个词项对应一个包含该词项的文档列表。
- 计算文档权重:使用BM25算法计算每个文档的权重。BM25算法考虑了词项的出现频率、文档长度和文档集合中的文档频率等因素。可以根据文本的标题、作者、内容等信息计算每个文本的得分,得分越高表示与查询的相关性越高。
- 查询处理:对用户的查询进行与步骤2相同的预处理操作,将查询文本转化为查询词项。
- 计算查询权重:根据BM25算法计算查询的权重。与步骤4类似,考虑词项在查询中的出现频率、查询长度和文档集合中的文档频率等因素。
- 检索与排序:使用查询的权重与步骤4中计算的文档权重进行匹配,得到每个文本与查询的相关性得分。根据得分对文档进行排序,得分越高的排在前面,表示与查询相关性更高。
- 结果展示与评估:将排序后的检索结果展示给用户,并进行相关性评估。常见的评估指标包括精确度、召回率、F1值等。
代码
from math import log
class BM25:
def __init__(self, docs):
self.docs = docs
self.doc_freq = {}
self.avg_doc_len = 0
self.k1 = 1.5
self.b = 0.75
self.calc_doc_freq()
def calc_doc_freq(self):
doc_len_sum = 0
for doc in self.docs:
doc_len_sum += len(doc)
term_set = set(doc)
for term in term_set:
if term in self.doc_freq:
self.doc_freq[term] += 1
else:
self.doc_freq[term] = 1
self.avg_doc_len = doc_len_sum / len(self.docs)
def calc_score(self, query):
scores = []
query_terms = set(query)
for doc in self.docs:
doc_len = len(doc)
score = 0
for term in query_terms:
if term in doc:
tf = doc.count(term)
idf = log((len(self.docs) - self.doc_freq.get(term, 0) + 0.5) / (self.doc_freq.get(term, 0) + 0.5))
score += idf * (tf * (self.k1 + 1)) / (tf + self.k1 * (1 - self.b + self.b * doc_len / self.avg_doc_len))
scores.append(score)
return scores
# 示例数据
docs = [
["诗歌1", "作者1", "诗歌1内容"],
["诗歌2", "作者2", "诗歌2内容"],
["诗歌3", "作者3", "诗歌3内容"],
# ...
]
# 初始化BM25模型
bm25_model = BM25(docs)
# 查询
query = ["关键词1", "关键词2", "关键词3"]
scores = bm25_model.calc_score(query)
# 结果排序
result = sorted(zip(docs, scores), key=lambda x: x[1], reverse=True)
for doc, score in result:
print(f"相关性得分:{score},诗歌:{doc[0]},作者:{doc[1]},内容:{doc[2]}")
标签:term,文本检索,BM25,doc,self,len,算法,文档,docs
From: https://blog.51cto.com/u_15655475/8853715