当前位置: 首页 > article >正文

【实战ES】实战 Elasticsearch:快速上手与深度实践-8.1.2近似最近邻(ANN)算法选型

👉 点击关注不迷路
👉 点击关注不迷路
👉 点击关注不迷路


文章大纲

  • 8.1.2 近似最近邻(ANN)算法选型深度指南
    • 1. ANN算法核心原理
      • 1.1 主流算法对比矩阵
      • 1.2 性能基准(100万128维向量)
    • 2. Elasticsearch集成配置
      • 2.1 向量索引模板
      • 2.2 查询DSL模板
    • 3. 算法参数调优
      • 3.1 HNSW参数矩阵
      • 3.2 IVF优化策略
    • 4. 企业级应用案例
      • 4.1 电商图像搜索
      • 4.2 生物特征识别
    • 5. 算法选型决策树
    • 6. 未来演进方向
      • 6.1 硬件加速方案
      • 6.2 算法演进趋势

8.1.2 近似最近邻(ANN)算法选型深度指南

  • Elasticsearch向量搜索核心架构与ANN算法集成
    • 近似最近邻(ANN)算法
      • 在高维向量空间中高效近似搜索,解决传统暴力搜索(如余弦相似度计算)在大数据量下计算复杂度高、响应慢的问题,广泛应用于:
        • 图像 / 视频检索(如以图搜图)
        • 文本语义匹配(如推荐系统)
        • 生物信息学(基因序列比对)
HNSW
KD - Tree
Annoy
HNSW
KD - Tree
Annoy
原始数据
数据预处理
特征提取
向量生成
选择 ANN 算法
HNSW 索引构建
KD - Tree 索引构建
Annoy 索引构建
Elasticsearch 向量索引存储
用户查询
查询预处理
查询向量生成
选择 ANN 算法
HNSW 搜索
KD - Tree 搜索
Annoy 搜索
Elasticsearch 搜索结果合并
结果后处理
返回搜索结果
监控系统
自动化运维工具

1. ANN算法核心原理

1.1 主流算法对比矩阵

算法类型核心原理索引速度查询速度准确率内存消耗适用场景
HNSW分层图结构(Hierarchical Navigable Small World),分层可导航小世界极高95-99%高精度实时搜索
IVF(Inverted File Index)倒排文件系统(倒排文件 + 聚类中心)85-95%大规模数据集
LSH(Locality Sensitive Hashing)局部敏感哈希极快极快60-80%快速近似匹配
PQ(Product Quantization)乘积量化70-90%高维压缩场景
NGT(Non-Graph Tree)邻域图遍历90-98%复杂空间关系

1.2 性能基准(100万128维向量)

算法索引时间单次查询时间内存占用Recall@10
HNSW(n=32)12min2.3ms4.2GB98.7%
IVF-40968min5.1ms2.8GB92.3%
LSH-256bit3min0.8ms1.1GB78.5%
PQ-8x825min1.2ms0.9GB85.6%

2. Elasticsearch集成配置

2.1 向量索引模板

// 向 Elasticsearch 发送 PUT 请求,用于创建一个名为 image_vectors 的索引。
PUT /image_vectors
{
    // settings 部分用于配置索引的各种参数,影响索引的性能、可用性和存储等方面。
    "settings": {
        // index 是索引设置的主要配置项。
        "index": {
            // number_of_shards 指定索引的主分片数量,这里设置为 3。
            // 分片是 Elasticsearch 中对索引进行水平拆分的机制,多个分片可以分布在不同的节点上,
            // 从而提高索引的并发处理能力和数据的存储容量。
            "number_of_shards": 3,
            // number_of_replicas 指定每个主分片的副本数量,这里设置为 1。
            // 副本是主分片的复制,用于提高数据的可用性和容错能力。当主分片所在节点出现故障时,
            // 副本可以接替主分片继续提供服务。
            "number_of_replicas": 1,
            // knn 设置为 true 表示启用该索引的 k - 近邻(KNN)搜索功能。
            // 因为后续我们要使用向量进行近似最近邻搜索,所以需要开启此功能。
            "knn": true
        }
    },
    // mappings 部分用于定义索引中文档的结构和字段类型。
    "mappings": {
        // properties 用于描述索引中各个字段的属性。
        "properties": {
            // 定义名为 image_vector 的字段,用于存储图像的向量表示。
            "image_vector": {
                // 指定该字段的类型为 dense_vector,即密集向量类型,适合存储连续的数值向量。
                "type": "dense_vector",
                // dims 指定向量的维度,这里设置为 512,意味着该向量有 512 个元素。
                // 通常图像经过特征提取模型处理后会得到固定维度的向量表示,这里的 512 维就是这种表示的维度。
                "dims": 512,
                // index 设置为 true 表示对该向量字段进行索引,以便后续进行快速的向量搜索。
                "index": true,
                // similarity 指定计算向量相似度时使用的方法,这里选择余弦相似度。
                // 余弦相似度常用于衡量向量之间的方向相似性,在语义搜索等场景中较为常用。
                "similarity": "cosine",
                // index_options 用于配置向量索引的具体参数。
                "index_options": {
                    // type 指定使用的近似最近邻(ANN)算法,这里选择 hnsw(Hierarchical Navigable Small World)。
                    // HNSW 是一种高效的 ANN 算法,能够在高维向量空间中快速找到近似的最近邻。
                    "type": "hnsw",
                    // m 是 HNSW 算法的一个重要参数,它表示每个节点在图中的最大连接数。
                    // 这里设置为 32,较大的值可以提高搜索的准确性,但会增加索引的构建时间和存储空间。
                    "m": 32,
                    // ef_construction 也是 HNSW 算法的参数,它控制在构建索引时每个节点探索的邻居数量。
                    // 这里设置为 200,较大的值可以提高索引的质量,但同样会增加构建时间。
                    "ef_construction": 200
                }
            }
        }
    }
}

2.2 查询DSL模板

  • DSL 即 Domain - Specific Language(领域特定语言)
    • 是为特定领域或特定问题而设计的计算机语言,与通用编程语言(如 Python、Java 等)相对。
    • 内部 DSL:基于通用编程语言构建,利用通用编程语言的语法和结构来实现特定领域的功能。例如,在 Python 中使用装饰器和函数调用的方式实现一个简单的测试框架,这个测试框架就是一个内部 DSL。
    • 外部 DSL:具有自己独立的语法和解析器,不依赖于通用编程语言。例如,SQL、正则表达式等都是典型的外部 DSL。
    • 应用场景:数据库操作、配置管理、业务规则引擎、图形化设计。
    • 示例:SQL(数据库查询语言)、正则表达式(文本模式匹配语言)、配置文件(如 Nginx 配置)等
// 向 Elasticsearch 发送 GET 请求,对名为 image_vectors 的索引进行搜索。
GET /image_vectors/_search
{
    // knn 部分表示使用 k - 近邻(KNN)搜索功能,用于在向量空间中查找与查询向量最相似的文档。
    "knn": {
        // field 指定要进行搜索的向量字段,这里是 image_vector,也就是之前索引中存储图像向量的字段。
        "field": "image_vector",
        // query_vector 是查询向量,由一系列数值组成,这里用 [0.12, 0.34, ...] 表示。
        // Elasticsearch 会在索引中查找与该查询向量最相似的文档。
        "query_vector": [0.12, 0.34, ...],
        // k 指定要返回的最相似文档的数量,这里设置为 10,即返回与查询向量最相似的 10 个文档。
        "k": 10,
        // num_candidates 是一个优化参数,它指定在搜索过程中首先考虑的候选文档数量。
        // Elasticsearch 会从这些候选文档中筛选出最终的 k 个最相似文档。这里设置为 100,
        // 较大的值可以提高搜索的准确性,但会增加搜索的时间和资源消耗。
        "num_candidates": 100,
        // filter 用于对搜索结果进行过滤,只返回满足特定条件的文档。
        "filter": {
            // term 是一种过滤类型,用于精确匹配字段的值。
            // 这里表示只返回 category 字段值为 "animal" 的文档。
            "term": { "category": "animal" }
        }
    },
    // fields 指定在搜索结果中要返回的字段,这里指定返回 title 和 category 字段。
    // 这样搜索结果中只会包含这两个字段的信息,而不是整个文档的内容。
    "fields": ["title", "category"]
}

3. 算法参数调优

3.1 HNSW参数矩阵

参数默认值推荐范围影响维度调优建议
m1624-48图连接数越大精度↑内存↑
ef_construction100200-400索引质量越大精度↑索引时间↑
ef_search100200-800搜索质量越大精度↑延迟↑
max_connections10050-200节点最大连接平衡性能与内存

3.2 IVF优化策略

{
    // index_options 用于配置 Elasticsearch 中向量索引的具体参数,这里配置的是使用倒排文件(IVF,Inverted File)算法相关的索引选项。
    "index_options": {
        // type 指定使用的近似最近邻(ANN)算法类型,这里设置为 "ivf",即使用倒排文件算法。
        // 倒排文件算法是一种常用的 ANN 算法,它通过将向量空间划分为多个聚类中心(质心),
        // 并建立倒排索引来提高向量搜索的效率。
        "type": "ivf",
        
        // nlist 表示倒排文件中聚类中心(质心)的数量,这里设置为 4096。
        // 这个值决定了向量空间被划分的粒度,较大的 nlist 值会使每个聚类包含更少的向量,
        // 可以提高搜索的精度,但会增加索引构建和搜索的时间;较小的 nlist 值则相反。
        "nlist": 4096,
        
        // nprobes 是在搜索时要检查的聚类中心的数量,这里设置为 20。
        // 当进行向量搜索时,Elasticsearch 会从 nprobes 个聚类中心对应的向量集合中查找近似最近邻。
        // 增加 nprobes 的值可以提高搜索的准确性,但会增加搜索的时间;减少 nprobes 的值则会加快搜索速度,但可能会降低搜索的准确性。
        "nprobes": 20,
        
        // code_size 表示每个向量的量化码本的大小,这里设置为 8。
        // 在使用 IVF 算法时,通常会结合乘积量化(PQ,Product Quantization)来进一步压缩向量存储。
        // code_size 决定了每个子向量的量化位数,较大的 code_size 可以提高量化的精度,但会增加存储空间;
        // 较小的 code_size 则可以减少存储空间,但会降低量化的精度。
       
        "code_size": 8,
        // code_version 表示量化码本的版本号,这里设置为 "1.0"。
        // 这个版本号用于标识量化码本的特定版本,在更新或维护索引时,
        // 可以通过版本号来确保使用的是正确的量化码本,避免因码本不一致导致的搜索结果不准确。
        "code_version": "1.0"
    }
}
  • 参数关系式
召回率 ≈ min(nprobes/nlist, 1) * 100%

4. 企业级应用案例

4.1 电商图像搜索

// 批量插入数据部分
// 向 Elasticsearch 发送 PUT 请求,使用 _bulk API 对名为 product_vectors 的索引进行批量操作。
// _bulk API 允许在一个请求中执行多个索引、更新或删除操作,从而提高数据写入的效率。
PUT /product_vectors/_bulk
// 这是一个元数据行,指示接下来要执行的操作是索引操作(即插入文档)。
// _id 指定了要插入文档的唯一标识符,这里设置为 "1"。
{ 
	"index": { 
		"_id": "1" 
	}
}
// 这是要插入的文档内容。
// image_vector 是一个向量字段,存储了图像的向量表示,这里用 [0.23,0.56,...] 表示具体的向量值。
// product_id 是产品的唯一标识符,这里为 "P1001"。
// category 表示产品的类别,这里是 "electronics",表示电子产品。
{ 
	"image_vector": [0.23,0.56,...], 
	"product_id": "P1001", 
	"category": "electronics" 
}
// 同样,这是另一个元数据行,指示要执行索引操作,文档的唯一标识符为 "2"。
{ "index": { "_id": "2" }}
// 要插入的第二个文档内容。
// image_vector 存储了另一个图像的向量表示。
// product_id 为 "P1002"。
// category 为 "clothing",表示服装类产品。
{ 
	"image_vector": [0.78,0.12,...], 
	"product_id": "P1002", 
	"category": "clothing" 
}


// 搜索数据部分
// 向 Elasticsearch 发送 GET 请求,对名为 product_vectors 的索引进行搜索。
GET /product_vectors/_search
{
    // knn 部分表示使用 k - 近邻(KNN)搜索功能,用于在向量空间中查找与查询向量最相似的文档。
    "knn": {
        // field 指定要进行搜索的向量字段,这里是 image_vector,即之前插入文档中存储图像向量的字段。
        "field": "image_vector",
        
        // query_vector 是查询向量,由一系列数值组成,这里用 [0.65,0.32,...] 表示。
        // Elasticsearch 会在索引中查找与该查询向量最相似的文档。
        "query_vector": [0.65,0.32,...],
        
        // k 指定要返回的最相似文档的数量,这里设置为 50,即返回与查询向量最相似的 50 个文档。
        "k": 50,
        
        // num_candidates 是一个优化参数,它指定在搜索过程中首先考虑的候选文档数量。
        // Elasticsearch 会从这些候选文档中筛选出最终的 k 个最相似文档。这里设置为 200,
        // 较大的值可以提高搜索的准确性,但会增加搜索的时间和资源消耗。
        "num_candidates": 200,
        
        // filter 用于对搜索结果进行过滤,只返回满足特定条件的文档。
        "filter": {
            // term 是一种过滤类型,用于精确匹配字段的值。
            // 这里表示只返回 category 字段值为 "clothing" 的文档,即只搜索服装类产品。
            "term": { "category": "clothing" }
        }
    }
}
  • 性能指标
    • 索引规模:1亿向量
    • 查询延迟:<50ms P99
    • 准确率:Recall@10=96.5%
    • 吞吐量:1200 QPS

4.2 生物特征识别

// 向 Elasticsearch 发送 PUT 请求,用于在 KNN(k - 近邻)插件中注册一个名为 face_model 的模型。
PUT _plugins/_knn/models/face_model
{
    // description 字段用于对模型进行简要描述,这里说明该模型是用于人脸识别的。
    // 描述信息可以帮助用户和开发者快速了解模型的用途。
    "description": "Face recognition model",
    
    // model_id 是该模型的唯一标识符,这里设置为 "face_v1"。
    // 在后续对该模型进行操作(如查询、使用等)时,会依据这个唯一的 ID 来定位模型。
    "model_id": "face_v1",
    
    // model_type 指定了模型所使用的近似最近邻(ANN)算法类型,这里选择 "hnsw",即 Hierarchical Navigable Small World。
    // HNSW 是一种高效的 ANN 算法,能够在高维向量空间中快速找到近似的最近邻。
    "model_type": "hnsw",
    
    // dimension 表示模型所处理的向量的维度,这里设置为 1024。
    // 通常在人脸识别等场景中,经过特征提取后的人脸向量会有固定的维度,这里的 1024 维就是该人脸向量的维度。
    "dimension": 1024,
    
    // training_data 部分用于指定训练模型所使用的数据来源。
    "training_data": {
        // index 指定了存储训练数据的 Elasticsearch 索引名称,这里是 "face_vectors"。
        // 该索引中应该包含用于训练模型的向量数据。
        "index": "face_vectors",
        // field 指定了在索引中存储向量数据的字段名,这里是 "embedding"。
        // 也就是说,模型会从 "face_vectors" 索引的 "embedding" 字段中获取训练所需的向量数据。
        "field": "embedding"
    },
    
    // training_parameters 部分用于配置模型训练时的参数,这些参数会影响模型的性能和效果。
    "training_parameters": {
        // m 是 HNSW 算法的一个重要参数,它表示每个节点在图中的最大连接数。
        // 这里设置为 48,较大的值可以提高搜索的准确性,但会增加索引的构建时间和存储空间。
        "m": 48,
        // ef_construction 也是 HNSW 算法的参数,它控制在构建索引时每个节点探索的邻居数量。
        // 这里设置为 500,较大的值可以提高索引的质量,但同样会增加构建时间。
        "ef_construction": 500
    }
}
  • 安全配置
    • 加密存储:AES-256向量加密
    • 访问控制:RBAC+字段级权限
    • 审计日志:全量操作记录

5. 算法选型决策树

在这里插入图片描述

6. 未来演进方向

6.1 硬件加速方案

技术方向实现方式预期收益商用化进度
GPU加速CUDA内核优化5-10倍速度提升部分云服务支持
FPGA加速定制化向量处理单元3-5倍能效比实验室阶段
存算一体近内存计算架构10倍吞吐提升预研阶段
  • FPGA
    • 是一种可编程的集成电路芯片,通过硬件描述语言(如 Verilog/VHDL)或图形化工具定义其逻辑功能。
    • 示例应用
实时性要求高
灵活性优先
原始图像
CNN提取特征向量
选择硬件
FPGA加速KNN搜索
GPU/CPU搜索
返回Top-K结果
  • FPGA与GPU/CPU的对比
维度FPGAGPUCPU
计算模式硬件定制化并行(ASIC级性能)通用并行(CUDA/OpenCL)串行/多核并行
延迟低(微秒级)中(毫秒级)高(毫秒级)
功耗低(10-100W)高(200-400W)中(50-150W)
灵活性需硬件开发(Verilog/VHDL)软件编程(Python/C++)通用指令集(C++/Java)
适用场景专用加速(如KNN、加密、视频处理)通用AI训练/推理(如ResNet)通用逻辑控制

6.2 算法演进趋势

    1. 混合索引技术:HNSW+PQ组合优化
    1. 动态图更新实时增量索引构建
    1. 自适应参数AI驱动的参数调优
    1. 多模态融合跨文本/图像联合搜索

  • 附录:向量搜索工具箱
工具类别推荐方案核心功能
性能测试ann-benchmarks算法基准测试框架
可视化分析TensorBoard Projector高维向量可视化
模型训练FAISS向量索引训练
质量评估GIST数据集召回率评估标准
  • ANN-Benchmarks
    • 近似最近邻搜索(Approximate Nearest Neighbor, ANN)算法的基准测试工具。
    • 评估不同 ANN 算法(如 HNSW、IVF、LSH 等)在速度、精度、内存占用等方面的性能。
    • 支持自定义数据集和查询参数,提供标准化的对比结果。
  • TensorBoard Projector
    • TensorFlow 生态中的可视化工具,用于高维数据降维和交互式探索。
    • 通过 PCA、t-SNE 等降维技术将高维向量投影到 2D/3D 空间。
    • 支持标签、颜色分组和交互式缩放,帮助分析数据分布和聚类效果。
  • FAISS
    • Facebook 开源的高效向量相似性搜索库,支持十亿级向量的 ANN 搜索和聚类。
    • 倒排索引(IVF):将向量聚类为子空间,搜索时仅遍历最相关的子空间。
    • 乘积量化(PQ):压缩向量存储(如将 128 维向量压缩为 8 字节),加速距离计算。
  • GIST 数据集!!!
    • 用于机器学习推荐和评级的公共数据集,包含用户行为、物品特征等信息。
    • 训练推荐系统模型(如协同过滤、双塔模型)。
    • 测试向量搜索算法在真实场景中的效果(如用户兴趣匹配)。
  • 四者的协同应用场景
    • 推荐系统优化:
      • 使用 GIST 数据集训练用户和物品的嵌入向量。
      • 用 FAISS 构建向量索引,实现快速 KNN 搜索。
      • 通过 TensorBoard Projector 可视化嵌入向量,分析推荐结果的合理性。
      • 用 ANN-Benchmarks 对比 FAISS 与其他算法(如 HNSW)的性能,选择最优方案。
    • 图像检索:
      • 图像特征(如 ResNet 输出)压缩后存入 FAISS 索引
      • 通过 TensorBoard Projector 观察不同类别的图像在低维空间中的分布。
      • 用 ANN-Benchmarks 评估不同压缩策略(如 PQ 参数)对检索速度和精度的影响。
    • 示例工作流程
    GIST数据集
    训练嵌入向量
    FAISS构建索引
    ANN-Benchmarks性能评估
    TensorBoard可视化分析
    选择最优算法

实施建议

  1. 生产环境推荐 HNSW+IVF 复合索引
  2. 定期执行Recall / Latency平衡测试
  3. 建立向量数据版本管理机制
  4. 注意8.x版本后的API变更

http://www.kler.cn/a/582792.html

相关文章:

  • 【Synchronized】不同的使用场景和案例
  • 信号处理之插值、抽取与多项滤波
  • 【C++】C++11新特性
  • ELK traceId 通过A服务调用B服务举例
  • Hive SQL 精进系列:COALESCE 手册
  • 跨境电商IP安全怎么做?从基础到高级防护的实战经验分享
  • 信息学奥赛c++语言:整数去重
  • idea maven 编译报错Java heap space解决方法
  • 华为欧拉操作系统安装Docker服务
  • 基于 GEE 利用 Sentinel-2 数据反演叶绿素与冠层水分含量
  • Android Glide 的显示与回调模块原理源码级深度剖析
  • Vue+Node.js+MySQL+Element-Plus实现一个账号注册与登录功能
  • FPGA 实现 OV5640 摄像头视频图像显示
  • 如何制作Windows系统盘、启动盘?(MediaCreationTool_22H2)
  • Banana Pi 与瑞萨电子携手共同推动开源创新:BPI-AI2N
  • Java 大视界 -- Java 大数据在智能安防视频摘要与检索技术中的应用(128)
  • 【数据结构】-- LinkedList与链表(1)
  • MySQL数据库复杂的增删改查操作
  • 如何在Android中实现SQLite数据库操作
  • 【架构艺术】Go语言微服务monorepo的代码架构设计