【Milvus】BM25(Best Matching 25)的定义、原理和应用

BM25(Best Matching 25)是一种广泛用于信息检索的排名函数,特别适合全文检索(Full Text Search) 场景。它是对传统 TF-IDF(Term Frequency-Inverse Document Frequency)模型的改进,通过引入词频饱和(Term Frequency Saturation)和文档长度归一化(Document Length Normalization)来优化文档与查询的相关性评分。BM25 在 Milvus 2.5.10 中被用来支持全文检索,将文本转换为稀疏向量(SPARSE_FLOAT_VECTOR)并计算相关性得分。

以下基于 Milvus 文档(https://milvus.io/docs/zh/full-text-search.md)、学术资源和其他公开信息,详细介绍 BM25 的定义、工作原理、数学公式、在 Milvus 中的应用、优缺点以及与分析器的关系。


1. BM25 定义

BM25 是一种概率检索模型,旨在根据查询词(Query Terms)与文档(Document)的相关性对文档进行排名。它由 Stephen E. Robertson 和 Karen Spärck Jones 在 1990 年代开发,广泛应用于搜索引擎(如 Elasticsearch、Solr)和向量数据库(如 Milvus)。BM25 的核心思想是:

  • 词频(Term Frequency, TF):查询词在文档中出现的频率越高,相关性越高,但高频词的贡献会逐渐饱和。
  • 逆文档频率(Inverse Document Frequency, IDF):查询词在整个文档集合中的稀有程度越高,权重越大。
  • 文档长度归一化:较短的文档通常比长文档更相关,因为词频在短文档中更集中。

BM25 通过调整参数(如 k1b)平衡这些因素,提供灵活且高效的排名。


2. BM25 工作原理

BM25 的工作流程包括以下步骤:

  1. 文本预处理
    • 使用分析器(Analyzer)对查询和文档文本进行分词(Tokenization)和过滤(Filtering,如小写、停用词移除)。
    • 示例:查询“vector database”分词为 ["vector", "database"]
  2. 令牌匹配
    • 比较查询的令牌与文档中的令牌,计算每个匹配令牌的贡献。
  3. 相关性评分
    • 为每个文档计算 BM25 分数,基于 TF、IDF 和文档长度。
  4. 结果排序
    • 按 BM25 分数从高到低排序,返回 Top-K 结果。

在 Milvus 中,BM25 通过 SPARSE_FLOAT_VECTOR 实现,分析器将文本转换为稀疏向量,BM25 算法计算向量间的相关性得分。


3. BM25 数学公式

BM25 的核心公式如下,用于计算查询 Q Q Q 和文档 D D D 的相关性得分:

score ( D , Q ) = ∑ i = 1 n IDF ( q i ) ⋅ TF ( q i , D ) ⋅ ( k 1 + 1 ) TF ( q i , D ) + k 1 ⋅ ( 1 − b + b ⋅ ∣ D ∣ avgdl ) \text{score}(D, Q) = \sum_{i=1}^{n} \text{IDF}(q_i) \cdot \frac{\text{TF}(q_i, D) \cdot (k_1 + 1)}{\text{TF}(q_i, D) + k_1 \cdot \left(1 - b + b \cdot \frac{|D|}{\text{avgdl}}\right)} score(D,Q)=i=1nIDF(qi)TF(qi,D)+k1(1b+bavgdlD)TF(qi,D)(k1+1)

公式分解

  • q i q_i qi:查询中的第 i i i 个词(令牌)。
  • TF ( q i , D ) \text{TF}(q_i, D) TF(qi,D):词 q i q_i qi 在文档 D D D 中的词频(Term Frequency)。
  • IDF ( q i ) \text{IDF}(q_i) IDF(qi):词 q i q_i qi 的逆文档频率,衡量词的稀有性:
    IDF ( q i ) = log ⁡ ( N − n ( q i ) + 0.5 n ( q i ) + 0.5 + 1 ) \text{IDF}(q_i) = \log \left( \frac{N - n(q_i) + 0.5}{n(q_i) + 0.5} + 1 \right) IDF(qi)=log(n(qi)+0.5Nn(qi)+0.5+1)
    • N N N:文档集合中的总文档数。
    • n ( q i ) n(q_i) n(qi):包含词 q i q_i qi 的文档数。
  • ∣ D ∣ |D| D:文档 D D D 的长度(通常以词数计)。
  • avgdl \text{avgdl} avgdl:集合中所有文档的平均长度。
  • k 1 k_1 k1:控制词频饱和的参数(通常 1.2-2.0,调整 TF 的影响)。
  • b b b:控制文档长度归一化的参数(通常 0.75,调整长文档的惩罚)。

参数解释

  • k 1 k_1 k1:调节词频的增益,值越大,高频词的贡献越大。
  • b b b:调节文档长度的影响, b = 0 b=0 b=0 忽略长度, b = 1 b=1 b=1 完全归一化。
  • IDF:稀有词(如“Milvus”)比常见词(如“the”)有更高权重。
  • TF 饱和:避免高频词(如出现 100 次 vs. 10 次)过度主导评分。
  • 长度归一化:短文档(如摘要)比长文档(如书籍)更容易获得高分。

4. BM25 在 Milvus 中的应用

Milvus 2.5.10 中,BM25 是全文检索(Full Text Search)的核心算法,通过稀疏向量(SPARSE_FLOAT_VECTOR)实现。以下是其在 Milvus 中的具体应用:

4.1 配置 BM25

  • 字段要求
    • VARCHAR 字段:存储原始文本,设置 enable_analyzer=True
    • SPARSE_FLOAT_VECTOR 字段:存储 BM25 生成的稀疏向量。
  • BM25 函数
    • 使用 FunctionFunctionType.BM25)将文本转换为稀疏向量。
    • 示例:
      bm25_function = Function(
          name="content_bm25",
          input_field_names=["content"],
          output_field_names=["sparse_vector"],
          function_type=FunctionType.BM25
      )
      schema.add_function(bm25_function)
      
  • 索引
    • 使用 AUTOINDEX 索引类型,指定 metric_type="BM25"
    • 示例:
      index_params.add_index(field_name="sparse_vector", index_type="AUTOINDEX", metric_type="BM25")
      
  • 分析器
    • 默认使用 standard 分析器,可通过 analyzer_params 指定 englishchinese 等。
    • 示例:analyzer_params={"type": "english"}

4.2 全文检索流程

  1. 插入数据
    • 用户插入 VARCHAR 字段的文本。
    • BM25 函数自动将文本转换为 SPARSE_FLOAT_VECTOR
  2. 查询
    • 用户输入自然语言查询(如 “vector database”)。
    • Milvus 使用相同的分析器分词,生成查询的稀疏向量。
  3. 搜索
    • 使用 client.searchsparse_vector 字段上执行 BM25 搜索。
    • 结果按相关性得分排序。

4.3 混合搜索

  • BM25(稀疏向量)常与密集向量(FLOAT_VECTOR)结合,用于混合搜索(Hybrid Search)。
  • 示例:结合 BM25(关键词匹配)和 HNSW(语义搜索),使用 RRFRanker 融合结果。

5. BM25 示例代码

以下是基于你的修正代码(混合搜索示例)的简化版本,专注于 BM25 全文检索,展示其在 Milvus 中的使用。

from pymilvus import MilvusClient, DataType, FunctionType, Function
from pymilvus.client.constants import ConsistencyLevel

# 连接 Milvus
client = MilvusClient(uri="http://localhost:19530")

try:
    # 创建数据库
    client.create_database(db_name="test_db")
    client.use_database(db_name="test_db")

    # 创建 Schema
    schema = MilvusClient.create_schema(auto_id=True)
    schema.add_field(
        field_name="pk",
        datatype=DataType.VARCHAR,
        is_primary=True,
        auto_id=True,
        max_length=100
    )
    schema.add_field(
        field_name="text",
        datatype=DataType.VARCHAR,
        max_length=65535,
        enable_analyzer=True,
        analyzer_params={"type": "english"}
    )
    schema.add_field(field_name="sparse_vector", datatype=DataType.SPARSE_FLOAT_VECTOR)

    # 定义 BM25 函数
    bm25_function = Function(
        name="text_bm25_sparse",
        input_field_names=["text"],
        output_field_names=["sparse_vector"],
        function_type=FunctionType.BM25
    )
    schema.add_function(bm25_function)

    # 创建集合
    client.create_collection(
        collection_name="bm25_collection",
        schema=schema,
        consistency_level=ConsistencyLevel.Session
    )

    # 创建索引
    index_params = MilvusClient.prepare_index_params()
    index_params.add_index(
        field_name="sparse_vector",
        index_type="AUTOINDEX",
        metric_type="BM25"
    )
    client.create_index(collection_name="bm25_collection", index_params=index_params)

    # 插入数据
    documents = [
        {"text": "Artificial intelligence was founded as an academic discipline in 1956."},
        {"text": "Alan Turing was the first person to conduct substantial research in AI."},
        {"text": "Born in Maida Vale, London, Turing was a mathematician and computer scientist."}
    ]
    client.insert(collection_name="bm25_collection", data=documents)

    # 加载集合
    client.load_collection(collection_name="bm25_collection")

    # BM25 全文检索
    results = client.search(
        collection_name="bm25_collection",
        data=["Artificial Intelligence"],
        anns_field="sparse_vector",
        limit=2,
        output_fields=["text"],
        consistency_level=ConsistencyLevel.Strong
    )
    print("BM25 search results:")
    for result in results[0]:
        print(f"Document: {result['entity']['text']}, Score: {result['distance']}")

except Exception as e:
    print(f"Error: {e}")

finally:
    # 清理
    client.drop_collection(collection_name="bm25_collection")
    client.drop_database(db_name="test_db")

输出示例

BM25 search results:
Document: Artificial intelligence was founded as an academic discipline in 1956., Score: 0.823
Document: Alan Turing was the first person to conduct substantial research in AI., Score: 0.654

代码说明

  • Schema:定义 textVARCHARenable_analyzer=True)和 sparse_vectorSPARSE_FLOAT_VECTOR)。
  • BM25 函数:将 text 转换为 sparse_vector
  • 索引:使用 AUTOINDEXmetric_type="BM25"
  • 搜索:直接输入查询文本,Milvus 自动分词并计算 BM25 分数。

6. BM25 的优缺点

优点

  • 高效性:稀疏向量表示(SPARSE_FLOAT_VECTOR)节省存储,适合大规模文本检索。
  • 相关性强:通过 TF 饱和和 IDF 权重,BM25 比 TF-IDF 更准确。
  • 灵活性:参数 k 1 k_1 k1 b b b 可调,适配不同场景。
  • 语言支持:结合 Milvus 分析器,支持多语言(如 englishchinese)。
  • 易集成:在 Milvus 中与密集向量搜索无缝结合,支持混合搜索。

缺点

  • 依赖分词:BM25 性能依赖分析器的分词质量(如中文分词可能需优化)。
  • 语义局限:BM25 基于词项匹配,无法捕捉深层语义(需结合密集向量)。
  • 参数调优 k 1 k_1 k1 b b b 的选择需要实验,影响排名效果。
  • 索引开销:稀疏向量和倒排索引增加存储和构建时间。

7. BM25 与分析器的关系

在 Milvus 中,BM25 依赖分析器(Analyzer) 处理文本:

  • 分词:分析器(如 english)将文本拆分为令牌,BM25 基于这些令牌计算 TF 和 IDF。
  • 过滤:分析器通过小写(lowercase)、词干提取(stemmer)、停用词移除(stop_words)优化令牌。
  • 配置
    • 默认 standard 分析器:简单分词,适合通用场景。
    • english 分析器:支持词干提取和停用词,适合英语文本。
    • chinese 分析器:基于 jieba 分词,适合中文文本。
  • 示例
    • 文本:“Milvus is a vector database”
    • english 分析器:["milvus", "vector", "databas"](小写、词干提取、移除“is”、“a”)。
    • BM25:计算每个令牌的 TF 和 IDF,生成稀疏向量。

8. 适用场景

  • RAG(Retrieval-Augmented Generation):检索相关文档作为大模型上下文(如 Milvus 的 RAG 应用)。
  • 关键词搜索:在技术文档、电商产品或新闻中查找包含查询词的记录。
  • 混合搜索:结合 BM25(关键词)和密集向量(语义),提升搜索准确性。
  • 多语言检索:使用特定语言分析器(如 chinese)处理非英语文本。

9. 注意事项

  • 版本兼容性:BM25 和 SPARSE_FLOAT_VECTOR 在 Milvus 2.5.x 中支持,确保使用 2.5.10 和 pymilvus 2.5.6。
  • 分析器选择:根据语言选择合适的分析器,中文文本需 chinese 分析器。
  • 参数调优:Milvus 默认 k1=1.5b=0.75,可通过 analyzer_params 调整(需验证支持)。
  • 性能:BM25 分词和索引构建会增加插入延迟,建议分批插入。
  • 错误处理:确保 FunctionType.BM25AUTOINDEX 正确配置,避免稀疏向量为空。

10. 总结

BM25 是一种高效的全文检索排名算法,基于 TF、IDF 和文档长度归一化,优化了查询与文档的相关性评分。在 Milvus 2.5.10 中,BM25 通过 SPARSE_FLOAT_VECTORFunctionType.BM25 实现,与分析器配合处理文本分词和过滤,支持全文检索和混合搜索。BM25 适用于关键词搜索、RAG 和多语言场景,结合密集向量可实现语义增强的检索。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彬彬侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值