使用 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,一经查实,立即删除!

相关文章

深入理解三高架构:高可用性、高性能、高扩展性的最佳实践

引言 在现代互联网环境下,随着用户规模和业务需求的快速增长,系统架构的设计变得尤为重要。为了确保系统能够在高负载和复杂场景下稳定运行,"三高架构"(高可用性、高性能、高扩展性)成为技术架构设计中的核…

Nginx 开发总结

文章目录 1. Nginx 基础概念1-1、什么是 Nginx1-2、Nginx 的工作原理1-3、Nginx 的核心特点1-4、Nginx 的常见应用场景1-5、Nginx 与 Apache 的区别1-6、 Nginx 配置的基本结构1-7、Nginx 常见指令 2. Nginx 配置基础2-1、Nginx 配置文件结构2-2、全局配置 (Global Block)2-3、…

Git 出现 Please use your personal access token instead of the password 解决方法

目录 前言1. 问题所示2. 原理分析3. 解决方法前言 1. 问题所示 执行Git提交代码的时候,出现如下所示: lixiaosong@IT07 MINGW64 /f/java_project/JavaDemo (master) $ git push -u origin --all libpng warning: iCCP: known incorrect sRGB profile libpng warning

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)。接下来,我…

LeetCode 0219.存在重复元素 II:哈希表

【LetMeFly】219.存在重复元素 II:哈希表 力扣题目链接:https://leetcode.cn/problems/contains-duplicate-ii/ 给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 i 和 j ,满足 nums[i] nums[j] 且 abs…

Android车机DIY开发之学习篇(七)NDK交叉工具构建

Android车机DIY开发之学习篇(七)NDK交叉工具构建 1.ubuntu安装GCC sudo apt-get update sudo apt-get install gcc g sudo gcc --version sudo g --version 2.测试GCC VSCODE中新建Hello.c编译 #include <stdio.h> int main(void) { printf(“Hello, this is a progr…

前端性能优化:HMR热更新和预获取加载

最近发现项目开发&#xff0c;有点加载快&#xff0c;有点却是卡机式&#xff0c;甚至刷新导致白屏情况。于是&#xff0c;我找开发和性能优化的方法&#xff0c;找到下面几种。 本文将深入探讨 预获取&#xff08;Prefetch&#xff09;、动态导入&#xff08;Dynamic Import&…

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

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

升级到Mac15.1后pod install报错

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

C语言中的函数有哪些种类型

在C语言中&#xff0c;函数可以根据多种方式进行分类。以下是一些常见的函数类型及其解释&#xff1a; 一、根据定义来源分类 库函数 也称为标准函数&#xff0c;由C标准库或其他库提供。用户无需定义&#xff0c;可直接使用&#xff0c;只需在程序前包含函数的原型声明的头文…

寻找两个正序数组的中位数:分治法与二分查找的结合

寻找两个正序数组的中位数&#xff1a;分治法与二分查找的结合 在算法领域&#xff0c;“寻找两个正序数组的中位数” 是一道经典的高频面试题&#xff08;LeetCode 第 4 题&#xff09;。它不仅考察基本的数组操作&#xff0c;还涉及二分查找与分治思想的结合。今天&#xff…

STM32 PWM驱动舵机

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

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

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

基于STM32的智能语音控制灯光系统设计

目录 引言系统设计 硬件设计软件设计 系统功能模块 语音识别模块灯光控制模块模式切换与场景管理模块用户交互与显示模块远程控制与数据上传模块 控制算法 语音识别与命令解析算法灯光强度与颜色调节算法数据记录与远程反馈算法 代码实现 语音识别与灯光控制代码场景模式与定时…

【NLP251】NLP RNN 系列网络

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

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

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

小智 AI 聊天机器人

小智 AI 聊天机器人 &#xff08;XiaoZhi AI Chatbot&#xff09; &#x1f449;参考源项目复现 &#x1f449; ESP32SenseVoiceQwen72B打造你的AI聊天伴侣&#xff01;【bilibili】 &#x1f449; 手工打造你的 AI 女友&#xff0c;新手入门教程【bilibili】 项目目的 本…