CLIP图文多模态模型onnxruntime和tensorrt推理

首先下载github项目:https://github.com/Lednik7/CLIP-ONNX
修改clip_onnx/utils.py第61行opset_version=12为opset_version=15 , 运行测试脚本:

import clip
from PIL import Image
import numpy as np

# ONNX不支持CUDA
model, preprocess = clip.load("ViT-B/32", device="cpu", jit=False)

# 批量优先
image = preprocess(Image.open("CLIP.png")).unsqueeze(0).cpu()  # [1, 3, 224, 224]
image_onnx = image.detach().cpu().numpy().astype(np.float32)

# 批量优先
text = clip.tokenize(["a diagram", "a dog", "a cat"]).cpu()  # [3, 77]
text_onnx = text.detach().cpu().numpy().astype(np.int32)


from clip_onnx import clip_onnx

onnx_model = clip_onnx(model, visual_path="clip_visual.onnx", textual_path="clip_textual.onnx")
onnx_model.convert2onnx(image, text, verbose=True)
onnx_model.start_sessions(providers=["CPUExecutionProvider"])  # CPU模式

image_features = onnx_model.encode_image(image_onnx)
text_features = onnx_model.encode_text(text_onnx)

logits_per_image, logits_per_text = onnx_model(image_onnx, text_onnx)
probs = logits_per_image.softmax(dim=-1).detach().cpu().numpy()
print("标签概率:", probs)

onnx_model = clip_onnx(None)
onnx_model.load_onnx(visual_path="clip_visual.onnx", textual_path="clip_textual.onnx", logit_scale=100.0000)  # model.logit_scale.exp()
onnx_model.start_sessions(providers=["CPUExecutionProvider"])
image_features = onnx_model.encode_image(image_onnx)
text_features = onnx_model.encode_text(text_onnx)

logits_per_image, logits_per_text = onnx_model(image_onnx, text_onnx)
probs = logits_per_image.softmax(dim=-1).detach().cpu().numpy()
print("标签概率:", probs)

onnxruntime推理

import clip
from PIL import Image
import numpy as np
import onnxruntime


model, preprocess = clip.load("ViT-B/32", device="cpu", jit=False)
image = preprocess(Image.open("CLIP.png")).unsqueeze(0).cpu()  # [1, 3, 224, 224]
image_input = image.detach().cpu().numpy().astype(np.float32)
text = clip.tokenize(["a diagram", "a dog", "a cat"]).cpu()  # [3, 77]
text_input = text.detach().cpu().numpy().astype(np.int32)


class clip_onnx:
    def __init__(self, model=None, visual_path: str = "clip_visual.onnx", textual_path: str = "clip_textual.onnx", logit_scale=None):
        self.model = model
        self.visual_path = visual_path
        self.textual_path = textual_path
        self.logit_scale = logit_scale

    def start_sessions(self, providers=['TensorrtExecutionProvider', 'CUDAExecutionProvider', 'CPUExecutionProvider']):
        self.visual_session = onnxruntime.InferenceSession(self.visual_path, providers=providers)
        self.textual_session = onnxruntime.InferenceSession(self.textual_path, providers=providers)

    def __call__(self, image, text, device: str = "cpu"):
        onnx_input_image = {self.visual_session.get_inputs()[0].name: image}
        image_features, = self.visual_session.run(None, onnx_input_image)
        onnx_input_text = {self.textual_session.get_inputs()[0].name: text}
        text_features, = self.textual_session.run(None, onnx_input_text)
        image_features = image_features /np.linalg.norm(image_features, axis=-1, keepdims=True)
        text_features = text_features / np.linalg.norm(text_features, axis=-1, keepdims=True)
        logits_per_image = self.logit_scale * image_features @ text_features.T
        logits_per_text = logits_per_image.T
        return logits_per_image, logits_per_text


onnx_model = clip_onnx(visual_path="clip_visual.onnx", textual_path="clip_textual.onnx", logit_scale=100.0000)  
onnx_model.start_sessions(providers=["CPUExecutionProvider"])
logits_per_image, logits_per_text = onnx_model(image_input, text_input)

def softmax(x, axis=-1):
    e_x = np.exp(x - np.max(x, axis=axis, keepdims=True))
    return e_x / np.sum(e_x, axis=axis, keepdims=True)

probs = softmax(logits_per_image)
print("标签概率:", probs)

tensorrt推理

要使得tensorrt正常推理还需注释掉clip_onnx/utils.py第63行的dynamic_axes,再生成onnx模型。
通过trtexec 转换onnx模型得到engine文件:

/docker_share/TensorRT-8.6.1.6/bin/trtexec --onnx=./clip_textual.onnx --saveEngine=./clip_textual.engine 
/docker_share/TensorRT-8.6.1.6/bin/trtexec --onnx=./clip_visual.onnx --saveEngine=./clip_visual.engine
import clip
from PIL import Image
import numpy as np
import tensorrt as trt
import pycuda.autoinit 
import pycuda.driver as cuda 


model, preprocess = clip.load("ViT-B/32", device="cpu", jit=False)
image = preprocess(Image.open("CLIP.png")).unsqueeze(0).cpu()  # [1, 3, 224, 224]
image_input = image.detach().cpu().numpy().astype(np.float32)
text = clip.tokenize(["a diagram", "a dog", "a cat"]).cpu()  # [3, 77]
text_input = text.detach().cpu().numpy().astype(np.int32)


class clip_tensorrt:
    def __init__(self, model=None, visual_path: str = "clip_visual.engine", textual_path: str = "clip_textual.engine", logit_scale=None):
        self.model = model
        self.visual_path = visual_path
        self.textual_path = textual_path
        self.logit_scale = logit_scale

    def start_engines(self, providers=['CUDAExecutionProvider', 'CPUExecutionProvider']):
        logger = trt.Logger(trt.Logger.WARNING)
        with open(self.visual_path, "rb") as f, trt.Runtime(logger) as runtime:
            self.visual_engine = runtime.deserialize_cuda_engine(f.read())
        self.visual_context = self.visual_engine.create_execution_context()
        self.visual_inputs_host = cuda.pagelocked_empty(trt.volume(self.visual_context.get_binding_shape(0)), dtype=np.float32)
        self.visual_outputs_host = cuda.pagelocked_empty(trt.volume(self.visual_context.get_binding_shape(1)), dtype=np.float32)
        self.visual_inputs_device = cuda.mem_alloc(self.visual_inputs_host.nbytes)
        self.visual_outputs_device = cuda.mem_alloc(self.visual_outputs_host.nbytes)
        self.visual_stream = cuda.Stream()

        with open(self.textual_path, "rb") as f, trt.Runtime(logger) as runtime:
            self.textual_engine = runtime.deserialize_cuda_engine(f.read())
        self.textual_context = self.textual_engine.create_execution_context()
        self.textual_inputs_host = cuda.pagelocked_empty(trt.volume(self.textual_context.get_binding_shape(0)), dtype=np.int32)
        self.textual_outputs_host = cuda.pagelocked_empty(trt.volume(self.textual_context.get_binding_shape(1)), dtype=np.float32)
        self.textual_inputs_device = cuda.mem_alloc(self.textual_inputs_host.nbytes)
        self.textual_outputs_device = cuda.mem_alloc(self.textual_outputs_host.nbytes)
        self.textual_stream = cuda.Stream()
        
    def __call__(self, image, text):
        np.copyto(self.visual_inputs_host, image.ravel())
        with self.visual_engine.create_execution_context() as context:
            cuda.memcpy_htod_async(self.visual_inputs_device, self.visual_inputs_host, self.visual_stream)
            context.execute_async_v2(bindings=[int(self.visual_inputs_device), int(self.visual_outputs_device)], stream_handle=self.visual_stream.handle)
            cuda.memcpy_dtoh_async(self.visual_outputs_host, self.visual_outputs_device, self.visual_stream)
            self.visual_stream.synchronize()  

        np.copyto(self.textual_inputs_host, text.ravel())
        with self.textual_engine.create_execution_context() as context:
            cuda.memcpy_htod_async(self.textual_inputs_device, self.textual_inputs_host, self.textual_stream)
            context.execute_async_v2(bindings=[int(self.textual_inputs_device), int(self.textual_outputs_device)], stream_handle=self.textual_stream.handle)
            cuda.memcpy_dtoh_async(self.textual_outputs_host, self.textual_outputs_device, self.textual_stream)
            self.textual_stream.synchronize()  
        
        image_features = self.visual_outputs_host.reshape(1,512)
        text_features = self.textual_outputs_host.reshape(3,512)
        image_features = image_features /np.linalg.norm(image_features, axis=-1, keepdims=True)
        text_features = text_features / np.linalg.norm(text_features, axis=-1, keepdims=True)
        logits_per_image = self.logit_scale * image_features @ text_features.T
        logits_per_text = logits_per_image.T
        return logits_per_image, logits_per_text


onnx_model = clip_tensorrt(visual_path="clip_visual.engine", textual_path="clip_textual.engine", logit_scale=100.0000)  
onnx_model.start_engines()
logits_per_image, logits_per_text = onnx_model(image_input, text_input)

def softmax(x, axis=-1):
    e_x = np.exp(x - np.max(x, axis=axis, keepdims=True))
    return e_x / np.sum(e_x, axis=axis, keepdims=True)

probs = softmax(logits_per_image)
print("标签概率:", probs)

CLIP.png
在这里插入图片描述

正常运行得到结果

标签概率: [[0.9927926  0.00421789 0.00298956]]
<think>嗯,用户让我介绍一下大模型多模态技术架构,以及它大语言模型的区别。我需要先理清楚这两个概念的定义核心差异。首先,大语言模型(LLM)主要处理文本数据,像GPT、BERT这些模型都是基于Transformer架构,专注于文本生成理解。而多模态大模型则是处理多种类型的数据,比如文本、图像、音频、视频等,需要整合不同模态的信息。 接下来,我应该从技术架构的角度来对比。大语言模型的结构相对单一,输入输出都是文本,依赖Transformer的自注意力机制处理序列数据。而多模态模型需要处理不同模态的数据,可能需要不同的编码器,比如CNN处理图像,Transformer处理文本,然后如何将这些编码后的特征融合起来是关键。这里可能需要提到跨模态对齐、联合表示学习等技术。 然后,应用场景的区别也很重要。多模态模型可以应用于更复杂的任务,比如图像描述生成、视频问答等,而大语言模型更多是文本相关的任务,比如翻译、摘要。同时,多模态模型在训练数据、计算资源上的需求也更大,因为需要处理多种数据类型,模型结构更复杂。 还要注意用户可能的深层需求,比如他们可能想知道为什么需要多模态模型,或者在实际应用中如何选择两者。这时候需要强调多模态在处理现实世界问题时的优势,因为现实中的数据通常是多模态的。 另外,要确保回答符合系统级指令,所有数学表达式用$...$,比如提到损失函数时写成$L = L_{\text{text}} + \lambda L_{\text{image}}$,并且独立公式用$$...$$。不过这个问题里可能数学公式不多,但要留意。 最后,结构要清晰,分点回答,先介绍各自架构,再对比区别,最后总结应用场景挑战。确保用中文,语言通俗易懂,避免专业术语过多,必要时举例说明。</think>### 大模型多模态技术架构 vs. 大语言模型:核心区别解析 #### 一、大语言模型(Large Language Model, LLM) 1. **核心定位** 大语言模型是专注于**文本模态**的生成与理解的模型,其输入输出均为文本序列。典型代表包括GPT、PaLM、BERT等。 2. **技术架构** - **基础结构**:基于Transformer架构,依赖自注意力机制(Self-Attention)捕捉长程依赖关系。 - **训练目标**:通过自回归(如GPT)或掩码语言建模(如BERT)学习文本概率分布。 - **数学表达**: 自回归生成公式为 $$P(w_t | w_{1:t-1})$$,掩码建模目标为 $\max \log P(w_m | w_{\setminus m})$。 3. **应用场景** 文本生成、翻译、问答、摘要等纯文本任务。 --- #### 二、多模态大模型(Multimodal Large Model) 1. **核心定位** 支持**跨模态理解与生成**,整合文本、图像、音频、视频等多类型数据,典型代表包括Flamingo、CLIP、GPT-4V等。 2. **技术架构** - **模态编码器**: - 文本:使用Transformer编码器 - 图像:使用CNN或Vision Transformer(ViT) - 音频:使用WaveNet或频谱特征提取器 - **跨模态对齐**: 通过对比学习(Contrastive Learning)或交叉注意力(Cross-Attention)实现模态间语义对齐。 例如,CLIP的损失函数为 $$L = -\log \frac{\exp(\text{sim}(T_i, I_i)/\tau)}{\sum_{j=1}^N \exp(\text{sim}(T_i, I_j)/\tau)}$$ - **统一解码器**: 将多模态特征映射到共享语义空间,支持跨模态生成(如“看图说话”)。 3. **关键技术挑战** - 异构数据表示的统一性 - 模态对齐的语义一致性 - 计算与存储资源的指数级增长 --- #### 三、核心区别对比 | **维度** | **大语言模型 (LLM)** | **多模态大模型** | |------------------|---------------------------|------------------------------| | **输入/输出** | 纯文本 | 文本、图像、音频、视频等任意组合 | | **模型结构** | 单一Transformer堆叠 | 多编码器+跨模态融合模块 | | **训练目标** | 文本概率建模 | 跨模态联合分布建模 | | **数据需求** | 大规模文本语料 | 多模态对齐数据(如图文对、视频字幕)| | **典型任务** | 文本生成、分类 | 图像描述、视频问答、跨模态检索 | --- #### 四、应用场景差异 - **大语言模型**:客服对话、代码生成、文档摘要 - **多模态模型**: - 医疗领域:结合医学影像与报告文本分析 - 教育领域:图解题辅助(输入公式$f(x)=x^2$与手写草图,输出解题步骤) - 机器人交互:理解环境感知(视觉)+ 自然语言指令 --- #### 五、未来趋势 1. **模态扩展**:触觉、3D点云等更复杂模态的融合。 2. **效率优化**:轻量化多模态架构(如参数共享、动态路由)。 3. **认知增强**:结合符号逻辑推理,解决多模态幻觉问题。 通过上述对比可见,多模态大模型的核心突破在于**跨模态语义理解与生成能力**,而大语言模型仍是其实现多模态交互的文本基座。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

给算法爸爸上香

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值