Elasticsearch:如何在 Elastic 中实现图片相似度搜索

news2024/11/26 18:24:31

作者:Radovan Ondas

在本文章,我们将了解如何通过几个步骤在 Elastic 中实施相似图像搜索。 开始设置应用程序环境,然后导入 NLP 模型,最后完成为你的图像集生成嵌入。

Elastic 图像相似性搜索概览 >>

如何设置环境

第一步是为你的应用程序设置环境。 一般要求包括:

  • Git
  • Python 3.9
  • Docker
  • 数百张图片

使用数百张图像以确保获得最佳效果非常重要。

转到工作文件夹并检查创建的存储库代码。 然后导航到存储库文件夹。

git clone https://github.com/radoondas/flask-elastic-image-search.git
cd flask-elastic-image-search
$ git clone https://github.com/radoondas/flask-elastic-image-search.git
Cloning into 'flask-elastic-image-search'...
remote: Enumerating objects: 105, done.
remote: Counting objects: 100% (105/105), done.
remote: Compressing objects: 100% (72/72), done.
remote: Total 105 (delta 37), reused 94 (delta 27), pack-reused 0
Receiving objects: 100% (105/105), 20.72 MiB | 9.75 MiB/s, done.
Resolving deltas: 100% (37/37), done.
$ cd flask-elastic-image-search/
$ pwd
/Users/liuxg/python/flask-elastic-image-search

因为你将使用 Python 来运行代码,所以你需要确保满足所有要求并且环境已准备就绪。 现在创建虚拟环境并安装所有依赖项。

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

安装

如果你还没有安装好自己的 Elasticsearch 及 Kibana,请参考如下的文章来进行安装:

  • 如何在 Linux,MacOS 及 Windows 上进行安装 Elasticsearch

  • Kibana:如何在 Linux,MacOS 及 Windows 上安装 Elastic 栈中的 Kibana

特别注意的是:我们将以最新的 Elastic Stack 8.6.1 来进行展示。请参考 Elastic Stack 8.x 的文章进行安装。

启动白金版试用功能

由于上传模型是一个白金版的功能,我们需要启动试用功能。更多关于订阅的信息,请参考网址:订阅 | Elastic Stack 产品和支持 | Elastic。

这样我们就成功地启动了白金版试用功能。 

Elasticsearch 集群和嵌入模型

登录到你的帐户以启动 Elasticsearch 集群。 设置一个小型集群:

  • 一个具有 2GB 内存的 HOT 节点
  • 一个具有 4GB 内存的 ML(机器学习)节点(此节点的大小很重要,因为你将导入 Elasticsearch 的 NLP 模型会消耗约 1.5GB 的内存。)

部署准备就绪后,转到 Kibana 并检查机器学习节点的容量。 你将在视图中看到一个机器学习节点。 目前没有加载模型。

使用 Eland 库从 OpenAI 上传 CLIP 嵌入模型。 Eland 是一个 Python Elasticsearch 客户端,用于在 Elasticsearch 中探索和分析数据,能够处理文本和图像。 您将使用此模型从文本输入生成嵌入并查询匹配图像。 在 Eland 库的文档中找到更多详细信息。

对于下一步,你将需要 Elasticsearch 端点。 你可以从部署详细信息部分的 Elasticsearch 云控制台获取它。

 

在本示例中,我们将使用本地部署来进行展示,所以,我们并不必要完成上面的步骤。

Eland

Eland 可以通过 pip 从 PyPI 安装。在安装之前,我们需要安装好自己的 Python。

$ python --version
Python 3.10.2

可以使用 Pip 从 PyPI 安装 Eland:

python -m pip install eland

也可以使用 Conda 从 Conda Forge 安装 Eland:

conda install -c conda-forge eland

希望在不安装 Eland 的情况下使用它的用户,为了只运行可用的脚本,可以构建 Docker 容器:

git clone https://github.com/elastic/eland
cd eland
docker build -t elastic/eland .

Eland 将 Hugging Face 转换器模型到其 TorchScript 表示的转换和分块过程封装在一个 Python 方法中; 因此,这是推荐的导入方法。

  1. 安装 Eland Python 客户端。
  2. 运行 eland_import_hub_model 脚本。 例如:
eland_import_hub_model --url <clusterUrl> \ 
--hub-model-id elastic/distilbert-base-cased-finetuned-conll03-english \ 
--task-type ner 
  • 指定 URL 以访问你的集群。 例如,https://<user>:<password>@<hostname>:<port>。
  • 在 Hugging Face 模型中心中指定模型的标识符。
  • 指定 NLP 任务的类型。 支持的值为 fill_mask、ner、text_classification、text_embedding, question_answering 和 zero_shot_classification。

上传模型

我们使用如下的命令来进行上传模型:

eland_import_hub_model --url https://<user>:<password>@<hostname>:<port> \
  --hub-model-id sentence-transformers/clip-ViT-B-32-multilingual-v1 \
  --task-type text_embedding \
  --ca-certs <your certificate> \
  --start

针对我的情况:

eland_import_hub_model --url https://elastic:ZgzSt2vHNwA6yPn-fllr@localhost:9200 \
  --hub-model-id sentence-transformers/clip-ViT-B-32-multilingual-v1 \
  --task-type text_embedding \
  --ca-certs /Users/liuxg/elastic/elasticsearch-8.6.1/config/certs/http_ca.crt \
  --start

请注意: 你需要根据自己的 Elasticsearch 访问端点,用户名及密码来修改上面的设置,同时你需要根据自己的配置修改上面的证书路径。

运行上面的命令:

上面显示,我们已经成功地上传了模型。我们可以到 Kibana 中进行查看:

 

 

 

上面显示我们已经上传了所需要的 CLIP 模型,并且它的状态是 started。

如何创建图像嵌入

在设置 Elasticsearch 集群并导入嵌入模型后,你需要矢量化图像数据并为数据集中的每个图像创建图像嵌入。 

 

要创建图像嵌入,请使用简单的 Python 脚本。 你可以在此处找到该脚本:create-image-embeddings.py。 该脚本将遍历你的图像目录并生成单独的图像嵌入。 它将使用名称和相对路径创建文档,并使用提供的映射将其保存到 Elasticsearch 索引 my-image-embeddings 中。

将所有图像(照片)放入文件夹 app/static/images。 使用带有子文件夹的目录结构来组织图像。 所有图像准备就绪后,使用几个参数执行脚本。

至少要有几百张图像才能获得合理的结果,这一点至关重要。 图像太少不会产生预期的结果,因为你要搜索的空间非常小,而且到搜索向量的距离也非常相似。我尝试在网上下载很多的照片,但是感觉一张一张地下载非常麻烦。你可以在谷歌浏览器中添加插件 Image downloader - Imageye。它可以方便地把很多照片一次下载下来。

在 image_embeddings 文件夹中,运行脚本并为变量使用你的值。

cd image_embeddings
python3 create-image-embeddings.py \
  --es_host='https://localhost:9200' \
  --es_user='elastic' --es_password='ZgzSt2vHNwA6yPn-fllr' \
  --ca_certs='/Users/liuxg/elastic/elasticsearch-8.6.1/config/certs/http_ca.crt'

根据图像的数量、它们的大小、你的 CPU 和你的网络连接,此任务将需要一些时间。 在尝试处理完整数据集之前,先试验少量图像。脚本完成后,吧可以使用 Kibana 开发工具验证索引 my-image-embeddings 是否存在并具有相应的文档。

我们在Kibana 中进行查看:

GET _cat/indices/my-image-embeddings?v

 上面命令的响应为:

health status index               uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   my-image-embeddings h6oUBdHCScWmXOZaf57oWg   1   1        145            0      1.4mb          1.4mb

查看文档,你会看到非常相似的 JSON 对象(如示例)。 你将在图像文件夹中看到图像名称、图像 ID 和相对路径。 此路径用于前端应用程序以在搜索时正确显示图像。JSON 文档中最重要的部分是包含 CLIP 模型生成的密集矢量的 image_embedding。 当应用程序正在搜索图像或类似图像时使用此矢量。

GET my-image-embeddings/_search
{
   "_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"
   }
}

使用 Flask 应用程序搜索图像

现在你的环境已全部设置完毕,你可以进行下一步,使用我们作为概念证明提供的 Flask 应用程序,使用自然语言实际搜索图像并查找相似图像。 该 Web 应用程序具有简单的 UI,使图像搜索变得简单。 你可以在此 GitHub 存储库中访问原型 Flask 应用程序。

后台应用程序执行两个任务。 在搜索框中输入搜索字符串后,文本将使用机器学习 _infer 端点进行矢量化。 然后,针对带有向量的索引 my-image-embeddings 执行带有密集向量的查询。

你可以在示例中看到这两个查询。 第一个 API 调用使用 _infer 端点,结果是一个密集矢量。

POST _ml/trained_models/sentence-transformers__clip-vit-b-32-multilingual-v1/_infer
{
  "docs" : [
    {"text_field": "Yellow mountain is the most beautiful mountain in China"}
    ]
}

上面的响应如下:

在第二个任务中,搜索查询,我们将使用密集矢量并获得按分数排序的图像。 

GET my-image-embeddings/_search
{
  "fields": [
    "image_id",
    "image_name",
    "relative_path"
  ],
  "_source": false,
  "knn": {
    "field": "image_embedding",
    "k": 5,
    "num_candidates": 10,
    "query_vector": [
        0.03395160660147667,
        0.007704082876443863,
        0.14996188879013062,
        -0.10693030804395676,
        ...
        0.05140634626150131,
        0.07114913314580917
   ]
  }
}

要启动并运行 Flask 应用程序,请导航到存储库的根文件夹并配置 .env 文件。 配置文件中的值用于连接到 Elasticsearch 集群。 你需要为以下变量插入值。 这些与图像嵌入生成中使用的值相同。 

.env

ES_HOST='URL:PORT'
ES_USER='elastic'
ES_PWD='password'

为了能够使得我们自构建的 Elasticsearch 集群能够被正确地访问,我们必须把 Elasticsearch 的根证书拷贝到 Flask 应用的相应目录中:

flask-elastic-image-search/app/conf/ca.crt

(.venv) $ pwd
/Users/liuxg/python/flask-elastic-image-search/app/conf
(.venv) $ cp ~/elastic/elasticsearch-8.6.1/config/certs/http_ca.crt ca.crt
overwrite ca.crt? (y/n [n]) y

在上面,我们替换了仓库中原有的证书文件 ca.crt。

准备就绪后,运行主文件夹中的 flask 应用程序并等待它启动。

# In the main directory 
$ flask run --port=5001

如果应用程序启动,你将看到类似于下面的输出,它在末尾指示你需要访问哪个 URL 才能访问该应用程序。

恭喜! 你的应用程序现在应该已启动并正在运行,并且可以通过互联网浏览器在 http://127.0.0.1:5001 上访问。

导航到图像搜索选项卡并输入描述你最佳图像的文本。 尝试使用非关键字或描述性文字。

在下面的示例中,输入的文本是 “Yellow mountain is the most beautiful mountain in China”。 结果显示在我们的数据集中。 如果用户喜欢结果集中的一张特定图像,只需单击它旁边的按钮,就会显示类似的图像。 用户可以无限次地这样做,并通过图像数据集构建自己的路径。

 

我们尝试另外的一个例子。这次我们输入:I love beautiful girls。

搜索也可以通过简单地上传图像来进行。 该应用程序会将图像转换为矢量并在数据集中搜索相似的图像。 为此,导航到第三个选项卡 “Similar Image”,从磁盘上传图像,然后点击 “Search”。

我们可以看到相似的图片。我们尝试使用一个女孩的照片再试试:

 

因为我们在 Elasticsearch 中使用的 NLP(sentence-transformers/clip-ViT-B-32-multilingual-v1)模型是多语言的,支持多语言推理,所以尽量搜索自己语言的图片。 然后也使用英文文本验证结果。我们尝试使用 “黄山是中国最漂亮的山”:

 

请务必注意,使用的模型是通用模型,这些模型非常准确,但你获得的结果会因用例或其他因素而异。 如果你需要更高的精度,则必须采用通用模型或开发自己的模型 —— CLIP 模型只是一个起点。

 

代码摘要

你可以在 GitHub 存储库中找到完整的代码。 你可能正在检查 routes.py 中的代码,它实现了应用程序的主要逻辑。 除了明显的路线定义之外,你还应该关注定义 _infer 和 _search 端点(infer_trained_modelknn_search_images)的方法。 生成图像嵌入的代码位于 create-image-embeddings.py文件中。

总结

现在你已经设置了 Flask 应用程序,你可以轻松地搜索你自己的图像集! Elastic 在平台内提供了矢量搜索的原生集成,避免了与外部进程的通信。 你可以灵活地开发和使用你可能使用 PyTorch 开发的自定义嵌入模型。

语义图像搜索具有其他传统图像搜索方法的以下优点:

  • 更高的准确度:向量相似性捕获上下文和关联,而不依赖于图像的文本元描述。
  • 增强的用户体验:与猜测哪些关键字可能相关相比,描述你正在寻找的内容或提供示例图像。
  • 图像数据库的分类:不用担心对图像进行分类——相似性搜索可以在一堆图像中找到相关图像,而无需对它们进行组织。

如果你的用例更多地依赖于文本数据,你可以在以前的博客中了解更多关于实现语义搜索和将自然语言处理应用于文本的信息。 对于文本数据,向量相似度与传统关键词评分的结合呈现了两全其美的效果。

准备好开始了吗? 在我们的虚拟活动中心报名参加矢量搜索实践研讨会,并在我们的在线论坛中与社区互动。

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

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

相关文章

【11】linux命令每日分享——useradd添加用户

大家好&#xff0c;这里是sdust-vrlab&#xff0c;Linux是一种免费使用和自由传播的类UNIX操作系统&#xff0c;Linux的基本思想有两点&#xff1a;一切都是文件&#xff1b;每个文件都有确定的用途&#xff1b;linux涉及到IT行业的方方面面&#xff0c;在我们日常的学习中&…

网页全屏截图、在线截图API

在我们的数字时代&#xff0c;网页截图已经成为了一个非常常见的需求&#xff0c;无论是为了记录网页信息、保存重要信息或是与他人分享自己看到的内容&#xff0c;截图工具都是必不可少的。今天&#xff0c;我想向大家推荐一个非常好用的在线网页全屏截图工具&#xff0c;它的…

获取html元素相对屏幕的位置

1. 写在前面 Javascript 由三部分构成&#xff0c;ECMAScript&#xff0c;DOM和BOM。 ECMAScript(核心)   描述了JS的语法和基本对象 Bom:(browser object model&#xff09;&#xff1b;浏览器对象模型&#xff0c;提供一些属性和方法可以操作浏览器&#xff0c;浏览器可…

【spring】Spring Data --Spring Data JPA

Spring Data 的委托是为数据访问提供熟悉且符合 Spring 的编程模型&#xff0c;同时仍保留着相关数据存储的特​​殊特征。 它使使用数据访问技术、关系和非关系数据库、map-reduce 框架和基于云的数据服务变得容易。这是一个伞形项目&#xff0c;其中包含许多特定于给定数据库…

详述java的设计模式(二)

1.工厂模式 简单工厂模式&#xff08;Simple Factory Pattern&#xff09;属于创建型模式&#xff0c;是指由一个工厂类根据传入的参数&#xff0c;动态决定应该创建哪一个产品类的对象&#xff0c;而被创建的对象通常都具有共同的父类或接口&#xff0c;这种模式又叫做静态工…

数据结构和算法学习

文章目录精通一个领域切题四件套算法算法的五个条件流程图数据结构数据与信息数据信息数据结构和算法数据结构算法时间复杂度空间复杂度数组 Array优点缺点数组和链表的区别时间复杂度链表 Linked List优点缺点时间复杂度单向链表双向链表循环链表双向循环链表堆栈 Stack队列 Q…

涂鸦开发资源中心硬核上线!支持产物包可视化、自由裁剪开发框架等功能

开发过程对于程序猿们来说&#xff0c;就像建碉堡&#xff0c;碉堡的建成速度、创造力&#xff0c;以及精致和牢固程度&#xff0c;取决于工具称不称手。不称手的开发工具&#xff0c;不仅能让人心力交瘁&#xff0c;还会多掉几根头发。 为了帮助开发者获得更好的开发体验&…

【搞透C语言指针】那年我双手插兜, 不知道指针是我的对手

☃️内容专栏&#xff1a;【C语言】进阶部分 ☃️本文概括&#xff1a; 征服C语言指针&#xff01;一篇文章搞清楚指针的全部要点。 ☃️本文作者&#xff1a;花香碟自来_ ☃️发布时间&#xff1a;2023.3.3 目录 一、字符指针 二、指针数组 三、数组指针 1.数组指针的定义…

UML常见图的总结

一、概述 UML&#xff1a;Unified Modeling Language&#xff0c;统一建模语言&#xff0c;支持从需求分析开始的软件开发的全过程。是一个支持模型化和软件系统开发的图形化语言、为软件开发的所有阶段提供模型化和可视化支持&#xff0c;包括由需求分析到规格&#xff0c;到…

ESP32设备驱动-SHT11温度湿度传感器驱动

SHT11温度湿度传感器驱动 SHT1x 数字湿度传感器是一种可回流焊接的传感器。 SHT1x 系列包括带有 SHT10 湿度传感器的低成本版本、带有 SHT11 湿度传感器的标准版本和带有 SHT15 湿度传感器的高端版本。 与 SHTxx 湿度传感器系列中的所有其他 Sensirion 传感器类型一样,它们经…

H2数据库连接时用户密码错误:Wrong user name or password [28000-214] 28000/28000 (Help)

H2数据库连接时用户密码错误: 2023-03-03 08:25:07 database: wrong user or password; user: "SA" org.h2.message.DbException: Wrong user name or password [28000-214]出现的问题配置信息原因解决办法org.h2.message.DbException: Wrong user name or password …

Python从入门到转行,看完这一篇就够了

Python零基础入门 零基础入门就得从最基本的变量&#xff0c;语法格式&#xff0c;数据类型&#xff0c;函数&#xff0c;作用域&#xff0c;模块等基本知识入手&#xff08;有编程基础基础也得这么来&#xff09; 和篮球一样&#xff0c;先来三步上篮&#xff1a; Python基…

Spring Boot 分片上传、断点续传、大文件上传、秒传

文件上传是一个老生常谈的话题了&#xff0c;在文件相对比较小的情况下&#xff0c;可以直接把文件转化为字节流上传到服务器&#xff0c;但在文件比较大的情况下&#xff0c;用普通的方式进行上传&#xff0c;这可不是一个好的办法&#xff0c;毕竟很少有人会忍受&#xff0c;…

MySQL面试题-基础篇

目录 前言 数据库基础 1.什么是关系型数据库和非关系型数据库&#xff1f; 2.什么是 SQL&#xff1f; 3.MySQL 有什么优点&#xff1f; 4.MySQL 的基础架构? 存储引擎 1.MySQL 支持哪些存储引擎&#xff1f;默认使用哪个&#xff1f; 2.MySQL 存储引擎架构了解吗&…

C# IoC控制反转学习笔记

一、什么是IOC IoC-Invertion of Control&#xff0c;即控制反转&#xff0c;是一种程序设计思想。 先初步了解几个概念&#xff1a; 依赖&#xff08;Dependency&#xff09;&#xff1a;就是有联系&#xff0c;表示一个类依赖于另一个类。 依赖倒置原则&#xff08;DIP&a…

苹果ipa软件下载网站和软件的汇总

随着时间的流逝&#xff0c;做苹果版软件安装包下载网站和软件的渐渐多了起来。 当然&#xff0c;已经关站、停运、下架、倒闭的苹果软件下载网站和软件我就不说了&#xff0c;也不必多说那些关站停运下架倒闭的网站和软件了。 下面我统计介绍的就是苹果软件安装包下载网站和软…

系列十二、MySQL管理

一、系统数据库 Mysql数据库安装完成后&#xff0c;自带了一下四个数据库&#xff0c;具体作用如下&#xff1a;二、常用工具 2.1、mysql 2.1.1、概述 该mysql不是指mysql服务&#xff0c;而是指mysql的客户端工具。 2.1.2、语法 # 语法 &#xff1a; mysql [options] [dat…

分库分表、分库分表带来的问题

文章目录1.分库垂直分库水平分库2.分表垂直分表水平分表3.水平分表的路由方式&#xff08;1&#xff09;范围路由&#xff08;2&#xff09;Hash 路由4.分库分表带来的问题分库&#xff08;1&#xff09;事务的问题注意&#xff08;2&#xff09;跨库 JOIN 问题分表&#xff08…

k8s-故障转移 livenessProbe readinessProbe 学习总结

k8s-故障转移学习总结 大纲 概念K8S中Pod健康检查livenessProbe & readinessProbelivenessProbe 存活探测实例readinessProbe 就绪探测实例 概念 故障转移有哪些情况 物理机故障程序故障 在计算机术语中&#xff0c;故障转移&#xff08;英语&#xff1a;failover&am…

深入底层源码的Listener内存马(内存马系列篇三)

写在前面 继前面的FilterServlet内存马技术&#xff0c;这是系列文章的第三篇了&#xff0c;这篇将给大家带来的是Listener内存马技术。 前置 什么是Listener&#xff1f; 监听器 Listener 是一个实现特定接口的 Java 程序&#xff0c;这个程序专门用于监听另一个 Java 对象…