OpenVINO™ 赋能 BLIP 实现视觉语言 AI 边缘部署

人类通过视觉和语言感知世界。人工智能的一个长期目标是构建智能体,通过视觉和语言输入来理解世界,并通过自然语言与人类交流。比如,在《几行代码加速 stable diffusion,使用 openvino 轻松文生图》中,我们介绍了利用 openvino 运行 stable diffusion 模型,快速实现文生图应用。让人人可以成为绘画大师,利用 ai 随心作画。
随着计算机视觉和自然语言处理领域的快速发展,视觉与语言的融合越来越受到研究人员的重视。在这个背景下,blip(bootstrapping language-image pre-training)作为一种创新的预训练模型,引起了广泛关注。该模型在大规模的图像文本数据集上预训练深度神经网络模型,以提高下游视觉语言任务的性能,如图像文本检索、图像字幕和视觉问答。通过联合训练图像和文本数据,为视觉与语言的融合提供了强大的基础。
blip 的预训练过程涉及两个关键组件:图像编码器和文本编码器。图像编码器负责将输入的图像转换为低维向量表示,而文本编码器则将输入的文本转换为另一个低维向量表示。为了实现统一的视觉-语言预训练,blip 采用了一种跨模态约束策略,即在预训练阶段,图像编码器和文本编码器被设计成相互约束的。这样的约束机制强制模型学习将视觉信息和语言信息进行对齐,从而使得模型在后续任务中能够更好地处理视觉与语言之间的联合信息。
除了视觉-语言理解任务,blip 还在视觉-语言生成任务中表现出色。在这个任务中,模型需要根据输入的图像和文本生成相关的描述或回答问题。blip 通过联合训练和引入了图像-文本生成任务,使得模型具备了更强大的图像描述和问题回答能力。这使得 blip 在图像描述生成和视觉问答等任务上取得了优异的成绩。
接下来,我们一起来看看如何在研扬科技(aaeon)的新品 up squared pro 7000 edge 运行利用 openvino 来优化加速 blip 的推理有哪些重点步骤吧。
作为研扬 up squared pro 系列的第三代产品,upsquared pro 7000 系列[1] 透过高性能计算能力、升级的电路板设计和扩展的显示接口,提供更大的开发潜力。作为该系列中首款采用 intel core/atom/n 系列处理器(原 alder lake-n)的产品,up squared pro 7000 是首款配备板载 lpddr5 内存的产品,提高了 i/o 的运行速度。此外,up squared pro 7000 在图像处理和显示功能方面都有显著提升,支持 mipi csi 照相机,并搭配 intel uhd 显卡,可同时进行三台 4k 显示器。
1.4 倍以上 cpu 性能提升
up squared pro 7000 采用 intel core/atom/n- 系列处理器,cpu 性能是上一代的 1.4 倍。up squared pro 7000 拥有多达 8 个 gracemont 内核,支持 openvino toolkit,以及第 12 代 intel 处理器的 uhd 显卡,拥有强大的计算能力、优化的推理引擎和图像处理功能,提供绝佳的智能解决方案。
同步支持 3 台 4k 显示器
up squared pro 7000 配备 hdmi 2.0b、dp 1.2 埠和透过 usb type-c 的 dp 1.4a,拥有出色的显示接口。up squared pro 7000 整合了 gpu 和多重输出,可以同步支持三个 4k 显示器,非常适合用于数字广告牌等视觉导向型的相关应用。
双倍的高速系统内存
作为 up squared pro 系列中第一块配备板载 lpddr5 系统内存的板卡,up squared pro 7000 搭载了 16gb 的系统内存,是上一代的两倍。此外,快达 4800mhz 的内存速度让用户的带宽和数据传输速度加倍,同时也更加省电。
全面的 i/o 升级
除了维持 up squared pro 系列 4 x 4 的紧凑外形之外,up squared pro 7000 在电路板设计上更为精实。up squared pro 7000 配备了两个 2.5gbe、三个 usb 3.2 和一个 fpc 端口,可外接更多像是 mipi csi 相机的外围设备。将这些特色与板载 lpddr5 及性能强大的 cpu 相结合,非常适合用于智慧工厂机器人方面的视觉解决方案。
第一步:安装相应工具包、加载模型并转换为 openvino ir 格式
本次代码示例需要首先安装 blip 相应工具包。
 !pip install transformers >= 4.26.0
向右滑动查看完整代码
然后下载及加载相应的 pytorch 模型。在本问中,您将使用可从 hugging face 下载的 blip-vqa-base [2] 基本模型。同样的操作也适用于 blip 系列中的其它模型。尽管该模型类是为执行问答而设计的,但其组件也可以用于图像字幕。要开始使用该模型,需要使用 from_pretrained 方法实例化 blipforquestionanswering 类。blipprocessor 是一个助手类,用于准备文本和视觉模态的输入数据以及生成结果的后处理。
           import sysimport timefrom pil import imagefrom transformers import blipprocessor, blipforquestionanswering
sys.path.append(../utils)from notebook_utils import download_file
# get model and processorprocessor = blipprocessor.from_pretrained(salesforce/blip-vqa-base)model = blipforquestionanswering.from_pretrained(salesforce/blip-vqa-base)
接下来,我们看看如何将原始模型转换为 openvino ir格式的模型,并利用 openvino 进行相应的优化以及部署推理加速。
第二步:将模型转换为 openvino ir 格式
根据我们前面的介绍,blip 模型包含视觉模型、文本编码和文本解码三个模型,因此我们需要分别将这三个模型转换为 openvino ir 格式。视觉模型的转换操作比较常规,具体代码可以参考我们的 notebook[3],这里重点介绍一下文本编码和文本解码模型的转换部分。
文本编码器转换
视觉问答任务使用文本编码器来构建问题的嵌入表示。它采用经过分词后的问题的 input_ids,并输出从视觉模型获得的图像嵌入和它们的注意力掩码。根据问题文本的不同,标记化输入后的标记数量可能不同。因此,为使用标记的模型输入保留动态形状,dynamic_axes 参数负责在 torch.onx.export 中保留输入的动态特定维度。代码如下:
                         text_encoder_ov = path(blip_text_encoder.xml)text_encoder_onnx = text_encoder_ov.with_suffix(.onnx)
text_encoder = model.text_encodertext_encoder.eval()
# if openvino model does not exist, convert it to onnx and then to irif not text_encoder_ov.exists():    if not text_encoder_onnx.exists():        # prepare example inputs for onnx export        image_embeds = vision_outputs[0]        image_attention_mask = torch.ones(image_embeds.size()[:-1], dtype=torch.long)        input_dict = {input_ids: inputs[input_ids], attention_mask: inputs[attention_mask], encoder_hidden_states: image_embeds, encoder_attention_mask: image_attention_mask}        # specify variable length axes        dynamic_axes = {input_ids: {1: seq_len}, attention_mask: {1: seq_len}}        # export pytorch model to onnx        with torch.no_grad():            torch.onnx.export(text_encoder, input_dict, text_encoder_onnx, input_names=list(input_dict), dynamic_axes=dynamic_axes)    # convert onnx model to ir using model conversion python api, use compress_to_fp16=true for compressing model weights to fp16 precision    ov_text_encoder = mo.convert_model(text_encoder_onnx, compress_to_fp16=true)    # save model on disk for next usages    serialize(ov_text_encoder, str(text_encoder_ov))    print(ftext encoder successfuly converted and saved to {text_encoder_ov})else:    print(ftext encoder will be loaded from {text_encoder_ov})
向右滑动查看完整代码
文本解码器转换
文本解码器负责使用图像(以及问题,如果需要的话)的表示来生成模型输出(问题的答案或标题)的分词 token 序列。生成方法基于这样的假设,即单词序列的概率分布可以分解为下一个单词条件分布的乘积。换言之,模型预测由先前生成的 token 引导循环生成下一个 token,直到达到停止生成的条件(生成达到最大长度序列或获得的字符串结束的 token)。在预测概率之上选择下一个 token的方式由所选择的解码方法来驱动。与文本编码器类似,文本解码器可以处理不同长度的输入序列,并且需要保留动态输入形状。这部分特殊的处理可由如下代码完成:
                        text_decoder = model.text_decodertext_decoder.eval()
text_decoder_ov = path(blip_text_decoder.xml)text_decoder_onnx = text_decoder_ov.with_suffix(.onnx)
# prepare example inputs for onnx exportinput_ids = torch.tensor([[30522]])  # begin of sequence token idattention_mask = torch.tensor([[1]])  # attention mask for input_idsencoder_hidden_states = torch.rand((1, 10, 768))  # encoder last hidden state from text_encoderencoder_attention_mask = torch.ones((1, 10), dtype=torch.long)  # attention mask for encoder hidden states
input_dict = {input_ids: input_ids, attention_mask: attention_mask, encoder_hidden_states: encoder_hidden_states, encoder_attention_mask: encoder_attention_mask}# specify variable length axesdynamic_axes = {input_ids: {1: seq_len}, attention_mask: {1: seq_len}, encoder_hidden_states: {1: enc_seq_len}, encoder_attention_mask: {1: enc_seq_len}}
# specify output names, logits is main output of modeloutput_names = [logits]
# past key values outputs are output for caching model hidden statepast_key_values_outs = []text_decoder_outs = text_decoder(**input_dict)for idx, _ in enumerate(text_decoder_outs[past_key_values]):    past_key_values_outs.extend([fout_past_key_value.{idx}.key, fout_past_key_value.{idx}.value])
向右滑动查看完整代码
接下来,对于文本解码器的转换,还有来自前一步骤的隐藏状态的额外输入。与输出类似,在模型导出为 onnx 格式后,它们将被展平。需要使用新的输入层更新 dynamic_axies 和 input_names。因此,其后面的转换过程与前面的文本编码器的转换过程类似,在本文中不再赘述。
第三步:运行 openvino 推理
如前所述,在这里我们将主要展示 blip 进行视觉问答以及图像字幕的流水线如何搭建、以及如何运行 openvino 来进行推理的情况。
图像字幕
视觉模型接受 blipprocessor 预处理的图像作为输入,并生成图像嵌入,这些图像嵌入直接传递给文本解码器以生成字幕标记。生成完成后,分词 tokenizer 的输出序列被提供给 blipprocessor,用于使用 tokenizer 解码为文本。
定义 ovblipmodel 类:
                class ovblipmodel:        model class for inference blip model with openvino        def __init__(self, config, decoder_start_token_id:int, vision_model, text_encoder, text_decoder):                initialization class parameters                self.vision_model = vision_model        self.vision_model_out = vision_model.output(0)        self.text_encoder = text_encoder        self.text_encoder_out = text_encoder.output(0)        self.text_decoder = text_decoder        self.config = config        self.decoder_start_token_id = decoder_start_token_id        self.decoder_input_ids = c
向右滑动查看完整代码
定义图像字幕函数如下,
                                        def generate_caption(self, pixel_values:torch.tensor, input_ids:torch.tensor = none, attention_mask:torch.tensor = none, **generate_kwargs):                image captioning prediction        parameters:          pixel_values (torch.tensor): preprocessed image pixel values          input_ids (torch.tensor, *optional*, none): pregenerated caption token ids after tokenization, if provided caption generation continue provided text          attention_mask (torch.tensor): attention mask for caption tokens, used only if input_ids provided        retruns:          generation output (torch.tensor): tensor which represents sequence of generated caption token ids                batch_size = pixel_values.shape[0]
       image_embeds = self.vision_model(pixel_values.detach().numpy())[self.vision_model_out]
       image_attention_mask = torch.ones(image_embeds.shape[:-1], dtype=torch.long)
       if isinstance(input_ids, list):            input_ids = torch.longtensor(input_ids)        elif input_ids is none:            input_ids = (                torch.longtensor([[self.config.text_config.bos_token_id, self.config.text_config.eos_token_id]])                .repeat(batch_size, 1)            )        input_ids[:, 0] = self.config.text_config.bos_token_id        attention_mask = attention_mask[:, :-1] if attention_mask is not none else none
       outputs = self.text_decoder.generate(            input_ids=input_ids[:, :-1],            eos_token_id=self.config.text_config.sep_token_id,            pad_token_id=self.config.text_config.pad_token_id,            attention_mask=attention_mask,            encoder_hidden_states=torch.from_numpy(image_embeds),            encoder_attention_mask=image_attention_mask,            **generate_kwargs,        )
       return outputs
向右滑动查看完整代码
视觉问答
视觉回答的流水线看起来很相似,但有额外的问题处理。在这种情况下,由 blipprocessor 标记的图像嵌入和问题被提供给文本编码器,然后多模态问题嵌入被传递给文本解码器以执行答案的生成。
在 ovblipmodel 类内部同理可定义视觉问答函数如下:
                                def generate_answer(self, pixel_values:torch.tensor, input_ids:torch.tensor, attention_mask:torch.tensor, **generate_kwargs):                visual question answering prediction        parameters:          pixel_values (torch.tensor): preprocessed image pixel values          input_ids (torch.tensor): question token ids after tokenization          attention_mask (torch.tensor): attention mask for question tokens        retruns:          generation output (torch.tensor): tensor which represents sequence of generated answer token ids                image_embed = self.vision_model(pixel_values.detach().numpy())[self.vision_model_out]        image_attention_mask = np.ones(image_embed.shape[:-1], dtype=int)        if isinstance(input_ids, list):            input_ids = torch.longtensor(input_ids)        question_embeds = self.text_encoder([input_ids.detach().numpy(), attention_mask.detach().numpy(), image_embed, image_attention_mask])[self.text_encoder_out]        question_attention_mask = np.ones(question_embeds.shape[:-1], dtype=int)
       bos_ids = np.full((question_embeds.shape[0], 1), fill_value=self.decoder_start_token_id)
       outputs = self.text_decoder.generate(            input_ids=torch.from_numpy(bos_ids),            eos_token_id=self.config.text_config.sep_token_id,            pad_token_id=self.config.text_config.pad_token_id,            encoder_hidden_states=torch.from_numpy(question_embeds),            encoder_attention_mask=torch.from_numpy(question_attention_mask),            **generate_kwargs,        )        return outputs
向右滑动查看完整代码
初始化 openvino 运行时并运行推理
初始化 openvino core 对象,选择推理设备,并加载、编译模型
                   # create openvino core object instancecore = core()
import ipywidgets as widgets
device = widgets.dropdown(    options=core.available_devices + [auto],    value='auto',    description='device:',    disabled=false,)
device
# load models on deviceov_vision_model = core.compile_model(vision_model_ov, device.value)ov_text_encoder = core.compile_model(text_encoder_ov, device.value)ov_text_decoder = core.compile_model(text_decoder_ov, device.value)ov_text_decoder_with_past = core.compile_model(text_decoder_with_past_ov, device.value)
向右滑动查看完整代码
运行图像字幕推理
out = ov_model.generate_caption(inputs[pixel_values], max_length=20)caption = processor.decode(out[0], skip_special_tokens=true)fig = visualize_results(raw_image, caption)
运行视觉问答推理
start = time.perf_counter()out = ov_model.generate_answer(**inputs, max_length=20)end = time.perf_counter() - startanswer = processor.decode(out[0], skip_special_tokens=true)fig = visualize_results(raw_image, answer, question)
小结
整个的步骤就是这样!现在就开始跟着我们提供的代码和步骤,动手试试用 open vino 和 blip 吧。
除此之外,为了方便大家了解并快速掌握 openvino 的使用,我们还提供了一系列开源的 jupyter notebook demo。运行这些 notebook,就能快速了解在不同场景下如何利用 openvino 实现一系列、包括计算机视觉、语音及自然语言处理任务。openvino notebooks 的资源可以在 github 这里下载安装:https://github.com/openvinotoolkit/openvino_notebooks 。
研扬科技简介
研扬科技成立于 1992 年,是工业物联网和人工智能边缘解决方案的领先设计商和制造商之一。以不断创新为核心价值观,研扬科技为市场带来可靠、高质量的计算平台,包括工业主板和系统、强固式平板电脑、嵌入式人工智能系统、ucpe 网络设备以及 lorawan/wwan 解决方案。研扬科技还带来行业领先的经验和知识,以在全球范围内提供 oem/odm 服务。此外,研扬科技与诸多城市和政府紧密合作,开发和部署智能城市生态系统,提供个性化平台和端到端解决方案。研扬科技与顶级芯片设计商紧密合作,提供稳定、可靠的平台,并被认可为 intel 物联网解决方案联盟的钛金级成员。

电信和国防应用推动射频氮化镓(RF GaN)蓬勃发展 专利之争全面开启
致远电子提出动力电池组系统can-bus组网方案
无线充电模块?传富士康为iPhone8研发
摩托罗拉推出XIR MOTOTRBO XiR M3188车载台解决方案
高隔离度X波段RF MEMS电容式并联开关
OpenVINO™ 赋能 BLIP 实现视觉语言 AI 边缘部署
讯飞输入法×讯飞智能鼠标 感恩节享福利用好物
光电编码器原理及应用电路
导致硫酸罐渗漏的原因是什么
汽车领域为什么缺芯片
元素分析仪的介绍
工业互联网是实现智能制造的抓手,推动工业互联网是长期的工作
人工智能是把双刃剑_稍有不慎就酿成无人驾驶的车祸
详解RFID之标准体系
臭氧传感器具有哪些优势
精密lcr测试仪介绍
超低噪声宽带运算放大器LMH6624
回顾2018,华为智能手机出货量上升至全球第二
石墨烯/聚酰亚胺复合材料的制备方法
LTC3614 2.5V、4A、2.25MHz、单片式同步降压型 DC/DC 转换器