本文围绕图文跨模态检索展开研究,采用Chinese-CLIP预训练模型,对电商图文数据进行训练。该系统具有 “以文搜图”、“以图搜文”和“以图搜图”三个功能,能够显著提升用户体验,增强消费者的购买意愿,同时,还能为电商平台的企业和商家提供宝贵的建议,推动电子商务行业的进步。
本项目包含图文检索系统+优质论文,数据集可替换为其他场景数据集。
获取链接:
【闲鱼】https://m.tb.cn/h.gMz0ekg?tk=Bq8w3gngeby CZ0001 「我在闲鱼发布了【基于多模态特征融合的电商图文检索系统】」点击链接直接打开
一.启动Flask服务
(1)window+R
(2)cd +项目地址
(3)输入python .\gr_API\cnclip_api.py 命令
二.启动App
三.效果展示
(1)以文搜图
(2)以图搜文
(3)以图搜图
四.实现原理
本文围绕图文跨模态检索展开研究,采用Chinese-CLIP预训练模型,对电商图文数据进行训练。在此基础上,引入知识蒸馏技术,对模型进行进一步的优化和增强。同时,应用Prompt条件提示学习,引导模型更好地完成任务。在模型训练完成后,将最优Pytorch模型转换为Onnx格式,相比原始Pytorch模型,提升了特征计算的推理速度,同时不影响特征提取的下游任务效果。接下来,使用BERT和Bi-GRU网络提取文本侧特征,结合Faster R-CNN和ResNet101网络提取图像侧特征,并通过计算其图文相似度进行匹配,实现电商图文检索系统。该系统具有 “以文搜图”、“以图搜文”和“以图搜图”三个功能,能够显著提升用户体验,增强消费者的购买意愿,同时,还能为电商平台的企业和商家提供宝贵的建议,推动电子商务行业的进步。
(1)环境准备
GPU硬件要求:请准备Volta架构及以上的Nvidia GPU显卡(配备FP16 Tensor Core),Nvidia各架构对应显卡型号请参见此文档表格。本文我们以T4显卡为例
CUDA:推荐CUDA版本11.6及以上,本文以11.6为例
CUDNN:推荐CUDNN 8.6.0及以上,本文以8.6.0为例。请注意TensorRT和CUDNN有版本match关系,如TensorRT 8.5.x必须使用CUDNN 8.6.0,详见TensorRT的版本要求
ONNX:注意我们转换TensorRT模型时,将沿着Pytorch → ONNX → TensorRT的步骤,所以准备TensorRT模型也需要先安装ONNX库。本文以onnx版本1.13.0,onnxruntime-gpu版本1.13.1,onnxmltools版本1.11.1为例
TensorRT:推荐TensorRT版本8.5.x,本文以8.5.2.2为例。TensorRT各版本对应的CUDNN匹配版本,请从文档页面,查阅此TensorRT版本的"NVIDIA TensorRT Support Matrix"
Pytorch:推荐1.12.1及以上,本文以1.12.1为例(建议直接pip安装1.12.1+cu116,环境尽量不要再使用conda安装cudatoolkit,避免环境CUDNN版本变化,导致TensorRT报错)
requirements.txt要求的其他依赖项
执行代码:
pip install tensorrt==8.5.2.2 onnx==1.13.0 onnxruntime-gpu==1.13.1 onnxmltools==1.11.1
pip install torch==1.12.1+cu116 torchvision==0.13.1+cu116 torchaudio==0.12.1 -f https://download.pytorch.org/whl/torch_stable.html
pip install -r requirements.txt
(2)转换和运行ONNX模型
2.1 转换模型
将Pytorch模型checkpoint转换为ONNX格式的代码,请参见cn_clip/deploy/pytorch_to_onnx.py
。我们以转换ViT-B-16规模的Chinese-CLIP预训练模型为例,具体的代码运行方式如下(请参考Readme代码组织部分建好${DATAPATH}
并替换下面的脚本内容,尽量使用相对路径):
cd Chinese-CLIP/
export CUDA_VISIBLE_DEVICES=0
export PYTHONPATH=${PYTHONPATH}:`pwd`/cn_clip
# ${DATAPATH}的指定,请参考Readme"代码组织"部分创建好目录,尽量使用相对路径:https://github.com/OFA-Sys/Chinese-CLIP#代码组织
checkpoint_path=${DATAPATH}/pretrained_weights/clip_cn_vit-b-16.pt # 指定要转换的ckpt完整路径
mkdir -p ${DATAPATH}/deploy/ # 创建ONNX模型的输出文件夹
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
其中各配置项定义如下:
model-arch: 模型规模,选项包括["RN50", "ViT-B-16", "ViT-L-14", "ViT-L-14-336", "ViT-H-14"],各规模细节详见Readme
pytorch-ckpt-path: 指定Pytorch模型ckpt路径,上面的代码示例中我们指定为预训练的ckpt路径,也可以指定为用户finetune ckpt的位置。ckpt中的参数需要与model-arch指定的模型规模对应
save-onnx-path: 指定输出ONNX格式模型的路径(前缀)。完成转换后,代码将分别输出文本侧和图像侧的ONNX格式编码模型文件,FP32与FP16各一版,该参数即指定了以上输出文件的路径前缀
convert-text和convert-vision: 指定是否转换文本侧和图像侧模型
context-length(可选): 指定文本侧ONNX模型,接收输入的序列长度,默认为我们预训练ckpt所使用的52
download-root(可选): 如果不指定pytorch-ckpt-path,代码将根据model-arch自动下载Chinese-CLIP官方预训练ckpt用于转换,存放于download-root指定的目录
运行此代码转换完成后,将得到以下的log输出:
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
上面示例代码执行结束后,我们得到了ViT-B-16规模,Chinese-CLIP文本侧和图像侧的ONNX模型,可以分别用于提取图文特征。输出ONNX模型的路径均以运行脚本时的save-onnx-path为前缀,后面依次拼上.img/.txt、.fp16/.fp32、.onnx。我们后续将主要使用FP16格式的ONNX模型vit-b-16.txt.fp16.onnx和vit-b-16.img.fp16.onnx
注意到部分ONNX模型文件还附带有一个extra_file,其也是对应ONNX模型的一部分。在使用这些ONNX模型时,由于.onnx文件存储了extra_file的路径(如${DATAPATH}/deploy/vit-b-16.txt.fp16.onnx.extra_file)并会根据此路径载入extra_file,所以使用ONNX模型请不要改动存放的路径名,转换时${DATAPATH}也尽量用相对路径(如../datapath),避免运行时按路径找不到extra_file报错
2.2 运行模型
2.2.1 提取图像侧特征
我们在Chinese-CLIP/
目录下,使用以下的示例代码,读取刚刚转换好的ViT-B-16规模ONNX图像侧模型vit-b-16.img.fp16.onnx
,并为Readme中示例的皮卡丘图片提取图像侧特征。注意转换好的ONNX模型只接受batch大小为1的输入,即一次调用只处理一张输入图片
# 完成必要的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, 特征向量维度]
2.2.2 提取文本侧特征
类似地,我们用如下代码完成文本侧ONNX模型的载入与特征计算,与图像侧相同,文本侧ONNX部署模型只接受batch大小为1的输入,即一次调用只处理一条输入文本。我们为4条候选文本依次计算ViT-B-16规模模型的文本特征。import相关代码与上文相同,这里省略:
# 载入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, 特征向量维度]
2.2.3 计算图文相似度
ONNX模型产出的归一化图文特征,内积后softmax即可计算相似度(需要考虑logit_scale
),与原始Pytorch模型操作相同,参见以下代码。import相关代码与上文相同,这里省略:
ONNX模型产出的归一化图文特征,内积后softmax即可计算相似度(需要考虑logit_scale),与原始Pytorch模型操作相同,参见以下代码。import相关代码与上文相同,这里省略:
可以看到,给出的图文相似概率,和Readme中快速使用部分,基于Pytorch同一个模型计算的结果基本一致,证明了ONNX模型特征计算的正确性,而ONNX模型的特征计算速度相比Pytorch更有优势
标签:模态,txt,16,ONNX,模型,检索系统,text,onnx,电商 From: https://blog.csdn.net/weixin_56233385/article/details/141821523