BM25(Best Matching 25)是一种用于信息检索(Information Retrieval)和文本挖掘的算法,它被广泛应用于搜索引擎和相关领域。BM25 基于 TF-IDF(Term Frequency-Inverse Document Frequency)的思想,但对其进行了改进以考虑文档的长度等因素。

一.基本思想

  以下是 BM25 算法的基本思想:

  1. TF-IDF 的改进: BM25 通过对文档中的每个词项引入饱和函数(saturation function)和文档长度因子,改进了 TF-IDF 的计算。
  2. 饱和函数: 在 BM25 中,对于词项的出现次数(TF),引入了一个饱和函数来调整其权重。这是为了防止某个词项在文档中出现次数过多导致权重过大。
  3. 文档长度因子: 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)算法基本思想的更多相关文章

  1. MP算法和OMP算法及其思想

    主要介绍MP(Matching Pursuits)算法和OMP(Orthogonal Matching Pursuit)算法[1],这两个算法尽管在90年代初就提出来了,但作为经典的算法,国内文献(可 ...

  2. 用哈希算法的思想解决排序和字符串去重问题,时间复杂度为O(N)

    第一个题目: int a[] = {12,13,12,13,19,18,15,12,15,16,17},要求对数组a进行排序,要求时间复杂度为O(N) 我们所知道的常规排序中,最优的解法也就是O(N* ...

  3. 从NLP任务中文本向量的降维问题,引出LSH(Locality Sensitive Hash 局部敏感哈希)算法及其思想的讨论

    1. 引言 - 近似近邻搜索被提出所在的时代背景和挑战 0x1:从NN(Neighbor Search)说起 ANN的前身技术是NN(Neighbor Search),简单地说,最近邻检索就是根据数据 ...

  4. icp算法基本思想

    Icp基本思想参考资料:http://www.cnblogs.com/jian-li/articles/4945676.html ,包括点-点,点-面的各种icp变种 Icp算法就是两个点云X.Y之间 ...

  5. Python算法——递归思想

    编程语言在构建程序时的基本操作有:内置数据类型操作.选择.循环.函数调用等,递归实际属于函数调用的一种特殊情况(函数调用自身),其数学基础是数学归纳法.递归在计算机程序设计中非常重要,是许多高级算法实 ...

  6. dinic 算法 基本思想及其模板

    “网络流博大精深”—sideman语 一个基本的网络流问题 感谢WHD的大力支持 最早知道网络流的内容便是最大流问题,最大流问题很好理解: 解释一定要通俗! 如右图所示,有一个管道系统,节点{1,2, ...

  7. 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 ...

  8. H5编辑器核心算法和思想-遁地龙卷风

    代码和特性在chrome49下测试有效. 文本渲染的本质是对文本节点的渲染,通过浏览器内置的对象Range可以获得选择的起始点.与终止点   var range = getRangeObject(); ...

  9. OpenCV stereo matching BM 算法

    一直找不到opencv stereo matching的根据和原理出处,下面这个文章贴了个链接,有时间看看: Basically OpenCV provides 2 methods to calcul ...

  10. 浅谈Tarjan算法及思想

    在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强连通子图,称为强连 ...

随机推荐

  1. Java11配置maven

    这里假设Java11和maven都正确安装,使用的版本为Java11.maven3.6.1 测试环境变量 Java win + r 打开运行,输入 cmd,打开命令行提示符,输入java --vers ...

  2. 深入理解 Netty FastThreadLocal

    作者:vivo 互联网服务器团队- Jiang Zhu 本文以线上诡异问题为切入点,通过对比JDK ThreadLocal和Netty FastThreadLocal实现逻辑以及优缺点,并深入解读源码 ...

  3. 2D物理引擎 Box2D for javascript Games 第五章 碰撞处理

    2D物理引擎 Box2D for javascript Games 第五章 碰撞处理 碰撞处理 考虑到 Box2D 世界和在世界中移动的刚体之间迟早会发生碰撞. 而物理游戏的大多数功能则依赖于碰撞.在 ...

  4. JS个人总结(1)

    1. html页面引入js文件优先使用引入外部js文件. 2. 如果在html页面里使用<script></script>,则把js内容放在html内容下面,也就是</b ...

  5. 实战|如何低成本训练一个可以超越 70B Llama2 的模型 Zephyr-7B

    每一周,我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新,包括我们的产品和平台更新.社区活动.学习资源和内容更新.开源库和模型更新等,我们将其称之为「Hugging Ne ...

  6. Python:基础&爬虫

    Python:基础&爬虫 Python爬虫学习(网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另 ...

  7. 完蛋!我被 Out of Memory 包围了!

    是极致魅惑.洒脱自由的Java heap space? 是知性柔情.温婉大气的GC overhead limit exceeded? 是纯真无邪.活泼可爱的Metaspace? 如果以上不是你的菜,那 ...

  8. 实例讲解C++连接各种数据库,包含SQL Server、MySQL、Oracle、ACCESS、SQLite 和 PostgreSQL、MongoDB 数据库

    C++ 是一种通用的编程语言,可以使用不同的库和驱动程序来连接各种数据库.以下是一些示例代码,演示如何使用 C++ 连接 SQL Server.MySQL.Oracle.ACCESS.SQLite 和 ...

  9. .net下功能强大的HTML解析库HtmlAgilityPack,数据抓取必备

    HtmlAgilityPack是一个.NET平台下的HTML解析库,它可以将HTML文本转换为DOM文档对象,方便我们对HTML文本进行操作和分析.HtmlAgilityPack支持XPath语法,可 ...

  10. CLion安装与配置教程

    一.下载并安装CLion 1.下载 1.官网: Download CLion 2.注意: 这里建议使用2021.1.3版本之前,为之后的使用便利而做打算. (这里以Windows系统为例,其他系统类似 ...