【Elasticsearch】-dense_vector与hnsw的含义
在Elasticsearch7.12 以后的版本,开始支持向量检索。
通常新增一个向量索引字段定义参数如下:
{
"mappings": {
"properties": {
// 索引字段名
"image_vector": {
// 声明字段类型
"type": "dense_vector",
"dims": 512,
"index": true,
// 相似性计算类型
"similarity": "dot_product",
"index_options": {
"type": "hnsw",
"m": 16,
"efConstruction": 100
}
}
}
}
}
其中的type=dense_vector
是 Elasticsearch 中用于定义字段类型的一种设置,表示该字段存储的是 高维稠密向量。这些向量通常用于机器学习或深度学习的应用,例如图片相似度检索、推荐系统、自然语言处理中的文本嵌入等。
附加java代码调用过程
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.mapping.Property;
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
import co.elastic.clients.elasticsearch.indices.Alias;
import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
import co.elastic.clients.elasticsearch.indices.CreateIndexResponse;
import co.elastic.clients.elasticsearch.indices.ExistsRequest;
CreateIndexResponse response = null;
try {
TypeMapping.Builder tmBuilder = new TypeMapping.Builder();
// 图片相似检索,采用点积运算 文本相似采用余线相似
tmBuilder.properties(VECTOR_FIELD, new Property.Builder().denseVector(builder -> builder.index(true)
.dims(DIM).similarity("dot_product")
.indexOptions(opBuilder -> opBuilder.type("hnsw").m(12).efConstruction(100))).build());
tmBuilder.properties(TEXT_FIELD, new Property.Builder().denseVector(builder -> builder.index(true)
.dims(DIM).similarity("cosine_similarity")
.indexOptions(opBuilder -> opBuilder.type("hnsw").m(12).efConstruction(100))).build());
TypeMapping typeMapping = tmBuilder.build();
CreateIndexRequest request = CreateIndexRequest.of(builder -> builder.index(indexName)
.aliases(indexName + "_alias", new Alias.Builder().isWriteIndex(true).build())
.mappings(typeMapping));
response = esClient.indices().create(request);
log.info("acknowledged: {}", response.acknowledged());
log.info("index: {}", response.index());
log.info("shardsAcknowledged: {}", response.shardsAcknowledged());
flag = response.acknowledged();
} catch (IOException e) {
e.printStackTrace();
}
1、HNSW
Hierarchical Navigable Small World
- 定义: HNSW 是一种近似最近邻搜索(ANN)算法,在大规模高维向量空间中,提供高效的向量相似性搜索。
- 功能: 它是为了解决在高维向量数据中进行相似性搜索时的性能问题。HNSW 通过构建一个分层图结构,以较低的时间复杂度提供近似最近邻搜索,避免了线性搜索的高成本。
- 原理: HNSW 构建了一个层次化的邻居图,向量数据会分层存储。每一层都有一部分数据点,数据点之间通过边相互连接,构成一个导航小世界结构。通过在该图上搜索,可以高效地找到目标向量的近似最近邻。
- 使用场景: 当你有大量向量数据(如数百万张图片、文本的嵌入向量等),希望进行高效的相似性检索时,可以启用 HNSW 索引来提高查询速度。
配置 HNSW 搜索时,会设置如 m
和 efConstruction
等参数来调整图的稠密度和搜索深度:
1.1、参数说明
-
m
参数:- 作用:控制 HNSW 图中每个节点的近邻连接数量。
m
越大,每个节点有更多的连接,图的稠密度增加。 - 影响:
- 较大的
m
值:会增加内存占用和索引构建时间,但搜索精度更高,因为每个节点连接了更多的近邻,搜索的路径选择更多。 - 较小的
m
值:减少内存使用和索引构建时间,但可能导致搜索精度下降。
- 较大的
- 推荐值:对于大多数场景,推荐将
m
设置为12~48
,这是典型的范围。- 小规模数据集可以尝试较小的
m
值,例如12
。 - 对于大规模、高维向量,使用较大的
m
,例如32~48
,可以提高搜索精度。
- 小规模数据集可以尝试较小的
- 作用:控制 HNSW 图中每个节点的近邻连接数量。
-
efConstruction
参数:- 作用:控制在索引构建阶段的搜索深度。
efConstruction
越大,HNSW 图的质量越高,因为在构建过程中搜索更多的候选近邻节点进行连接。 - 影响:
- 较大的
efConstruction
值:构建索引时更慢,消耗更多资源,但图结构质量更高,搜索时精度更好。 - 较小的
efConstruction
值:构建索引时更快,内存消耗更少,但可能会导致索引质量下降,从而影响搜索精度。
- 较大的
- 推荐值:通常将
efConstruction
设置为100~500
。- 对于高精度需求,可以选择
200~500
,但会增加索引构建时间。 - 对于低内存和构建时间敏感的场景,可以使用较小的值(如
100
)。
- 对于高精度需求,可以选择
- 作用:控制在索引构建阶段的搜索深度。
1.2、设置参数的建议
-
小数据集(< 10 万条向量):
m
: 12~16efConstruction
: 100~200- 在小数据集场景中,较小的
m
和efConstruction
值可以提供足够的搜索精度,并且在内存消耗和构建时间上更为高效。
-
中等规模数据集(10 万 ~ 100 万条向量):
m
: 16~32efConstruction
: 200~300- 中等规模数据集通常要求较好的精度,但内存和构建时间也需要控制,适中的
m
和efConstruction
值可以提供较好的平衡。
-
大数据集(> 100 万条向量):
m
: 32~48efConstruction
: 300~500- 大规模数据集通常需要较高的搜索精度,尤其是在向量维度高(如 512 或 2048 维)时。较大的
m
值和efConstruction
可以构建高质量的索引,但会消耗更多内存和时间。
1.3、调优策略
- 初始设置:
- 开始时可以将
m
设置为16
,efConstruction
设置为200
,这是一种比较中性的选择。
- 开始时可以将
- 根据实际情况调整:
- 如果精度不够:提高
m
和efConstruction
值,尤其是m
值。 - 如果内存占用过高:降低
m
值。通常m
对内存影响较大。 - 如果索引构建时间过长:降低
efConstruction
值。构建时间和内存开销与该参数密切相关。
- 如果精度不够:提高
m
控制图的稠密度:影响内存消耗和搜索精度,值越大,图的连接更稠密,搜索精度更高,但内存消耗更大。efConstruction
控制索引构建阶段的搜索深度:影响索引构建时间和图的质量,值越大,索引质量更好,但构建时间和资源消耗更多。
2、相似性度量方式
在选择相似性度量方式时,余弦相似度(Cosine Similarity)和点积(Dot Product)是常用的两种方法。具体使用哪种方式取决于应用场景和数据的特性。下面从多个角度分析这两种方法的优劣。
2.1、余弦相似度(Cosine Similarity)
余弦相似度用于衡量两个向量之间的夹角,而不关注它们的长度。
其值范围在 -1 和 1 之间,1 表示两个向量方向相同,0 表示正交,-1 表示方向相反。
优点:
- 适用于归一化数据:如果数据已经归一化,或者不关注向量的大小(例如,文本嵌入向量),余弦相似度是理想选择。
- 对长度不敏感:它忽略了向量的绝对大小,仅关注向量的方向,适用于长度差异较大的向量。
- 标准化检索:在比较文档、句子等相似性时,余弦相似度常用于 NLP(自然语言处理)等场景。
缺点:
- 无法区分向量长度:如果向量的大小(长度)在你的应用中有重要意义,余弦相似度可能不适用。
- 高维时效率低:在非常高维的情况下,计算余弦相似度可能相对较慢。
适用场景:
- 自然语言处理(NLP):比如文本嵌入的比较。
- 无需考虑向量的长度或幅度时,关注向量的方向一致性。
2.2、点积(Dot Product)
点积计算的是两个向量的标量积。与余弦相似度不同,点积会同时考虑向量的大小和方向。
优点:
- 计算简单:点积计算简单,尤其适用于向量的相似性比较,特别是在机器学习模型输出的向量表示中。
- 考虑向量的大小:在某些应用中(例如图像检索、推荐系统),向量的大小可能是关键因素,此时点积可以更好地反映相似性。
- 高效的计算:相比余弦相似度,点积的计算开销更低,因此在大规模检索系统中性能更好。
缺点:
- 敏感于向量大小:如果向量的幅度差异较大,点积可能会给出误导性的结果。对于未经归一化的数据,点积结果会受到向量长度的强烈影响。
- 正值偏差:点积结果为正数的向量通常被认为更相似,即使它们的方向可能不同。
适用场景:
- 图片相似性搜索:点积在图像向量相似性比较中表现良好,尤其是当向量的大小有意义时。
- 推荐系统:在考虑用户和项目的特征向量大小时,点积可以提供更准确的相似度评估。
选择的建议
根据不同的应用场景和向量特性,选择适合的相似度度量方式:
-
余弦相似度适用于以下场景:
- 当向量的大小无关紧要,且只关注方向一致性。
- 文本嵌入和自然语言处理中的语义相似性计算。
- 对于归一化后的向量(例如长度为 1 的向量),余弦相似度是首选。
-
点积适用于以下场景:
- 当向量的大小与相似性有直接关系(例如图像特征向量)。
- 在需要高效计算且关注向量大小和方向的情况下。
- 在推荐系统、图片相似性检索等场景中表现更好。