文本相关性是信息检索和自然语言处理中的一个核心问题。在文本相关性中,我们希望能够量化文本之间的相似程度或相关程度,以便有效地处理和组织文本数据。例如,在搜索引擎中,我们希望通过用户的查询来找到与查询相关的最相关的文档或网页。在文档分类和聚类中,我们希望将相似的文档放在一起,以便更好地管理和分析它们。在文本匹配和相似性匹配中,我们希望找到两个文本之间的相似度,以便评估它们之间的关系。
这篇博客会介绍 TF-IDF 以及 BM25
tf-idf
tf-idf (Term Frequency-Inverse Document Frequency)是一种用于评估文档中单词重要性的统计方法,广泛应用于信息检索、自然语言处理等领域。
他的整体公式如下
tf-idf ( t , d , D ) = tf ( t , d ) ⋅ idf ( t , D ) \text{tf-idf}(t,d,D) = \text{tf}(t,d) \cdot \text{idf}(t,D) tf-idf ( t , d , D ) = tf ( t , d ) ⋅ idf ( t , D )
其中,t t t 是指某个单词(term),d d d 是指某个文档(document),D D D 是指整个文档集合。tf 表示单词在文档中的频率(term frequency)。idf 表示单词在整个文档集合中的逆文档频率(inverse document frequency)。
它们的计算公式如下:
tf ( t , d ) = f t , d ∑ t ′ ∈ d f t ′ , d \text{tf}(t,d) = \frac{f_{t,d}}{\sum_{t' \in d} f_{t',d}} tf ( t , d ) = ∑ t ′ ∈ d f t ′ , d f t , d
其中,f t , d f_{t,d} f t , d 是指单词 t t t 在文档 d d d 中出现的次数。
idf ( t , D ) = log N ∣ d ∈ D : t ∈ d ∣ \text{idf}(t,D) = \log{\frac{N}{|{d \in D : t \in d}|}} idf ( t , D ) = log ∣ d ∈ D : t ∈ d ∣ N
其中,N N N 是指整个文档集合中文档的总数,∣ d ∈ D : t ∈ d ∣ |{d \in D : t \in d}| ∣ d ∈ D : t ∈ d ∣ 是指包含单词 t t t 的文档数。
tf-idf 考虑了一个单词在文档中的频率以及在整个文档集合中的频率,从而确定它在文档中的重要性。一个单词在某个文档中出现的次数越多,其重要性就越高(即tf 越高),但是如果它在整个文集中出现的次数也很多,那么它的重要性就会降低(即idf 越低)
通过例子深入理解tf-idf
假设我们有一个包含以下 4 个文档的文档集合:
Doc 1: the cat in the hat
Doc 2: the rat in the hat
Doc 3: the cat and the rat
Doc 4: the cat sat on the hat
现在,我们想要计算单词 “cat” 在文档集合中的 tf-idf 值。首先,我们需要计算单词 “cat” 在每个文档中的 tf 值。计算公式如下:
tf ( t , d ) = f t , d ∑ t ′ ∈ d f t ′ , d \text{tf}(t,d) = \frac{f_{t,d}}{\sum_{t' \in d} f_{t',d}} tf ( t , d ) = ∑ t ′ ∈ d f t ′ , d f t , d
其中,f t , d f_{t,d} f t , d 表示单词 t t t 在文档 d d d 中出现的次数,∑ t ′ ∈ d f t ′ , d \sum_{t' \in d} f_{t',d} ∑ t ′ ∈ d f t ′ , d 表示文档 d d d 中所有单词的出现次数之和。因此,单词 “cat” 在每个文档中的 tf 值为:
tf(cat, Doc 1) = 1/5 = 0 .2
tf(cat, Doc 2) = 0/5 = 0
tf(cat, Doc 3) = 1/6 = 0 .1667
tf(cat, Doc 4) = 1/7 = 0 .1429
接下来,我们需要计算单词 “cat” 在整个文档集合中的 idf 值。计算公式如下:
idf ( t , D ) = log N ∣ d ∈ D : t ∈ d ∣ \text{idf}(t,D) = \log{\frac{N}{|{d \in D : t \in d}|}} idf ( t , D ) = log ∣ d ∈ D : t ∈ d ∣ N
其中,N N N 表示文档集合中文档的总数,∣ d ∈ D : t ∈ d ∣ |{d \in D : t \in d}| ∣ d ∈ D : t ∈ d ∣ 表示包含单词 t t t 的文档数。因此,单词 “cat” 在整个文档集合中的 idf 值为:
idf ( c a t , D ) = log 4 3 ≈ 0.2877 \text{idf}(cat, D) = \log{\frac{4}{3}} \approx 0.2877 idf ( c a t , D ) = log 3 4 ≈ 0.2877
最后,我们可以计算单词 “cat” 在每个文档中的 tf-idf 值,计算公式如下:
tf-idf ( t , d , D ) = tf ( t , d ) ⋅ idf ( t , D ) \text{tf-idf}(t,d,D) = \text{tf}(t,d) \cdot \text{idf}(t,D) tf-idf ( t , d , D ) = tf ( t , d ) ⋅ idf ( t , D )
因此,单词 “cat” 在每个文档中的 tf-idf 值为:
tf-idf(cat, Doc 1, D) = 0 .2 * 0 .2877 = 0 .0575
tf-idf(cat, Doc 2, D) = 0 * 0 .2877 = 0
tf-idf(cat, Doc 3, D) = 0 .1667 * 0 .2877 = 0 .0481
tf-idf(cat, Doc 4, D) = 0 .1429 * 0 .2877 = 0 .0412
这样,我们就计算出了单词 “cat” 在每个文档中的 tf-idf 值。可以看到,单词 “cat” 在 Doc 1 和 Doc 3中的 tf-idf 值比较高,因为它们在文档中出现得比较少,并且在文档集合中出现的文档数也比较少,表明它们在文档集合中比较重要。
BM25
与 tf-idf 相似,BM25 也是基于词频的算法,但与 tf-idf 不同的是,BM25 引入了文档长度的因素,同时对词频的权重进行了调整。BM25 的全称是 Best Matching 25 ,它计算的是一个查询(query)与一个文档(document)之间的相似度得分。BM25 基于以下三个因素来计算文档的得分:
查询项(query term)在文档中的出现次数
文档的长度(即包含的单词数)
查询项的文档频率(即包含查询项的文档数量)
BM25 的公式如下:
BM25 ( q , d ) = ∑ i = 1 ∣ q ∣ idf ( q i ) ⋅ f ( q i , d ) ⋅ ( k 1 + 1 ) f ( q i , d ) + k 1 ⋅ ( 1 − b + b ⋅ ∣ d ∣ avgdl ) \text{BM25}(q, d) = \sum_{i=1}^{|q|} \text{idf}(q_i) \cdot \frac{f(q_i, d) \cdot (k_1 + 1)}{f(q_i, d) + k_1 \cdot (1 - b + b \cdot \frac{|d|}{\text{avgdl}})} BM25 ( q , d ) = i = 1 ∑ ∣ q ∣ idf ( q i ) ⋅ f ( q i , d ) + k 1 ⋅ ( 1 − b + b ⋅ avgdl ∣ d ∣ ) f ( q i , d ) ⋅ ( k 1 + 1 )
其中,
q q q 是查询项
d d d 是文档
∣ q ∣ |q| ∣ q ∣ 是查询项的数量
q i q_i q i 是第 i i i 个查询项
idf ( q i ) \text{idf}(q_i) idf ( q i ) 是查询项 q i q_i q i 的逆文档频率(inverse document frequency),定义为 idf ( q i ) = log N − n ( q i ) + 0.5 n ( q i ) + 0.5 \text{idf}(q_i) = \log{\frac{N - n(q_i) + 0.5}{n(q_i) + 0.5}} idf ( q i ) = log n ( q i ) + 0.5 N − n ( q i ) + 0.5
N N N 是文档集合中的文档数
n ( q i ) n(q_i) n ( q i ) 是包含查询项 q i q_i q i 的文档数
f ( q i , d ) f(q_i, d) f ( q i , d ) 是查询项 q i q_i q i 在文档 d d d 中出现的次数
∣ d ∣ |d| ∣ d ∣ 是文档 d d d 中的单词数
avgdl \text{avgdl} avgdl 是文档集合中所有文档的平均长度
k 1 k_1 k 1 和 b b b 是常数,通常取 k 1 = 1.2 k_1 = 1.2 k 1 = 1.2 ,b = 0.75 b = 0.75 b = 0.75
在 BM25 中,查询项的权重由两个因素决定:逆文档频率(idf)和词频(tf)。与 tf-idf 相似,idf 用于衡量一个查询项的重要程度,tf 用于衡量查询项在文档中的出现频率。不同之处在于,BM25 引入了文档长度和查询项的文档频率来对词频进行加权。
具体来说,当文档长度很小时,BM25 对词频进行较大的加权,这可以帮助我们区分出现次数很少但重要的查询项;而当文档长度很大时,BM25 对词频进行较小的加权,以避免受过多出现的常见查询项的影响。此外,BM25 的常数参数 k 1 k_1 k 1 和 b b b 也可以根据实际情况进行调整,以获得更好的结果。
计算 BM25 的例子:
假设我们有一个文档集合,其中包含三个文档 D 1 , D 2 , D 3 D_1, D_2, D_3 D 1 , D 2 , D 3 ,它们的长度分别为 ∣ D 1 ∣ = 100 , ∣ D 2 ∣ = 200 , ∣ D 3 ∣ = 300 |D_1|=100, |D_2|=200, |D_3|=300 ∣ D 1 ∣ = 100 , ∣ D 2 ∣ = 200 , ∣ D 3 ∣ = 300 。我们还有一个查询项 q q q ,其中包含两个单词 q 1 q_1 q 1 和 q 2 q_2 q 2 。假设 q 1 q_1 q 1 在 D 1 D_1 D 1 中出现了 2 次,在 D 2 D_2 D 2 中出现了 5 次,在 D 3 D_3 D 3 中出现了 10 次;q 2 q_2 q 2 在 D 1 D_1 D 1 中出现了 3 次,在 D 2 D_2 D 2 中出现了 1 次,在 D 3 D_3 D 3 中没有出现。
我们需要计算每个文档与查询项 q q q 的 BM25 得分。为了简化,我们假设 k 1 = 1.2 k_1 = 1.2 k 1 = 1.2 ,b = 0.75 b = 0.75 b = 0.75 。
首先,我们需要计算每个查询项的逆文档频率 idf ( q i ) \text{idf}(q_i) idf ( q i ) 。根据公式,我们可以得到:
idf ( q 1 ) = log 3 − 2 + 0.5 2 + 0.5 ≈ 0.29 \text{idf}(q_1) = \log{\frac{3 - 2 + 0.5}{2 + 0.5}} \approx 0.29 idf ( q 1 ) = log 2 + 0.5 3 − 2 + 0.5 ≈ 0.29
idf ( q 2 ) = log 3 − 0 + 0.5 0 + 0.5 ≈ 1.79 \text{idf}(q_2) = \log{\frac{3 - 0 + 0.5}{0 + 0.5}} \approx 1.79 idf ( q 2 ) = log 0 + 0.5 3 − 0 + 0.5 ≈ 1.79
接下来,我们需要计算每个文档与查询项 q q q 的 BM25 得分。根据公式,我们可以得到:
BM25 ( q , D 1 ) = idf ( q 1 ) ⋅ 2 ⋅ ( 1.2 + 1 ) 2 + 1.2 ⋅ ( 1 − 0.75 + 0.75 ⋅ 100 200 ) + idf ( q 2 ) ⋅ 3 ⋅ ( 1.2 + 1 ) 3 + 1.2 ⋅ ( 1 − 0.75 + 0.75 ⋅ 100 200 ) ≈ 0.78 \text{BM25}(q, D_1) = \text{idf}(q_1) \cdot \frac{2 \cdot (1.2 + 1)}{2 + 1.2 \cdot (1 - 0.75 + 0.75 \cdot \frac{100}{200})} + \text{idf}(q_2) \cdot \frac{3 \cdot (1.2 + 1)}{3 + 1.2 \cdot (1 - 0.75 + 0.75 \cdot \frac{100}{200})} \approx 0.78 BM25 ( q , D 1 ) = idf ( q 1 ) ⋅ 2 + 1.2 ⋅ ( 1 − 0.75 + 0.75 ⋅ 200 100 ) 2 ⋅ ( 1.2 + 1 ) + idf ( q 2 ) ⋅ 3 + 1.2 ⋅ ( 1 − 0.75 + 0.75 ⋅ 200 100 ) 3 ⋅ ( 1.2 + 1 ) ≈ 0.78
BM25 ( q , D 2 ) = idf ( q 1 ) ⋅ 5 ⋅ ( 1.2 + 1 ) 5 + 1.2 ⋅ ( 1 − 0.75 + 0.75 ⋅ 200 200 ) + idf ( q 2 ) ⋅ 1 ⋅ ( 1.2 + 1 ) 1 + 1.2 ⋅ ( 1 − 0.75 + 0.75 ⋅ 200 200 ) ≈ 0.63 \text{BM25}(q, D_2) = \text{idf}(q_1) \cdot \frac{5 \cdot (1.2 + 1)}{5 + 1.2 \cdot (1 - 0.75 + 0.75 \cdot \frac{200}{200})} + \text{idf}(q_2) \cdot \frac{1 \cdot (1.2 + 1)}{1 + 1.2 \cdot (1 - 0.75 + 0.75 \cdot \frac{200}{200})} \approx 0.63 BM25 ( q , D 2 ) = idf ( q 1 ) ⋅ 5 + 1.2 ⋅ ( 1 − 0.75 + 0.75 ⋅ 200 200 ) 5 ⋅ ( 1.2 + 1 ) + idf ( q 2 ) ⋅ 1 + 1.2 ⋅ ( 1 − 0.75 + 0.75 ⋅ 200 200 ) 1 ⋅ ( 1.2 + 1 ) ≈ 0.63
BM25 ( q , D 3 ) = idf ( q 1 ) ⋅ 10 ⋅ ( 1.2 + 1 ) 10 + 1.2 ⋅ ( 1 − 0.75 + 0.75 ⋅ 300 200 ) + idf ( q 2 ) ⋅ 0 ⋅ ( 1.2 + 1 ) 0 + 1.2 ⋅ ( 1 − 0.75 + 0.75 ⋅ 300 200 ) ≈ 0.69 \text{BM25}(q, D_3) = \text{idf}(q_1) \cdot \frac{10 \cdot (1.2 + 1)}{10 + 1.2 \cdot (1 - 0.75 + 0.75 \cdot \frac{300}{200})} + \text{idf}(q_2) \cdot \frac{0 \cdot (1.2 + 1)}{0 + 1.2 \cdot (1 - 0.75 + 0.75 \cdot \frac{300}{200})} \approx 0.69 BM25 ( q , D 3 ) = idf ( q 1 ) ⋅ 10 + 1.2 ⋅ ( 1 − 0.75 + 0.75 ⋅ 200 300 ) 10 ⋅ ( 1.2 + 1 ) + idf ( q 2 ) ⋅ 0 + 1.2 ⋅ ( 1 − 0.75 + 0.75 ⋅ 200 300 ) 0 ⋅ ( 1.2 + 1 ) ≈ 0.69
因此,我们可以得到三个文档与查询项 q q q 的 BM25 得分分别为 0.78、0.63 和 0.69。
这个例子说明了,虽然 q 1 q_1 q 1 在 D 3 D_3 D 3 中出现的次数最多,但是由于 D 3 D_3 D 3 的长度较长,而且 q 2 q_2 q 2 没有在 D 3 D_3 D 3 中出现,因此 D 1 D_1 D 1 的得分最高。这也说明了 BM25 算法的优点之一,即克服了 tf-idf 算法中常见查询项对结果的影响。
BM25的公式进一步解读
BM25 中的idf公式 与原版的idf公式 不一致
传统的 idf 公式是 log N d f \log\frac{N}{df} log df N ,其中 N N N 是文档集合中文档的总数,d f df df 是包含查询项 t t t 的文档数。而 BM25 中使用的 idf 公式是 log N − d f + 0.5 d f + 0.5 \log\frac{N-df+0.5}{df+0.5} log df + 0.5 N − df + 0.5 。这个公式与传统的 idf 公式相比,主要做了两个改动:
加入了平滑因子:在传统的 idf 公式中,当某个查询项在文档集合中未出现时,其 idf 值会变成负无穷。为了避免这种情况,BM25 中的 idf 公式加入了平滑因子 0.5。
减少 idf 的影响:在传统的 idf 公式中,当某个查询项在很少的文档中出现时,其 idf 值会很大,对结果产生过大的影响。BM25 中的 idf 公式通过减少 idf 的影响,使得查询项在出现文档数较少时,不会对结果产生过大的影响。但是当文档出现的数量超过一半时,计算出的idf值为负数,Lucene中为了解决这个问题,更改了idf公式为log 1 + N − d f + 0.5 d f + 0.5 \log1+\frac{N-df+0.5}{df+0.5} log 1 + df + 0.5 N − df + 0.5 ,从而防止了负数的产生。
BM25 中的k是如何影响计算出的结果
k k k 的值控制了词频对得分的影响程度,可以看作是一个词频的归一化因子。
当 k k k 的值较小时,词频的影响就相对较小,得分的变化范围也相对较小;当 k k k 的值较大时,词频的影响就相对较大,得分的变化范围也相对较大。当 k k k 的值等于 0 0 0 时,相当于将文档中所有词项的词频都视为 1 1 1 ,此时得分只与文档与查询语句的匹配程度有关。同时,因为有k k k 的存在,即使词频特别大,也不会对最终计算的结果有大的影响。即当词频达到一定程度,计算出的BM25的值并不会线性提升。
BM25 中的b是如何影响计算出的结果
在 BM25 中,参数 b b b 用来平衡文档长度对得分的影响。它控制了文档长度对得分的影响程度,可以看作是一个文档长度的归一化因子。b b b 的取值会影响文档中的词项权重 w i w_i w i 的大小,这里的 w i w_i w i 是指包含词项 i i i 的文档的 i i i 的权重。当 b b b 越大时,表示文档长度对词项权重的影响越大,这意味着文档中的词项权重 w i w_i w i 会相应地趋于缩小;反之,当 b b b 越小时,表示文档长度对词项权重的影响越小,这意味着文档中的词项权重 w i w_i w i 会相应地趋于扩大。
BM25 中的文档长度如何影响计算出的结果
一篇文档如果所含的单词越少,那么 ∣ d ∣ avgdl \frac{|d|}{\text{avgdl}} avgdl ∣ d ∣ 越小,从而导致最终的BM25 越大,因此文档字数越少,相关性越高.
idf 为什么要用对数计算?
在计算文档中每个词项的逆文档频率时,使用对数函数的目的是将idf值的范围压缩到一个较小的区间内。由于文档的大小通常会很大,因此一个词项可能会出现几千甚至几十万次,这样计算得到的idf值就会非常大。使用对数函数可以将这些大数值压缩到一个较小的区间内,便于计算和处理。
此外,对数函数还能够使得低频词项的idf值更加突出。如果不使用对数函数,那么在某些情况下,一些低频词项的idf值可能会非常小,甚至可能会被忽略。而使用对数函数后,这些低频词项的idf值就会被放大,使得它们在检索时能够更好地区分文档的相关性。
BM25F
BM25F 是BM25 算法的一种变体,它在BM25 的基础上增加了对多字段的支持。在BM25F 中,每个文档可以包含多个字段(例如标题、正文、标签等),每个字段都有一个权重。BM25F 通过将每个字段的得分相加来计算文档的相关性得分。BM25F 的公式如下:
s c o r e ( D , Q ) = ∑ i = 1 n w e i g h t ( q i ) ⋅ I D F ( q i ) ⋅ f ( q i , D ) ⋅ ( k i + 1 ) f ( q i , D ) + k i ⋅ ( 1 − b i + b i ⋅ ∣ D ∣ a v g d l i ) score(D,Q) = \sum_{i=1}^{n}weight(q_i)\cdot IDF(q_i)\cdot \frac{f(q_i,D)\cdot (k_i + 1)}{f(q_i,D) + k_i\cdot (1 - b_i + b_i \cdot \frac{|D|}{avgdl_i})} score ( D , Q ) = ∑ i = 1 n w e i g h t ( q i ) ⋅ I D F ( q i ) ⋅ f ( q i , D ) + k i ⋅ ( 1 − b i + b i ⋅ a vg d l i ∣ D ∣ ) f ( q i , D ) ⋅ ( k i + 1 )
其中,D D D 表示文档,Q Q Q 表示查询,n n n 表示查询中的词项数,q i q_i q i 表示查询中的第i i i 个词项,w e i g h t ( q i ) weight(q_i) w e i g h t ( q i ) 表示第i i i 个词项的权重,I D F ( q i ) IDF(q_i) I D F ( q i ) 表示第i i i 个词项的逆文档频率,f ( q i , D ) f(q_i,D) f ( q i , D ) 表示文档D D D 中第i i i 个词项的出现频率,k i k_i k i 和b i b_i b i 分别表示第i i i 个词项的参数k k k 和b b b ,∣ D ∣ |D| ∣ D ∣ 表示文档D D D 的长度,a v g d l i avgdl_i a vg d l i 表示包含第i i i 个字段的所有文档的平均长度。
在BM25F 中,每个词项的权重由其所在的字段的权重和全局权重两部分组成。全局权重表示该词项在整个文集中的重要性,字段权重则表示该词项在当前字段中的重要性。词项的权重可以通过以下公式计算:
w e i g h t ( q i ) = w e i g h t f i e l d ( q i ) ⋅ w e i g h t g l o b a l ( q i ) weight(q_i) = weight_{field}(q_i)\cdot weight_{global}(q_i) w e i g h t ( q i ) = w e i g h t f i e l d ( q i ) ⋅ w e i g h t g l o ba l ( q i )
其中,w e i g h t f i e l d ( q i ) weight_{field}(q_i) w e i g h t f i e l d ( q i ) 表示第i i i 个词项在当前字段中的权重,w e i g h t g l o b a l ( q i ) weight_{global}(q_i) w e i g h t g l o ba l ( q i ) 表示第i i i 个词项在全局文档集中的权重。
BM25F 的优点是能够有效地处理多字段查询,可以更好地匹配查询和文档中不同字段的相关性。它可以通过调整字段的权重来对不同字段的重要性进行调整,从而提高搜索结果的准确性。
总结
tf-idf 词频越高,词频在整个文档集中越稀少,值越高
BM25 词频在整个文档集中越稀少,词频越高,文档的单词数越少 ,值越高
BM25F 词频在整个文档集中越稀少,词频越高, 文档的单词数越少,权重越高 ,值越高