算法说明
BM25(Best Matching 25)是一种信息检索领域的排名算法,用于计算查询(Query)与文档(Document)之间的相关性得分。它改进了传统的TF-IDF算法,引入文档长度归一化和词频饱和机制,使检索结果更准确。
公式表示:
其中:
- f(qi,D) 是词项 qi在文档 D中的出现次数(TF),
- N 是文档总数,
- n(qi) 是包含词项 qi的文档数,
- ∣D∣是文档 D的长度,
- avgdl 是所有文档的平均长度,
- k1 和 b是调整参数,通常设置为 k1=1.2和 b=0.75 。
简单示例
假设我们有以下文档集合:
文档1:”我喜欢编程”
文档2:”编程很有趣”
- 查询:”他喜欢编程”
步骤:
- 分词:将文档和查询拆分为词。
- 文档1:[“我”, “喜欢”, “编程”]
- 文档2:[“编程”, “很”, “有趣”]
- 查询:[“他”, “喜欢”, “编程”]
- 计算BM25得分:使用
rank_bm25库计算每个文档与查询的相关性。
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| import jieba from rank_bm25 import BM25L
class BM25Search: def __init__(self, documents): self.documents = documents self.tokenized_docs = [jieba.lcut(doc) for doc in documents] self.bm25 = BM25L(self.tokenized_docs) logger.info("BM25模型初始化完成")
def search(self, query): tokenized_query = jieba.lcut(query) try: scores = self.bm25.get_scores(tokenized_query) print(f'scores--》{scores}') best_idx = scores.argmax() best_score = scores[best_idx] best_doc = self.documents[best_idx] logger.info(f"查询: {query}, 最佳匹配: {best_doc}, 得分: {best_score}") return best_doc, best_score except Exception as e: logger.error(f"检索失败: {e}") return None, 0.0 def main(): documents = ["我喜欢编程", "编程很有趣"] bm25_search = BM25Search(documents) query = "他喜欢编程" result, score = bm25_search.search(query) if result: logger.info(f"查询结果: {result}, 得分: {score}") else: logger.info("未找到匹配结果")
if __name__ == "__main__": main()
|
结果如下:
1 2 3
| 2025-04-02 19:01:27,463 - INFO - BM25模型初始化完成 2025-04-02 19:01:27,464 - INFO - 查询: 他喜欢编程, 最佳匹配: 我喜欢编程, 得分: 1.094 2025-04-02 19:01:27,464 - INFO - 查询结果: 我喜欢编程, 得分: 1.094
|