当前位置: 首页 > article >正文

【Lucene】搜索引擎和文档相关性评分 BM25 算法的工作原理

BM25 算法的工作原理:


什么是 BM25 算法?

BM25 是一种流行的文本检索算法,广泛用于搜索引擎和文档相关性评分。它基于概率检索模型,旨在评估查询和文档之间的相关性。

核心公式

BM25 的公式如下:

score ( D , Q ) = ∑ t ∈ Q I D F ( t ) ⋅ f ( t , D ) ⋅ ( k 1 + 1 ) f ( t , D ) + k 1 ⋅ ( 1 − b + b ⋅ ∣ D ∣ avgdl ) \text{score}(D, Q) = \sum_{t \in Q} IDF(t) \cdot \frac{f(t, D) \cdot (k_1 + 1)}{f(t, D) + k_1 \cdot (1 - b + b \cdot \frac{|D|}{\text{avgdl}})} score(D,Q)=tQIDF(t)f(t,D)+k1(1b+bavgdlD)f(t,D)(k1+1)

  • I D F ( t ) IDF(t) IDF(t):词项 ( t ) 的逆文档频率。
  • f ( t , D ) f(t, D) f(t,D):词项 ( t ) 在文档 ( D ) 中的频率。
  • ∣ D ∣ |D| D:文档 ( D ) 的长度。
  • avgdl \text{avgdl} avgdl:所有文档的平均长度。
  • k 1 k_1 k1:控制词项饱和度的参数,通常取 ( 1.2 )。
  • b b b:长度归一化参数,通常取 ( 0.75 )。
IDF 的计算

I D F ( t ) = log ⁡ N − n t + 0.5 n t + 0.5 + 1 IDF(t) = \log \frac{N - n_t + 0.5}{n_t + 0.5} + 1 IDF(t)=lognt+0.5Nnt+0.5+1

  • ( N ):文档总数。
  • ( n_t ):包含词 ( t ) 的文档数量。

代码实现

以下是 BM25 的简单 Python 实现:

import math

class BM25:
    def __init__(self, documents, k1=1.2, b=0.75):
        self.documents = documents
        self.k1 = k1
        self.b = b
        self.doc_lengths = [len(doc) for doc in documents]
        self.avgdl = sum(self.doc_lengths) / len(self.doc_lengths)
        self.inverted_index = self._build_inverted_index()

    def _build_inverted_index(self):
        index = {}
        for i, doc in enumerate(self.documents):
            for word in set(doc):
                index.setdefault(word, []).append(i)
        return index

    def idf(self, term):
        n_t = len(self.inverted_index.get(term, []))
        return math.log((len(self.documents) - n_t + 0.5) / (n_t + 0.5) + 1)

    def score(self, query, doc_index):
        doc = self.documents[doc_index]
        score = 0
        for term in query:
            if term in doc:
                f = doc.count(term)
                idf = self.idf(term)
                score += idf * ((f * (self.k1 + 1)) / (f + self.k1 * (1 - self.b + self.b * len(doc) / self.avgdl)))
        return score

# 示例文档
documents = [
    ["hello", "world", "search", "engine"],
    ["hello", "search", "bm25", "algorithm"],
]
bm25 = BM25(documents)

# 查询得分
query = ["hello", "bm25"]
print(bm25.score(query, 0))  # 文档 0 的相关性得分
print(bm25.score(query, 1))  # 文档 1 的相关性得分

图示

  1. 词频与文档长度归一化

    • 用柱状图表示不同文档中词频和长度的对比,展示 BM25 如何平衡短文档和长文档。
  2. IDF 权重

    • 用折线图展示常见词和稀有词的 IDF 值,突出稀有词对相关性的重要贡献。

为细化 BM25 相关图表,以下是具体建议和生成方式:


图表 1: 词频与文档长度归一化

目标:展示 BM25 如何平衡短文档和长文档的评分。

  • 图类型:条形图。
  • 数据结构:每个文档的总词频与长度。
  • 关键点:对比文档长度对评分的影响。
    在这里插入图片描述

示例生成代码(使用 Matplotlib):

import matplotlib.pyplot as plt

# 示例文档数据
doc_lengths = [4, 4, 6, 10]  # 文档长度
term_frequencies = [2, 3, 4, 5]  # 查询词的频率

# 绘图
plt.bar(range(len(doc_lengths)), doc_lengths, label="Document Lengths", alpha=0.6)
plt.bar(range(len(term_frequencies)), term_frequencies, label="Term Frequencies", alpha=0.6)
plt.xlabel("Documents")
plt.ylabel("Values")
plt.legend()
plt.title("Term Frequency vs Document Length")
plt.show()

图表 2: 逆文档频率 (IDF) 权重

目标:展示 IDF 在常见词与稀有词上的差异。

  • 图类型:折线图。
  • 数据结构:不同词项的文档频率与其对应的 IDF。
  • 关键点:稀有词拥有更高权重,帮助区分相关性。
    在这里插入图片描述

示例生成代码:

import numpy as np

# 示例词项数据
doc_count = 100  # 总文档数
term_doc_freq = np.array([1, 5, 20, 50, 90])  # 包含查询词的文档数
idf_values = np.log((doc_count - term_doc_freq + 0.5) / (term_doc_freq + 0.5) + 1)

# 绘图
plt.plot(term_doc_freq, idf_values, marker='o')
plt.xlabel("Term Document Frequency")
plt.ylabel("IDF Value")
plt.title("IDF Curve")
plt.grid()
plt.show()

图表 3: BM25 综合评分变化

目标:展示 BM25 参数 (k_1) 和 (b) 的调整对评分的影响。

  • 图类型:3D 表面图或热图。
  • 数据结构:BM25 分数在不同 (k_1) 和 (b) 参数组合下的变化。
  • 关键点:参数对相关性评分的微调作用。

在这里插入图片描述

示例生成代码:

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

# 参数网格
k1 = np.linspace(0.5, 2.0, 50)
b = np.linspace(0.0, 1.0, 50)
k1, b = np.meshgrid(k1, b)
scores = (k1 + 1) / (k1 * (1 - b + b * 0.5) + 1)

# 绘制 3D 图
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(k1, b, scores, cmap='viridis')
ax.set_xlabel("k1")
ax.set_ylabel("b")
ax.set_zlabel("Score")
ax.set_title("BM25 Scoring Surface")
plt.show()

以上图表可以帮助直观理解 BM25 的重要概念。

ref:https://emschwartz.me/understanding-the-bm25-full-text-search-algorithm/?continueFlag=1f3c7fda32b1a504d3118d71fe55ae8f


http://www.kler.cn/a/404262.html

相关文章:

  • 实战 | C#中使用YoloV8和OpenCvSharp实现目标检测 (步骤 + 源码)
  • Python深度学习环境配置(Pytorch、CUDA、cuDNN),包括Anaconda搭配Pycharm的环境搭建以及基础使用教程(保姆级教程,适合小白、深度学习零基础入门)
  • springboot基于微信小程序的旧衣回收系统的设计与实现
  • 嵌入式Linux的RTC读写操作应用
  • 大语言模型中ReLU函数的计算过程及其函数介绍
  • Statsmodels之OLS回归
  • 大数据新视界 -- 大数据大厂之 Impala 性能优化:资源分配与负载均衡的协同(下)(24 / 30)
  • 如何使用GPT API 自定义 自己的 RAG
  • [羊城杯 2020]easyre
  • Java基础夯实——2.6 Java中的锁
  • 【Linux网络编程】套接字使用--TCP echo server的实现
  • 【腾讯云产品最佳实践】腾讯云CVM入门技术与实践:通过腾讯云快速构建云上应用
  • Jmeter中的断言(三)
  • 《Vue零基础入门教程》第一课:Vue简介
  • 初识ArkUI
  • SAP BC 记录一次因为HANA服务器内存满的问题
  • 如何选择合适的数据集成工具或平台来实现全域数据的高效整合
  • 机器学习之量子机器学习(Quantum Machine Learning, QML)
  • Lucene数据写入与数据刷盘机制
  • 0基础跟德姆(dom)一起学AI NLP自然语言处理01-自然语言处理入门
  • 实验室管理现代化:Spring Boot技术方案
  • ros2--实时性--preempt-rt
  • 系统安全第十四次作业题目及答案
  • 备赛蓝桥杯--算法题目(1)
  • AWS云服务器:开启高效计算的新纪元
  • YOLOP 多任务算法详解