HNSW
HNSW索引是一种基于图的索引算法,可以提高搜索高维浮动向量时的性能。它具有出色的搜索精度和低延迟,但需要较高的内存开销来维护其分层图结构。
概览
分层导航小世界(HNSW)算法构建了一个多层图,有点像不同缩放级别的地图。底层包含所有数据点,而上层则由从底层采样的数据点子集组成。
在这种层次结构中,每一层都包含代表数据点的节点,节点之间由表示其接近程度的边连接。上层提供远距离跳转,以快速接近目标,而下层则进行细粒度搜索,以获得最准确的结果。
下面是它的工作原理:
- 入口点:搜索从顶层的一个固定入口点开始,该入口点是图中的一个预定节点。
- 贪婪搜索:算法贪婪地移动到当前层的最近邻居,直到无法再接近查询向量为止。上层起到导航作用,作为粗过滤器,为下层的精细搜索找到潜在的入口点。
- 层层下降:一旦当前层达到局部最小值,算法就会利用预先建立的连接跳转到下层,并重复贪婪搜索。
- 最后 细化:这一过程一直持续到最底层,在最底层进行最后的细化步骤,找出最近的邻居。
HNSW
HNSW 的性能取决于控制图结构和搜索行为的几个关键参数。这些参数包括
M
:图中每个节点在层次结构的每个层级所能拥有的最大边数或连接数。M
越高,图的密度就越大,搜索结果的召回率和准确率也就越高,因为有更多的路径可以探索,但同时也会消耗更多内存,并由于连接数的增加而减慢插入时间。如上图所示,M = 5表示 HNSW 图中的每个节点最多与 5 个其他节点直接相连。这就形成了一个中等密度的图结构,节点有多条路径到达其他节点。efConstruction
:索引构建过程中考虑的候选节点数量。efConstruction
越高,图的质量越好,但需要更多时间来构建。ef
:搜索过程中评估的邻居数量。增加ef
可以提高找到最近邻居的可能性,但会减慢搜索过程。
有关如何根据需要调整这些设置的详情,请参阅索引参数。
建立索引
要在 Milvus 中的向量场上建立HNSW
索引,请使用add_index()
方法,为索引指定index_type
,metric_type
, 以及附加参数。
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
:要建立的索引类型。在本例中,将值设为HNSW
。metric_type
:用于计算向量间距离的方法。支持的值包括COSINE
,L2
, 和IP
。有关详细信息,请参阅公制类型。params
:用于建立索引的附加配置选项。M
:每个节点可连接的最大邻居数量。efConstruction
:索引构建过程中考虑连接的候选邻居数量。
配置好索引参数后,可直接使用create_index()
方法或在create_collection
方法中传递索引参数来创建索引。有关详情,请参阅创建 Collections。
在索引上搜索
建立索引并插入实体后,就可以在索引上执行相似性搜索。
search_params = {
"params": {
"ef": 10, # Number of neighbors to consider during the search
}
}
res = MilvusClient.search(
collection_name="your_collection_name", # Collection 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
:在索引上搜索的其他配置选项。ef
:搜索时要考虑的邻居数量。
要了解
HNSW
索引可用的更多搜索参数,请参阅特定于索引的搜索参数。
索引参数
本节概述了用于建立索引和在索引上执行搜索的参数。
索引建立参数
下表列出了建立索引时可在params
中配置的参数。
参数 | 说明 | 值范围 | 调整建议 |
---|---|---|---|
M | 图中每个节点可拥有的最大连接数(或边),包括出边和入边。 该参数直接影响索引构建和搜索。 | 类型:整数 范围: [2, 2048[2, 2048] 默认值: 30 (每个节点最多 30 条出边和 30 条入边) | 较大的M 通常会提高准确率,但会增加内存开销,并减慢索引构建和搜索速度。如果数据集的维度较高,或高召回率至关重要时,可考虑提高 M 。当内存使用和搜索速度是首要考虑因素时,可考虑降低 M 。在大多数情况下,我们建议您在此范围内设置一个值:[5, 100]. |
efConstruction | 索引构建过程中考虑连接的候选邻居数量。 每个新元素都会评估一个更大的候选池,但实际建立的最大连接数仍受 M 限制。 | 类型:整数 范围: [1, int_max[1,int_max] 默认值: 360 | efConstruction 越高,索引越准确,因为会探索更多潜在连接。不过,这也会导致建立索引的时间延长和内存使用量增加。考虑增加 efConstruction 以提高准确性,尤其是在索引时间不太重要的情况下。在资源紧张的情况下,可考虑降低 efConstruction ,以加快索引构建速度。在大多数情况下,我们建议在此范围内设置一个值:[50, 500]. |
特定于索引的搜索参数
下表列出了在索引上搜索时可在search_params.params
中配置的参数。
参数 | 说明 | 值范围 | 调整建议 |
---|---|---|---|
ef | 控制近邻检索时的搜索范围。它决定访问多少节点并将其评估为潜在近邻。该参数只影响搜索过程,并且只适用于图形的底层。 | 类型:整数 范围: [1, int_max[1,int_max] 默认值:limit(返回的前 K 个近邻) | ef 越大,搜索精度越高,因为会考虑更多的潜在近邻。不过,这也会增加搜索时间。如果实现高召回率至关重要,而搜索速度则不那么重要,则可考虑提高 ef 。考虑降低 ef 以优先提高搜索速度,尤其是在可以接受稍微降低准确率的情况下。在大多数情况下,我们建议您在此范围内设置一个值:[K,10K]。 |