【Milvus】 支持的度量类型(Metric Types)列举和说明

Milvus 2.5.10(搭配 pymilvus 2.5.6)中,度量类型(Metric Types) 是用于衡量向量之间相似性或距离的核心参数,广泛应用于向量索引构建和相似性搜索(ANN,近似最近邻搜索)。度量类型决定了如何计算两个向量之间的距离或相似度,直接影响搜索结果的语义和性能。Milvus 支持多种度量类型,根据向量数据类型的不同(如浮点向量、二进制向量、稀疏向量),适用的度量类型也有所差异。

以下基于 Milvus 2.5.10 的官方文档(https://milvus.io/docs/zh/metric.md)和其他相关资源,详细介绍 Milvus 支持的度量类型,包括定义、适用场景、支持的向量类型、数学公式、代码示例以及选择建议。内容将涵盖所有度量类型,确保准确、全面,并基于最新版本。


1. 概述

度量类型(Metric Types)是 Milvus 中用于量化向量相似性的方法,常见于以下场景:

  • 向量索引构建:在创建索引(如 HNSW、IVF_FLAT)时,指定度量类型以定义索引的距离计算方式。
  • 向量搜索:在搜索时,指定度量类型以确定返回结果的排序依据(最近邻或最相似)。
  • 混合查询:结合标量过滤和向量搜索时,度量类型影响向量部分的排序。

Milvus 支持的度量类型根据向量数据类型分为三类:

  • 浮点向量(FLOAT_VECTOR, FLOAT16_VECTOR, BFLOAT16_VECTOR):支持多种距离和相似度度量。
  • 二进制向量(BINARY_VECTOR):支持基于位运算的距离度量。
  • 稀疏向量(SPARSE_FLOAT_VECTOR):仅支持内积度量。

度量类型分为两类:

  • 距离度量:如欧几里得距离(L2),值越小表示向量越接近。
  • 相似度度量:如余弦相似度(COSINE),值越大表示向量越相似。

2. 度量类型详解

以下按向量数据类型分类,介绍 Milvus 2.5.10 支持的所有度量类型,包括定义、公式、适用场景和代码示例。

2.1 浮点向量度量类型

浮点向量(FLOAT_VECTORFLOAT16_VECTORBFLOAT16_VECTOR)是 Milvus 中最常用的向量类型,适用于机器学习模型(如 BERT、ResNet)生成的嵌入。支持的度量类型包括:

(1) L2(欧几里得距离)
  • 定义:计算两个向量之间的欧几里得距离(平方和开根号),表示几何空间中的直线距离。
  • 公式
    L 2 ( x , y ) = ∑ i = 1 n ( x i − y i ) 2 L2(x, y) = \sqrt{\sum_{i=1}^n (x_i - y_i)^2} L2(x,y)=i=1n(xiyi)2
    其中 x x x y y y 是两个 n n n 维向量, x i x_i xi y i y_i yi 是第 i i i 个维度。
  • 适用场景
    • 向量未归一化,需直接比较绝对距离。
    • 图像处理、推荐系统等需要精确几何距离的场景。
  • 优点
    • 直观反映向量间的绝对差异。
    • 计算简单,广泛支持。
  • 缺点
    • 对向量幅值敏感,未归一化的向量可能导致偏差。
    • 高维数据可能受维数灾难影响。
  • 支持的索引:FLAT、IVF_FLAT、IVF_PQ、IVF_SQ8、HNSW、HNSW_SQ、HNSW_PQ、HNSW_PRQ、SCANN、DiskANN、GPU_CAGRA、GPU_IVF_FLAT、GPU_IVF_PQ、GPU_BRUTE_FORCE。
  • 代码示例
    from pymilvus import MilvusClient, CollectionSchema, FieldSchema, DataType
    from pymilvus.milvus_client.index import IndexParams
    import random
    
    client = MilvusClient(uri="http://localhost:19530")
    fields = [
        FieldSchema(name="id", dtype=DataType.INT64, is_primary=True),
        FieldSchema(name="vector", dtype=DataType.FLOAT_VECTOR, dim=128)
    ]
    schema = CollectionSchema(fields=fields)
    client.create_collection(collection_name="l2_example", schema=schema)
    
    # 创建 HNSW 索引,指定 L2
    index_params = IndexParams()
    index_params.add_index(
        field_name="vector",
        index_type="HNSW",
        metric_type="L2",
        params={"M": 16, "efConstruction": 200}
    )
    client.create_index(collection_name="l2_example", index_params=index_params)
    
    client.load_collection(collection_name="l2_example")
    
    # 插入数据
    data = [
        {"id": i, "vector": [random.random() for _ in range(128)]}
        for i in range(1000)
    ]
    client.insert(collection_name="l2_example", data=data)
    
    # 搜索
    query_vector = [random.random() for _ in range(128)]
    results = client.search(
        collection_name="l2_example",
        data=[query_vector],
        limit=5,
        search_params={"metric_type": "L2", "params": {"ef": 64}}
    )
    print("L2 search results:", results)
    
(2) IP(内积)
  • 定义:计算两个向量的内积,通常用于衡量方向相似性(需归一化向量以等价于余弦相似度)。
  • 公式
    I P ( x , y ) = ∑ i = 1 n x i ⋅ y i IP(x, y) = \sum_{i=1}^n x_i \cdot y_i IP(x,y)=i=1nxiyi
    • 对于归一化向量, I P ( x , y ) = cos ⁡ ( θ ) IP(x, y) = \cos(\theta) IP(x,y)=cos(θ),值越大表示越相似。
  • 适用场景
    • 归一化向量,衡量方向相似性。
    • NLP(如词嵌入)、推荐系统(如用户-物品相似性)。
  • 优点
    • 计算效率高,适合高维数据。
    • 对于归一化向量,等价于余弦相似度。
  • 缺点
    • 对未归一化向量敏感,需预处理。
    • 不直接反映几何距离。
  • 支持的索引:FLAT、IVF_FLAT、IVF_PQ、IVF_SQ8、HNSW、HNSW_SQ、HNSW_PQ、HNSW_PRQ、SCANN、DiskANN、GPU_CAGRA、GPU_IVF_FLAT、GPU_IVF_PQ、GPU_BRUTE_FORCE。
  • 代码示例
    # 类似 L2 示例,仅修改 metric_type 为 IP
    index_params.add_index(
        field_name="vector",
        index_type="HNSW",
        metric_type="IP",
        params={"M": 16, "efConstruction": 200}
    )
    client.create_index(collection_name="ip_example", index_params=index_params)
    results = client.search(
        collection_name="ip_example",
        data=[query_vector],
        limit=5,
        search_params={"metric_type": "IP", "params": {"ef": 64}}
    )
    print("IP search results:", results)
    
(3) COSINE(余弦相似度)
  • 定义:计算两个向量夹角的余弦值,衡量方向相似性,与向量幅值无关。
  • 公式
    C O S I N E ( x , y ) = ∑ i = 1 n x i ⋅ y i ∑ i = 1 n x i 2 ⋅ ∑ i = 1 n y i 2 COSINE(x, y) = \frac{\sum_{i=1}^n x_i \cdot y_i}{\sqrt{\sum_{i=1}^n x_i^2} \cdot \sqrt{\sum_{i=1}^n y_i^2}} COSINE(x,y)=i=1nxi2 i=1nyi2 i=1nxiyi
    • 范围: [ − 1 , 1 ] [-1, 1] [1,1],值越大表示越相似。
  • 适用场景
    • 向量已归一化或需忽略幅值差异。
    • 文本语义搜索、图像检索(如 CLIP 模型)。
  • 优点
    • 忽略向量幅值,仅关注方向,适合语义相似性。
    • 归一化后计算效率高。
  • 缺点
    • 对未归一化向量需额外计算归一化。
    • 不反映绝对距离。
  • 支持的索引:FLAT、IVF_FLAT、IVF_PQ、IVF_SQ8、HNSW、HNSW_SQ、HNSW_PQ、HNSW_PRQ、SCANN、DiskANN、GPU_CAGRA、GPU_IVF_FLAT、GPU_IVF_PQ、GPU_BRUTE_FORCE。
  • 代码示例
    # 类似 L2 示例,仅修改 metric_type 为 COSINE
    index_params.add_index(
        field_name="vector",
        index_type="HNSW",
        metric_type="COSINE",
        params={"M": 16, "efConstruction": 200}
    )
    client.create_index(collection_name="cosine_example", index_params=index_params)
    results = client.search(
        collection_name="cosine_example",
        data=[query_vector],
        limit=5,
        search_params={"metric_type": "COSINE", "params": {"ef": 64}}
    )
    print("COSINE search results:", results)
    

2.2 二进制向量度量类型

二进制向量(BINARY_VECTOR)存储 1 位值(每 8 位占 1 字节),适用于高效的二值化特征。支持的度量类型基于位运算,计算两个向量之间的差异。

(1) HAMMING(汉明距离)
  • 定义:计算两个二进制向量对应位不同的数量(异或运算后统计 1 的个数)。
  • 公式
    H A M M I N G ( x , y ) = ∑ i = 1 n ( x i ⊕ y i ) HAMMING(x, y) = \sum_{i=1}^n (x_i \oplus y_i) HAMMING(x,y)=i=1n(xiyi)
    其中 ⊕ \oplus 表示异或运算, n n n 是位数。
  • 适用场景
    • 二值化特征(如图像哈希、签名)。
    • 需要快速比较的场景。
  • 优点
    • 计算效率极高(位运算)。
    • 适合低存储成本的场景。
  • 缺点
    • 仅反映位差异,语义表达有限。
    • 精度较低。
  • 支持的索引:BIN_FLAT、BIN_IVF_FLAT。
  • 代码示例
    from pymilvus import MilvusClient, CollectionSchema, FieldSchema, DataType
    from pymilvus.milvus_client.index import IndexParams
    import random
    from bitarray import bitarray  # pip install bitarray
    
    client = MilvusClient(uri="http://192.168.1.110:19530")
    fields = [
        FieldSchema(name="id", dtype=DataType.INT64, is_primary=True),
        FieldSchema(name="vector", dtype=DataType.BINARY_VECTOR, dim=128)
    ]
    schema = CollectionSchema(fields=fields)
    client.create_collection(collection_name="hamming_example", schema=schema)
    
    # 创建 BIN_FLAT 索引,指定 HAMMING
    index_params = IndexParams()
    index_params.add_index(
        field_name="vector",
        index_type="BIN_FLAT",
        metric_type="HAMMING"
    )
    client.create_index(collection_name="hamming_example", index_params=index_params)
    
    def generate_binary_vector(dim=128):
        bits = bitarray()
        for _ in range(dim):
            bits.append(random.choice([True, False]))
        return bits.tobytes()
    
    # 插入数据
    data = [
        {"id": i, "vector": generate_binary_vector(128)}
        for i in range(1000)
    ]
    client.insert(collection_name="hamming_example", data=data)
    
    client.load_collection(collection_name="hamming_example")
       
    # 搜索
    query_vector = generate_binary_vector(128)
    results = client.search(
        collection_name="hamming_example",
        data=[query_vector],
        limit=5,
        search_params={"metric_type": "HAMMING"}
    )
    print("HAMMING search results:", results)
    
(2) JACCARD(杰卡德距离)
  • 定义:计算两个二进制向量的杰卡德距离,表示交集与并集的比率。
  • 公式
    J A C C A R D ( x , y ) = 1 − ∣ x ∩ y ∣ ∣ x ∪ y ∣ = ∣ x ⊕ y ∣ ∣ x ∪ y ∣ JACCARD(x, y) = 1 - \frac{|x \cap y|}{|x \cup y|} = \frac{|x \oplus y|}{|x \cup y|} JACCARD(x,y)=1xyxy=xyxy
    • ∣ x ∩ y ∣ |x \cap y| xy:对应位均为 1 的数量。
    • ∣ x ∪ y ∣ |x \cup y| xy:至少一位为 1 的数量。
  • 适用场景
    • 集合相似性比较(如标签集、特征集)。
    • 需要归一化差异的场景。
  • 优点
    • 归一化距离,适合比较集合相似性。
    • 对向量长度不敏感。
  • 缺点
    • 计算复杂度略高于 HAMMING。
    • 语义表达有限。
  • 支持的索引:BIN_FLAT、BIN_IVF_FLAT。
  • 代码示例
    # 类似 HAMMING 示例,仅修改 metric_type 为 JACCARD
    index_params.add_index(
        field_name="vector",
        index_type="BIN_FLAT",
        metric_type="JACCARD"
    )
    client.create_index(collection_name="jaccard_example", index_params=index_params)
    results = client.search(
        collection_name="jaccard_example",
        data=[query_vector],
        limit=5,
        search_params={"metric_type": "JACCARD"}
    )
    print("JACCARD search results:", results)
    
(3) TANIMOTO(谷本距离)
  • 定义:计算两个二进制向量的谷本距离,扩展了杰卡德距离,考虑位差异和共同位。
  • 公式
    T A N I M O T O ( x , y ) = ∣ x ⊕ y ∣ ∣ x ∪ y ∣ + ∣ x ∩ y ∣ TANIMOTO(x, y) = \frac{|x \oplus y|}{|x \cup y| + |x \cap y|} TANIMOTO(x,y)=xy+xyxy
  • 适用场景
    • 集合相似性比较,强调共同特征。
    • 化学信息学、指纹匹配。
  • 优点
    • 比 JACCARD 更细致地考虑共同位。
    • 适合特定领域(如化学相似性)。
  • 缺点
    • 计算复杂度略高。
    • 应用场景较窄。
  • 支持的索引:BIN_FLAT、BIN_IVF_FLAT。
  • 代码示例
    # 类似 HAMMING 示例,仅修改 metric_type 为 TANIMOTO
    index_params.add_index(
        field_name="vector",
        index_type="BIN_FLAT",
        metric_type="TANIMOTO"
    )
    client.create_index(collection_name="tanimoto_example", index_params=index_params)
    results = client.search(
        collection_name="tanimoto_example",
        data=[query_vector],
        limit=5,
        search_params={"metric_type": "TANIMOTO"}
    )
    print("TANIMOTO search results:", results)
    

2.3 稀疏向量度量类型

稀疏向量(SPARSE_FLOAT_VECTOR)存储非零值及其索引,适用于稀疏数据(如 BM25 词频向量)。Milvus 2.5.10 仅支持一种度量类型:

(1) IP(内积)
  • 定义:计算稀疏向量的内积,仅考虑非零值的乘积。
  • 公式
    I P ( x , y ) = ∑ i ∈ I x ∩ I y x i ⋅ y i IP(x, y) = \sum_{i \in I_x \cap I_y} x_i \cdot y_i IP(x,y)=iIxIyxiyi
    其中 I x I_x Ix I y I_y Iy 是向量 x x x y y y 的非零索引集合。
  • 适用场景
    • 关键词搜索(如 BM25)。
    • 稀疏特征表示(如文档向量)。
  • 优点
    • 计算效率高,仅处理非零值。
    • 适合稀疏数据,存储成本低。
  • 缺点
    • 仅支持内积,无法使用其他度量。
    • 需确保数据稀疏性以获得最佳性能。
  • 支持的索引:SPARSE_INVERTED_INDEX(支持 DAAT_WAND 算法)。
  • 代码示例
    from pymilvus import MilvusClient, CollectionSchema, FieldSchema, DataType
    from pymilvus.milvus_client.index import IndexParams
    
    client = MilvusClient(uri="http://localhost:19530")
    fields = [
        FieldSchema(name="id", dtype=DataType.INT64, is_primary=True),
        FieldSchema(name="vector", dtype=DataType.SPARSE_FLOAT_VECTOR)
    ]
    schema = CollectionSchema(fields=fields)
    client.create_collection(collection_name="sparse_ip_example", schema=schema)
    
    # 创建 SPARSE_INVERTED_INDEX 索引,指定 IP
    index_params = IndexParams()
    index_params.add_index(
        field_name="vector",
        index_type="SPARSE_INVERTED_INDEX",
        metric_type="IP",
        params={"inverted_index_algo": "DAAT_WAND"}
    )
    client.create_index(collection_name="sparse_ip_example", index_params=index_params)
    
    # 插入数据
    data = [
        {"id": 0, "vector": {0: 0.1, 100: 0.5}},
        {"id": 1, "vector": {1: 0.2, 200: 0.3}}
    ]
    client.insert(collection_name="sparse_ip_example", data=data)
    
    client.load_collection(collection_name="sparse_ip_example")
    
    # 搜索
    query_vector = {0: 0.2, 100: 0.4}
    results = client.search(
        collection_name="sparse_ip_example",
        data=[query_vector],
        limit=5,
        search_params={"metric_type": "IP"}
    )
    print("Sparse IP search results:", results)
    

3. 度量类型与向量类型的对应关系

以下是 Milvus 2.5.10 中度量类型与向量类型的支持矩阵:

度量类型FLOAT_VECTORBINARY_VECTORSPARSE_FLOAT_VECTOR
L2
IP
COSINE
HAMMING
JACCARD
TANIMOTO

说明

  • 浮点向量支持最广泛的度量类型,适合通用场景。
  • 二进制向量仅支持位运算相关的度量,适合高效存储和计算。
  • 稀疏向量仅支持内积,专为稀疏数据优化。

4. 选择度量类型的建议

选择度量类型时,需考虑向量类型、数据特性、应用场景和预处理方式。以下是建议:

  • 浮点向量

    • L2:适合未归一化的向量,或需精确几何距离的场景(如图像处理)。
    • IP:适合归一化向量,强调方向相似性(如推荐系统)。
    • COSINE:适合忽略幅值的语义搜索(如文本嵌入、CLIP 模型)。推荐对向量预归一化以提高效率。
    • 选择依据
      • 如果向量已归一化,IPCOSINE 等价,选择 COSINE 更直观。
      • 如果向量未归一化且幅值重要,选择 L2
      • 如果性能优先,IP 计算最快。
  • 二进制向量

    • HAMMING:默认选择,计算最快,适合快速比较(如图像哈希)。
    • JACCARD:适合集合相似性,强调交集与并集的比例。
    • TANIMOTO:适合特定领域(如化学相似性),对共同特征敏感。
    • 选择依据
      • 优先选择 HAMMING 除非有特定需求(如集合归一化或化学应用)。
  • 稀疏向量

    • IP:唯一选项,适合关键词搜索或稀疏特征(如 BM25)。
    • 注意:确保数据足够稀疏以最大化性能。
  • 预处理建议

    • 对于 IPCOSINE,建议预归一化向量(L2 范数归一化)以提高搜索效率和一致性:
      import numpy as np
      def normalize_vector(v):
          norm = np.linalg.norm(v)
          return v / norm if norm > 0 else v
      
    • 对于二进制向量,确保数据是二值化的(0 或 1)。

5. 注意事项

  • 版本兼容性
    • 确保使用 Milvus 2.5.10 和 pymilvus 2.5.6,所有度量类型均受支持。
    • 稀疏向量的 IP 度量在 Milvus 2.5.x 中进一步优化,需验证版本。
  • 索引与度量一致性
    • 索引构建时的 metric_type 必须与搜索时的 metric_type 一致,否则会报错:
      try:
          client.search(..., search_params={"metric_type": "L2"})
      except Exception as e:
          print(f"Error: {e}")
      
  • 性能优化
    • IPCOSINE 在归一化向量上计算效率高于 L2
    • 二进制向量的位运算度量(HAMMING)速度极快,适合高吞吐量。
  • 硬件支持
    • GPU 索引(如 GPU_CAGRA)支持浮点向量的所有度量类型,但需 NVIDIA GPU 和 CUDA。
    • 稀疏向量索引(如 SPARSE_INVERTED_INDEX)仅支持 CPU。
  • 数据预处理
    • 浮点向量需检查是否归一化,影响 IPCOSINE 的结果。
    • 二进制向量需确保维度是 8 的倍数(按字节存储)。
    • 稀疏向量需确保非零值比例低以优化存储和计算。

6. 混合查询示例

度量类型常与标量过滤结合使用,实现混合查询。以下是一个示例,展示浮点向量使用 COSINE 度量,结合 JSON 字段过滤:

from pymilvus import MilvusClient, CollectionSchema, FieldSchema, DataType
from pymilvus.milvus_client.index import IndexParams
import random

client = MilvusClient(uri="http://localhost:19530")

# 定义 schema
fields = [
    FieldSchema(name="id", dtype=DataType.INT64, is_primary=True),
    FieldSchema(name="metadata", dtype=DataType.JSON),
    FieldSchema(name="vector", dtype=DataType.FLOAT_VECTOR, dim=128)
]
schema = CollectionSchema(fields=fields)
client.create_collection(collection_name="mixed_query_example", schema=schema)

# 创建索引
index_params = IndexParams()
# JSON 字段索引
index_params.add_index(
    field_name="metadata",
    index_type="INVERTED",
    index_name="json_category",
    params={"json_path": "metadata[\"category\"]", "json_cast_type": "varchar"}
)
# 向量索引
index_params.add_index(
    field_name="vector",
    index_type="HNSW",
    metric_type="COSINE",
    params={"M": 16, "efConstruction": 200}
)
client.create_index(collection_name="mixed_query_example", index_params=index_params)

# 插入数据
data = [
    {
        "id": i,
        "metadata": {"category": "electronics" if i % 2 == 0 else "clothing"},
        "vector": [random.random() for _ in range(128)]
    }
    for i in range(1000)
]
client.insert(collection_name="mixed_query_example", data=data)

client.load_collection(collection_name="mixed_query_example")

# 混合查询
query_vector = [random.random() for _ in range(128)]
results = client.search(
    collection_name="mixed_query_example",
    data=[query_vector],
    limit=5,
    filter='metadata["category"] == "electronics"',
    output_fields=["id", "metadata"],
    search_params={"metric_type": "COSINE", "params": {"ef": 64}}
)
print("Mixed query results:", results)

7. 总结

Milvus 2.5.10 支持的度量类型涵盖浮点向量(L2IPCOSINE)、二进制向量(HAMMINGJACCARDTANIMOTO)和稀疏向量(IP),满足多样化的相似性计算需求。浮点向量度量适用于通用场景,二进制向量度量高效且节省存储,稀疏向量度量专为稀疏数据优化。选择度量类型时,需考虑向量类型、数据预处理(如归一化)和应用场景(如语义搜索或集合比较)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

彬彬侠

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

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

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

打赏作者

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

抵扣说明:

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

余额充值