能否将ONNX ConvInteger算子转换为OpenVINO并保留张量精度?
关于OpenVINO转换ConvInteger算子保留INT8/UINT8精度的解答
转换阶段能否强制保留INT8/UINT8精度
- 你当前使用的基础转换命令
mo --input_model {onnx_model}无法实现该需求。模型优化器(MO)内置的ONNX ConvInteger算子转换规则默认会将INT8/UINT8的输入、权重张量抬升为INT32精度,自动插入convert算子完成精度转换,目前没有公开的命令行参数可以直接关闭这个默认逻辑。 - 如果需要在转换阶段就保留原始低精度,需要自定义编写MO的算子扩展,重写ConvInteger的前端转换逻辑,移除自动插入精度转换节点的代码,同时指定算子输入端口匹配INT8/UINT8张量类型。注意该操作需要提前确认你使用的OpenVINO版本对应的目标硬件插件支持INT8精度卷积计算,否则即使转换阶段保留了低精度,推理加载时Runtime仍会自动插入精度转换算子。
IR生成后转换为INT8/UINT8精度的简便方法
不需要重写MO转换逻辑,有两种可直接落地的方案:
- 方案一:通过OpenVINO Python API直接修改计算图,删除冗余转换节点,操作步骤如下:
- 调用
core.read_model()接口读取转换生成的IR模型 - 按拓扑序遍历模型节点,定位所有输入为INT8/UINT8、输出为INT32,且输出直接连接到ConvInteger节点输入端口的
convert算子 - 将这些
convert节点的输入直接连接到后续ConvInteger节点的对应输入端口,移除冗余的convert节点 - 注意不要修改ConvInteger节点本身的输出精度:该算子唯一支持的输出精度为INT32,强行修改会触发推理报错
- 调用
ov.serialize()接口导出修改后的模型即可
参考实现代码:
import openvino as ov core = ov.Core() model = core.read_model("your_converted_model.xml") # 移除冗余的INT8->INT32转换节点 for op in model.get_ordered_ops(): if op.get_type_name() == "Convert" and op.get_output_element_type(0) == ov.Type.i32: input_type = op.get_input_element_type(0) if input_type in (ov.Type.i8, ov.Type.u8): # 重连输出边,跳过Convert节点 target_inputs = op.output(0).get_target_inputs() source_output = op.input(0).get_source_output() for inp in target_inputs: source_output.connect(inp) # 导出修改后的模型 ov.serialize(model, "int8_preserved_model.xml", "int8_preserved_model.bin") - 调用
- 方案二:如果你的最终目标是部署低精度模型获得推理加速,可以直接使用OpenVINO自带的后训练量化工具(POT)对生成的IR做INT8量化。该工具会自动对算子做精度适配,移除冗余的精度转换节点,生成的模型可直接在支持INT8加速的硬件上运行,不需要手动修改计算图。
注意:无论使用哪种方案修改精度,都需要确认部署目标硬件支持INT8/UINT8精度的算子执行,否则OpenVINO Runtime加载模型时仍会自动插入精度转换算子,无法达到降低内存占用、提升推理速度的效果。
内容的提问来源于stack exchange,提问作者shmark
相关产品推荐
相关产品推荐

