BM25(Best Matching 25)算法基本思想
BM25(Best Matching 25)是一种用于信息检索(Information Retrieval)和文本挖掘的算法,它被广泛应用于搜索引擎和相关领域。BM25 基于 TF-IDF(Term Frequency-Inverse Document Frequency)的思想,但对其进行了改进以考虑文档的长度等因素。
一.基本思想
以下是 BM25 算法的基本思想:
TF-IDF 的改进: BM25 通过对文档中的每个词项引入饱和函数(saturation function)和文档长度因子,改进了 TF-IDF 的计算。 饱和函数: 在 BM25 中,对于词项的出现次数(TF),引入了一个饱和函数来调整其权重。这是为了防止某个词项在文档中出现次数过多导致权重过大。 文档长度因子: BM25 考虑了文档的长度,引入了文档长度因子,使得文档长度对权重的影响不是线性的。这样可以更好地适应不同长度的文档。
二.计算方程
BM25 的具体计算公式如下:
其中:
是查询中的词项数。 是查询中的第个词项。 是逆文档频率,计算方式通常是,其中是文档总数, 是包含词项的文档数。 是词项在文档 中的出现次数(TF)。 是文档 的长度。 是所有文档的平均长度。 和 是调整参数,通常设置为 和 。
BM25 算法的实现通常用于排序文档,使得与查询更相关的文档排名更靠前。在信息检索领域,BM25 已经成为一个经典的算法。
三.Python 实现
以下是一个简单的 Python 实现 BM25 算法的例子。请注意,实际应用中可能需要进行更复杂的文本预处理,例如去除停用词、词干化等。
import math
from collections import Counter
class BM25:
def __init__(self, corpus, k1=1.5, b=0.75):
self.k1 = k1
self.b = b
self.corpus = corpus
self.doc_lengths = [len(doc) for doc in corpus]
self.avg_doc_length = sum(self.doc_lengths) / len(self.doc_lengths)
self.doc_count = len(corpus)
self.doc_term_freqs = [Counter(doc) for doc in corpus]
self.inverted_index = self.build_inverted_index()
def build_inverted_index(self):
inverted_index = {}
for doc_id, doc_term_freq in enumerate(self.doc_term_freqs):
for term, freq in doc_term_freq.items():
if term not in inverted_index:
inverted_index[term] = []
inverted_index[term].append((doc_id, freq))
return inverted_index
def idf(self, term):
doc_freq = len(self.inverted_index.get(term, []))
if doc_freq == 0:
return 0
return math.log((self.doc_count - doc_freq + 0.5) / (doc_freq + 0.5) + 1.0)
def bm25_score(self, query_terms, doc_id):
score = 0
doc_length = self.doc_lengths[doc_id]
for term in query_terms:
tf = self.doc_term_freqs[doc_id].get(term, 0)
idf = self.idf(term)
numerator = tf * (self.k1 + 1)
denominator = tf + self.k1 * (1 - self.b + self.b * (doc_length / self.avg_doc_length))
score += idf * (numerator / denominator)
return score
def rank_documents(self, query):
query_terms = query.split()
scores = [(doc_id, self.bm25_score(query_terms, doc_id)) for doc_id in range(self.doc_count)]
sorted_scores = sorted(scores, key=lambda x: x[1], reverse=True)
return sorted_scores
# Example usage
corpus = [
"The quick brown fox jumps over the lazy dog",
"A quick brown dog outpaces a swift fox",
"The dog is lazy but the fox is swift",
"Lazy dogs and swift foxes"
]
bm25 = BM25(corpus)
query = "quick brown dog"
result = bm25.rank_documents(query)
print("BM25 Scores for the query '{}':".format(query))
for doc_id, score in result:
print("Document {}: {}".format(doc_id, score))
此代码创建了一个简单的 BM25 类,通过给定的语料库计算查询与文档的相关性得分。
NLP工程化
1.本公众号以对话系统为中心,专注于Python/C++/CUDA、ML/DL/RL和NLP/KG/DS/LLM领域的技术分享。
2.本公众号Roadmap可查看飞书文档:https://z0yrmerhgi8.feishu.cn/wiki/Zpewwe2T2iCQfwkSyMOcgwdInhf
NLP工程化

飞书文档

BM25(Best Matching 25)算法基本思想的更多相关文章
- MP算法和OMP算法及其思想
主要介绍MP(Matching Pursuits)算法和OMP(Orthogonal Matching Pursuit)算法[1],这两个算法尽管在90年代初就提出来了,但作为经典的算法,国内文献(可 ...
- 用哈希算法的思想解决排序和字符串去重问题,时间复杂度为O(N)
第一个题目: int a[] = {12,13,12,13,19,18,15,12,15,16,17},要求对数组a进行排序,要求时间复杂度为O(N) 我们所知道的常规排序中,最优的解法也就是O(N* ...
- 从NLP任务中文本向量的降维问题,引出LSH(Locality Sensitive Hash 局部敏感哈希)算法及其思想的讨论
1. 引言 - 近似近邻搜索被提出所在的时代背景和挑战 0x1:从NN(Neighbor Search)说起 ANN的前身技术是NN(Neighbor Search),简单地说,最近邻检索就是根据数据 ...
- icp算法基本思想
Icp基本思想参考资料:http://www.cnblogs.com/jian-li/articles/4945676.html ,包括点-点,点-面的各种icp变种 Icp算法就是两个点云X.Y之间 ...
- Python算法——递归思想
编程语言在构建程序时的基本操作有:内置数据类型操作.选择.循环.函数调用等,递归实际属于函数调用的一种特殊情况(函数调用自身),其数学基础是数学归纳法.递归在计算机程序设计中非常重要,是许多高级算法实 ...
- dinic 算法 基本思想及其模板
“网络流博大精深”—sideman语 一个基本的网络流问题 感谢WHD的大力支持 最早知道网络流的内容便是最大流问题,最大流问题很好理解: 解释一定要通俗! 如右图所示,有一个管道系统,节点{1,2, ...
- PAT 1033 To Fill or Not to Fill (25分) 贪心思想
题目 With highways available, driving a car from Hangzhou to any other city is easy. But since the tan ...
- H5编辑器核心算法和思想-遁地龙卷风
代码和特性在chrome49下测试有效. 文本渲染的本质是对文本节点的渲染,通过浏览器内置的对象Range可以获得选择的起始点.与终止点 var range = getRangeObject(); ...
- OpenCV stereo matching BM 算法
一直找不到opencv stereo matching的根据和原理出处,下面这个文章贴了个链接,有时间看看: Basically OpenCV provides 2 methods to calcul ...
- 浅谈Tarjan算法及思想
在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强连通子图,称为强连 ...
随机推荐
- 【PHP正则表达式】
[PHP正则表达式] 最近写题总是遇到php正则表达式的匹配函数,于是进行一个总结. 1.什么是正则表达式 是php在进行搜索时用于匹配的模式字符串.一般用于php对特定字符序列的替换和搜索. 2.正 ...
- redis主从同步及redis哨兵机制
1.主从和哨兵的作用: 角色 作用 主从 1.(提供)数据副本:多一份数据副本,保证redis高可用 2. 扩展(读)性能:如容量.QPS等 哨兵 1.监控: 监控redis主库及从库运行状态: 2 ...
- 一文讲透DevOps理论体系的演进
一.前言 当前,我国处于以信息化.数字化.网络化.智能化为特征的科技变革浪潮中,企业数字化转型大势所趋,那么作为支撑企业IT运转的运营体系也在向多元方向发展,比如DevOps(研发运营一体化).AIO ...
- Java8新特性(Lambda表达式、Stream流、Optional类)等
1. Lambda表达式由来 1 package java8; 2 3 public class EmployeeTest { 4 public static void main(String[] a ...
- EFCore 使用FluntApi配置 全局查询筛选器
我们在类中通常会有一个属性为 IsDel来表示软删除或也称逻辑删除,这个属性会导致我们在进行查询操作时,每一次都要 .where(s=>s.IsDel==false) 非常的麻烦.在使用efCo ...
- 【发布】DDD 工程脚手架 + 一键安装分布式技术栈环境!
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 大家好,我是技术UP主小傅哥. 写了那么多案例工程,开发了那么多技术项目.那小傅哥做的这些案例 ...
- 二进制安装Kubernetes(k8s)v1.28.3
二进制安装Kubernetes(k8s)v1.28.3 https://github.com/cby-chen/Kubernetes 开源不易,帮忙点个star,谢谢了 介绍 kubernetes(k ...
- 生成伪随机数 rand;srand函数
1 相关内容来自鱼c论坛https://fishc.com.cn/forum.php?mod=viewthread&tid=84363&extra=page%3D1%26filter% ...
- C语言输入任意长度数组后,再在该数组中查找特定的值,并且可查找多个相同的值
C语言输入任意长度数组后,再在该数组中查找特定的值,并且可查找多个相同的值 例:在a[20] = { 99,42,57,74,46,85,32,78,40,33,74,88,65,27,38,69,5 ...
- 浮点类型(double与float及其它们的输入输出)
<1>浮点类型 (1)两种类型 double 字长64位(8个字节),有效数字15,范围大概为2.2* 10^-308 ~ 1.79*10^308,0,nan; float字长32位(4个 ...