1. 核心思想
BM25 是一种用于信息检索 的算法,用来计算一个查询 (Query)和一个文档(Document)之间的相关性分数。它的核心思想是:
- 词频越高,相关性可能越高,但收益会递减(避免过度依赖重复词)。
- 文档长度:如果文档很长,词频高可能是正常的,所以会对长文档进行惩罚。
- 逆文档频率:如果某个词在所有文档中都很常见(如"的"、"是"),那么它的区分度就低,权重应该小;反之,罕见词权重高。
2. 假设我们有一个微型文档库
文档库(3个文档):
- D1 :
苹果 手机 很好 用 - D2 :
苹果 是一种 水果 - D3 :
手机 品牌 有 苹果 华为 小米
查询 Q : 苹果 手机
3. 步骤拆解
步骤1:对查询进行分词
- 查询词:
苹果、手机
步骤2:计算逆文档频率(IDF)
IDF 公式(常见形式):
IDF(q_i) = \\log\\left( \\frac{N - n(q_i) + 0.5}{n(q_i) + 0.5} + 1 \\right)
其中:
- ( N ) = 文档总数(这里 ( N = 3 ))
- ( n(q_i) ) = 包含词 ( q_i ) 的文档数量
计算:
-
"苹果":
- 出现在 D1、D2、D3 → ( n(\text{苹果}) = 3 )
- ( IDF(\text{苹果}) = \log\left( \frac{3 - 3 + 0.5}{3 + 0.5} + 1 \right) = \log\left( \frac{0.5}{3.5} + 1 \right) = \log(1.1429) \approx 0.1335 )
(说明:因为"苹果"出现在所有文档,IDF 很低,区分度小。)
-
"手机":
- 出现在 D1、D3 → ( n(\text{手机}) = 2 )
- ( IDF(\text{手机}) = \log\left( \frac{3 - 2 + 0.5}{2 + 0.5} + 1 \right) = \log\left( \frac{1.5}{2.5} + 1 \right) = \log(1.6) \approx 0.4700 )
步骤3:为每个文档计算每个查询词的得分
BM25 公式(简化常用版):
\\text{Score}(D, Q) = \\sum_{i=1}\^{n} IDF(q_i) \\cdot \\frac{f(q_i, D) \\cdot (k_1 + 1)}{f(q_i, D) + k_1 \\cdot \\left(1 - b + b \\cdot \\frac{\|D\|}{\\text{avgdl}}\\right)}
其中:
- ( f(q_i, D) ) = 词 ( q_i ) 在文档 D 中出现的次数
- ( |D| ) = 文档 D 的长度(词数)
- avgdl = 所有文档的平均长度
- ( k_1 ) 和 ( b ) 是超参数,通常 ( k_1 \in [1.2, 2.0] ),( b = 0.75 ),这里我们取 ( k_1 = 1.2, b = 0.75 )。
先计算 avgdl:
- D1 长度 = 4
- D2 长度 = 4
- D3 长度 = 6
- 总词数 = 14,平均长度 avgdl = 14 / 3 ≈ 4.667
步骤4:逐文档计算
D1:苹果 手机 很好 用
- 长度 = 4
- "苹果" f = 1
- "手机" f = 1
对于"苹果":
\\text{TF 部分} = \\frac{1 \\times (1.2+1)}{1 + 1.2 \\times \\left(1 - 0.75 + 0.75 \\times \\frac{4}{4.667}\\right)}
先算括号内:
( 1 - b = 0.25 )
( b \cdot \frac{|D|}{\text{avgdl}} = 0.75 \times \frac{4}{4.667} \approx 0.75 \times 0.857 = 0.64275 )
所以 ( 1 - b + b \cdot \frac{|D|}{\text{avgdl}} \approx 0.25 + 0.64275 = 0.89275 )
分母:( 1 + 1.2 \times 0.89275 \approx 1 + 1.0713 = 2.0713 )
分子:( 1 \times 2.2 = 2.2 )
TF 部分 ≈ ( 2.2 / 2.0713 \approx 1.062 )
乘以 IDF:( 1.062 \times 0.1335 \approx 0.1418 )
对于"手机":
同样 f=1,文档长度和上面一样,所以 TF 部分也是 ≈ 1.062
乘以 IDF(手机) = ( 1.062 \times 0.4700 \approx 0.4991 )
D1 总分 = 0.1418 + 0.4991 ≈ 0.6409
D2:苹果 是一种 水果
- 长度 = 4
- "苹果" f = 1,"手机" f = 0(不出现则该项为 0)
"苹果"部分计算:
文档长度与 D1 相同,所以 TF 部分 ≈ 1.062(同上)
乘以 IDF(苹果) ≈ 0.1418
"手机"得分 = 0
D2 总分 ≈ 0.1418
D3:手机 品牌 有 苹果 华为 小米
- 长度 = 6
- "苹果" f = 1,"手机" f = 1
先算长度归一化部分:
( 1 - b + b \cdot \frac{6}{4.667} = 0.25 + 0.75 \times 1.2856 \approx 0.25 + 0.9642 = 1.2142 )
对于"苹果"(f=1):
分母:( 1 + 1.2 \times 1.2142 \approx 1 + 1.4570 = 2.4570 )
分子:( 1 \times 2.2 = 2.2 )
TF 部分 ≈ ( 2.2 / 2.4570 \approx 0.8954 )
乘以 IDF(苹果):( 0.8954 \times 0.1335 \approx 0.1195 )
对于"手机"(f=1,文档长度一样所以 TF 部分相同 0.8954):
乘以 IDF(手机):( 0.8954 \times 0.4700 \approx 0.4208 )
D3 总分 = 0.1195 + 0.4208 ≈ 0.5403
5. 排序结果
- D1:0.6409
- D3:0.5403
- D2:0.1418
所以对于查询"苹果 手机",最相关的文档是 D1("苹果 手机 很好 用"),因为它同时包含两个词且文档长度适中;D3 虽然也包含两个词,但文档更长,受到了长度惩罚;D2 只包含一个词,得分最低。
6. 直观理解
- "手机"的 IDF 比"苹果"高,因为"苹果"在三个文档都出现,区分度低。
- D1 长度短,两个词出现一次,因此权重高;D3 长度长,同样频次下分数降低(BM25 认为长文档可能包含更多无关内容,需要惩罚)。
- BM25 平衡了词频、文档长度、全局词分布,比单纯用 TF-IDF 更健壮。
这就是 BM25 的一个简单手工计算示例。实际应用中,参数可能调整,并且会预先构建倒排索引加速计算。