BM25S:Python打造超越RANK-BM25的实现

在信息检索领域,BM25是一种广泛应用的排名函数,其核心思想是根据词频、文档长度和文档在整个集合中的重要性来评估文档与查询的相关性。然而,传统的BM25在处理某些特定的检索场景时可能存在局限性,因此开发了BM25S模型。BM25S对BM25进行了扩展,旨在提高检索效果和文档排序准确性。本文将介绍BM25S的基本原理,并给出相应的Python实现代码示例。

BM25的基本原理

BM25模型基于概率检索理论,通过以下公式来计算文档与查询的相关性得分:

[ \text{BM25}(d, q) = \sum_{t \in q} \text{idf}(t) \times \frac{f(t, d) \times (k_1 + 1)}{f(t, d) + k_1 \times (1 - b + b \times \frac{|d|}{\text{avgdl}})} ]

其中: - (d) 是文档,(q) 是查询。 - (f(t, d)) 是词t在文档d中的频率。 - (|d|) 是文档d的长度(词数)。 - (\text{avgdl}) 是文档集合中所有文档的平均长度。 - (k_1) 和 (b) 是调节参数,通常设定为 (k_1 \in [1.2, 2.0]) 和 (b \in [0.5, 0.8])。

BM25S的改进

BM25S在BM25的基础上增加了对短文档和长文档的不同处理方式。BM25S考虑了目标文档的整体语义信息,通过引入“内容深度”和“相关性加权”的思想来改善相关性评分,使得模型能够更好地适应多种不同的检索场景。

Python实现示例

以下是BM25及BM25S的Python实现示例,我们先实现BM25:

import math
from collections import Counter

class BM25:
    def __init__(self, documents, k1=1.5, b=0.75):
        self.documents = documents
        self.k1 = k1
        self.b = b
        self.avgdl = sum(len(doc) for doc in documents) / len(documents)
        self.doc_freqs = []
        self.idf = {}

        # 计算文档频率
        for document in documents:
            counter = Counter(document)
            self.doc_freqs.append(counter)

        self._compute_idf()

    def _compute_idf(self):
        df = Counter()
        for doc in self.doc_freqs:
            for word in doc.keys():
                df[word] += 1
        N = len(self.documents)
        for word, freq in df.items():
            self.idf[word] = math.log((N - freq + 0.5) / (freq + 0.5) + 1)

    def score(self, document, query):
        score = 0.0
        doc_len = len(document)
        counter = Counter(document)
        for term in query:
            if term in counter:
                tf = counter[term]
                score += self.idf[term] * (tf * (self.k1 + 1)) / (tf + self.k1 * (1 - self.b + self.b * (doc_len / self.avgdl)))
        return score

# 示例
documents = [['this', 'is', 'a', 'sample', 'document'], ['this', 'document', 'is', 'another', 'example']]
bm25 = BM25(documents)
query = ['this', 'document']
for idx, doc in enumerate(documents):
    print(f'Document {idx} score: {bm25.score(doc, query)}')

接下来实现BM25S:

class BM25S(BM25):
    def __init__(self, documents, k1=1.5, b=0.75):
        super().__init__(documents, k1, b)

    def score(self, document, query):
        score = super().score(document, query)
        # 加入BM25S的扩展调整
        content_depth = self._compute_content_depth(document, query)
        return score * content_depth

    def _compute_content_depth(self, document, query):
        # 一个简单的内容深度计算示例
        relevance = len(set(document) & set(query)) / len(query)
        return 1 + relevance

# 示例
bm25s = BM25S(documents)
for idx, doc in enumerate(documents):
    print(f'Document {idx} BM25S score: {bm25s.score(doc, query)}')

总结

BM25S通过引入新颖的内容深度计算方式,提升了文档与查询的匹配度,为信息检索提供了更为精准的排名结果。以上代码实现展示了BM25和BM25S在Python中的基本应用。在实际应用中,可以进一步根据不同的业务需求调整参数和扩展模型,以达到最优的检索效果。

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部