BM25算法的概念、定性理解+公式定量理解、举例说明、一文详解。

“BM25 是检索系统的根基算法”,而不是简单的 API 细节问题。下面我会从零假设你“完全不理解 BM25”,一步一步把它讲透,并且所有概念都会和你实际写 ES / RAG / 搜索代码的场景强绑定**。

说明:算法严格名称是 BM25(Best Matching 25),这是一个家族算法的第 25 号变体。


一、BM25 解决的到底是什么问题?

一句话先定性:

BM25 是用来回答一个问题的:
“在一堆文本里,哪一篇最像我现在输入的关键词?”

它不是:

  • 语义理解 ❌
  • 推理 ❌
  • 向量相似度 ❌

它是:

  • 基于词项统计的相关性排序算法

你真实面对的工程问题

假设你有 3 篇文档:

Doc1

AI 合规 平台 支持 监管 报告 自动 生成

Doc2

合规 平台 合规 平台 合规 平台 合规 平台

Doc3

AI 技术 平台 支持 模型 推理

用户 query:

AI 合规 平台

你直觉会觉得:
👉 Doc1 > Doc2 > Doc3

BM25 的目标就是:
用“可解释的数学规则”算出这个顺序


二、BM25 的前身:为什么 TF-IDF 不够好?

在理解 BM25 前,必须先知道它改进了什么


1️⃣ TF(词频)的问题

TF 的原始想法:

一个词在文档里出现越多,说明越相关

问题是:

文档 “合规”出现次数
Doc1 1
Doc2 4

TF 会认为 Doc2 远强于 Doc1

但你作为人会觉得:

Doc2 只是重复刷词,没有更多信息


2️⃣ IDF(逆文档频率)的局限

IDF 解决的是:

“平台”这种词谁都有,权重应该低

IDF 只关心“全局”,不关心“当前文档结构”


3️⃣ 文档长度偏置问题

长文档天然有优势:

词多 → 命中概率高 → 分数高

但长 ≠ 相关。


👉 BM25 的核心目标

同时解决 3 件事:

  1. 词出现一次和出现十次,不应差十倍
  2. 长文档不能天然占便宜
  3. 稀有词比常见词更重要

三、BM25 的直觉版本(非常重要)

我先不给你公式,只给人类直觉版规则

BM25 对每个 query 词做如下判断:


规则 1:这个词在文档里出现了吗?

  • 没出现 → 贡献 0 分
  • 出现了 → 进入下一步

规则 2:出现 1 次和 2 次差很多吗?

  • 第一次出现:加分很大
  • 第二次出现:还行
  • 第 10 次出现:几乎没啥额外价值

👉 这叫“词频饱和”


规则 3:这是一个“稀有词”吗?

  • “AI 合规” → 稀有 → 加分多
  • “系统 平台” → 常见 → 加分少

规则 4:这篇文档是不是特别长?

  • 很长 → 稍微打点折
  • 很短 → 稍微给点优势

BM25 = 把上面 4 条规则数学化


四、现在给你 BM25 的完整公式(逐项拆)

image

我们拆成 4 块。


1️⃣ 外层求和:按“词”算分

image

意思是:

Query 里有几个词,就分别算几次,再加起来

Query:AI 合规 平台
→ 分别算 3 次


2️⃣ IDF(t):这个词值不值钱?

image

直觉解释:

情况 IDF
所有文档都有 接近 0
只有少数文档有 很大

👉 这一步解决“平台 / 系统”这种词的水分问题


3️⃣ 分子:词频 × 放大因子

image

  • ( f(t, D) ):出现次数
  • ( k_1 ):控制“饱和速度”

k1 ≈ 1.2(ES 默认)


4️⃣ 分母:BM25 的“灵魂”

image

这是最重要的一部分。

它做了两件事:

A. 控制 TF 不无限增长

当 ( f ) 越来越大时:

image

👉 再刷词也刷不动了


B. 文档长度归一化

image

  • 文档比平均长 → 分母变大 → 分数下降
  • 文档比平均短 → 分母变小 → 分数上升

b ≈ 0.75(惩罚强度)


五、用一个完整“算分例子”帮你对齐直觉

假设:

  • avgdl = 100
  • Doc1 长度 = 80
  • Doc2 长度 = 300
  • 查询词 “合规”
文档 f(合规)
Doc1 1
Doc2 5

直觉你觉得:

Doc2 不应该是 Doc1 的 5 倍

BM25 会算出:

  • Doc1:接近满分
  • Doc2:略高或相近,但不会成倍增长

六、BM25 的本质总结(非常重要)

BM25 本质不是“相似度”
而是“相关性打分规则”

它的判断逻辑是:

  • 词是否匹配(Boolean 检索)
  • 再按“信息量”给权重
  • 再按“文本结构”做修正

七、为什么 BM25 在你现在的项目里“非常合理”?

结合你的背景(ES + 合规 / 文档 / RAG):

场景 BM25 表现
法规条文 极强
技术文档 极强
精确术语 极强
长文档 稳定
召回阶段 一流
语义改写 不行

八、你下一步应该做什么(建议)

如果你现在 “理解了公式,但没形成肌肉记忆”,我建议你:

  1. explain: true 看真实 BM25 拆解
  2. 手算 1 个 query × 2 个文档
  3. 对比 BM25 vs 向量召回结果

如下BM25公式中的每个字母详细解释:

你这个追问非常到位,而且这是理解 BM25 是否“真正吃透”的分水岭。下面我会严格、完整、逐符号地解释 BM25 公式中出现的每一个字母、每一个常量、每一个下标,不跳步、不省略、不假设你“应该懂”。


一、BM25 完整公式(原样再贴一次)

image

]

下面开始 逐个符号解释


二、最外层符号(对象级别)

1️⃣ ( Q ):Query(查询)

  • 含义:用户输入的查询文本
  • 在 ES 中:"query": "AI 合规 平台"
  • 经过分词后:
    image

2️⃣ ( t \in Q ):Query 中的一个词项(term)

  • ( t ):单个词项

  • 例如:

    • query = "AI 合规 平台"
    • 分词后:

image


3️⃣ ( D ):Document(文档)

  • 含义:索引中的一篇文档

  • ES 中:一条 _source

  • 可以是:

    • 一段法规
    • 一篇文章
    • 一条知识片段

4️⃣ ( score(D, Q) )

  • 含义:文档 D 对查询 Q 的相关性得分

  • ES 中:hit['_score']

  • 数值特性:

    • 无上界
    • 仅用于相对排序

三、求和符号相关(结构层)

5️⃣ ( image

)

  • 含义:
    对 Query 中的每一个词 t 分别算分,再加起来

  • 说明:

    • Query 越长,理论上贡献项越多
    • 如果某个词在文档中不存在,该词贡献为 0

四、IDF 部分(全局统计量)

6️⃣ ( IDF(t) ):Inverse Document Frequency

衡量一个词“稀不稀有”

数学定义:

image


每个符号解释:

6.1️⃣ ( N )

  • 含义:索引中 文档总数

  • 示例:

    • 索引里一共有 100 万篇文档
    • ( N = 1{,}000{,}000 )

6.2️⃣ ( df(t) )(document frequency)

  • 含义:
    包含词项 t 的文档数量

  • 示例:

    • “平台” 出现在 80 万篇文档中
      → ( df(\text{平台}) = 800{,}000 )

6.3️⃣ 常数 ( 0.5 )

  • 含义:平滑项(smoothing)

  • 作用:

    • 防止:

      • 分母为 0
      • IDF 无限大
    • 保证数值稳定


6.4️⃣ 对数 ( \log )

  • 含义:

    • 压缩数值范围
    • 防止极稀有词权重爆炸
  • Lucene 中使用的是自然对数 ln


五、TF 相关部分(局部统计量)

7️⃣ ( f(t, D) ):Term Frequency

  • 含义:
    词项 t 在文档 D 中出现的次数

  • 示例:

    • 文档 D 中 “合规” 出现 3 次
    • ( f(合规, D) = 3 )

8️⃣ ( k_1 ):TF 饱和控制参数

  • 含义:
    控制“词频增长到多少开始饱和”

  • 特点:

    • 数值越大 → 词频影响越强
    • 数值越小 → 更快进入饱和
  • Elasticsearch 默认:
    image


9️⃣ ( k1 + 1 )

  • 含义:
    用于把分子最大值归一化到 1 左右

  • 工程意义:

    • 保证当词频很大时,TF 部分不会超过预期

六、文档长度归一化部分(关键)

🔟 ( |D| ):文档长度

  • 含义:
    文档 D 中的总词项数

  • 注意:

    • 是分词后的 term 数
    • 不是字符数,也不是字节数

1️⃣1️⃣ ( avgdl ):Average Document Length

  • 含义:
    整个索引中,文档长度的平均值
  • 计算方式:
    image

1️⃣2️⃣ image

  • 含义:
    当前文档长度相对于平均文档长度的比例

  • 解释:

    • 1 → 文档偏长

    • <1 → 文档偏短

1️⃣3️⃣ ( b ):长度惩罚系数

  • 含义:
    控制“文档长度”对分数的影响程度
  • 取值范围:
    image
b 值 含义
0 完全不考虑长度
1 完全按长度归一化
0.75 经验最优(ES 默认)

1️⃣4️⃣ image

  • 含义:
    BM25 的长度归一化因子

  • 作用:

    • 长文档 → 分母变大 → 分数降低
    • 短文档 → 分母变小 → 分数提高

七、整体结构的“逻辑拆解”

你现在可以把 BM25 看成:

score = ∑(
    稀有度(IDF)
  × 出现次数(有上限)
  × 文档长度修正
)

八、把每个字母映射回你写的 ES 代码

数学符号 ES / Lucene 中的来源
Q 用户 query
t 分词后的 term
D 一条 document
score(D,Q) _score
f(t,D) 倒排索引 term frequency
df(t) 倒排索引统计
N 索引文档数
D term 数
avgdl segment 统计
k1, b BM25Similarity 参数

九、一个非常关键的认知(请记住)

BM25 不是“相似度函数”,
而是“基于概率的相关性估计公式”

所以:

  • 分数不可跨 query 比较
  • 只能在同一 query 内排序

追问:为什么文档率计算的分子是N-df(t),而不是N,(就好像IDF公式中通常介绍的那样)?

这是一个非常关键、也非常“理论味”的问题。你已经不在“怎么用 BM25”这个层面了,而是在问:

为什么 IDF 的分子不是 N,而是 ( N - df(t) )?
这个设计在概率和信息论上到底想表达什么?

下面我会从直觉 → 数学 → 历史演化 → 工程效果四个层面,把这个问题彻底讲清楚。


一、先给你结论(然后证明)

IDF 的分子之所以是 ( N - df(t) ),而不是 ( N ),是因为:

BM25 试图估计的是:
“一个词区分相关文档 vs 不相关文档的能力”
而不是简单地“这个词在全集里有多罕见”。

换句话说:

  • ( df(t) ):包含 t 的文档数
  • ( N - df(t) ):不包含 t 的文档数

👉 区分能力来自“正负样本的对比”,而不是只看正样本。


二、如果分子直接用 N,会发生什么?

假设你用一个“朴素(Navie) IDF”:

image

这其实就是经典 TF-IDF

这个公式隐含的假设是:

“一个词的价值,只和它出现的频率有关。”

但它忽略了一个事实:

一个词的区分力,来自“它没出现在哪里”。


直觉反例

假设:

  • N = 100
  • 词 t 出现在 99 篇文档中

那它几乎没有区分能力

但:

image

虽然很小,但并没有明确表达“几乎所有文档都有”


三、BM25 的视角:区分“相关 vs 不相关”

BM25 来自 概率相关模型(Probabilistic Relevance Model)

它的核心思想是:

一个词有多重要,取决于它是否能区分:

  • 相关文档
  • 非相关文档

在这个模型里,世界被分成两类文档:

类别 是否包含词 t
相关文档 常包含
非相关文档 很少包含

于是问题变成:

词 t 出现在相关文档中的概率
vs
出现在不相关文档中的概率


概率对比的自然形式是“比值”

image


但问题来了

在检索前:

  • 我们不知道哪些文档是 relevant
  • 所以用 全局统计量 近似

于是:

image


四、为什么分子是 ( N - df(t) )(核心推导)

BM25 使用的是 log odds(对数几率) 形式:

image

出现在分子的根本原因。


五、加入 +0.5 是干什么的?

最终 BM25 用的是:

image

原因:

  1. 防止 df(t)=0
  2. 防止 df(t)=N
  3. 保证数值稳定
  4. 保证对数有限

这叫 Robertson/Sparck Jones 平滑


六、直觉再强化一次(非常重要)

你可以把 IDF 理解为一句话:

“这个词在‘不该出现的地方’出现得有多少?”

  • 若几乎所有文档都有这个词
    → ( N - df(t) ) 很小
    → IDF 很小
    → 几乎不提供信息

  • 若只有极少文档有
    → ( N - df(t) ) 很大
    → IDF 很大
    → 强区分词


七、为什么 BM25 不直接用 (log(N/df))?

因为:

TF-IDF BM25
频率视角 区分视角
看“出现多少” 看“没出现在哪里”
信息论弱 概率模型强
经验算法 理论推导

八、工程上的直接后果(你会真实感受到)

  1. 停用词天然权重≈0
  2. 高频词不需要手动过滤
  3. 排序更稳定
  4. 不容易被刷词攻击

九、一句话总结(请记住)

BM25 的 IDF 不是在问:
“这个词有多稀有?”
而是在问:
“这个词能不能把相关文档和不相关文档区分开?”

所以,
分子必须是 (N - df(t)),而不是 ( N )。


posted @ 2026-01-04 16:10  AlphaGeek  阅读(782)  评论(0)    收藏  举报