使用 KNN 搜索和 CLIP 嵌入构建多模态图像检索系统

作者:来自 Elastic James Gallagher

了解如何使用 Roboflow Inference 和 Elasticsearch 构建强大的语义图像搜索引擎。

在本指南中,我们将介绍如何使用 Elasticsearch 中的 KNN 聚类和使用计算机视觉推理服务器 Roboflow Inference 计算的 CLIP 嵌入构建图像检索系统。

Roboflow Universe 是网络上最大的计算机视觉数据存储库,托管超过 1 亿张图像,它使用 CLIP 嵌入为我们的数据集搜索引擎提供高效的语义查询。

不用多说,让我们开始吧!

CLIP 和 Roboflow 推理简介

CLIP(Contrastive Language-Image Pretraining - 对比语言-图像预训练)是 OpenAI 开发的一种计算机视觉模型架构和模型。该模型于 2021 年根据 MIT 许可发布。

该模型的训练目的是 “根据图像预测最相关的文本片段”。在此过程中,CLIP 学会了通过模型使用的向量来识别图像和文本之间的相似性。 CLIP 将图像和文本映射到向量空间。这允许向量比较并找到与文本查询相似的图像,或与另一幅图像相似的图像。

CLIP 等多模式模型的进步使得构建语义图像搜索引擎变得比以往任何时候都更容易。

像 CLIP 这样的模型可用于创建捕获有关图像或文本查询的语义信息的 “嵌入”。向量嵌入是一种数据表示类型,它将单词、句子和其他数据转换为捕捉其含义和关系的数字。

Roboflow Inference 是一款高性能计算机视觉推理服务器。 Roboflow Inference 支持各种最先进的视觉模型,从用于物体检测的 YOLO11 到用于视觉问答的 PaliGemma 再到用于多模态嵌入的 CLIP。

你可以将 Roboflow Inference 与 Python SDK 一起使用,或者在 Docker 环境中使用。

在本指南中,我们将使用 Inference 计算 CLIP 嵌入,然后将它们存储在 Elasticsearch 集群中,以用于构建图像检索系统。

先决条件

要遵循本指南,你需要:

  • 支持 KNN 搜索的 Elasticsearch 实例
  • 免费的 Roboflow 帐户
  • Python 3.12+

我们准备了一个 Jupyter Notebook,你可以在计算机上或 Google Colab 上运行它,以便按照本指南使用。打开笔记本。

步骤#1:设置支持 KNN 的 Elasticsearch 索引

对于本指南,我们将使用 Elasticsearch Python SDK。你可以使用以下代码来安装它:

pip install elasticsearch

如果你尚未设置 Elasticsearch 集群,请参阅 Elasticsearch 文档以开始使用。

注:你也可以阅读文章 “使用 start-local 脚本在本地运行 Elasticsearch” 开始使用。

安装 SDK 并设置集群后,创建一个新的 Python 文件并添加以下代码以连接到客户端:

from elasticsearch import Elasticsearchclient = Elasticsearch("https://localhost:9200",api_key=“your-api-key",
)

要在 Elasticsearch 中运行嵌入搜索,我们需要一个包含 density_vector 属性类型的索引映射。对于本指南,我们将创建一个包含两个字段的索引:一个包含与图像相关的 CLIP 嵌入的密集向量,以及一个与图像相关的文件名。

运行以下代码来创建索引:

client.indices.create(index="knn",body={"mappings": {"properties": {"vector": {"type": "dense_vector","dims": 512,"similarity": "cosine",},"filename": {"type": "keyword",},},},}
)

输出应类似于以下内容:

ObjectApiResponse({'acknowledged': True, 'shards_acknowledged': True, 'index': 'knn'})

KNN 搜索使用的默认索引类型是 L2 Norm,也称为欧几里得距离。此距离度量不适用于 CLIP 相似度。因此,上面我们明确表示我们想要创建余弦相似度索引。CLIP 嵌入与余弦相似度相比效果最好。

对于本指南,我们将使用具有 512 个维度的 CLIP 模型。如果你使用其他 CLIP 模型,请确保将 dims 值设置为 CLIP 模型返回的向量的维数。

步骤 2:安装 Roboflow Inference

接下来,我们需要安装 Roboflow Inference 和 Supervision,这是一个用于处理视觉模型预测的工具。你可以使用以下命令安装所需的依赖项:

pip install "inference[clip]" supervision

这将安装 Roboflow Inference 和我们将用于计算向量的 CLIP 模型扩展。

安装 Roboflow Inference 后,我们可以开始计算和存储 CLIP 嵌入。

步骤 3:计算和存储 CLIP 嵌入

在本指南中,我们将为 COCO 128 数据集构建一个语义搜索引擎。此数据集包含从更大的 Microsoft COCO 数据集中采样的 128 张图像。COCO 128 中的图像多种多样,使其成为用于测试我们的语义搜索引擎的理想数据集。

要下载 COCO 128,首先创建一个免费的 Roboflow 帐户。然后,导航到 Roboflow Universe(Roboflow 的开放计算机视觉数据集社区)上的 COCO 128 数据集页面。

单击 “Download Dataset”:

选择 “YOLOv8” 格式。选择显示下载代码的选项:

复制终端命令以下载数据集。该命令应如下所示:

curl -L "https://universe.roboflow.com…r" > roboflow.zip; unzip roboflow.zip; rm roboflow.zip

运行该命令时,数据集将下载到你的计算机并解压。

我们现在可以开始计算 CLIP 嵌入。

从之前的 Python 文件中添加以下代码,然后运行完整文件:

from inference.models import Clip
import osIMAGE_DIRECTORY = "./COCO-128-2/train/images"# See a full list of supported models at
# https://inference.roboflow.com/foundation/clip/#how-can-i-use-clip-model-in-inference
clip = Clip(model_id="clip/ViT-B-16")# create index if it doesn't exist for KNN with two fields: vector and file name
for file in os.listdir(IMAGE_DIRECTORY):if not file.endswith(".jpg"):continueimage_path = os.path.join(IMAGE_DIRECTORY, file)vector = clip.embed_image(image_path)client.index(index="demo",body={"vector": vector.tolist()[0],"filename": file,})

这段代码会遍历 COCO 128 数据集训练集中的所有图像,并通过 Roboflow Inference 使用 CLIP 模型对它们进行处理。然后,我们将生成的向量与每个向量关联的文件名一起索引到 Elasticsearch 中。

CLIP 模型权重可能需要 1-2 分钟才能下载。完成此操作时,你的脚本将暂时暂停。然后,CLIP 模型权重将缓存在你的系统中以供将来使用。

注意:运行上述代码时,你可能会看到一些与 ExecutionProviders 相关的警告。这与 Inference 中针对不同设备的可用优化有关。例如,如果你在 CUDA 上部署,CoreMLExecutionProvide 将不可用,因此会发出警告。看到这些警告时无需采取任何措施。

步骤 4:从 Elasticsearch 检索数据

索引数据后,即可运行测试查询!

要使用文本作为输入,你可以使用此代码检索用于运行搜索的输入向量:

query_vector = clip.embed_text("coffee")

要使用图像作为输入,你可以使用以下代码:

query_vector = clip.embed_image(“path/to/image”)

在本指南中,我们使用查询“coffee”运行文本搜索。

我们将使用 k-最近邻 (k-nearest neighbours - KNN) 搜索。此搜索类型接受输入嵌入并在我们的数据库中查找嵌入与输入相似的值。KNN 搜索通常用于向量比较。

KNN 搜索始终返回前 k 个最近邻。如果 k = 3,Elasticsearch 将返回与输入向量最相似的三个文档。

使用 Elasticsearch, 你可以在几毫秒内从大型向量存储中检索结果。

我们可以使用以下代码运行 KNN 搜索:

import supervision as sv
from PIL import Imageresponse = client.search(index="demo",body={"query": {"knn": {"field": "vector","query_vector": query_vector.tolist()[0],  # The input vector"k": 3}}}
)images = [Image.open(os.path.join(IMAGE_DIRECTORY, i["_source"]["filename"])) for i in response["hits"]["hits"][:3]]sv.plot_images_grid(images, grid_size=(1, 3))

上面的 k 值表示应从每个分片中检索多少个最近的向量。查询的大小参数决定要返回多少个结果。由于我们在此演示中使用一个分片,因此查询将返回三个结果。

我们的代码返回:

我们已成功运行语义搜索并找到与输入查询相似的图像!上面,我们可以看到三张最相似的图像:一张户外桌子上的咖啡杯和蛋糕的照片,然后是我们索引中的两张桌子上有咖啡杯的重复图像。

结论

借助 Elasticsearch 和 Roboflow Inference 中的 CLIP 功能,你可以创建一个多模态搜索引擎。你可以使用搜索引擎进行图像检索、图像比较和重复数据删除、带有视觉提示的多模态检索增强生成等。

Roboflow 大规模使用 Elasticsearch 和 CLIP。我们存储了超过 1 亿个 CLIP 嵌入并对其进行索引,以供希望大规模搜索数据集的客户进行多模态搜索。随着我们平台上的数据从数百张图像增长到数亿张,Elasticsearch 实现了无缝扩展。

要了解有关使用 Roboflow Inference 的更多信息,请参阅 Roboflow Inference 文档。要为你的下一个计算机视觉项目查找数据,请查看 Roboflow Universe。

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

Elasticsearch 包含许多新功能,可帮助你为你的用例构建最佳搜索解决方案。深入了解我们的示例笔记本以了解更多信息,开始免费云试用,或立即在本地机器上试用 Elastic。

原文:Build a multimodal image retrieval system using KNN search and CLIP embeddings - Elasticsearch Labs

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

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

相关文章

maven的打包插件如何使用

默认的情况下,当直接执行maven项目的编译命令时,对于结果来说是不打第三方包的,只有一个单独的代码jar,想要打一个包含其他资源的完整包就需要用到maven编译插件,使用时分以下几种情况 第一种:当只是想单纯…

Golang Gin系列-7:认证和授权

在本章中,我们将探讨Gin框架中身份验证和授权的基本方面。这包括实现基本的和基于令牌的身份验证,使用基于角色的访问控制,应用中间件进行授权,以及使用HTTPS和漏洞防护保护应用程序。 实现身份认证 Basic 认证 Basic 认证是内置…

CTF-web: phar反序列化+数据库伪造 [DASCTF2024最后一战 strange_php]

step 1 如何触发反序列化? 漏洞入口在 welcome.php case delete: // 获取删除留言的路径,优先使用 POST 请求中的路径,否则使用会话中的路径 $message $_POST[message_path] ? $_POST[message_path] : $_SESSION[message_path]; $msg $userMes…

C语言自定义数据类型详解(一)——结构体类型(上)

什么是自定义数据类型呢?顾名思义,就是我们用户自己定义和设置的类型。 在C语言中,我们的自定义数据类型一共有三种,它们分别是:结构体(struct),枚举(enum),联合(union)。接下来,我…

SpringCloud系列教程:微服务的未来(十八)雪崩问题、服务保护方案、Sentinel快速入门

前言 在分布式系统中,雪崩效应(Avalanche Effect)是一种常见的故障现象,通常发生在系统中某个组件出现故障时,导致其他组件级联失败,最终引发整个系统的崩溃。为了有效应对雪崩效应,服务保护方…

升级到Mac15.1后pod install报错

升级Mac后,Flutter项目里的ios项目运行 pod install报错, 遇到这种问题,不要着急去百度,大概看一下报错信息,每个人遇到的问题都不一样。 别人的解决方法并不一定适合你; 下面是报错信息: #…

STM32 PWM驱动舵机

接线图: 这里将信号线连接到了开发板的PA1上 代码配置: 这里的PWM配置与呼吸灯一样,呼吸灯连接的是PA0引脚,输出比较单元用的是OC1通道,这里只需改为OC2通道即可。 完整代码: #include "servo.h&quo…

使用 concurrently 实现前后端一键启动

使用 concurrently 实现前后端一键启动 本文适合: 前后端分离项目(如 React Node.js),希望通过一条命令同时启动前端和后端服务。 工具链: Node.js、npm、concurrently。 耗时: 3 分钟。 文章目录 使用 c…

【NLP251】NLP RNN 系列网络

NLP251 系列主要记录从NLP基础网络结构到知识图谱的学习 1.原理及网络结构 1.1RNN 在Yoshua Bengio论文中( http://proceedings.mlr.press/v28/pascanu13.pdf )证明了梯度求导的一部分环节是一个指数模型…

OpenCV:在图像中添加噪声(瑞利、伽马、脉冲、泊松)

目录 简述 1. 瑞利噪声 2. 伽马噪声 3. 脉冲噪声 4. 泊松噪声 总结 相关阅读 OpenCV:在图像中添加高斯噪声、胡椒噪声-CSDN博客 OpenCV:高通滤波之索贝尔、沙尔和拉普拉斯-CSDN博客 OpenCV:图像处理中的低通滤波-CSDN博客 OpenCV&…

小智 AI 聊天机器人

小智 AI 聊天机器人 (XiaoZhi AI Chatbot) 👉参考源项目复现 👉 ESP32SenseVoiceQwen72B打造你的AI聊天伴侣!【bilibili】 👉 手工打造你的 AI 女友,新手入门教程【bilibili】 项目目的 本…

亚博microros小车-原生ubuntu支持系列:16 机器人状态估计

本来想测试下gmapping建图,但是底层依赖了yahboomcar_bringup做底层的数据处理,所以先把依赖的工程导入。 程序启动后,会订阅imu和odom数据,过滤掉一部分的imu数据后,然后与odom数据进行融合,最后输出一个…

C++中的类与对象(中)

在上一节中,我们初步了解了一下,C中的类,这一概念,这一节让我们进一步深入了解一下。 文章目录 目录 前言 一、类中的默认成员函数 1.1 构造函数 构造函数的特点: 1.2 析构函数 析构函数的特点: 1.3 …

Kotlin开发(六):Kotlin 数据类,密封类与枚举类

引言 想象一下,你是个 Kotlin 开发者,敲着代码忽然发现业务代码中需要一堆冗长的 POJO 类来传递数据。烦得很?别急,Kotlin 贴心的 数据类 能帮你自动生成 equals、hashCode,直接省时省力!再想想需要多种状…

redis数据安全与性能保障

数据安全与性能保障 1、持久化1.1 快照持久化1.2 AOF持久化1.3 重写/压缩AOF文件 2、复制2.1 Redis复制的启动过程2.2 主从链 3、处理系统故障3.1 验证快照文件和AOF文件 4、事务4.1 java中的redis事务使用 如有侵权,请联系~ 如有错误,也欢迎…

数据分析系列--③RapidMiner算子说明及数据预处理

一、算子说明 1.新建过程 2.算子状态灯 状态灯说明: (1)状态指示灯: 红色:指示灯说明有参数未被设置或输入端口未被连接等问题; 黄色:指示灯说明还未执行算子,不管配置是否基本齐全; 绿色:指示灯说明一切正常,已成功执行算子。 (2)三角…

基于Go语言的三甲医院人机与智能体协同环境系统(上.文章部分)

一、引言 1.1 研究背景与意义 1.1.1 三甲医院对高效协同系统的需求 三甲医院作为医疗体系的核心力量,承担着疑难病症诊治、医学科研教学等重要任务,其业务具有高度的复杂性。在日常运营中,三甲医院涉及多个科室,每个科室又包含众多专业领域,各科室之间需要紧密协作,共…

js笔记(黑马程序员)

(Web APIs day4) 一、日期对象 1.实例化 在代码中发现了 new 关键字时,一般将这个操作称为实例化 创建一个时间对象并获取时间// 1.得到当前时间 2.日期对象方法 因为日期对象返回的数据我们不能直接使用,所以需…

SOME/IP--协议英文原文讲解2

前言 SOME/IP协议越来越多的用于汽车电子行业中,关于协议详细完全的中文资料却没有,所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块: 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 4.1 Speci…

python-leetcode-反转链表 II

92. 反转链表 II - 力扣(LeetCode) # Definition for singly-linked list. # class ListNode: # def __init__(self, val0, nextNone): # self.val val # self.next next class Solution:def reverseBetween(self, head: Optional…