BM25全文检索

概述

BM25是一种经典的全文检索排序算法,常用于搜索引擎、RAG和文档检索。它的核心目标是:根据用户查询中的关键词,判断哪些文档最相关,并给这些文档打分排序。

你可以把BM25理解成,比简单关键词匹配更聪明的TF-IDF( Term Frequency-Inverse Document Frequency , 词频-逆文档频率 )。

比如用户搜索:

latex 复制代码
GitNexus MCP Stdio

系统里有3篇文档:

latex 复制代码
文档A:GitNexus MCP Server使用Stdio通信
文档B:MCP支持Stdio和SSE
文档C:GitNexus代码索引架构

BM25会分别计算这3篇文档和查询的相关性分数:

latex 复制代码
文档A:8.7
文档B:6.2
文档C:2.1

然后按分数排序返回:

latex 复制代码
文档A
文档B
文档C

BM25考虑3件事

关键词出现次数

比如搜索:

latex 复制代码
MCP Stdio

如果一篇文章里频繁出现:

latex 复制代码
MCP
Stdio

那么它通常会获得更高分。

但BM25不会认为出现越多越无限重要。

例如:

latex 复制代码
出现1次 → 提升明显
出现3次 → 继续提升
出现20次 → 提升已经很有限

这叫**词频饱和**。因为一个词出现100次,并不意味着相关性就是出现10次的10倍。


关键词的稀有程度

假设整个文档库里:

latex 复制代码
"the"出现100万次
"GitNexus"出现100次

那么搜索:

latex 复制代码
GitNexus

这个词的信息量明显更大。所以BM25会让稀有词获得更高权重。

这部分本质上就是IDF(Inverse Document Frequency, 逆文档频率),也就是说:一个词在整个语料库里越少见,它越有区分度。

比如:

latex 复制代码
"server" → 权重较低
"GitNexus" → 权重较高
"CompatibleStdioServerTransport" → 权重更高

文档长度

假设:

latex 复制代码
文档A:100字,其中MCP出现5次
文档B:10000字,其中MCP出现5次

虽然出现次数一样,但显然文档A更可能专门讨论MCP。所以BM25会做文档长度归一化。也就是说:短文档中关键词密集通常比长文档中偶尔出现关键词得分更高。

BM25公式

给定查询Q和文档D主要,经典形式可以写成:

$ score(D,Q)=\sum_{q_i\in Q}

IDF(q_i)

\cdot

\frac{f(q_i,D)(k_1+1)}

{f(q_i,D)+k_1(1-b+b\frac{|D|}{avgdl})} $

看几个变量:

  • f(q_i,D) 表示某个关键词在文档中出现几次。
  • IDF(q_i) 表示这个词有多稀有
  • \|D\| 表示当前文档长度
  • avgdl 表示所有文档的平均长度。
  • k1控制词频饱和程度, 常见k1 ≈ 1.2~2.0
  • b控制文档长度归一化程度,b ≈ 0.75
相关推荐
不正经学生4 小时前
C语言预处理详解:编译器真正动手之前的那些事
c语言·开发语言·算法·面试·bug
门思科技4 小时前
LoRaWAN 设备类别:Class A、B、C 对比与选型指南
c语言·开发语言·php
恋恋西风7 小时前
C++ 理解 std::thread 在单核和多核上的行为差异
开发语言·c++
Brilliantwxx7 小时前
【Linux】 进程(9)程序与进程地址空间(基础+进阶+面试题)
linux·运维·服务器·开发语言·c++
BizzZ_8 小时前
C++(22)——类型转换和IO流
开发语言·c++
小范同学_8 小时前
JDK1.7 与 JDK1.8 HashMap 底层原理对比 + 数组并发扩容死循环详解
java·开发语言
geovindu8 小时前
CSharp: 万年历
开发语言·后端·c#·.net
傲笑风8 小时前
【openvino】tinybert基于openvino服务化部署(四)
人工智能·python·自然语言处理·nlp·bert·openvino
我找到地球的支点啦9 小时前
Matlab系列(009) 一CRC循环冗余校验详解
开发语言·数据结构·算法·matlab·信息与通信
维基框架9 小时前
WIKI 知识库 v1.1.1 正式发布
人工智能·python