openvno简介
OpenVINO是Intel开发的模型压缩部署工具,可以将ptorch训练出的pt模型转化成onnx中间模型,最终转换成OpenVINO的xml模型,实现压缩加速。Intel对自家的CPU及核显iGPU,以及最新发布的独显都进行了适配,是个不错的部署加速工具。
转化后的xml模型可以由python或C++调用openvino官方API进行推理,当然C++的运行效率会更高,毕竟是关注性能才进行的模型部署。
OpenVINO2022工具包进行了较大的变化,删除了之前包内自带的OpenCV等冗余部件,避免和本机环境产生冲突,同时也精简了工具包,变得更加灵活易用。其中,Mo是模型转化工
- python训练得到pth权重,转化成Openvino的xml权重,按照openvino的API编写C++代码调用xml权重即可完成部署(pth→onnx→xml)
- pth→onnx调用API,上CSDN搜
- openvino文档
Documentation - OpenVINO™ documentation
- 下载mo转化工具套件(onnx→xml)
Download Intel® Distribution of OpenVINO™ Toolkit
利用mo进行模型转化
运行安装包中的mo.py,常用的参数有:
--input_shape [x,x,x,x] 用于指定张量形状
--input_model path/to/model 指定xxx模型路径
--output_dir path/to/dir 指定IR模型输出路径
--reverse_input_channels 反转输入通道
--mean_values [x,x,x] 指定数据预处理标准化的均值
--scale_values [x,x,x] 指定数据预处理标准化的方差
转换示例(RGB训练,包含均值方差Normalize):
python /path/to/openvino/deployment_tools/model_optimizer/mo.py --input_model /path/to/onnx/model --output_dir /path/to/output/dir --mean_values [number,number,number] --scale_values [number,number,number] --reverse_input_channels
当然,可能你的包中并没有这个模块,那可能你是后来的mo版本,可以直接用mo命令调用模型转化工具,如下面代码所示,其中mean_values和scale_values需要根据你训练过程中得到的数值进行设置,如果没有使用标准化预处理,则不用设置这两个参数。
mo --input_model 待转化的onnx模型路径 --output_dir xml输出路径
--mean_values [ , , ] --scale_values [ , , ]
- 如果使用了标准化预处理,则最好使用mean_values,scale_values,且根据OpenVINO的输入要求为:
mean_values=mean*255, scale_values=scale*255
其中mean、scale为归一化后计算的均值方差的结果 这样在部署时传入的目标图像只要进行一次resize
到对应的输入大小传入推理引擎即可,无须进行任何额外操作。 3. 关于图像通道的问题,注意 OpenVINO采用的是BGR通道输入,而OpenCV使用的也是BGR通道输入,如果模型的训练是使用RGB通道进行训练的,使用--reverse_input_channels
反转输入通道。 这样在部署后图像就不需要再进行BGR2RGB
转换了。
转化示例代码
- pth转onnx
def _option_onnx(self):
"""
需要自定义
"""
global filename
if not os.path.exists(self.args.onnx_outpath): os.makedirs(self.args.onnx_outpath)
for i in range(1, 51):
filename = os.path.join(self.args.onnx_outpath,
f"{self.train_info.MODEL_NAME}_{i}.onnx")
if not os.path.exists(filename): break
temp = torch.ones(
1, 3, self.train_info.INPUT_SHAPE[0], self.train_info.INPUT_SHAPE[1])
torch.onnx.export(
self.model,
temp.to(self.device),
filename,
opset_version=10,
do_constant_folding=True,
input_names=['input'],
output_names=['output']
)
shutil.copy(f'task_output{choose}/task_0/task_option.json', self.args.onnx_outpath)
print(f"Export {filename} done.")
- onnx转xml(利用mo,用python调用shell实现命令行脚本,调用mo完成转化)
def _option_xml(self):
"""
把_option_onnx()转化完的权重继续转化成xml保存在创建的xml文件夹中
在parser的xml-outpath中设置权重输出路径,默认在model/xml中,按照权重批次分文件夹
"""
if not os.path.exists(self.args.xml_outpath): os.makedirs(self.args.xml_outpath)
mean_255 = [i * 255.0 for i in self.train_info.MEAN]
std_255 = [i * 255.0 for i in self.train_info.STD]
command = f'mo --input_model {filename} --output_dir {self.args.xml_outpath} --mean_values ' \\
f'[{mean_255[0]},{mean_255[1]},{mean_255[2]}] --scale_values ' \\
f'[{std_255[0]},{std_255[1]},{std_255[2]}]'
os.system(command)