BM25 — 用概率框架给搜索结果排队
待复核BM25 是一套给搜索结果打分排序的方法;这篇 2009 综述讲的不是某个新公式,而是 BM25 背后的整条概率检索框架(PRF)。
日常类比:你问图书馆管理员”有没有讲概率检索的书”,管理员不会把所有含”概率”两个字的书都抱来,而是估计哪本最可能真正回答你的需求。BM25 就像这个管理员的一张打分表:稀有词更重要,重复出现有用但会饱和,短文档里集中命中比长文档里随手提一句更强。
这篇的核心价值是把 1960 年以来的概率检索思想串起来:从”相关性是一个概率”到 RSJ 权重、BIM、相关反馈、BM25、BM25F,再到参数怎么调。它是理解传统稀疏检索排序函数的入口。
读它时不要只盯公式。更重要的是看每一步假设:哪些证据被认为和相关性有关,哪些变换只保留排序顺序,哪些参数需要靠实验调出来。
不理解这篇,下面这些事都没法解释:
- 为什么 BM25 不是”TF-IDF 加两个参数”,而是从 Probability Ranking Principle 推出来的一族模型
- 为什么 IDF 里会出现
+0.5,k1 控制词频饱和,b 控制文档长度归一化 - 为什么标题、正文、锚文本要先按字段合并成 BM25F,而不是给每个字段单独跑 BM25 再相加
- 为什么现代 RAG 仍然把 BM25 当第一道召回基线,再接向量检索、RRF 或重排序
-
先问”相关的概率”。PRF 的起点是:对某个 query-document pair,系统只能估计
P(相关 | 文档, 查询)。类比:医生没有绝对答案,只能根据症状和检查结果估计患病概率。 -
把复杂概率改写成可加的词权重。论文用 odds、Bayes 变换、取 log、去掉与文档无关的项,最后得到”只对 query 中且文档里出现的词求和”。类比:复杂账本被整理成每个命中词一张小票,最后把小票加起来。
-
BM25 是 PRF 的工程化版本。2-Poisson / eliteness 模型解释了为什么词频贡献会饱和,文档长度模型解释了为什么要除以
1-b+b·dl/avgdl。类比:一个词第一次出现很关键,第十次出现只是重复强调,不能无限加分。
这里有个很重要的边界:BM25 分数适合排序,不适合直接解释成”这篇文档有 80% 概率相关”。论文在推导中多次使用 rank equivalence,只保证顺序尽量合理。
案例 1:最小 BM25 打分
Section titled “案例 1:最小 BM25 打分”import math
def bm25(tf, df, N, dl, avgdl, k1=1.5, b=0.75): idf = math.log((N - df + 0.5) / (df + 0.5)) norm = k1 * (1 - b + b * dl / avgdl) return idf * tf / (norm + tf)逐部分解释:
idf:词越少见,说明它越能区分文档;+0.5是概率估计里的平滑norm:长文档分母变大,防止”篇幅长所以碰巧命中多”占便宜tf / (norm + tf):词频越高分越高,但增长越来越慢,这就是饱和
案例 2:k1 和 b 怎么影响直觉
Section titled “案例 2:k1 和 b 怎么影响直觉”for tf in [1, 3, 10, 30]: print(tf, round(tf / (1.5 + tf), 3))输出大概是 0.4, 0.667, 0.87, 0.952。第 1 次到第 3 次增长明显,第 10 次到第 30 次增长很小。
逐部分解释:
- k1 越大,饱和越慢,重复词还能继续加不少分
- b 越大,长度归一越强,长文档里的命中会被压得更低
- 如果语料都是商品标题这种短文本,b 太大反而可能过度惩罚
案例 3:BM25F 为什么先合字段
Section titled “案例 3:BM25F 为什么先合字段”def weighted_tf(title_tf, body_tf): return 5 * title_tf + 1 * body_tf
print(weighted_tf(title_tf=1, body_tf=0))print(weighted_tf(title_tf=0, body_tf=5))逐部分解释:
- 标题命中一次,可能比正文命中五次还强,因为标题更浓缩地表达主题
- BM25F 的思想是:先把 title/body/anchor 等字段转成一个加权词频,再做一次饱和
- 这避免了”每个字段各自饱和后再相加”导致同一个词在多个字段里被重复奖励
实际系统里,title、body、anchor 的权重通常不是拍脑袋,而是拿一批 query 和人工相关性判断做参数搜索;这也是论文最后一章讨论优化的原因。
- 把 BM25 当成普通 TF-IDF:错在忽略 PRF 推导;BM25 的 IDF、饱和、长度归一都来自概率假设和工程近似。
- 以为 tf 越高越相关:原因是线性直觉太强;论文强调 eliteness 只能提供有限证据,所以词频必须饱和。
- 把默认参数当真理:原因是 k1、b 没有模型内生答案;论文说它们鲁棒,但不同语料仍要用 judged queries 调。
- 字段分数直接相加:原因是没理解 BM25F;正确做法通常是先跨字段积累同一个词的证据,再让这个词统一饱和。
适用 vs 不适用场景
Section titled “适用 vs 不适用场景”适用:
- 文档库、代码库、日志、知识库这种需要关键词精确命中的检索
- 没有训练数据的新语料,先要一个强、快、可解释的 baseline
- RAG 的第一阶段召回,再接 rrf-cormack-2009、dpr-2020 或 colbert-2020
- 标题、正文、锚文本等字段明确的 Web / 企业搜索,用 BM25F 建模
不适用:
- 同义改写很多的查询,比如”车险理赔” vs “汽车保险报案”,BM25 不懂语义等价
- 跨语言、图片、音频等没有共享词表的检索
- 已有大量点击和标注数据、目标是最终排序时,应接学习排序或神经重排
- 需要输出校准概率的场景;PRF 为了排序做了 rank-equivalent 变换,分数不等于真实概率
判断边界的简单方法:如果用户必须输入同一个词才能命中,BM25 很强;如果用户说法经常换词,BM25 就需要扩展、向量或重排帮忙。
历史小故事(可跳过)
Section titled “历史小故事(可跳过)”- 1960 年:Maron 和 Kuhns 把”相关性概率”带进信息检索,但还没有现代 query-doc 排序公式。
- 1970s:Robertson 和 Spärck Jones 发展 PRP 与 RSJ 权重,奠定”按相关概率排序”的理论入口。
- 1980s:概率模型逐步接入相关反馈,系统可以根据用户判定重新加权和扩展 query。
- 1994 年:Okapi 线索把 2-Poisson 的复杂曲线近似成 BM25,稀疏检索有了稳定公式。
- 2004 年:BM25F 把标题、正文、锚文本等字段纳入同一个概率框架。
- 2009 年:Robertson 和 Zaragoza 写下这篇综述,把 30 年模型、假设、变体和调参方法合成一张地图。
- BM25 的背后是一套概率检索观:先定义相关性,再讨论哪些证据能改变相关 odds。
- 好公式来自假设 + 近似:PRF 给方向,2-Poisson 给形状,BM25 用少数参数把它落地。
- 可解释性来自可加证据:每个 query term 都是一条证据,为什么加分、为什么饱和都能说清。
- 传统模型没有过时:在没有训练数据、需要低延迟和可解释 baseline 时,BM25 仍然是第一选择。
- 论文 PDF:Robertson & Zaragoza 2009(系统综述,适合当 BM25 地图)
- 前置论文:okapi-bm25-1994 —— BM25 公式定型的工程论文
- 概率源头:croft-harper-1979 —— 没有相关反馈时如何估计概率权重
- 实验工具:anserini-2017 —— 现代 Lucene / BM25 学术基线
- 混合检索:splade-2021 —— 神经稀疏模型如何继承倒排索引路线
- maron-kuhns-1960 —— 早期把检索问题改写成”文档相关概率”的源头之一
- croft-harper-1979 —— 解释没有 relevance feedback 时概率检索怎么启动
- okapi-bm25-1994 —— 把 PRF / 2-Poisson 的思想压成 BM25 公式
- indri-2005 —— 语言模型检索路线,与 PRF / BM25 是同一时代的平行框架
- anserini-2017 —— 现代实验中最常复现 BM25 的 Lucene 工具链
- rrf-cormack-2009 —— 常把 BM25 排名和向量检索排名融合成混合召回
- splade-2021 —— 用神经网络学习稀疏词权重,是 BM25 路线的现代延伸
- anserini-2017 —— Anserini — 把工业搜索引擎 Lucene 改造成学术 IR 实验台
- croft-harper-1979 —— Croft-Harper 1979 — 没有相关性反馈也能跑概率检索
- rm3-2001 —— RM3 — 让搜索引擎自己看一眼结果再重搜一次
- rrf-cormack-2009 —— RRF — 把多个搜索结果列表合并成一个的最简单办法
- llama-index —— LlamaIndex — 给大模型接上私有资料库
- llamaindex —— LlamaIndex — LLM 数据框架