Elasticsearch:基于多个 kNN 字段对文档进行评分

作者:来自 Elastic Madhusudhan Konda

通过具有多个 kNN 字段的最接近的文档对文档进行评分

Elasticsearch 不仅仅是一个词法(文本)搜索引擎。 Elasticsearch 是多功能搜索引擎,除了传统的文本匹配之外,还支持 k 最近邻 (kNN) 搜索以及语义搜索。

Elasticsearch 中的 kNN 搜索主要用于查找多维空间中给定点的 “最近邻居”。文档被表示为一组数字(向量),在搜索时,kNN 特征会获取更接近查询向量的相关文档。 kNN 搜索通常应用于涉及向量的场景,其中向量是通过使用深度神经网络的 “嵌入” 过程从文本、图像或音频创建的。

另一方面,语义搜索是一种由自然语言处理特征驱动的搜索,它有助于根据意图和含义搜索相关结果,而不仅仅是文本匹配。

在本文中,我们的重点是搜索具有多个 kNN 字段的文档,并根据多个 kNN 向量字段对结果文档进行评分。

由于我们将在本文中详细了解 kNN 搜索,因此让我们花几分钟时间详细了解 kNN 的机制。

kNN 机制

kNN(k 最近邻居)获取的搜索结果几乎是最接近给定用户查询的 k 个文档(使用算法测量)。

它的工作方式是通过计算向量之间的距离(通常是欧几里得相似度或余弦相似度)。当我们使用 kNN 对数据集执行查询时,Elasticsearch 会找到最接近我们的查询向量的前 “k” 个条目。

在执行与搜索相关的活动以获取结果之前,必须使用适当的嵌入对索引进行预处理 —— 嵌入是向量化数据的术语。这些字段的类型是 dense_vector,用于保存数值数据。

让我们举个例子:

如果你有图像数据集,并且已使用神经网络将这些图像转换为向量,则可以使用 kNN 搜索来查找与查询图像最相似的图像。如果你提供 “披萨” 图像的向量表示,kNN 可以帮助你找到视觉上相似的其他图像,例如薄煎饼,也许还有意大利面:)

kNN 搜索是关于在向量空间中查找最近的数据点,因此适用于文本或图像嵌入的相似性搜索。相比之下,语义搜索是为了理解搜索查询中单词的含义和上下文,使其对于意图和上下文都很重要的基于文本的搜索非常强大。

为文当打分

当你有多个 k 最近邻 (kNN) 字段时,根据最接近的文档对文档进行评分需要利用 Elasticsearch 处理向量相似性的能力来对文档进行排名。这种方法在语义搜索和推荐引擎等场景中特别有用。或者我们正在处理多维数据并需要基于多个方面(字段)找到 “最接近” 或最相似的项目的情况。

文本嵌入(text embedding)及向量字段

让我们以电影(movies)索引为例,它由一些文件组成,例如标题(title)、概要(synopsis)等。我们将使用常见的数据类型(例如文本数据类型)来表示它们。除了这些普通字段之外,我们还将创建另外两个字段:title_vector 和 synopsis_vector 字段 - 顾名思义 - 它们是密集向量数据类型字段。这意味着,数据将使用称为 “文本嵌入” 的过程进行向量化。

嵌入模型是一个自然语言处理神经网络,它将输入转换为数字数组。然后,向量化数据将存储在密集向量类型字段中。数据文档可以有多个字段,包括一些用于存储向量数据的 dense_vector 字段。

因此,在下一节中,我们将混合使用普通字段和 kNN 字段来创建索引。

使用 kNN 字段创建索引

让我们创建一个名为 movies 的索引,其中包含示例电影文档。我们的文档将有多个字段,包括几个用于存储向量数据的 kNN 字段。以下片段演示了索引映射代码:

PUT /movies
{"mappings": {"properties": {"title": {"type": "text"},"title_vector.predicted_value": {"type": "dense_vector","dims": 384},"synopsis": {"type": "text"},"synopsis_vector.predicted_value": {"type": "dense_vector","dims": 384},"genre": {"type": "text"}}}
}

值得注意的是,文本类型的 title 字段有一个等效的向量类型字段:title_vector.predicted_value。类似地,synopsis 的向量字段是 synopsis_vector.predicted_value 字段。此外,密集向量场的维度 (384) 在上面的代码中提到为 dims。这表明模型将为每个摄取的字段生成 384 个维度。我们可以请求在密集向量字段上生成的最大维度是 2048。

执行此脚本将创建一个名为 movies 的新索引,其中包含两个向量字段:title_vector 和 synopsis_vector。

索引示例文档

现在我们有了索引,我们可以索引一些电影并进行搜索。除了 title 和 synopsis 字段外,文档还将包含向量字段。在索引文档之前,我们需要用相应的向量填充文档。以下代码演示了生成向量后的电影文档示例:

POST /movies/_doc/1
{"title": "The Godfather","title_vector": [0.1, 0.5, 3, 4,...], // vectorized data "synopsis": "The aging patriarch of an organized crime dynasty....","synopsis_vector": [0.2, 0.6, 1, 0.7,...] // vectorized data 
}

如你所见,需要准备好向量数据以供文档提取。有几种方法可以做到这一点:

  • 一种是在 Elasticsearch 之外调用 text_embedding 模型上的 inference API 来对数据进行向量化,如上所示(我在这里提到它作为参考,尽管我们更希望使用推理处理器管道)
  • 另一种是设置和使用推理管道。

设置推理处理器(inference processor)

我们可以设置一个摄取管道,该管道将嵌入函数应用于相关字段以生成矢量化数据。例如,以下代码创建 movie_embedding_pipeline 处理器,该处理器将为每个字段生成嵌入并将其添加到文档中:

PUT _ingest/pipeline/movie_embedding_pipeline
{"processors": [{"inference": {"model_id": ".multilingual-e5-small","target_field": "title_vector","field_map": { "title": "text_field" }}},{"inference": {"model_id": ".multilingual-e5-small","target_field": "synopsis_vector","field_map": { "synopsis": "text_field" }}}]
}

摄取管道可能需要一点解释:

  • 两个字段 - title_vector 和 synopsis_vector - 被称为 target_field - 是 dense_vector 字段类型。因此,它们存储由 multilingual-e5-small 嵌入模型生成的向量化数据
  • field_map 提到文档中的字段(在本例中为 title 和 synopsis 字段)被映射到模型的 text_field 字段
  • model_id 声明用于嵌入数据的嵌入模型
  • target_field 是向量化数据将被复制到的字段的名称

执行上述代码将创建一个 movie_embedding_pipeline 摄取管道。也就是说 - 仅包含 title 和 synopsis 的文档将通过附加字段(title_vector 和 synopsis_vector)进行增强,这些字段将具有内容的向量化版本。

索引文档

电影文档将由 title 和 synopsis 字段组成,正如预期的那样 - 因此我们可以按如下所示对其进行索引。请注意,文档通过 URL 中启用的管道处理器进行增强。以下代码片段显示了索引少量电影:

POST movies/_doc/?pipeline=movie_embedding_pipeline
{"title": "The Godfather","synopsis": "The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son."
}POST movies/_doc/?pipeline=movie_embedding_pipeline
{"title": "Avatar","synopsis": "A paraplegic Marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home."
}POST movies/_doc/?pipeline=movie_embedding_pipeline
{"title": "Godzilla","synopsis": "The world is beset by the appearance of monstrous creatures, but one of them may be the only one who can save humanity."
}POST movies/_doc/?pipeline=movie_embedding_pipeline
{"title": "The Good, The Bad and The Ugly","synopsis": "A bounty hunting scam joins two men in an uneasy alliance against a third in a race to find a fortune in gold buried in a remote cemetery."
}POST movies/_doc/?pipeline=movie_embedding_pipeline
{"title": "A Few Good Men","synopsis": "Military lawyer Lieutenant Daniel Kaffee defends Marines accused of murder. They contend they were acting under orders."
}

我们当然可以使用 _bulk API 来一次性索引文档 - 请查看此 Bulk API 文档以了解更多详细信息。

一旦这些文档被索引,你就可以通过执行搜索查询来获取电影来检查是否添加了向量化内容:

GET movies/_search

这将导致 movies 索引具有由向量化内容组成的两个附加字段,如下图所示:

现在我们已经对文档进行了索引,让我们使用 kNN 搜索功能对这些文档进行搜索。

kNN 搜索

Elasticsearch 中的 k-最近邻搜索会获取最接近给定(查询)向量的向量(文档)。Elasticsearch 支持两种类型的 kNN 搜索:

  • 近似 kNN 搜索
  • 强力(或精确)KNN 搜索

虽然两种搜索都会产生结果,但强力搜索会以最大资源利用率和查询时间为代价找到准确的结果。近似 kNN 足以满足大多数搜索情况,因为它可以提供接近准确的结果。

Elasticsearch 为近似搜索提供 knn 查询,而我们应该使用 script_score 查询进行精确 kNN 搜索。

近似搜索

让我们对 movies 进行近似搜索,如下所示。Elasticsearch 提供了一个 kNN 查询,其中包含由我们的查询要求组成的 query_build_vector 块。让我们先编写代码片段,然后再讨论其组成部分:

GET movies/_search
{"knn": {"field": "title_vector.predicted_value","query_vector_builder": {"text_embedding": {"model_id": ".multilingual-e5-small","model_text": "Good"}},"k": 3,"num_candidates": 100},"_source": ["id","title"]
}

传统的搜索查询支持 query 功能,但是 Elasticsearch 引入了 knn 搜索功能作为查询向量的一等公民。

knn 块由我们要搜索的字段组成 - 在本例中,它是标题向量 - title_vector.predicted_value 字段。请记住,这是我们之前在映射中提到的字段的名称。

query_vector_builder 是我们需要提供查询以及嵌入查询所需的模型的地方。在本例中,我们将 multilingual-e5-small 设置为我们的模型,文本只是 “Good”。Elasticsearch 将使用文本嵌入模型 (multilingual-e5-small) 对相关查询进行向量化。然后,它将向量查询与可用的标题向量进行比较。

k 值表示需要返回多少文档作为结果。

此查询应该为我们提供前三份文档:

"hits": [{"_index": "movies","_id": "ZADvgo4BDf-WoG_MTka1","_score": 0.92932993,"_source": {"title": "The Good, The Bad and The Ugly"}},{"_index": "movies","_id": "uJ3wgo4BMlgFmHKKtFSp","_score": 0.91828954,"_source": {"title": "A Few Good Men"}},{"_index": "movies","_id": "tp15fY4BMlgFmHKK6VRV","_score": 0.90952975,"_source": {"title": "The Godfather"}}]

当我们针对片名搜索 “Good” 时,得分最高的电影是《The Good, The Bad and the Ugly》。请注意,即使结果电影不匹配,kNN 搜索也总能得到结果 - 这是 kNN 匹配的固有特性。

记下每个文档的相关性分数 (_score) - 正如预期的那样,文档是根据此分数排序的。

搜索多个 kNN 字段

我们有两个向量字段 - 电影文档中的 title_vector 和 synopsis_vector 字段 - 我们当然可以针对这两个字段进行搜索,并根据组合分数期望得到结果文档。

假设我们想在 title 中搜索 “Good”,但在 synopsis 字段中搜索 “orders”。记得从之前使用 “Good” 的单个 title 字段搜索中,我们检索到了《The Good, The Bad and the Ugly》这部电影。让我们看看根据概要的 “orders” 部分作为搜索条件,将获取哪部电影。

以下代码声明了我们的多 kNN 字段搜索:

POST movies/_search
{"knn":[{"field": "title_vector.predicted_value","query_vector_builder": {"text_embedding": {"model_id": ".multilingual-e5-small","model_text": "Good"}},"k": 3,"num_candidates": 100},{"field": "synopsis_vector.predicted_value","query_vector_builder": {"text_embedding": {"model_id": ".multilingual-e5-small","model_text": "orders"}},"k": 3,"num_candidates": 100}]
}

正如你所想象的,knn 查询可以接受多个搜索字段作为数组 - 在这里我们从两个字段中提供了搜索条件。答案是 “A Few Good Men”,因为包含 “order” 向量的概要向量就是这部电影。

何时使用多 kNN 字段进行搜索

我们可以使用多个 kNN 字段进行搜索的一些情况如下:

  • 根据图像相似性(视觉 kNN 字段)和推文相似性(文本 kNN 字段)搜索 “tweets”。
  • 根据音频特征(音频作为 kNN 字段)推荐类似的歌曲,如节奏和韵律;可能还有标题/艺术家/流派信息(文本 kNN 字段)。
  • 根据用户行为(用于用户交互的 kNN 字段)和电影/产品属性(基于这些属性的 kNN 字段)推荐电影或产品。

就这样了。在本文中,我们研究了 kNN 搜索的机制,以及当我们有多个向量化字段时如何找到最近的文档。

准备好自己尝试一下了吗?开始免费试用。

想要获得 Elastic 认证吗?了解下一次 Elasticsearch 工程师培训何时开始!

原文:Elasticsearch Scoring: Based on multiple kNN fields — Elastic Search Labs

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/338411.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为设备配置静态路由和默认路由

华为设备配置静态路由和默认路由 理论部分知识: 路由分为两个大类:静态路由-----动态路由 静态路由:手工指定,适用于小规模的网络应用场景,如果网络规模变大,这样的方式非常不适合而且容易出错。 语法&…

【JavaEE进阶】——Mybatis操作数据库(使用注解和XML方式)

目录 🚩三层架构 🎈JDBC操作回顾 🚩什么是MyBatis 🚩MyBatis⼊⻔ 🎈准备工作 📝创建⼯程 📝数据准备 🎈配置数据库连接字符串 🎈写持久层代码 🎈单…

STM32作业设计

目录 STM32作业设计 STM32作业实现(一)串口通信 STM32作业实现(二)串口控制led STM32作业实现(三)串口控制有源蜂鸣器 STM32作业实现(四)光敏传感器 STM32作业实现(五)温湿度传感器dht11 STM32作业实现(六)闪存保存数据 STM32作业实现(七)OLED显示数据 STM32作业实现(八)触摸按…

PyQt5创建与MySQL数据库集成的应用程序

最近,对之前的mysql管理系统进行了更新升级,制作了一版关于车牌的管理系统! (1)实现了对车牌和用户基本信息的增删改查的功能 ! (2)加入了对数据库的刷新和状态显示功能 &#xff…

没有知网资源如何快速下载知网论文

今天有位同学求助一篇知网论文,“球磨-点击化学反应:无溶剂绿色反应方式”,其实下载知网论文是一件非常简单的事情,下面小编就把如何在家轻松查找下载知网论文的方法给大家演示一遍。 一、首先你需要获取知网使用权限&#xff0c…

css特殊效果和页面布局

特殊效果 圆角边框:div{border-radius: 20px 10px 50px 30px;} 四个属性值按顺时针排列,左上的1/4圆半径为20px,右上10,右下50,左下30。 div{border-radius: 20px;} 四角都为20px。 div{border-radius: 20px 10…

Maven配置

Maven – Download Apache Maven https://maven.apache.org/install.html 得下载有 bin的

MongoDB~俩大特点管道聚合和数据压缩(snappy)

场景 在MySQL中,通常会涉及多个表的一些操作,MongoDB也类似,有时需要将多个文档甚至是多个集合汇总到一起计算分析(比如求和、取最大值)并返回计算后的结果,这个过程被称为 聚合操作 。 根据官方文档介绍&…

Facebook开户 | Facebook二不限户

Facebook二不限户的正确使用方法 Facebook 二不限是指 Facebook 国内二不限户,是通过代理开出来的一种特殊账户,️需要广告主准备主页。 其特点是:限主页、不限域名、额度没解限,解限后则不限额度。 相比于三不限户,…

Notepad++不显示CRLF的方法

View -> Show Symbol -> 去掉勾选 Show All Characters

threejs 场景构建技巧与优化策略探讨

threejs 场景构建技巧与优化策略探讨 一、引言 在使用 Three.js 进行三维场景开发时,艾斯视觉作为行业ui设计与前端开发服务商很高兴能在这里与你共同探讨:如何高效地构建场景并实现良好的性能表现是至关重要的。本文将深入探讨一些场景构建的技巧以及…

LabVIEW在高校电力电子实验中的应用

概述:本文介绍了如何利用LabVIEW优化高校电力电子实验,通过图形化编程实现参数调节、实时数据监控与存储,并与Simulink联动,提高实验效率和数据处理能力。 需求背景高校实验室在进行电机拖动和电力电子实验时,通常使用…

Nodejs-- 网络编程

网络编程 构建tcp服务 TCP tcp全名为传输控制协议。再osi模型中属于传输层协议。 tcp是面向连接的协议,在传输之前需要形成三次握手形成会话 只有会话形成了,服务端和客户端才能想发送数据,在创建会话的过程中,服务端和客户…

关于如何通过APlayer+MetingJS为自己的wordpress博客网页添加网易音乐播放器(无需插件)

本文转自博主的个人博客:https://blog.zhumengmeng.work,欢迎大家前往查看。 原文链接:点我访问 序言:最近在网上冲浪,发现大家的博客大部分都有一个音乐播放器能够播放音乐,随机我也开始寻找解决方法。可是找来找去我…

已解决java.nio.charset.CoderMalfunctionError: 编码器故障错误的正确解决方法,亲测有效!!!

已解决java.nio.charset.CoderMalfunctionError: 编码器故障错误的正确解决方法,亲测有效!!! 亲测有效 报错问题解决思路解决方法1. 检查和清理输入数据2. 选择正确的字符集3. 处理异常情况4. 更新Java版本或库5. 检查第三方库的依…

Java | Leetcode Java题解之第123题买卖股票的最佳时机III

题目&#xff1a; 题解&#xff1a; class Solution {public int maxProfit(int[] prices) {int n prices.length;int buy1 -prices[0], sell1 0;int buy2 -prices[0], sell2 0;for (int i 1; i < n; i) {buy1 Math.max(buy1, -prices[i]);sell1 Math.max(sell1, b…

p2p文件传输小工具

使用webRTC的相关技术栈可以很轻松的开发一个p2p文件传输工具&#xff0c;这里主要讲下使用datachannel开发的一个文件传输工具client程序的使用 客户端A&#xff1a;需要可以访问公网&#xff0c;运行client的主机 客户端B&#xff1a;可以访问公网&#xff0c;可以和客户端…

【Linux】 深入讲解自动化构建工具

各位大佬好 &#xff0c;这里是阿川的博客&#xff0c;祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 Linux一系列的文章&#xff08;质量分均在93分 以…

JavaScript倍速播放视频

F12打开开发者工具&#xff0c;打开控制台&#xff0c;输入这行代码&#xff0c;视频即可加速播放&#xff0c; 可以调整倍速&#xff08;2&#xff0c;4&#xff0c;8&#xff0c;16&#xff09; document. getElementsByTagName("video")[0]. playbackRate16

数论1---整除

概念与基本性质就不说了 例题1&#xff1a;已知a|n&#xff0c;b|n.且axby1,求证&#xff1a;ab|n 即&#xff1a; 所以&#xff1a;ab|n 例题2&#xff1a;设m是一个大于2的正整数&#xff0c;证明&#xff1a;对于任意正整数n&#xff0c;都有 由于我不想打公式了直接拍照…