Elasticsearch:图片相似度搜索的 5 个技术组成部分
作者:Radovan Ondas,Bernhard Suhm
在本系列博文的第一部分中,我们介绍了图像相似度搜索,并回顾了一种可以降低复杂性并便于实施的高级架构。 此博客解释了实现图像相似性搜索应用程序所需的每个组件的基本概念和技术注意事项。 学习更多关于:
- 嵌入模型:机器学习模型生成应用向量搜索所需数据的数值表示
- 推理端点:用于将嵌入模型应用于 Elastic 中的数据的 API
- 矢量搜索:相似性搜索如何与最近邻搜索一起工作
- 生成图像嵌入:将数字表示的生成扩展到大型数据集
- 应用逻辑:交互前端如何与后端矢量搜索引擎通信
深入研究这五个组件,你可以了解如何在 Elastic 中应用矢量搜索来实现更直观的搜索体验。
1. 嵌入模型
要将相似性搜索应用于自然语言或图像数据,你需要机器学习模型将数据转换为其数值表示,也称为矢量嵌入。 在这个例子中:
- NLP “transformer” 模型将自然语言转化为矢量。
- OpenAI CLIP(对比语言 - 图像预训练)模型对图像进行矢量化。
Transformer 模型是经过训练以各种方式处理自然语言数据的机器学习模型,例如语言翻译、文本分类或命名实体识别。 他们接受了极大的带注释文本数据集的训练,以学习人类语言的模式和结构。
图像相似性应用程序根据文本、自然语言描述找到匹配的图像。 要实现这种相似性搜索,你需要一个在文本和图像上都经过训练并且可以将文本查询转换为矢量的模型。 然后可以使用它来查找相似图像。
详细了解如何在 Elasticsearch 中上传和使用 NLP 模型 >>
CLIP 是 OpenAI 开发的一种可以处理文本和图像的大规模语言模型。给定一小段文本作为输入,该模型被训练来预测图像的文本表示。 这涉及学习以允许模型做出准确预测的方式对齐图像的视觉和文本表示。
CLIP 的另一个重要方面是它是一个 “零样本” 模型,允许它执行没有经过专门训练的任务。 例如,它可以在训练期间从未见过的语言之间进行翻译,或者将图像分类到以前从未见过的类别中。 这使得 CLIP 成为一个非常灵活和通用的模型。
你将使用 CLIP 模型对你的图像进行矢量化处理,使用 Elastic 中的推理端点(如下所述)并对大量图像执行推理(如下文第 3 节所述)。
2. 推理端点
一旦将 NLP 模型加载到 Elasticsearch 中,你就可以处理实际的用户查询。 首先,你需要使用 Elasticsearch _infer 端点将查询文本转换为矢量。 该端点提供了一种在 Elastic 中原生使用 NLP 模型的内置方法,不需要查询外部服务,从而显着简化了实施。
POST _ml/trained_models/sentence-transformers__clip-vit-b-32-multilingual-v1/deployment/_infer
{"docs" : [{"text_field": "A mountain covered in snow"}]
}
3. 向量(相似度)搜索
在使用矢量嵌入对查询和文档进行索引后,相似文档是嵌入空间中查询的最近邻居。 实现该目标的一种流行算法是 k 最近邻 (kNN),它找到与查询向量最近的 k 个向量。 但是,对于你通常在图像搜索应用程序中处理的大型数据集,kNN 需要非常高的计算资源,并可能导致执行时间过长。 作为一种解决方案,近似最近邻 (ANN) 搜索牺牲了完美的准确性,以换取在高维嵌入空间中大规模高效执行。
在 Elastic 中,_search 端点支持精确和近似最近邻搜索。 使用下面的代码进行 kNN 搜索。 它假定 your-image-index 中所有图像的嵌入都在 image_embedding 字段中可用。 下一节将讨论如何创建嵌入。
# Run kNN search against <query-embedding> obtained above
POST <your-image-index>/_search
{"fields": [...],"knn": {"field": "image_embedding","k": 5,"num_candidates": 10,"query_vector": <query-embedding>}
}
要了解有关 Elastic 中 kNN 的更多信息,请参阅我们的文档:k-nearest neighbor (kNN) search | Elasticsearch Guide [8.6] | Elastic.
4. 生成图像嵌入
上面提到的图像嵌入对于图像相似性搜索的良好性能至关重要。 它们应该存储在一个单独的索引中,该索引包含图像嵌入,在上面的代码中称为 your-image-index。 该索引由每个图像的文档以及上下文字段和图像的密集矢量(图像嵌入)解释组成。 图像嵌入表示低维空间中的图像。 相似的图像被映射到这个空间中的附近点。 原始图像可能有几 MB 大,具体取决于其分辨率。
如何生成这些嵌入的具体细节可能会有所不同。 一般来说,这个过程涉及从图像中提取特征,然后使用数学函数将它们映射到低维空间。 该函数通常在大量图像数据集上进行训练,以学习在低维空间中表示特征的最佳方式。 生成嵌入是一项一次性任务。
在此博客中,我们将为此目的使用 CLIP 模型。 它由 OpenAI 分发,提供了一个很好的起点。 你可能需要为专门的用例训练自定义嵌入模型以实现所需的性能,具体取决于你要分类的图像类型在用于训练 CLIP 模型的公开可用数据中的表现程度。
Elastic 中的嵌入生成需要在摄取时发生,因此在搜索外部的过程中发生,步骤如下:
- 加载 CLIP 模型。
- 对于每个图像:
- 加载图像。
- 使用模型评估图像。
- 将生成的嵌入保存到文档中。
- 将文档保存到数据存储/Elasticsearch 中。
如下的伪代码使这些步骤更加具体,你可以在示例存储库中访问完整代码。
...
img_model = SentenceTransformer('clip-ViT-B-32')
...
for filename in glob.glob(PATH_TO_IMAGES, recursive=True):doc = {}image = Image.open(filename)embedding = img_model.encode(image)doc['image_name'] = os.path.basename(filename)doc['image_embedding'] = embedding.tolist()lst.append(doc)
...
或者参考下图作为说明:
处理后的文档可能如下所示。 关键部分是存储密集向量表示的字段 image_embedding。
{"_index": "my-image-embeddings","_id": "_g9ACIUBMEjlQge4tztV","_score": 6.703597,"_source": {"image_id": "IMG_4032","image_name": "IMG_4032.jpeg","image_embedding": [-0.3415695130825043,0.1906963288784027,.....-0.10289803147315979,-0.15871885418891907],"relative_path": "phone/IMG_4032.jpeg"}
}
5. 应用逻辑
在这些基本组件的基础上,你最终可以将所有部分组合在一起并通过逻辑来实现交互式图像相似性搜索。 让我们从概念上开始,了解当你想要以交互方式检索与给定描述匹配的图像时需要发生的事情。
对于文本查询,输入可以简单到像 "roses" 这样的单个词,也可以是更广泛的描述,如 “a mountain covered in snow”。 或者你也可以提供一张图片并要求提供与你拥有的图片相似的图片。
尽管你使用不同的模式来制定查询,但两者都是在底层矢量搜索中使用相同的步骤序列执行的,即对由其嵌入(作为 “dense” 矢量)表示的文档使用查询 (kNN)。 我们在前面的部分中描述了使 Elasticsearch 能够对大型图像数据集执行非常快速和可扩展的矢量搜索的机制。 请参阅此文档以了解有关在 Elastic 中调整 kNN 搜索以提高效率的更多信息。
- 那么如何实现上述逻辑呢? 在下面的流程图中,你可以看到信息是如何流动的:用户发出的查询,作为文本或图像,由嵌入模型矢量化 —— 取决于输入类型:NLP 模型用于文本描述,而 CLIP 模型用于图像。
- 两者都将输入查询转换为它们的数字表示,并将结果存储为 Elasticsearch 中的密集矢量类型([number, number, number...])。
- 然后在 kNN 搜索中使用向量表示来查找相似的向量(图像),这些向量作为结果返回。
推理:矢量化用户查询
后台的应用程序会向 Elasticsearch 中的推理 API 发送请求。 对于文本输入,是这样的:
POST _ml/trained_models/sentence-transformers__clip-vit-b-32-multilingual-v1/deployment/_infer
{"docs" : [{"text_field": "A mountain covered in snow"}]
}
对于图像,你可以使用以下简化代码使用 CLIP 模型处理单个图像,你需要提前将其加载到 Elastic 机器学习节点中:
model = SentenceTransformer('clip-ViT-B-32')
image = Image.open(file_path)
embedding = model.encode(image)
你将得到一个 512 长的 Float32 值数组,如下所示:
{"predicted_value" : [-0.26385045051574707,0.14752596616744995,0.4033305048942566,0.22902603447437286,-0.15598160028457642,...]
}
搜索:寻找相似的图片
对于两种类型的输入,搜索工作相同。 将带有 kNN 搜索定义的查询发送到带有图像嵌入 my-image-embeddings 的索引。 放入先前查询的密集向量 ("query_vector": [ ... ]) 并执行搜索。
GET my-image-embeddings/_search
{"knn": {"field": "image_embedding","k": 5,"num_candidates": 10,"query_vector": [-0.19898493587970734,0.1074572503566742,-0.05087625980377197,...0.08200495690107346,-0.07852292060852051]},"fields": ["image_id", "image_name", "relative_path"],"_source": false
}
Elasticsearch 的响应将根据我们的 kNN 搜索查询为你提供存储在 Elasticsearch 中最匹配的图像。
下面的流程图总结了交互式应用程序在处理用户查询时所经历的步骤:
- 加载交互式应用程序,它的前端。
- 用户选择他们感兴趣的图像。
- 你的应用程序通过应用 CLIP 模型将图像矢量化,并将生成的嵌入存储为密集矢量。
- 应用程序在 Elasticsearch 中启动 kNN 查询,它获取嵌入并返回其最近的邻居。
- 你的应用程序处理响应并呈现一个(或多个)匹配图像。
现在你已经了解了实现交互式图像相似性搜索所需的主要组件和信息流,你可以浏览本系列的最后一部分,了解如何实现它。 你将获得有关如何设置应用程序环境、导入 NLP 模型以及最终完成图像嵌入生成的分步指南。 然后,你将能够使用自然语言搜索图像 —— 无需关键字。
开始设置图片相似度搜索 >>
相关文章:

Elasticsearch:图片相似度搜索的 5 个技术组成部分
作者:Radovan Ondas,Bernhard Suhm 在本系列博文的第一部分中,我们介绍了图像相似度搜索,并回顾了一种可以降低复杂性并便于实施的高级架构。 此博客解释了实现图像相似性搜索应用程序所需的每个组件的基本概念和技术注意事项。 学…...

【CVPR2022】Class Re-Activation Maps for Weakly-Supervised Semantic Segmentation
论文标题:Class Re-Activation Maps for Weakly-Supervised Semantic Segmentation收录:CVPR 2022paper: https://arxiv.org/abs/2203.00962code: https://github.com/zhaozhengChen/ReCAM解读:https://zhuanlan.zhihu.com/p/478133151https:…...

PMP项目管理项目运行环境
目录1 概述2 事业环境因素和组织过程资产3 组织系统3.1 概述3.2 组织治理框架3.2.1 治理框架3.2.2 项目治理3.3 管理要素3.4 组织结构类型3.4.1 组织结构类型3.4.2 项目管理办公室1 概述 项目所处的环境可能对项目的开展产生有利或不利的影响,这些影响的两大主要来…...
Vue 3.0 渲染函数 【Vue3 从零开始】
Vue 推荐在绝大多数情况下使用模板来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力。这时你可以用渲染函数,它比模板更接近编译器。 让我们深入一个简单的例子,这个例子里 render 函数很实用。假设我们要生成一些…...

西电软件体系结构核心考点汇总(期末真题+核心考点)
文章目录前言一、历年真题二、核心考点汇总2.1 什么是软件体系架构?(软件体系结构的定义)2.2 架构风格优缺点2.3 质量属性2.4 质量评估前言 主要针对西安电子科技大学《软件体系结构》的核心考点进行汇总。 【期末期间总结资料如下】 针对西电计科院软件工程专业大三《软件体…...

SRS源码分析-SDP内容解析
前言 在学习SRS的RTC模块之前,首先来分析下SRS在将rtmp推流转成rtc流,通过浏览器拉取webrtc流场景下产生的SDP内容 SDP格式介绍 SDP数据是文本格式,由多个 <key><value> 表达式构成,<key>的值只能是一个字符…...
HTML 颜色
HTML 颜色 HTML 颜色采用的是 RGB 颜色,是通过对红 (R)、绿 (G)、蓝 (B) 三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB 即是代表红、绿、蓝三个通道的颜色。 Color Values HTML 颜色由一个十六进制符号来定义,这个符…...
MySQL高可用架构之InnoDB Cluster部署
MySQL高可用架构之InnoDB Cluster部署InnoDB Cluster适用场景准备工作安装MySQL Shell使用MySQL Shell搭建InnoDB Cluster初始化第一个实例创建InnoDB Cluster添加副本实例创建相关用户MySQL Router部署安装MySQL Router引导MySQL Router启动MySQL Router环境准备 主机名IPOS版…...

Linux安装minio单机版
说明:因为前面记录了一下minio的使用,这里说一下minio的安装,只是单机版哦 环境准备:Linux系统 说明图: 1.创建文件夹命令 我的是安装在/usr/local 文件夹下面的创建文件夹命令 #进入目标文件夹 cd /usr/local#创建…...
网络总结知识点(网络工程师必备)四
♥️作者:小刘在C站 ♥️个人主页:小刘主页 ♥️每天分享云计算网络运维课堂笔记,努力不一定有收获,但一定会有收获加油!一起努力,共赴美好人生! ♥️夕阳下,是最美的绽放,树高千尺,落叶归根人生不易,人间真情 目录 前言 71.NAPT有什么特点? 72.ARP欺骗解决方法...
数据结构——第三章 栈与队列(5)
共用栈和双队列1.共用栈2.双端队列栈与队列的本章小节1.共用栈 在实际应用中,有时一个应用程序需要多个栈,但这些栈的数据元素类型相同。假设每个栈都采用顺序栈,由于每个栈的使用情况不尽相同,势必会造成存储空间的浪费。若让多…...
CSDN竞赛第33期题解
CSDN竞赛第33期题解 1、题目名称:奇偶排序 给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数。(奇数和偶数的顺序根据输入的数字顺序排 列) #include<bits/stdc.h> using namespace std; t…...

农产品销售系统的设计与实现
技术:Java、JSP等摘要:这篇文章主要描述的是农产品蔬菜在线销售系统的设计与实现。主要应用关于JSP网站开发技术,并联系到网站所处理的数据的结构特点和所学到的知识,应用的主要是Mysql数据库系统。系统实现了网站的基本功能&…...

C语言-基础了解-08-C判断
C判断 一、C判断 判断结构要求程序员指定一个或多个要评估或测试的条件,以及条件为真时要执行的语句(必需的)和条件为假时要执行的语句(可选的)。 C 语言把任何非零和非空的值假定为 true,把零或 null 假…...

用数组名作函数参数的详解,以及形参实参采用数组名,形参实参采用指针变量的几种情况解析
关于地址,指针,指针变量可以参考我的这篇文章: 地址,指针,指针变量是什么?他们的区别?符号(*)在不同位置的解释?_juechen333的博客-CSDN博客https://blog.csd…...

k8s中的PV和PVS
前言:容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时,kubelet 会重启它,但是容器中的文件将丢失——容器以干净的状态(镜像最初的状态)…...

【云原生】Gateway网关选型
网关一般分为流量网关和业务网关,流量网关负责接入所有的流量,并分发给不同的子系统,那在具体的业务接入之前,还有一层业务网关。流量网关提供全局性的、与后端业务应用无关的策略,例如 HTTPS证书卸载、Web防火墙、全局…...

QML Button详解
1.Button简介 Button表示用户可以按下或单击的按钮控件。按钮通常用于执行一个动作,或回答一个问题。典型的按钮有确定、应用、取消、关闭、是、否和帮助。 Button继承自AbstractButton,提供了以下几种信号。 void canceled() //当按…...
【编程实践】什么是好/坏代码?非程序员的示例
What is good/bad code? An illustrated example for non-programmers 什么是好/坏代码?非程序员的示例 目录 What is good/bad code? An illustrated example for non-programmers什么是好/坏代码?非程序员的示例 So what is ‘Bad Code’, as a layperson?那么,作为…...

一个简单的Sublime设置
问题 如果读者熟悉我,应该会发现我经常使用 VSCode 作为主力编辑器,但随着我安装的 VSCode 的插件逐渐增加,我发现对于部分较小的任务使用 VSCode 过于笨重,比如简单的 Markdown 文件编辑工作。 在经过一系列寻找后,…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...