跳到主要内容

稀疏向量

稀疏向量(Sparse Vector)是信息检索和自然语言处理中的一种重要数据表示方法。虽然稠密向量(Dense Vector)因其出色的语义理解能力而广受欢迎,但在需要精确匹配关键词或短语的应用中,稀疏向量往往能够提供更为准确的结果。

概述

稀疏向量是一种高维向量的特殊表示方法,其大多数元素为零,只有少数维度上有非零值。如下图所示,稠密向量通常以连续数组的形式表示,每个位置都有一个值(如 [0.3, 0.8, 0.2, 0.3, 0.1])。相比之下,稀疏向量仅存储非零元素及其索引位置,通常表示为键值对列表(如 [{2: 0.2}, ..., {9997: 0.5}, {9999: 0.7}])。

XSFJwXDGGhJGoob8UaMcvpCrnOb

通过符号化和打分体系,文档由词袋向量表示,每个维度对应词表中的一个单词。文档中出现的单词在对应的向量中才有非 0 的取值。将所有非 0 的维度拼接起来就形成了该文档的稀疏向量表示。您可以使用如下两种方式生成稀疏向量:

  • 传统统计方法:例如词频-逆文档频率(TF-IDF)和最佳匹配 25(BM25)等。这些方法基于词汇在语料库中的频率和重要性为词汇赋予权重,通过计算简单统计量作为每个维度的评分。每个维度代表一个词元。 Zilliz Cloud内置基于 BM25 算法的全文搜索功能,可自动将文本转换为稀疏向量,无需人工预处理。该方案特别适用于强调精确匹配和搜索精度的关键词检索场景。更多详情,请参阅Full Text Search

  • 神经稀疏向量嵌入模型:基于大量数据训练的可以生成使用稀疏向量表示的模型。通常都是 Transformer 架构的深度学习模型,能够根据语义上下文扩充和权衡待评估词句。Zilliz Cloud 也支持使用诸如 SPLADE 等外部的生成式稀疏向量模型。更多详情,请参阅 Embeddings

数据在向量化后,可以存储在 Zilliz Cloud 中进行管理和向量检索。下图展示了基本流程。

AAIowWHINh4lYhbAmPlcJ5yQnUn

📘说明

除了稀疏向量,Zilliz Cloud 还支持稠密向量和 Binary 向量。稠密向量适用于捕捉深层次的语义关联,而 Binary 向量则在快速相似性比较和内容去重等场景中表现出色。有关更多信息,请参考稠密向量Binary 向量

数据格式

Zilliz Cloud 支持用以下任意格式表示稀疏向量:

  • 字典列表(格式为 {dimension_index: value, ...}

    # Represent each sparse vector using a dictionary
    sparse_vectors = [{27: 0.5, 100: 0.3, 5369: 0.6} , {100: 0.1, 3: 0.8}]
  • 稀疏矩阵(使用 scipy.sparse 类)

    from scipy.sparse import csr_matrix

    # First vector: indices [27, 100, 5369] with values [0.5, 0.3, 0.6]
    # Second vector: indices [3, 100] with values [0.8, 0.1]
    indices = [[27, 100, 5369], [3, 100]]
    values = [[0.5, 0.3, 0.6], [0.8, 0.1]]
    sparse_vectors = [csr_matrix((vals, ([0]*len(idx), idx)), shape=(1, 5369+1)) for idx, vals in zip(indices, values)]
  • 元组迭代器列表(格式为 [(dimension_index, value)]

    # Represent each sparse vector using a list of iterables (e.g. tuples)
    sparse_vector = [
    [(27, 0.5), (100, 0.3), (5369, 0.6)],
    [(100, 0.1), (3, 0.8)]
    ]

定义 Collection Schema

在创建 Collection 之前,需要定义 Collection Schema。这包括添加字段和定义将文本转换成对应稀疏向量表示的派生方法。

添加字段

要在 Zilliz Cloud 中使用稀疏向量,首先需要在创建 Collection 时定义用于存储稀疏向量的字段。这个过程包括:

  1. 设置 datatype 为支持的稀疏向量数据类型,即 SPARSE_FLOAT_VECTOR。该字段的值可以由您提供或由指定 VARCHAR 字段自动转换而来。

  2. 通常建议您将原始文本和向量字段都存入 Collection中。您可以使用 VARCHAR 字段来存放原始文本。

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri="YOUR_CLUSTER_ENDPOINT")

schema = client.create_schema(
auto_id=True,
enable_dynamic_fields=True,
)

schema.add_field(field_name="pk", datatype=DataType.VARCHAR, is_primary=True, max_length=100)
schema.add_field(field_name="sparse_vector", datatype=DataType.SPARSE_FLOAT_VECTOR)
schema.add_field(field_name="text", datatype=DataType.VARCHAR, max_length=65535, enable_analyzer=True)

以上示例中,我们添加了三个名字段。它们分别为:

  • pk: 该字段用于存放 VARCHAR 类型的主键,其值为最大长度不超过 100 字节的自动生成的文本。

  • sparse_vector: 该字段用于存放 SPARSE_FLOAT_VECTOR 类型的向量字段,用于存储稀疏向量。

  • text: 该字段用于存放 VARCHAR 类型的文本字符串,最大长度为 1000 字节。

📘说明

如果希望 or Zilliz Cloud 在插入数据时将指定的文本转换成稀疏向量。您还需要创建 Function。关于 Function 的更多内容,可以参考 Full Text Search

为稀疏向量创建索引

为稀疏向量创建索引的过程和稠密向量类似,但指定的索引类型(index_type),距离度量类型(metric_type),和索引参数(params)有所差别。

index_params = client.prepare_index_params()

index_params.add_index(
field_name="sparse_vector",
index_name="sparse_auto_index",
index_type="AUTOINDEX",
metric_type="IP"
)

上述示例使用索引类型为 SPARSE_INVERTED_INDEX,度量类型为 BM25。更多详细内容,可以参考如下内容:

创建 Collection

稀疏向量和索引定义完成后,我们便可以创建包含稀疏向量的 Collection。以下示例通过 create_collection 方法创建了一个名为 my_sparse_collection 的 Collection。

client.create_collection(
collection_name="my_collection",
schema=schema,
index_params=index_params
)

插入稀疏向量

在插入数据时,您需要为所有在 Schema 中字义的字段提供相应的值,除了那些自动生成的字段(如因开启 AutoID 为自动生成的主键等)。如果您使用内置的 BM25 功能自动生成稀疏向量字段,在插入数据时,也不需要提供该字段的取值。

data = [
{
"text": "information retrieval is a field of study.",
"sparse_vector": {1: 0.5, 100: 0.3, 500: 0.8}
},
{
"text": "information retrieval focuses on finding relevant information in large datasets.",
"sparse_vector": {10: 0.1, 200: 0.7, 1000: 0.9}
}
]

client.insert(
collection_name="my_collection",
data=data
)

要基于稀疏向量进行相似性搜索,您需要先准备查询向量和搜索参数。

# Prepare search parameters
search_params = {
"params": {"drop_ratio_search": 0.2}, # A tunable drop ratio parameter with a valid range between 0 and 1
}

# Query with sparse vector
query_data = [{1: 0.2, 50: 0.4, 1000: 0.7}]

然后就可以使用 search 方法进行相似性搜索了。

res = client.search(
collection_name="my_collection",
data=query_data,
limit=3,
output_fields=["pk"],
search_params=search_params,
consistency_level="Strong"
)

print(res)

# Output
# data: ["[{'id': '453718927992172266', 'distance': 0.6299999952316284, 'entity': {'pk': '453718927992172266'}}, {'id': '453718927992172265', 'distance': 0.10000000149011612, 'entity': {'pk': '453718927992172265'}}]"]

有关更多搜索相关信息,请参考基本 ANN Search