1、问题描述:

        使用的模型是PAN模型,在转Onnx以后,测试正常,将Onnx模型转成OM模型以后,准确率出现了大幅下降,查看PAN输出的分割区域发现与Onnx也产生了非常明显的差异;经过各种尝试以后,确定是ResizeBilinearV2算子的问题,得以解决。

2、问题现象

        (1)将PAN的Onnx模型转成OM模型以后,整体准确率出现了较大下降,对比输出的分割结果,在图像上的范围也产生了明显的差异,所以是模型精度出现了问题。

        (2)使用mist工具可以对比Onnx模型和OM模型各节点输出的差异,使用 mist debug compare 工具dump数据进行对比,并获得输出的精度差异报告result_{timestamp}.csv,根据mist项目说明中的结果指标参数分析产生精度差异的节点。还有一个指标是 IsPrecisionError ,是给出的认为出现异常的节点。

msit debug compare -gm model.onnx -om model.om -i input.bin -is "image:1,3,192,256" -c /usr/local/Ascend/ascend-toolkit/latest -o om_out

        (3)当前模型结果中首先出现异常的就是Resize节点,所以就从Resize节点开始分析。其中groundTruth是Onnx模型中的节点名称;NPUDump是OM模型中的节点名称;OpType是OM模型中的算子类型。

3、问题解决

最终在昇腾论坛中找到一篇文章记录了ResizeBilinearV2算子的问题,参照其方法得到了解决。

        原贴地址:gfpgan_1.4.onnx转om时将Reszie使用ResizeBilinearV2后出现精度问题_CANN_昇腾论坛

       (1)原贴作者分析原因是:

                1)、Onnx中Resize算子的coordinate_transformation_mode默认使用half_pixel模式。

                2)、昇腾ResizeBilinearV2算子使用的模式是pytorch_half_pixel模式。

                二者的差异导致了该算子出现精度问题。

        (2)解决问题

        在PAN的torch代码中使用的是 nn.Upsample 的方法,模式都是默认模式;使用Netron打开pt模型是upsample_bilinear2d节点。

        在转成Onnx模型以后,upsample_bilinear2d节点转成了Resize算子,其中的coordinate_transformation_mode 默认是 half_pixel。

        需要将coordinate_transformation_mode 的值修改成 pytorch_half_pixel 才行

import onnx
from onnx import helper

model = onnx.load("model.onnx")
graph = model.graph

# 2. 遍历所有 Resize 节点
for node in graph.node:
    if node.op_type == "Resize":
        # 查找已有的 coordinate_transformation_mode 属性
        found = False
        for attr in node.attribute:
            if attr.name == "coordinate_transformation_mode":
                # 修改为 pytorch_half_pixel
                attr.s = b"pytorch_half_pixel"
                found = True
                break
        if not found:
            # 如果没有,就追加一个新的属性
            node.attribute.append(
                helper.make_attribute(
                    "coordinate_transformation_mode",
                    "pytorch_half_pixel"
                )
            )

# 3. 保存新模型
onnx.save(model, "model_pytorch_half_pixel.onnx")
print("model_pytorch_half_pixel.onnx")

        最后再使用atc工具将Onnx模型转成OM模型即可,精度与Onnx输出差异极小。

4、其他

        这里使用PAN模型输出在昇腾的NPU上出现了较大的精度差异,另一个原因可能是该模型中用到了15个Upsample,导致累积的差异越来越大,反应在输出结果上就比较明显;如果使用的个数较少,可能就不明显。

Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐