从零开发短视频电商 OpenSearch k-NN插件

2023-11-29 19:28

本文主要是介绍从零开发短视频电商 OpenSearch k-NN插件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • k-NN索引
      • 简介
      • 索引设置(Setting)
    • Script Score k-NN 精准KNN
      • 创建KNN字段索引
      • 添加数据
      • 精确KNN搜索
    • 近似K-NN搜索
      • 示例
      • 创建KNN字段索引
      • 添加数据
      • 近似KNN查询
    • 带过滤器的k-NN搜索
      • 过滤搜索优化

该篇OpenSearch的版本为2.11

  • https://opensearch.org/docs/2.11/search-plugins/knn/index/

k-NN 插件是 k-近邻的缩写,使用户能够在向量索引中搜索查询点的 k-近邻。要确定邻居,您可以指定要用于测量点之间距离的空间(距离函数)。

用例包括推荐(例如,音乐应用程序中的“您可能喜欢的其他歌曲”功能)、图像识别和欺诈检测。有关 k-NN 搜索的更多背景信息,请参阅维基百科。

该插件支持三种不同的方法来从向量索引中获取 k 最近邻:

  1. 近似 k-NN ,通常,这些算法会牺牲索引速度和搜索准确性,以换取性能优势,例如更低的延迟、更小的内存占用和更具可扩展性的搜索。要了解有关算法的更多信息,请参阅 nmslib 和 faiss 的文档。
    • 近似 k-NN 是需要低延迟的大型索引(即数十万个向量或更多)搜索的最佳选择。如果您想在 k-NN 搜索之前对索引应用过滤器,则不应使用近似 k-NN,这会大大减少要搜索的向量数量。在这种情况下,您应该使用Script Score k-NN或 Painless 扩展。
  2. Script Score k-NN,精确的 k-NN 搜索。通过这种方法,您可以对索引中的向量子集运行 k-NN 搜索(有时称为预过滤搜索)。使用此方法搜索较小的文档主体或需要预过滤器时。对大型索引使用此方法可能会导致高延迟。预过滤,先keyword过滤后向量搜索。
  3. Painless extensions ,可以在更复杂的组合中使用它。与 k-NN 脚本评分类似,您可以使用此方法在索引中执行强力、精确的 k-NN 搜索,该搜索也支持预过滤。与 Script Score k-NN相比,此方法的查询性能稍慢。如果您的用例需要对最终分数进行更多自定义,则应使用此方法而不是Script Score k-NN

总的来说,对于较大的数据集,您通常应该选择近似最近邻方法,因为它的扩展性明显更好。对于较小的数据集,您可能想要应用过滤器,您应该选择Script Score k-NN。如果您有更复杂的用例,需要使用距离函数作为评分方法的一部分,则应该使用Painless extensions

k-NN索引

简介

k-NN 插件引入了自定义数据类型 knn_vector ,它允许用户将其 k-NN 向量提取到 OpenSearch 索引中并执行不同类型的 k-NN 搜索。 knn_vector 字段是高度可配置的,可以服务于许多不同的 k-NN 工作负载。

Mapping映射参数必需的默认可更新描述
nametruen/afalse最近邻方法的标识符。hnsw、ivf(需要训练),一般都是选hnsw
space_typefalsel2false用于计算向量之间距离的向量空间类型。
enginefalsenmslibfalse用于索引和搜索的近似 k-NN 库。可用的库有 faiss、nmslib 和 lucene。
parametersnullfalse用于最近邻法的参数。

Mapping示例

{"type": "knn_vector","dimension": 100,"method": {"name":"hnsw","engine":"lucene","space_type": "l2","parameters":{"m":2048,"ef_construction": 245}}
}{"type":"knn_vector","dimension":100,"method":{"name":"hnsw","engine":"faiss","space_type":"l2","parameters":{"encoder":{"name":"pq","parameters":{"code_size":8,"m":8}}}}
}{"type":"knn_vector","dimension":100,"method":{"name":"ivf","engine":"faiss","space_type":"l2","parameters":{"nlist":4,"nprobes":2}}
}

选择建议

构建 knn_vector 字段时有很多选项可供选择。要确定选择正确的方法和参数,做出哪些权衡。

要考虑的因素包括

(1) 查询延迟

(2) 查询质量

(3) 内存限制

(4) 索引延迟

  • 如果内存不是问题,HNSW 提供非常强大的查询延迟/查询质量权衡。
  • 如果您想使用比 HNSW 更少的内存和更快的索引,同时保持类似的查询质量,您应该用IVF。
  • 如果内存是一个问题,请考虑将 PQ 编码器添加到您的 HNSW 或 IVF 索引中。由于PQ是有损编码,查询质量会下降。

内存估计

HNSW 所需的内存估计为 1.1 * (4 * dimension + 8 * M) 字节/向量。

例如,假设您有 100 万个向量,维度为 256,M 为 16。内存需求可估计如下:

1.1 * (4 * 256 + 8 * 16) * 1,000,000 ~= 1.267 GB
  • m:插件为每个新元素创建的双向链接的数量。增加和减少该值会对内存消耗产生很大影响。将此值保持在 2 到 100 之间。

IVF 所需的内存估计为 1.1 * (((4 * dimension) * num_vectors) + (4 * nlist * d)) 字节。

例如,假设您有 100 万个向量,维度为 256,nlist 为 128。内存需求可估计如下:

1.1 * (((4 * 256) * 1,000,000) + (4 * 128 * 256))  ~= 1.126 GB
  • nlist:将向量划分成的桶的数量。较高的值可能会导致更准确的搜索,但会牺牲内存和训练延迟。

索引设置(Setting)

k-NN 插件引入了几个索引设置,也可用于配置 k-NN 结构。

设置中定义的几个参数正在弃用过程中。这些参数应该在映射(Mapping)中设置,而不是在索引(Index)设置中。映射中设置的参数将覆盖索引设置中设置的参数。在映射中设置参数允许索引拥有多个具有不同参数的 knn_vector 字段。

SettingDefaultUpdatableDescription
index.knnfalsefalse索引是否应该为 knn_vector 字段构建本机库索引。如果设置为 false, knn_vector 字段将存储在文档值中,但近似 k-NN 搜索功能将被禁用。
index.knn.algo_param.ef_search512truek-NN 搜索期间使用的动态列表的大小。值越高,搜索越准确,但搜索速度越慢。仅适用于 nmslib。
index.knn.algo_param.ef_construction512false1.0.0 中已弃用。请使用映射参数来设置该值。
index.knn.algo_param.m16false1.0.0 中已弃用。请使用映射参数来设置该值。
index.knn.space_typel2false1.0.0 中已弃用。请使用映射参数来设置该值。

Script Score k-NN 精准KNN

可以在执行最近邻搜索之前对索引应用过滤器。这对于索引主体可能根据其他条件而变化的动态搜索情况很有用。

如果您打算仅使用分数脚本方法(而不是近似方法),您可以将 index.knn 设置为 false

创建KNN字段索引

创建一个包含两个 knn_vector 字段的索引

PUT my-knn-index-2
{"mappings": {"properties": {"my_vector": {"type": "knn_vector","dimension": 2},"color": {"type": "keyword"}}}
}

添加数据

POST _bulk
{ "index": { "_index": "my-knn-index-2", "_id": "1" } }
{ "my_vector": [1, 1], "color" : "RED" }
{ "index": { "_index": "my-knn-index-2", "_id": "2" } }
{ "my_vector": [2, 2], "color" : "RED" }
{ "index": { "_index": "my-knn-index-2", "_id": "3" } }
{ "my_vector": [3, 3], "color" : "RED" }
{ "index": { "_index": "my-knn-index-2", "_id": "4" } }
{ "my_vector": [10, 10], "color" : "BLUE" }
{ "index": { "_index": "my-knn-index-2", "_id": "5" } }
{ "my_vector": [20, 20], "color" : "BLUE" }
{ "index": { "_index": "my-knn-index-2", "_id": "6" } }
{ "my_vector": [30, 30], "color" : "BLUE" }

精确KNN搜索

在识别最近的邻居之前,使用 script_score 查询预先过滤您的文档:

GET my-knn-index-2/_search
{"size": 2,"query": {"script_score": {"query": {"bool": {"filter": {"term": {"color": "BLUE"}}}},"script": {"lang": "knn","source": "knn_score","params": {"field": "my_vector","query_value": [9.9, 9.9],"space_type": "l2"}}}}
}

所有参数都是必需的。

  • lang 是脚本类型。该值通常为 painless ,但此处必须指定 knn
  • source 是脚本的名称 knn_score
  • field 是包含矢量数据的字段。
  • query_value 是您要查找最近邻居的点。对于欧几里得和余弦相似空间,该值必须是与字段映射中设置的维度相匹配的浮点数组。对于汉明位距离,该值可以是有符号长整型或 Base64 编码字符串(分别适用于长整型和二进制字段类型)。
  • space_type 对应距离函数。l1,l2,linf,cosinesimil,innerproduct,hammingbit
    • 余弦相似度返回 -1 到 1 之间的数字,并且由于 OpenSearch 相关性分数不能低于 0,因此 k-NN 插件加 1 以获得最终分数。

近似K-NN搜索

标准 k-NN 搜索方法使用强力方法计算相似度,该方法测量查询与多个点之间的最近距离,从而产生准确的结果。这在许多应用中效果很好。然而,在高维数据集非常大的情况下,这会产生缩放问题,从而降低搜索效率。近似 k-NN 搜索方法可以通过使用更有效地重构索引并降低可搜索向量的维数的工具来克服这个问题。使用这种方法需要牺牲准确性,但会显着提高搜索处理速度。

OpenSearch 利用的近似 k-NN 搜索方法使用 nmslib、faiss 和 Lucene 库中的近似最近邻 (ANN) 算法来支持 k-NN 搜索。这些搜索方法采用 ANN 来改善大型数据集的搜索延迟。在 k-NN 插件提供的三种搜索方法中,此方法为大型数据集提供了最佳的搜索可扩展性。当数据集达到数十万个向量时,此方法是首选方法。

k-NN 插件在索引期间为每个 knn 向量字段/Lucene 段对构建向量的本机库索引,可用于在搜索期间有效地查找查询向量的 k 最近邻。

由于本机库索引是在索引期间构建的,因此不可能对索引应用过滤器然后使用此搜索方法。所有过滤器都应用于近似最近邻搜索产生的结果。

示例

要使用 k-NN 插件的近似搜索功能,您必须首先创建一个 k-NN 索引,并将 index.knn 设置为 true 。此设置告诉插件为索引创建本机库索引。

接下来,您必须添加一个或多个 knn_vector 数据类型的字段。此示例创建一个包含两个 knn_vector 字段的索引,一个使用 faiss 字段,另一个使用 nmslib 字段:

创建KNN字段索引

PUT my-knn-index-1
{"settings": {"index": {"knn": true,"knn.algo_param.ef_search": 100}},"mappings": {"properties": {"my_vector1": {"type": "knn_vector","dimension": 2,"method": {"name": "hnsw","space_type": "l2","engine": "nmslib","parameters": {"ef_construction": 128,"m": 24}}},"my_vector2": {"type": "knn_vector","dimension": 4,"method": {"name": "hnsw","space_type": "innerproduct","engine": "faiss","parameters": {"ef_construction": 256,"m": 48}}}}}
}

knn_vector 数据类型支持浮点数向量,对于 nmslib 和 faiss 引擎,该向量的维度计数最多为 16,000,由维度映射参数设置。 Lucene 库的最大维度数为 1,024。

添加数据

POST _bulk
{ "index": { "_index": "my-knn-index-1", "_id": "1" } }
{ "my_vector1": [1.5, 2.5], "price": 12.2 }
{ "index": { "_index": "my-knn-index-1", "_id": "2" } }
{ "my_vector1": [2.5, 3.5], "price": 7.1 }
{ "index": { "_index": "my-knn-index-1", "_id": "3" } }
{ "my_vector1": [3.5, 4.5], "price": 12.9 }
{ "index": { "_index": "my-knn-index-1", "_id": "4" } }
{ "my_vector1": [5.5, 6.5], "price": 1.2 }
{ "index": { "_index": "my-knn-index-1", "_id": "5" } }
{ "my_vector1": [4.5, 5.5], "price": 3.7 }
{ "index": { "_index": "my-knn-index-1", "_id": "6" } }
{ "my_vector2": [1.5, 5.5, 4.5, 6.4], "price": 10.3 }
{ "index": { "_index": "my-knn-index-1", "_id": "7" } }
{ "my_vector2": [2.5, 3.5, 5.6, 6.7], "price": 5.5 }
{ "index": { "_index": "my-knn-index-1", "_id": "8" } }
{ "my_vector2": [4.5, 5.5, 6.7, 3.7], "price": 4.4 }
{ "index": { "_index": "my-knn-index-1", "_id": "9" } }
{ "my_vector2": [1.5, 5.5, 4.5, 6.4], "price": 8.9 }

近似KNN查询

GET my-knn-index-1/_search
{"size": 2,"query": {"knn": {"my_vector2": {"vector": [2, 3, 5, 6],"k": 2}}}
}

k 是每个图的搜索将返回的邻居数量。您还必须包含 size 选项,该选项指示查询实际返回的结果数量。该插件返回每个分片(和每个段)的 k 数量的结果以及整个查询的 size 数量的结果。该插件支持的最大 k 值为 10,000。

带过滤器的k-NN搜索

1.高效的 k-NN 过滤:此方法在 k-NN 搜索期间应用过滤,而不是在 k-NN 搜索之前或之后,这确保返回 k 结果(如果至少有 k 总计结果)。此方法由以下引擎支持:

  • 具有分层可导航小世界 (HNSW) 算法的 Lucene 引擎(k-NN 插件版本 2.4 及更高版本)
  • 具有 HNSW 算法(k-NN 插件版本 2.9 及更高版本)或 IVF 算法(k-NN 插件版本 2.10 及更高版本)的 Faiss 引擎

2.后过滤:由于它是在 k-NN 搜索之后执行的,因此此方法可能会返回明显少于限制性过滤器的 k 结果。您可以为此方法使用以下两种过滤策略:

  • 布尔后置过滤器:此方法运行近似最近邻 (ANN) 搜索,然后对结果应用过滤器。两个查询部分独立执行,然后根据查询中提供的查询运算符( shouldmust 等)组合结果。
  • post_filter 参数:此方法对完整数据集运行 ANN 搜索,然后将过滤器应用于 k-NN 结果。

3.评分脚本过滤器:此方法涉及预过滤文档集,然后对过滤后的子集运行精确的 k-NN 搜索。当过滤的子集很大时,它可能具有高延迟并且无法扩展。

下表总结了前面的过滤用例。

Filter何时应用过滤器搜索类型支持的引擎和方法在哪里放置 filter 子句
Efficient k-NN filtering 高效的 k-NN 过滤搜索期间(预过滤和后过滤的混合)Approximate 近似- lucene (hnsw) - lucene ( hnsw ) - faiss (hnsw, ivf) - faisshnswivf在 k-NN 查询子句内。
Boolean filter 布尔过滤器After search (post-filtering) 搜索后(后过滤)Approximate 近似- lucene - nmslib - faiss在 k-NN 查询子句之外。必须是叶子句。
post_filter 参数After search (post-filtering) 搜索后(后过滤)Approximate 近似- lucene - nmslib - faissOutside the k-NN query clause. 在 k-NN 查询子句之外。
Scoring script filter 评分脚本过滤器Before search (pre-filtering) 搜索前(预过滤)Exact 精确N/A在脚本分数查询子句内。

过滤搜索优化

一旦您估计了索引中的文档数量、过滤器的限制性以及所需的最近邻居数量,请使用下表选择可优化召回或延迟的过滤方法。

索引中的文档数过滤器返回的文档百分比k用于提高召回率的过滤方法用于降低延迟的过滤方法
10M2.5100高效的 k-NN 过滤/评分脚本评分脚本
10M38100高效的 k-NN 过滤高效的 k-NN 过滤
10M80100高效的 k-NN 过滤高效的 k-NN 过滤
1M2.5100高效的 k-NN 过滤/评分脚本评分脚本
1M38100高效的 k-NN 过滤高效的 k-NN 过滤
1M80100高效的 k-NN 过滤高效的 k-NN 过滤

这篇关于从零开发短视频电商 OpenSearch k-NN插件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/434034

相关文章

基于Python开发电脑定时关机工具

《基于Python开发电脑定时关机工具》这篇文章主要为大家详细介绍了如何基于Python开发一个电脑定时关机工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 简介2. 运行效果3. 相关源码1. 简介这个程序就像一个“忠实的管家”,帮你按时关掉电脑,而且全程不需要你多做

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

Python视频处理库VidGear使用小结

《Python视频处理库VidGear使用小结》VidGear是一个高性能的Python视频处理库,本文主要介绍了Python视频处理库VidGear使用小结,文中通过示例代码介绍的非常详细,对大家的... 目录一、VidGear的安装二、VidGear的主要功能三、VidGear的使用示例四、VidGea

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

IDEA常用插件之代码扫描SonarLint详解

《IDEA常用插件之代码扫描SonarLint详解》SonarLint是一款用于代码扫描的插件,可以帮助查找隐藏的bug,下载并安装插件后,右键点击项目并选择“Analyze”、“Analyzewit... 目录SonajavascriptrLint 查找隐藏的bug下载安装插件扫描代码查看结果总结Sona

C#图表开发之Chart详解

《C#图表开发之Chart详解》C#中的Chart控件用于开发图表功能,具有Series和ChartArea两个重要属性,Series属性是SeriesCollection类型,包含多个Series对... 目录OverviChina编程ewSeries类总结OverviewC#中,开发图表功能的控件是Char

鸿蒙开发搭建flutter适配的开发环境

《鸿蒙开发搭建flutter适配的开发环境》文章详细介绍了在Windows系统上如何创建和运行鸿蒙Flutter项目,包括使用flutterdoctor检测环境、创建项目、编译HAP包以及在真机上运... 目录环境搭建创建运行项目打包项目总结环境搭建1.安装 DevEco Studio NEXT IDE

Python开发围棋游戏的实例代码(实现全部功能)

《Python开发围棋游戏的实例代码(实现全部功能)》围棋是一种古老而复杂的策略棋类游戏,起源于中国,已有超过2500年的历史,本文介绍了如何用Python开发一个简单的围棋游戏,实例代码涵盖了游戏的... 目录1. 围棋游戏概述1.1 游戏规则1.2 游戏设计思路2. 环境准备3. 创建棋盘3.1 棋盘类

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS