跳到主要内容

HNSW

HNSW index 是一种基于图的索引算法,可以在搜索高维浮点向量时提高性能。它提供出色的搜索准确性和延迟,同时需要内存开销来维护其分层图结构。

概述

分层可导航小世界 (HNSW) 算法构建一个多层图,有点像具有不同缩放级别的地图。底层包含所有数据点,而上层由从下层采样的数据点子集组成。

在这个层次结构中,每一层都包含表示数据点的节点,通过表示其邻近性的边连接。更高的层提供长距离跳跃以快速接近目标,而较低的层启用细粒度搜索以获得最准确的结果。

工作原理如下:

  1. 入口点:搜索从顶层的固定入口点开始,这是图中的预定节点。

  2. 贪婪搜索:算法贪婪地移动到当前层的最近邻居,直到它无法更接近查询向量。上层具有导航目的,充当粗过滤器来定位较低级别精细搜索的潜在入口点。

  3. 层下降:一旦在当前层达到局部最小值,算法使用预先建立的连接跳转到下层,并重复贪婪搜索。

  4. 最终细化:此过程持续到达到底层,在那里最终细化步骤识别最近邻居。

HNSW

HNSW 的性能取决于几个关键参数,这些参数控制图的结构和搜索行为。包括:

  • M:层次结构每一级图中每个节点可以拥有的最大边数或连接数。更高的 M 会导致更密集的图,并增加召回率和准确性,因为搜索有更多路径可探索,这也会消耗更多内存并由于额外连接而减慢插入时间。如上图所示,M = 5 表示 HNSW 图中的每个节点直接连接到最多 5 个其他节点。这创建了一个适度密集的图结构,其中节点有多个路径到达其他节点。

  • efConstruction:索引构建期间考虑的候选数量。更高的 efConstruction 通常会产生更好质量的图,但需要更多时间来构建。

  • ef:搜索期间评估的邻居数量。增加 ef 提高找到最近邻居的可能性,但会减慢搜索过程。

有关如何调整这些设置以满足您需求的详细信息,请参阅 Index 参数

构建 Index

要在 Milvus 中的向量 field 上构建 HNSW index,使用 add_index() 方法,指定 index_typemetric_type 和 index 的其他参数。

from pymilvus import MilvusClient

# Prepare index building params
index_params = MilvusClient.prepare_index_params()

index_params.add_index(
field_name="your_vector_field_name", # Name of the vector field to be indexed
index_type="HNSW", # Type of the index to create
index_name="vector_index", # Name of the index to create
metric_type="L2", # Metric type used to measure similarity
params={
"M": 64, # Maximum number of neighbors each node can connect to in the graph
"efConstruction": 100 # Number of candidate neighbors considered for connection during index construction
} # Index building params
)

在此配置中:

  • index_type:要构建的 index 类型。在此示例中,将值设置为 HNSW

  • metric_type:用于计算向量之间距离的方法。支持的值包括 COSINEL2IP。有关详细信息,请参阅 度量类型

  • params:构建 index 的其他配置选项。

    • M:每个节点可以连接的最大邻居数。

    • efConstruction:索引构建期间考虑连接的候选邻居数量。

    要了解 HNSW index 可用的更多构建参数,请参阅 Index 构建参数

配置 index 参数后,您可以直接使用 create_index() 方法创建 index,或在 create_collection 方法中传递 index 参数。有关详细信息,请参阅 创建 Collection

在 Index 上搜索

构建 index 并插入 entity 后,您可以在 index 上执行相似性搜索。

search_params = {
"params": {
"ef": 10, # Number of neighbors to consider during the search
}
}

res = MilvusClient.search(
collection_name="your_collection_name", # Collection name
anns_field="vector_field", # Vector field name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector
limit=10, # TopK results to return
search_params=search_params
)

在此配置中:

  • params:在 index 上搜索的其他配置选项。

    • ef:搜索期间考虑的邻居数量。

    要了解 HNSW index 可用的更多搜索参数,请参阅 Index 特定搜索参数

Index 参数

本节概述了用于构建 index 和在 index 上执行搜索的参数。

Index 构建参数

下表列出了在构建 index 时可以在 params 中配置的参数。

参数

描述

值范围

调优建议

M

图中每个节点可以拥有的最大连接数(或边),包括传出和传入边。此参数直接影响索引构建和搜索。

类型:整数 范围:[2, 2048]

默认值30(每个节点最多 30 条传出和 30 条传入边)

更大的 M 通常会导致更高的准确性,但增加内存开销减慢索引构建和搜索。考虑为高维数据集或高召回率至关重要时增加 M

当内存使用和搜索速度是主要关注点时,考虑减少 M

在大多数情况下,我们建议您在此范围内设置值:[5, 100]。

efConstruction

索引构建期间考虑连接的候选邻居数量。为每个新元素评估更大的候选池,但实际建立的最大连接数仍受 M 限制。

类型:整数 范围:[1, int_max]

默认值360

更高的 efConstruction 通常会产生更准确的索引,因为探索了更多潜在连接。但是,这也会导致更长的索引时间和构建期间增加的内存使用。考虑增加 efConstruction 以提高准确性,特别是在索引时间不太关键的场景中。

当资源约束是关注点时,考虑减少 efConstruction 以加速索引构建。

在大多数情况下,我们建议您在此范围内设置值:[50, 500]。

Index 特定搜索参数

下表列出了在在 index 上搜索时可以在 search_params.params 中配置的参数。

参数

描述

值范围

调优建议

ef

控制最近邻检索期间搜索的广度。它确定访问和评估多少节点作为潜在最近邻居。此参数仅影响搜索过程,并专门应用于图的底层。

类型:整数 范围:[1, int_max]

默认值limit(要返回的 TopK 最近邻居)

更大的 ef 通常会导致更高的搜索准确性,因为考虑了更多潜在邻居。但是,这也会增加搜索时间。当实现高召回率至关重要且搜索速度不太关注时,考虑增加 ef

考虑减少 ef 以优先考虑更快的搜索,特别是在可以接受准确性略有降低的场景中。

在大多数情况下,我们建议您在此范围内设置值:[K, 10K]。