Elasticsearch向量检索需要的数据集以及768维向量生成

Elasticsearch8.17.0在mac上的安装

Kibana8.17.0在mac上的安装

Elasticsearch检索方案之一:使用from+size实现分页

快速掌握Elasticsearch检索之二:滚动查询(scrool)获取全量数据(golang)

Elasticsearch检索之三:官方推荐方案search_after检索实现(golang)

1、面临的首要问题

对于elasticsearch的向量检索的学习,我打算做一个图片检索的方案,图片检索在自动驾驶、ai识图、搜索都有广泛的应用,因此就借着学习elasticsearch的机会,设计一个mvp版本的图像搜索方案,以供有需要的各位小伙伴参考。

在学习向量检索之前,数据是基石,从哪里找上几千张图片,而且还有有一定的代表性,又如何将这些图片转化成向量,都是首先要解决的问题。

2、寻找数据集

12月中旬去阿里参加了elastic的线下meetup,当时阿里同学分享了一个向量测试的性能数据,我对这个数据印象非常深刻,于是在问答环节,请教了这个性能数据测试使用了多大的数据量,索引大小多少等问题,当时说到了一个数据集:ANN_GIST1M 960维,我们可以从这里下载到它:

http://corpus-texmex.irisa.fr/

下载解压后:

这些文件数据,需要使用matlab读取,咱也不太懂,还是找找图片的吧,再用模型跑一下就能出向量。

之后搜索了一些公开的图片数据集,找到了一个小猫、小狗数据集,这个挺有意思,小猫1000张图片,小狗1000张图片,除了训练集还有200张评测集,就用它了,我将数据集上传到了github上,点击查看icon-default.png?t=O83Ahttps://github.com/liupengh3c/career/tree/main/cats_and_dogs_v2需要的同学可以自取。

 这样数据集的问题就解决了,接下来解决抽取图像特征的问题。

3、寻找开源模型,抽取图像特征

本想着网上找个免费的api,输入图片,返回图片768维的特征向量,最后没有找到,只好求助于团队内算法同学,他给推荐了一个openai的开源模型:

https://hf-mirror.com/openai/clip-vit-large-patch14/tree/main

这里所有的文件都需要下载下来:

并汇总放到一个文件夹下,之后编写python代码,用此模型抽取图片特征:

import torch
from PIL import Image
from transformers import CLIPProcessor, CLIPModel
import numpy as np
# 加载预训练的CLIP模型和处理器
model = CLIPModel.from_pretrained("/Users/liupeng/Downloads/clip-vit-large-patch14")
processor = CLIPProcessor.from_pretrained("/Users/liupeng/Downloads/clip-vit-large-patch14")
# 加载图像并进行预处理
image = Image.open("/Users/liupeng/Downloads/dog.11001.jpg")  # 替换为你的图像路径
inputs = processor(images=image, return_tensors="pt")
# 提取图像特征
with torch.no_grad():
    image_features = model.get_image_features(**inputs)
print("shape:",image_features.shape)
# 对图像特征进行 L2 归一化
# 使用 .norm() 计算 L2 范数并进行归一化
image_features_normalized = image_features / image_features.norm(p=2, dim=-1, keepdim=True)
numpy_array = image_features_normalized.numpy()
# 打印归一化后的特征和特征的模长(应该为 1)
print("归一化后的图像特征:", numpy_array[0])
print("归一化后的模长:", image_features_normalized.norm(p=2, dim=-1))  # 应该接近 1

上面代码实现了单张图片特征提取,后面根据需求再完善。

4、向量索引设计

向量检索,最大的机器瓶颈就是内存,因此我们在设计索引时,应该最大限度的保证内存的占用最低,即使牺牲掉部分精度。

而检索算法:KNN(最近邻检索),它的原理是:计算待查询向量与数据库中所有向量之间的距离,然后按照距离从小到大排序,选择距离最近的 K 个向量作为查询结果。KNN 算法的优点是可以保证精确的结果,但是效率较低,不是elastic的默认检索算法,大家可以参考这篇文章:

ElasticSearch向量检索技术方案介绍,

为了提升向量检索的效率、降低机器内存占用,elastic采用HNSW算法支持向量检索,HNSW是一种近似紧邻检索,牺牲了一定的精度,但是大大提升了检索的效率。

对于向量索引,我们只设计3个字段:

name:本张图片小动物名称,猫or狗
IFV:本章图片向量
path:图片路径或地址

其中检索算法采用hnsw,并使用int8量化,以减少内存占用,这样会牺牲一定的精度,同时磁盘占用量会增加25%左右,向量距离计算逻辑为欧氏距离: 

PUT /vector_search_202412
{
    "mappings": {
        "properties": {
            "name": {
                "type": "keyword",
                "ignore_above": 256
            },
            "path": {
                "type": "keyword",
                "ignore_above": 256
            },
            "IFV": {
                "type": "dense_vector",
                "index": true,
                "dims": 768,
                "similarity": "l2_norm",
                "index_options": {
                    "type": "int8_hnsw"
                }
            }
        }
    }
}

5、全部数据集抽取特征并入库

首先调整我们抽取特征脚本,增加遍历文件夹所有图片+写入es部分:

import torch
from PIL import Image
from transformers import CLIPProcessor, CLIPModel
import numpy as np
import os
from elasticsearch import Elasticsearch, helpers
# Elasticsearch服务器地址和端口
host = 'https://localhost:9200'
# 用户名和密码
username = 'elastic'
password = 'xpE4DQGWE9bCkoj7WXYE'
 
# 创建Elasticsearch客户端实例,并提供用户名和密码
es = Elasticsearch(hosts=[host], http_auth=(username, password), verify_certs=False,ca_certs="/Users/liupeng/Documents/study/elasticsearch-8.17.0/config/certs/http_ca.crt")
# 检查连接是否成功
if not es.ping():
    print("无法连接到Elasticsearch")
    exit()
else:
    print("成功连接到Elasticsearch")
# 现在你可以使用es变量来与Elasticsearch进行交互了
# 加载预训练的CLIP模型和处理器
model = CLIPModel.from_pretrained("/Users/liupeng/Documents/career/clip-vit-large-patch14")
processor = CLIPProcessor.from_pretrained("/Users/liupeng/Documents/career/clip-vit-large-patch14")
# 加载图像并进行预处理
# folder = "/Users/liupeng/Documents/career/cats_and_dogs_v2/train/cats"
folder = "/Users/liupeng/Documents/career/cats_and_dogs_v2/train/dogs"
for root, dirs, files in os.walk(folder):
    index_id = 1000
    for file in files:
        index_id += 1
        print(os.path.join(root, file))
        image = Image.open(os.path.join(root, file))  
        inputs = processor(images=image, return_tensors="pt")
        # 提取图像特征
        with torch.no_grad():
            image_features = model.get_image_features(**inputs)
        print("shape:",image_features.shape)
        # 对图像特征进行 L2 归一化
        # 使用 .norm() 计算 L2 范数并进行归一化
        image_features_normalized = image_features / image_features.norm(p=2, dim=-1, keepdim=True)
        numpy_array = image_features_normalized.numpy()
        # 打印归一化后的特征和特征的模长(应该为 1)
        # print("归一化后的图像特征:", numpy_array[0])
        # print("归一化后的模长:", image_features_normalized.norm(p=2, dim=-1))  # 应该接近 1
        documents = [
            {"name": "cat_"+str(index_id), "IFV": numpy_array[0].tolist(),"path":file},
        ]
        helpers.bulk(es, [
            {
                "_index": "vector_search_202412",
                "_id": index_id,
                "_source": doc
            }
            for doc in documents
        ])

上面代码,由于数据集中小猫和小狗是两个不同的文件夹,所以需要跑2次,小猫和小狗各一次。

同时代码都已上传到github上: 

https://github.com/liupengh3c/career/blob/main/features/main.py

推理过程很耗费资源,mac的风扇呼呼的转呀。

占用的空间大小35M:

 到这里向量数据就全部入库完成了。

新的一年。就让我们对过去所有开心的事做个总结,对不开心的所有事也做个了结,微笑着迎接属于我们所有人的2025年,祝我可爱的小伙伴们新年快乐。 

天亮了,去跑个20.25km迎接新一年的到来~~~~~~~~~~~~~

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网关的主要作用

在网络安全领域,网关扮演着举足轻重的角色,它不仅是网络间的桥梁,更是安全防线的守护者。以下是网关在网络安全中的几个关键作用: 1. 防火墙功能:网关常常集成了防火墙技术,能够对进出网络的数据包进行严格…

【Cocos TypeScript 零基础 4.1】

目录 背景滚动 背景滚动 创建一个 空节点 背景丟进去 ( 复制一个,再丢一次都行) 新建TS脚本 并绑定到 空节点 上 再对TS脚本进行编辑 export class TS2bg extends Component {property (Node) // 通过属性面板去赋值bg1:Node nullproperty (Node) bg2:Node nullprope…

如何利用群晖NAS实现远程访问你的网页版Linux虚拟桌面环境

文章目录 前言1. 下载Docker-Webtop镜像2. 运行Docker-Webtop镜像3. 本地访问网页版Linux系统4. 群晖NAS安装Cpolar工具5. 配置异地访问Linux系统6. 异地远程访问Linux系统7. 固定异地访问的公网地址 前言 今天我要给大家介绍一下如何在群晖NAS设备上部署Docker-Webtop&#x…

MySQL 04 章——运算符

一、算数运算符 算数运算符主要用于数学运算,其可以连接运算符前后的两个数值或表达式 运算符名称作用示例加法运算符计算两个值或表达式的和SELECT AB-减法运算符计算两个值或表达式的差SELECT A-B*乘法运算符计算两个值或表达式的乘积SELECT A*B/或DIV除法运算符…

ES IK分词器插件

前言 ES中默认了许多分词器,但是对中文的支持并不友好,IK分词器是一个专门为中文文本设计的分词工具,它不是ES的内置组件,而是一个需要单独安装和配置的插件。 Ik分词器的下载安装(Winows 版本) 下载地址:…

Oracle DG备库数据文件损坏修复方法(ORA-01578/ORA-01110)

今天负责报表的同事反馈在DG库查询时出现如下报错 ORA-01578:ORACLE数据块损坏(文件号6,块号 2494856)ORA-01110:数据文件6: /oradata/PMSDG/o1 mf users_molczgmn_.dbfORA-26040:数据块是使用 NOLOGGING 选项加载的 可以看到报错是数据文件损坏,提示了file id和b…

idea无法安装插件

目录 修改工具配置 本地安装 无法下载很多时候就是延迟太高导致的,我们先打开插件官网看一下 Python - IntelliJ IDEs Plugin | Marketplace 修改工具配置 1、配置代理(点击 setting-点击 plugins-在点击 http proxy Settings) 输入&…

Linux部署web项目【保姆级别详解,Ubuntu,mysql8.0,tomcat9,jdk8 附有图文】

文章目录 部署项目一.安装jdk1.1 官网下载jdk81.2 上传到Linux1.3 解压1.4 配置环境变量1.5 查看是jdk是否安装成功 二.安装TomCat2.1 官网下载2.2 上传到Linux2.3 解压2.4配置2.5 启动Tomcat2.6 验证是否成功 三.安装mysql四.部署javaweb项目4.1 打包4.2 启动tomcat 部署项目 …

服务器等保测评日志策略配置

操作系统日志 /var/log/message 系统启动后的信息和错误日志,是Red Hat Linux中最常用的日志之一 /var/log/secure 与安全相关的日志信息 /var/log/maillog 与邮件相关的日志信息 /var/log/cron 与定时任务相关的日志信息 /var/log/spooler 与UUCP和news设备相关的…

初学stm32 --- FSMC驱动LCD屏

目录 FSMC简介 FSMC框图介绍 FSMC通信引脚介绍 FSMC_NWE 的作用 FSMC_NWE 的时序关系 FSMC_NOE 的含义 FSMC_NOE 的典型用途 FSMC_NOE 的时序关系 使用FSMC驱动LCD FSMC时序介绍 时序特性中的 OE ILI9341重点时序: FSMC地址映射 HADDR与FSMC_A关系 LCD的…

业务模型与UI设计

业务数据模型的设计、UI设计这应该是程序设计中不可缺少的部分。做程序设计的前提应该先把这两块设计好,那么,来一个实际案例,看看这2块的内容。 汽车保养记录业务模型与UI设计: 一、【车辆清单】 记录车辆相关的数据&#xff0…

【JavaScript】变量-常量-数据类型-类型转换

目录 一、JavaScript 介绍 1. JavaScript (是什么?) 2. 作用(做什么?) 3. JavaScript的组成(有什么?) 3.1 ECMAScript: 3.2 Web APIs : 总结: 4. Jav…

day30-awk精讲

awk其实不仅仅是工具软件,还是一种编程语言。 不过,本文只介绍它的命令行用法,对于大多数场合,应该足够用了。 awk是什么 awk是一个强大的linux命令,有强大的文本格式化的能力,好比将一些文本数据格式化…

实战设计模式之建造者模式

概述 在实际项目中,我们有时会遇到需要创建复杂对象的情况。这些对象可能包含多个组件或属性,而且每个组件都有自己的配置选项。如果直接使用构造函数或前面介绍的工厂方法来创建这样的对象,可能会导致以下两个严重问题。 1、参数过多。当一个…

滤波器的主要参数

为什么选择高阶: 滤波器的主要参数通常包括以下几个方面: 截止频率 (Cutoff Frequency): 这是滤波器能够有效通过或抑制信号的频率点。对于低通滤波器,信号低于截止频率的部分会被通过,高于截止频率的部分会被衰减。高…

HNSW概述

1. \textbf{1. } 1. 一些导论 1.1. \textbf{1.1. } 1.1. 朴素基于图的 ANN \textbf{ANN} ANN 1️⃣建图:对数据库中所有的点,构建 k -NN k\text{-NN} k-NN图(下图以 3 -NN 3\text{-NN} 3-NN为例) 2️⃣检索: GreedySearch \text{GreedySearch…

小程序学习07—— uniapp组件通信props和$emit和插槽语法

目录 一 父组件向子组件传递消息 1.1 props (a)传递静态或动态的 Prop (b)单向数据流 二 子组件通知父组件 2.1 $emit (a)定义自定义事件 (b)绑定自定义事件 三 插槽语法…

【视频笔记】基于PyTorch从零构建多模态(视觉)大模型 by Umar Jamil【持续更新】

视频链接: 基于PyTorch从零构建多模态(视觉)大模型 by Umar Jamil 从头编写一个视觉语言模型:PloyGamma,是谷歌的一个模型 1:原始图像 2:视觉编码器(本文是viT),通过对比学习进行训练。这个对比学习最开始是CLIP,后来被谷歌改成了SigLIP 3:线性投影层 4:如何将图…

UniApp | 从入门到精通:开启全平台开发的大门

UniApp | 从入门到精通:开启全平台开发的大门 一、前言二、Uniapp 基础入门2.1 什么是 Uniapp2.2 开发环境搭建三、Uniapp 核心语法与组件3.1 模板语法3.2 组件使用四、页面路由与导航4.1 路由配置4.2 导航方法五、数据请求与处理5.1 发起请求5.2 数据缓存六、样式与布局6.1 样…

《数据结构》期末考试测试题【中】

《数据结构》期末考试测试题【中】 21.循环队列队空的判断条件为?22. 单链表的存储密度比1?23.单链表的那些操作的效率受链表长度的影响?24.顺序表中某元素的地址为?25.m叉树第K层的结点数为?26. 在双向循环链表某节点…