全称:Okapi BM25,概率检索排序算法,是 Elasticsearch、Lucene、RAG 关键词检索的基础,你代码里用的
BM25Okapi就是它的 Python 实现。
核心:关键词精确匹配打分,词袋模型,不理解语义,只看分词后的词是否重合。
一、核心公式
(score(D,Q)=\sum_{q_i\in Q} IDF(q_i)\cdot \frac{TF(q_i,D)\cdot(k_1+1)}{TF(q_i,D)+k_1\cdot\left(1-b+b\cdot\frac{|D|}{avgdl}\right)})- Q:查询;D:文档
- (TF(q_i,D)):词(q_i)在文档 D 内出现次数(词频)
- (IDF(q_i)):逆文档频率,词越稀有,IDF 越大,权重越高
- (|D|):文档长度;avgdl:全部文档平均长度
- (k_1、b):可调超参
- (k_1):控制词频饱和(默认 1.5):词重复再多,分数不会无限上涨,防止关键词堆砌刷分
- b:控制文档长度归一(默认 0.75),压制长文档天然的优势arXiv
二、三大核心设计(对比 TF-IDF 的改进)
- 词频 TF 饱和
TF-IDF:词出现 100 分≈100 倍 1 次。
BM25:词出现 1 次收益很大;出现 10 次之后,继续重复,分数提升极少。避免堆砌关键词作弊。 - IDF 逆文档频率
词在越少文档出现,IDF 越高。
例:专业术语医学影像,只在少数文档出现,命中后权重很高;的这种高频停用词 IDF 接近 0,几乎不贡献分数。 - 文档长度归一化
长文档天然更容易命中关键词,BM25 会做惩罚,长短文档打分更公平。
注意:词袋模型:不关心词语顺序,
人工智能辅助医生和医生辅助人工智能分词一样,分数一样。
三、使用流程(就是你写的代码流程)
- 文档集合:
documents = ["文本1","文本2"...] - 对每篇文档分词 + 清洗 + 去停用词,得到二维列表
corpus=[[词1,词2],[词3,词4]] - 构建 BM25 模型:
bm25_model = BM25Okapi(corpus) - 查询文本做同样分词,得到 query_tokens
get_scores(query_tokens):一次性返回所有文档的相关性分数- 按分数降序排序,召回 TopN 文档
四、优缺点
✅ 优点
- 速度快、可解释性强,CPU 就能跑,不需要训练、不需要 GPU
- 精准匹配关键词,适合知识库、文档检索,常用来做 RAG 的关键词召回
- 稳定,小数据集也能正常工作
❌ 缺点(你踩坑的根源)
- 只做精确字符串匹配,不懂语义、同义词
医疗和医学影像是近义词,但 token 不一样,完全不命中,分数 = 0 - 不理解语序、上下文
- 错别字、同义词无法召回
五、RAG 里的工程用法
工业界一般BM25 关键词检索 + Embedding 向量检索,混合召回(RRF 融合)
- BM25:抓关键词,保证关键词一定能召回,结果可解释
- 向量检索:抓语义、同义词、模糊含义
两者互补。
六、面试极简背诵版
BM25 是概率检索排序算法,基于 TF-IDF 做两处改进:词频饱和、文档长度归一;它是词袋模型,只做精确词匹配,适合关键词检索;缺点是没有语义理解能力,RAG 中常和向量检索搭配使用。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/zhangchen124/article/details/167173184



