【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 搜索时,会设置如 mefConstruction 等参数来调整图的稠密度和搜索深度:

1.1、参数说明

  1. m 参数

    • 作用:控制 HNSW 图中每个节点的近邻连接数量。m 越大,每个节点有更多的连接,图的稠密度增加。
    • 影响:
      • 较大的 m 值:会增加内存占用和索引构建时间,但搜索精度更高,因为每个节点连接了更多的近邻,搜索的路径选择更多。
      • 较小的 m 值:减少内存使用和索引构建时间,但可能导致搜索精度下降。
    • 推荐值:对于大多数场景,推荐将 m 设置为 12~48,这是典型的范围。
      • 小规模数据集可以尝试较小的 m 值,例如 12
      • 对于大规模、高维向量,使用较大的 m,例如 32~48,可以提高搜索精度。
  2. efConstruction 参数

    • 作用:控制在索引构建阶段的搜索深度。efConstruction 越大,HNSW 图的质量越高,因为在构建过程中搜索更多的候选近邻节点进行连接。
    • 影响:
      • 较大的 efConstruction 值:构建索引时更慢,消耗更多资源,但图结构质量更高,搜索时精度更好。
      • 较小的 efConstruction 值:构建索引时更快,内存消耗更少,但可能会导致索引质量下降,从而影响搜索精度。
    • 推荐值:通常将 efConstruction 设置为 100~500
      • 对于高精度需求,可以选择 200~500,但会增加索引构建时间。
      • 对于低内存和构建时间敏感的场景,可以使用较小的值(如 100)。

1.2、设置参数的建议

  • 小数据集(< 10 万条向量)

    • m: 12~16
    • efConstruction: 100~200
    • 在小数据集场景中,较小的 mefConstruction 值可以提供足够的搜索精度,并且在内存消耗和构建时间上更为高效。
  • 中等规模数据集(10 万 ~ 100 万条向量)

    • m: 16~32
    • efConstruction: 200~300
    • 中等规模数据集通常要求较好的精度,但内存和构建时间也需要控制,适中的 mefConstruction 值可以提供较好的平衡。
  • 大数据集(> 100 万条向量)

    • m: 32~48
    • efConstruction: 300~500
    • 大规模数据集通常需要较高的搜索精度,尤其是在向量维度高(如 512 或 2048 维)时。较大的 m 值和 efConstruction 可以构建高质量的索引,但会消耗更多内存和时间。

1.3、调优策略

  • 初始设置:
    • 开始时可以将 m 设置为 16efConstruction 设置为 200,这是一种比较中性的选择。
  • 根据实际情况调整:
    1. 如果精度不够:提高 mefConstruction 值,尤其是 m 值。
    2. 如果内存占用过高:降低 m 值。通常 m 对内存影响较大。
    3. 如果索引构建时间过长:降低 efConstruction 值。构建时间和内存开销与该参数密切相关。
  • m 控制图的稠密度:影响内存消耗和搜索精度,值越大,图的连接更稠密,搜索精度更高,但内存消耗更大。
  • efConstruction 控制索引构建阶段的搜索深度:影响索引构建时间和图的质量,值越大,索引质量更好,但构建时间和资源消耗更多。

2、相似性度量方式

在选择相似性度量方式时,余弦相似度(Cosine Similarity)和点积(Dot Product)是常用的两种方法。具体使用哪种方式取决于应用场景和数据的特性。下面从多个角度分析这两种方法的优劣。

2.1、余弦相似度(Cosine Similarity)

余弦相似度用于衡量两个向量之间的夹角,而不关注它们的长度。

其值范围在 -1 和 1 之间,1 表示两个向量方向相同,0 表示正交,-1 表示方向相反。

优点:

  1. 适用于归一化数据:如果数据已经归一化,或者不关注向量的大小(例如,文本嵌入向量),余弦相似度是理想选择。
  2. 对长度不敏感:它忽略了向量的绝对大小,仅关注向量的方向,适用于长度差异较大的向量。
  3. 标准化检索:在比较文档、句子等相似性时,余弦相似度常用于 NLP(自然语言处理)等场景。

缺点:

  1. 无法区分向量长度:如果向量的大小(长度)在你的应用中有重要意义,余弦相似度可能不适用。
  2. 高维时效率低:在非常高维的情况下,计算余弦相似度可能相对较慢。

适用场景:

  • 自然语言处理(NLP):比如文本嵌入的比较。
  • 无需考虑向量的长度或幅度时,关注向量的方向一致性。

2.2、点积(Dot Product)

点积计算的是两个向量的标量积。与余弦相似度不同,点积会同时考虑向量的大小和方向。

优点:

  1. 计算简单:点积计算简单,尤其适用于向量的相似性比较,特别是在机器学习模型输出的向量表示中。
  2. 考虑向量的大小:在某些应用中(例如图像检索、推荐系统),向量的大小可能是关键因素,此时点积可以更好地反映相似性。
  3. 高效的计算:相比余弦相似度,点积的计算开销更低,因此在大规模检索系统中性能更好。

缺点:

  1. 敏感于向量大小:如果向量的幅度差异较大,点积可能会给出误导性的结果。对于未经归一化的数据,点积结果会受到向量长度的强烈影响。
  2. 正值偏差:点积结果为正数的向量通常被认为更相似,即使它们的方向可能不同。

适用场景:

  • 图片相似性搜索:点积在图像向量相似性比较中表现良好,尤其是当向量的大小有意义时。
  • 推荐系统:在考虑用户和项目的特征向量大小时,点积可以提供更准确的相似度评估。

选择的建议

根据不同的应用场景和向量特性,选择适合的相似度度量方式:

  1. 余弦相似度适用于以下场景:

    • 当向量的大小无关紧要,且只关注方向一致性。
    • 文本嵌入和自然语言处理中的语义相似性计算。
    • 对于归一化后的向量(例如长度为 1 的向量),余弦相似度是首选。
  2. 点积适用于以下场景:

    • 当向量的大小与相似性有直接关系(例如图像特征向量)。
    • 在需要高效计算且关注向量大小和方向的情况下。
    • 在推荐系统、图片相似性检索等场景中表现更好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

宣晨光

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

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

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

打赏作者

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

抵扣说明:

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

余额充值