【深度学习】Chinese-CLIP 使用教程,图文检索,跨模态检索,零样本图片分类

代码:https://github.com/OFA-Sys/Chinese-CLIP/blob/master/deployment.md

文章目录

  • 安装环境和onnx推理
  • 转换所有模型为onnx
  • 测试所有onnx模型的脚本
  • onnx cpu方式执行
  • docker镜像

安装环境和onnx推理

安装环境,下载权重放置到指定目录,进行onnx转换:

conda create -n clip_cn python=3.8 -y
conda activate clip_cn
conda install pytorch==1.12.1 torchvision==0.13.1 torchaudio==0.12.1 cudatoolkit=11.6 -c pytorch -c conda-forge -y
conda install numpy tqdm six -y
conda install -c conda-forge timm -y
conda install -c anaconda lmdb==1.3.0 -ycd Chinese-CLIP
pip install -e .
mkdir DATAPATH
export CUDA_VISIBLE_DEVICES=0
export PYTHONPATH=${PYTHONPATH}:`pwd`/cn_clip
export DATAPATH="./DATAPATH"
checkpoint_path=${DATAPATH}/pretrained_weights/clip_cn_vit-b-16.pt # 指定要转换的ckpt完整路径
echo checkpoint_path
echo $checkpoint_path
mkdir -p ${DATAPATH}/deploy/ # 创建ONNX模型的输出文件夹
pip install onnx onnxruntime-gpu onnxmltools
python cn_clip/deploy/pytorch_to_onnx.py \--model-arch ViT-B-16 \--pytorch-ckpt-path ${checkpoint_path} \--save-onnx-path ${DATAPATH}/deploy/vit-b-16 \--convert-text --convert-vision

转换成功后:

Finished PyTorch to ONNX conversion...
>>> The text FP32 ONNX model is saved at ./DATAPATH/deploy/vit-b-16.txt.fp32.onnx
>>> The text FP16 ONNX model is saved at ./DATAPATH/deploy/vit-b-16.txt.fp16.onnx with extra file ./DATAPATH/deploy/vit-b-16.txt.fp16.onnx.extra_file
>>> The vision FP32 ONNX model is saved at ./DATAPATH/deploy/vit-b-16.img.fp32.onnx
>>> The vision FP16 ONNX model is saved at ./DATAPATH/deploy/vit-b-16.img.fp16.onnx with extra file ./DATAPATH/deploy/vit-b-16.img.fp16.onnx.extra_file

可以看到转换好的文件:
在这里插入图片描述

测试是否转换成功的python代码:

# 完成必要的import(下文省略)
import onnxruntime
from PIL import Image
import numpy as np
import torch
import argparse
import cn_clip.clip as clip
from clip import load_from_name, available_models
from clip.utils import _MODELS, _MODEL_INFO, _download, available_models, create_model, image_transform# 载入ONNX图像侧模型(**请替换${DATAPATH}为实际的路径**)
img_sess_options = onnxruntime.SessionOptions()
img_run_options = onnxruntime.RunOptions()
img_run_options.log_severity_level = 2
img_onnx_model_path="./DATAPATH/deploy/vit-b-16.img.fp16.onnx"
img_session = onnxruntime.InferenceSession(img_onnx_model_path,sess_options=img_sess_options,providers=["CUDAExecutionProvider"])# 预处理图片
model_arch = "ViT-B-16" # 这里我们使用的是ViT-B-16规模,其他规模请对应修改
preprocess = image_transform(_MODEL_INFO[model_arch]['input_resolution'])
# 示例皮卡丘图片,预处理后得到[1, 3, 分辨率, 分辨率]尺寸的Torch Tensor
image = preprocess(Image.open("examples/pokemon.jpeg")).unsqueeze(0)# 用ONNX模型计算图像侧特征
image_features = img_session.run(["unnorm_image_features"], {"image": image.cpu().numpy()})[0] # 未归一化的图像特征
image_features = torch.tensor(image_features)
image_features /= image_features.norm(dim=-1, keepdim=True) # 归一化后的Chinese-CLIP图像特征,用于下游任务
print(image_features.shape) # Torch Tensor shape: [1, 特征向量维度]# 载入ONNX文本侧模型(**请替换${DATAPATH}为实际的路径**)
txt_sess_options = onnxruntime.SessionOptions()
txt_run_options = onnxruntime.RunOptions()
txt_run_options.log_severity_level = 2
txt_onnx_model_path="./DATAPATH/deploy/vit-b-16.txt.fp16.onnx"
txt_session = onnxruntime.InferenceSession(txt_onnx_model_path,sess_options=txt_sess_options,providers=["CUDAExecutionProvider"])# 为4条输入文本进行分词。序列长度指定为52,需要和转换ONNX模型时保持一致(参见转换时的context-length参数)
text = clip.tokenize(["杰尼龟", "妙蛙种子", "小火龙", "皮卡丘"], context_length=52)# 用ONNX模型依次计算文本侧特征
text_features = []
for i in range(len(text)):one_text = np.expand_dims(text[i].cpu().numpy(),axis=0)text_feature = txt_session.run(["unnorm_text_features"], {"text":one_text})[0] # 未归一化的文本特征text_feature = torch.tensor(text_feature)text_features.append(text_feature)
text_features = torch.squeeze(torch.stack(text_features),dim=1) # 4个特征向量stack到一起
text_features = text_features / text_features.norm(dim=1, keepdim=True) # 归一化后的Chinese-CLIP文本特征,用于下游任务
print(text_features.shape) # Torch Tensor shape: [4, 特征向量维度]# 内积后softmax
# 注意在内积计算时,由于对比学习训练时有temperature的概念
# 需要乘上模型logit_scale.exp(),我们的预训练模型logit_scale均为4.6052,所以这里乘以100
# 对于用户自己的ckpt,请使用torch.load载入后,查看ckpt['state_dict']['module.logit_scale']或ckpt['state_dict']['logit_scale']
logits_per_image = 100 * image_features @ text_features.t()
print(logits_per_image.softmax(dim=-1)) # 图文相似概率: [[1.2252e-03, 5.2874e-02, 6.7116e-04, 9.4523e-01]]

转换所有模型为onnx

在这里插入图片描述

# ["RN50", "ViT-B-16", "ViT-L-14", "ViT-L-14-336", "ViT-H-14"]
checkpoint_path=${DATAPATH}/pretrained_weights/clip_cn_rn50.pt
python cn_clip/deploy/pytorch_to_onnx.py \--model-arch RN50 \--pytorch-ckpt-path ${checkpoint_path} \--save-onnx-path ${DATAPATH}/deploy/RN50 \--convert-text --convert-visioncheckpoint_path=${DATAPATH}/pretrained_weights/clip_cn_vit-b-16.pt
python cn_clip/deploy/pytorch_to_onnx.py \--model-arch ViT-B-16 \--pytorch-ckpt-path ${checkpoint_path} \--save-onnx-path ${DATAPATH}/deploy/ViT-B-16 \--convert-text --convert-visioncheckpoint_path=${DATAPATH}/pretrained_weights/clip_cn_vit-l-14.pt
python cn_clip/deploy/pytorch_to_onnx.py \--model-arch "ViT-L-14"\--pytorch-ckpt-path ${checkpoint_path} \--save-onnx-path ${DATAPATH}/deploy/ViT-L-14 \--convert-text --convert-visioncheckpoint_path=${DATAPATH}/pretrained_weights/clip_cn_vit-l-14-336.pt
python cn_clip/deploy/pytorch_to_onnx.py \--model-arch "ViT-L-14-336"\--pytorch-ckpt-path ${checkpoint_path} \--save-onnx-path ${DATAPATH}/deploy/ViT-L-14-336 \--convert-text --convert-visioncheckpoint_path=${DATAPATH}/pretrained_weights/clip_cn_vit-h-14.pt
python cn_clip/deploy/pytorch_to_onnx.py \--model-arch "ViT-H-14"\--pytorch-ckpt-path ${checkpoint_path} \--save-onnx-path ${DATAPATH}/deploy/ViT-H-14 \--convert-text --convert-vision

测试所有onnx模型的脚本

# 完成必要的import(下文省略)
import onnxruntime
from PIL import Image
import numpy as np
import torch
import argparse
import cn_clip.clip as clip
from clip import load_from_name, available_models
from clip.utils import _MODELS, _MODEL_INFO, _download, available_models, create_model, image_transformmodel_list=["RN50", "ViT-B-16", "ViT-L-14", "ViT-L-14-336", "ViT-H-14"]for model_name in model_list:print(model_name)# 载入ONNX图像侧模型(**请替换${DATAPATH}为实际的路径**)img_sess_options = onnxruntime.SessionOptions()img_run_options = onnxruntime.RunOptions()img_run_options.log_severity_level = 2img_onnx_model_path=f"./DATAPATH/deploy/{model_name}.img.fp16.onnx"img_session = onnxruntime.InferenceSession(img_onnx_model_path,sess_options=img_sess_options,providers=["CUDAExecutionProvider"])# 预处理图片model_arch = model_name # 这里我们使用的是ViT-B-16规模,其他规模请对应修改preprocess = image_transform(_MODEL_INFO[model_arch]['input_resolution'])# 示例皮卡丘图片,预处理后得到[1, 3, 分辨率, 分辨率]尺寸的Torch Tensorimage = preprocess(Image.open("examples/pokemon.jpeg")).unsqueeze(0)# 用ONNX模型计算图像侧特征image_features = img_session.run(["unnorm_image_features"], {"image": image.cpu().numpy()})[0] # 未归一化的图像特征image_features = torch.tensor(image_features)image_features /= image_features.norm(dim=-1, keepdim=True) # 归一化后的Chinese-CLIP图像特征,用于下游任务print(image_features.shape) # Torch Tensor shape: [1, 特征向量维度]# 载入ONNX文本侧模型(**请替换${DATAPATH}为实际的路径**)txt_sess_options = onnxruntime.SessionOptions()txt_run_options = onnxruntime.RunOptions()txt_run_options.log_severity_level = 2txt_onnx_model_path=f"./DATAPATH/deploy/{model_name}.txt.fp16.onnx"txt_session = onnxruntime.InferenceSession(txt_onnx_model_path,sess_options=txt_sess_options,providers=["CUDAExecutionProvider"])# 为4条输入文本进行分词。序列长度指定为52,需要和转换ONNX模型时保持一致(参见转换时的context-length参数)text = clip.tokenize(["杰尼龟", "妙蛙种子", "小火龙", "皮卡丘"], context_length=52)# 用ONNX模型依次计算文本侧特征text_features = []for i in range(len(text)):one_text = np.expand_dims(text[i].cpu().numpy(),axis=0)text_feature = txt_session.run(["unnorm_text_features"], {"text":one_text})[0] # 未归一化的文本特征text_feature = torch.tensor(text_feature)text_features.append(text_feature)text_features = torch.squeeze(torch.stack(text_features),dim=1) # 4个特征向量stack到一起text_features = text_features / text_features.norm(dim=1, keepdim=True) # 归一化后的Chinese-CLIP文本特征,用于下游任务print(text_features.shape) # Torch Tensor shape: [4, 特征向量维度]# 内积后softmax# 注意在内积计算时,由于对比学习训练时有temperature的概念# 需要乘上模型logit_scale.exp(),我们的预训练模型logit_scale均为4.6052,所以这里乘以100# 对于用户自己的ckpt,请使用torch.load载入后,查看ckpt['state_dict']['module.logit_scale']或ckpt['state_dict']['logit_scale']logits_per_image = 100 * image_features @ text_features.t()print(logits_per_image.softmax(dim=-1)) # 图文相似概率: [[1.2252e-03, 5.2874e-02, 6.7116e-04, 9.4523e-01]]

onnx cpu方式执行

环境:

conda create -n clip_cn_cpu python=3.8 -y
conda activate clip_cn_cpu
conda install pytorch==1.12.1 torchvision==0.13.1 torchaudio==0.12.1 cpuonly -c pytorch -y
conda install numpy tqdm six -y
conda install -c conda-forge timm -y
conda install -c anaconda lmdb==1.3.0 -y
cd Chinese-CLIP
pip install -e .
export PYTHONPATH=${PYTHONPATH}:`pwd`/cn_clip
pip install onnx onnxruntime onnxmltools

测试脚本:

# 完成必要的import(下文省略)
import onnxruntime
from PIL import Image
import numpy as np
import torch
import argparse
import cn_clip.clip as clip
from clip import load_from_name, available_models
from clip.utils import _MODELS, _MODEL_INFO, _download, available_models, create_model, image_transformmodel_list=["RN50", "ViT-B-16", "ViT-L-14", "ViT-L-14-336", "ViT-H-14"]for model_name in model_list:print(model_name)# 载入ONNX图像侧模型(**请替换${DATAPATH}为实际的路径**)img_sess_options = onnxruntime.SessionOptions()img_run_options = onnxruntime.RunOptions()img_run_options.log_severity_level = 2img_onnx_model_path=f"./DATAPATH/deploy/{model_name}.img.fp16.onnx"img_session = onnxruntime.InferenceSession(img_onnx_model_path,sess_options=img_sess_options,providers=["CPUExecutionProvider"])# 预处理图片model_arch = model_name # 这里我们使用的是ViT-B-16规模,其他规模请对应修改preprocess = image_transform(_MODEL_INFO[model_arch]['input_resolution'])# 示例皮卡丘图片,预处理后得到[1, 3, 分辨率, 分辨率]尺寸的Torch Tensorimage = preprocess(Image.open("examples/pokemon.jpeg")).unsqueeze(0)# 用ONNX模型计算图像侧特征image_features = img_session.run(["unnorm_image_features"], {"image": image.cpu().numpy()})[0] # 未归一化的图像特征image_features = torch.tensor(image_features)image_features /= image_features.norm(dim=-1, keepdim=True) # 归一化后的Chinese-CLIP图像特征,用于下游任务print(image_features.shape) # Torch Tensor shape: [1, 特征向量维度]# 载入ONNX文本侧模型(**请替换${DATAPATH}为实际的路径**)txt_sess_options = onnxruntime.SessionOptions()txt_run_options = onnxruntime.RunOptions()txt_run_options.log_severity_level = 2txt_onnx_model_path=f"./DATAPATH/deploy/{model_name}.txt.fp16.onnx"txt_session = onnxruntime.InferenceSession(txt_onnx_model_path,sess_options=txt_sess_options,providers=["CPUExecutionProvider"])# 为4条输入文本进行分词。序列长度指定为52,需要和转换ONNX模型时保持一致(参见转换时的context-length参数)text = clip.tokenize(["杰尼龟", "妙蛙种子", "小火龙", "皮卡丘"], context_length=52)# 用ONNX模型依次计算文本侧特征text_features = []for i in range(len(text)):one_text = np.expand_dims(text[i].cpu().numpy(),axis=0)text_feature = txt_session.run(["unnorm_text_features"], {"text":one_text})[0] # 未归一化的文本特征text_feature = torch.tensor(text_feature)text_features.append(text_feature)text_features = torch.squeeze(torch.stack(text_features),dim=1) # 4个特征向量stack到一起text_features = text_features / text_features.norm(dim=1, keepdim=True) # 归一化后的Chinese-CLIP文本特征,用于下游任务print(text_features.shape) # Torch Tensor shape: [4, 特征向量维度]# 内积后softmax# 注意在内积计算时,由于对比学习训练时有temperature的概念# 需要乘上模型logit_scale.exp(),我们的预训练模型logit_scale均为4.6052,所以这里乘以100# 对于用户自己的ckpt,请使用torch.load载入后,查看ckpt['state_dict']['module.logit_scale']或ckpt['state_dict']['logit_scale']logits_per_image = 100 * image_features @ text_features.t()print(logits_per_image.softmax(dim=-1)) # 图文相似概率: [[1.2252e-03, 5.2874e-02, 6.7116e-04, 9.4523e-01]]

docker镜像

dockerfile

FROM ubuntu:20.04
RUN apt-get update && apt-get install -y wget curl
RUN wget http://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/conda.sh && \bash /tmp/conda.sh -b && rm /tmp/conda.sh
WORKDIR /Chinese-CLIP/
COPY ./ /Chinese-CLIP/
RUN cp ./deps/.condarc /root/
ENV DEBIAN_FRONTEND=noninteractive
# 安装 tzdata 包并设置时区为上海(无交互)
RUN apt-get update && \apt-get install -y tzdata && \ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \echo "Asia/Shanghai" > /etc/timezone
RUN ~/miniconda3/bin/conda init bash && . ~/.bashrcRUN apt-get install -y python3-pipRUN . ~/.bashrc && pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simpleRUN . ~/.bashrc && conda create -n clip_cn_cpu python=3.8 -y &&  \conda activate clip_cn_cpu &&  \conda install pytorch==1.12.1 torchvision==0.13.1 torchaudio==0.12.1 cpuonly -c pytorch -y
RUN . ~/.bashrc && conda activate clip_cn_cpu && conda install numpy tqdm six -y
RUN . ~/.bashrc && conda activate clip_cn_cpu && conda install -c conda-forge timm -y
RUN . ~/.bashrc && conda activate clip_cn_cpu && pip install  lmdb==1.3.0
RUN . ~/.bashrc && conda activate clip_cn_cpu && pip install onnx onnxruntime onnxmltools fastapi uvicorn python-multipart
RUN . ~/.bashrc && conda activate clip_cn_cpu &&  cd /Chinese-CLIP && pip install -e .
ENV PYTHONPATH=${PYTHONPATH}:/Chinese-CLIP/cn_clip
COPY ./main_clip_cn.py /Chinese-CLIP/main_clip_cn.py
COPY ./deps/startProject.sh /Chinese-CLIP/deps/startProject.sh
EXPOSE 7863
ENTRYPOINT ["bash", "/Chinese-CLIP/deps/startProject.sh"]

1号进程:

#!/bin/bash
set -u
cd /Chinese-CLIP/ && nohup /root/miniconda3/envs/clip_cn_cpu/bin/python main_clip_cn.py >/log.alg  2>&1 &
echo "----------------------------------------"
echo "running..."
while [ 1 ]
doecho "sleep"sleep 3600
done

启动容器服务:

docker run -d -p7863:7863 kevinchina/deeplearning:clip_chinese

访问接口:

import requests
import torch
# 模型可选 ["RN50", "ViT-B-16", "ViT-L-14", "ViT-L-14-336", "ViT-H-14"]
url = "http://home.elvisiky.com:7863/cal_image_feature"
with open("no_text.png", "rb") as f:files = {"fileb": ("no_text.png", f)}  # 将文件字段键设置为 "fileb"data = {"model_name": "ViT-B-16"}  # 传递 model_name 作为表单数据res1 = requests.post(url=url, files=files, data=data, timeout=None)print(res1.json())url = "http://home.elvisiky.com:7863/cal_text_feature"
data = {"text": "夕阳", "model_name": "ViT-B-16"}  # 传递 model_name 作为表单数据
res2 = requests.post(url=url, data=data, timeout=None)
print(res2.json())data = {"text": "怪兽", "model_name": "ViT-B-16"}  # 传递 model_name 作为表单数据
res3 = requests.post(url=url, data=data, timeout=None)
print(res3.json())image_vector = res1.json()["data"]
text_vector = res2.json()["data"] + res3.json()["data"]
vector1 = torch.tensor(image_vector)
vector2 = torch.tensor(text_vector)
inner = vector1 @ vector2.t()
print("一张图片和多个文本的内积", inner)
logits_per_image = 100 * inner
print("换算成softmax概率", logits_per_image.softmax(dim=-1))

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

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

相关文章

Kubernetes革命:云原生时代的应用编排和自动化

文章目录 什么是Kubernetes以及为何它备受欢迎?云原生应用和K8s的关系Kubernetes的核心概念:Pods、Services、ReplicaSets等部署、扩展和管理应用程序的自动化容器编排的演进:Docker到Kubernetes实际用例:企业如何受益于K8s的应用…

相机坐标系之间的转换

一、坐标系之间的转换 一个有4个坐标系:图像坐标系、像素坐标系、相机坐标系、世界坐标系。 1.图像坐标系和像素坐标系之间的转换 图像坐标系和像素坐标系在同一个平面,利用平面坐标系之间的转换关系可以之知道两个坐标系变换的公式,并且该…

MFC文本输出学习

void CTxttstView::OnDraw(CDC* pDC) {CTxttstDoc* pDoc GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data hereCString str1;pDC->SetBkColor(RGB(0,0,0));pDC->TextOut(50, 50, "一段文字");pDC->SetBkColor(RGB(255,255,255))…

关于 打开虚拟机出现“...由VMware产品创建,但该产品与此版VMwareWorkstateion不兼容,因此无法使用” 的解决方法

文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/133678951 红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结…

超低延时直播技术演进之路-进化篇

一、概述 网络基础设施升级、音视频传输技术迭代、WebRTC 开源等因素,驱动音视频服务时延逐渐降低,使超低延时直播技术成为炙手可热的研究方向。实时音视频业务在消费互联网领域蓬勃发展,并逐渐向产业互联网领域加速渗透。经历了行业第一轮的…

Spark 9:Spark 新特性

Spark 3.0 新特性 Adaptive Query Execution 自适应查询(SparkSQL) 由于缺乏或者不准确的数据统计信息(元数据)和对成本的错误估算(执行计划调度)导致生成的初始执行计划不理想,在Spark3.x版本提供Adaptive Query Execution自适应查询技术,通过在”运行…

Kafka集群架构设计原理详解

从 Zookeeper 数据理解 Kafka 集群工作机制 这一部分主要是理解 Kafka 的服务端重要原理。但是 Kafka 为了保证高吞吐,高性能,高可扩展的三高架构,很多具体设计都是相当复杂的。如果直接跳进去学习研究,很快就会晕头转向。所以&am…

SpringBoot 对接 MinIO 实现文件上传下载删除

前言 MinIO 是一个开源的对象存储服务器,它可以存储大容量非结构化的数据,例如图片、音频、视频、日志文件、备份数据和容器/虚拟机镜像等。 Spring Boot 与 MinIO 的整合可以方便地实现文件的上传和下载等功能 在实际应用中,Spring Boot …

再获深交所认可,Smartbi实力领跑金融BI赛道

“十四五”规划中提到,健全具有高度适应性、竞争力、普惠性的现代金融体系,构建有效支撑实体经济的体制机制。《证券期货业科技发展“十四五”规划》作为指导证券期货业科技发展的纲领性文件, 秉承国家“十四五”规划的数字化发展理念&#x…

flutter开发实战-Universal Links配置及flutter微信分享实现

flutter开发实战-Universal Links配置及flutter微信分享实现 在最近开发中碰到了需要实现微信分享,在iOS端需要配置UniversalLink,在分享使用fluwx插件来实现微信分享功能。 一、配置UniversalLink 1.1、什么是UniversalLink Universal link 是Apple…

在asp.net中,实现类似安卓界面toast的方法(附更多弹窗样式)

目录 一、背景 二、操作方法 2.1修改前 2.2修改后 三、总结 附:参考文章: 一、背景 最近在以前的asp.net网页中,每次点击确定都弹窗,然后还要弹窗点击确认,太麻烦了,这次想升级一下,实现…