一、基础介绍
BM25 是一种用来评价搜索词和文档之间相关性的算法。通常用来做搜索相关性评分的,也是ES(弹性搜索)中的搜索算法。通常用来计算搜索和文本集合中每篇文本之间的相关性,并返回对应分数。
二、计算公式
(1) 用Q表示query,在这里Q一般是搜索词条(一个句子)。在此,需要对Q进行语素解析(中文一般是jieba分词),在这里以分词为例,我们对Q进行分词,得到q1,q2,......,qt这样一个词序列。
(2)给定文本d∈D,d属于文档集合中的一个子文档。
(3) 则,基于BM25获得Query与文档集合中d的分数计算表达式如下所示:
上式中,表示的权重,R(,d)为和d的相关性,就是每个词和d的相关性加权和。
(4)针对权值
的计算方法很多,一般用IDF来表示,但这里的IDF计算和上面的有所不同:
其中,表示预料集大小、表示包含词的文档集个数,0.5主要目的是作平滑;
(5)的计算公式
其中,
式子中,为词在文本中出现的频率,为词在中出现的频率,都是可调节的参数(超参),分别为文本的长度和文本集中所有文本的平均长度。
通常,这样可以去除后面一项,将编程:
三、代码实现
参考github代码:https://github.com/dorianbrown/rank_bm25
3.1 库下载
pip install rank_bm25
3.2 库引用
from rank_bm25 import BM25Okapi
3.3 BM25初始化(构建搜索语料库)
from rank_bm25 import BM25Okapi
# 语料库
corpus = [
"Hello there good man!",
"It is quite windy in London",
"How is the weather today?"
]
# 分割成字(中文相当于分词)
# "Hello there good man!",=》 ['Hello','there','good','man']
tokenized_corpus = [doc.split(" ") for doc in corpus]
bm25 = BM25Okapi(tokenized_corpus)
# <rank_bm25.BM25Okapi at 0x1047881d0>
3.4 文档搜索得分(新词条搜索)
# 输入Query搜索词条
query = "windy London"
# 分词
tokenized_query = query.split(" ")
# query与每一个语料库文档的得分
doc_scores = bm25.get_scores(tokenized_query)
# array([0. , 0.93729472, 0. ])
3.5 文档最高得分n个句子,参数n可以调选择top几数据
bm25.get_top_n(tokenized_query, corpus, n=1)
# ['It is quite windy in London']
3.6 文档最高得分n个句子的id,参数n可以调选择top几数据
scores = self.get_scores(query)
top_n = np.argsort(scores)[::-1][:n]
return top_n
四、缺陷
100W数据3个小时,数据量太大的话,真的很慢!!!
优化选择可以做bm25倒排,或faiss 和局部敏感哈希
五、参考文献
1、https://www.cnblogs.com/jiangxinyang/p/10516302.html
2、https://github.com/dorianbrown/rank_bm25
网友评论