PaddlePaddle / Paddle2ONNX

ONNX Model Exporter for PaddlePaddle
Apache License 2.0
710 stars 162 forks source link

hard_sigmoid问题 #485

Open axdo opened 2 years ago

axdo commented 2 years ago

使用paddle2onnx将训练好的picodet模型转换成了onnx格式,代码如下: paddle2onnx --model_dir inference_model/picodet_s_320_voc/ \ --model_filename model.pdmodel \ --params_filename model.pdiparams \ --opset_version 11 \ --save_file picodet_s_320_voc.onnx python -m onnxsim picodet_s_320_voc.onnx picodet_s_320_voc_f1.onnx 然后使用opencv进行调用 import cv2 import onnx

载入onnx模块

model_ = onnx.load("PaddleDetection/picodet_s_320_voc_f1.onnx")

检查IR是否良好

print(onnx.checker.checkmodel(model))

opencv 推理

net = cv2.dnn.readNetFromONNX("PaddleDetection/picodet_s_320_voc_f1.onnx") # 加载训练好的识别模型 print('load successful') image = cv2.imread("PaddleDetection/dataset/voc/images/000003.png") # 读取图片 blob = cv2.dnn.blobFromImage(image) # 由图片加载数据 这里还可以进行缩放、归一化等预处理 net.setInput(blob) # 设置模型输入 out = net.forward() # 推理出结果 运行然后报错: Traceback (most recent call last): File "opecvonnx.py", line 10, in net = cv2.dnn.readNetFromONNX("PaddleDetection/picodet_s_320_voc_f1.onnx") # 加载训练好的识别模型 cv2.error: OpenCV(4.1.1) /io/opencv/modules/dnn/src/dnn.cpp:525: error: (-2:Unspecified error) Can't create layer "hardsigmoid_0.tmp_0" of type "HardSigmoid" in function 'getLayerInstance'

不能read hardsigmoid层 请问这个有啥解决办法吗?

jiangjiajun commented 2 years ago

HardSigmoid在OpenCV中不支持,可以考虑使用其它OP来组合完成 https://github.com/PaddlePaddle/Paddle2ONNX/blob/develop/paddle2onnx/op_mapper/activation.py#L163 可以将此函数替换为下面的实现,重新安装后再导出ONNX模型

    @classmethod
    def opset_1(cls, graph, node, **kw):
        slope = node.attr('slope')
        offset = node.attr('offset')
        slope_node = graph.make_node(
            'Constant', attrs={'dtype': dtypes.ONNX.FLOAT,
                               'value': slope})
        offset_node = graph.make_node(
            'Constant',
            attrs={'dtype': dtypes.ONNX.FLOAT,
                   'value': offset})
        tmp0 = graph.make_node(
            'Div', inputs=[node.input('X')[0], slope_node])
        tmp1 = graph.make_node('Add', inputs=[tmp0, offset_node])
        mapper_helper.clip_helper(graph, tmp1,
                                  max=1.0, min=0.0,
                                  output=node.output('Out', 0))
jiangjiajun commented 2 years ago

另外方便的话,麻烦抽出半分钟时间帮我们完成一个Paddle2ONNX的调研问卷, 帮助Paddle2ONNX做得更好https://iwenjuan.baidu.com/?code=r8hu2s 谢谢!

yuenshangli commented 2 years ago

HardSigmoid在OpenCV中不支持,可以考虑使用其它OP来组合完成 https://github.com/PaddlePaddle/Paddle2ONNX/blob/develop/paddle2onnx/op_mapper/activation.py#L163 可以将此函数替换为下面的实现,重新安装后再导出ONNX模型

    @classmethod
    def opset_1(cls, graph, node, **kw):
        slope = node.attr('slope')
        offset = node.attr('offset')
        slope_node = graph.make_node(
            'Constant', attrs={'dtype': dtypes.ONNX.FLOAT,
                               'value': slope})
        offset_node = graph.make_node(
            'Constant',
            attrs={'dtype': dtypes.ONNX.FLOAT,
                   'value': offset})
        tmp0 = graph.make_node(
            'Div', inputs=[node.input('X')[0], slope_node])
        tmp1 = graph.make_node('Add', inputs=[tmp0, offset_node])
        mapper_helper.clip_helper(graph, tmp1,
                                  max=1.0, min=0.0,
                                  output=node.output('Out', 0))

嗨,您好。我名叫礼,我现在在尝试用paddleocr来export model, 然后再转换onnx,再让opencv上使用。

我也是遇到hard_sigmoid的问题,谢谢您给出解决方法,但是尝试这个方法后,又出现新的问题如下:

xxx\inference>paddle2onnx --model_dir saved_inference_model --model_filename model.pdmodel --params_filename model.pdiparams --save_file model.onnx --opset_version 10
xxx\lib\site-packages\paddle\vision\transforms\functional_pil.py:36: DeprecationWarning: NEAREST is deprecated and will be removed in Pillow 10 (2023-07-01). Use Resampling.NEAREST or Dither.NONE instead.
  'nearest': Image.NEAREST,
xxx\lib\site-packages\paddle\vision\transforms\functional_pil.py:37: DeprecationWarning: BILINEAR is deprecated and will be removed in Pillow 10 (2023-07-01). Use Resampling.BILINEAR instead.
  'bilinear': Image.BILINEAR,
xxx\lib\site-packages\paddle\vision\transforms\functional_pil.py:38: DeprecationWarning: BICUBIC is deprecated and will be removed in Pillow 10 (2023-07-01). Use Resampling.BICUBIC instead.
  'bicubic': Image.BICUBIC,
xxx\lib\site-packages\paddle\vision\transforms\functional_pil.py:39: DeprecationWarning: BOX is deprecated and will be removed in Pillow 10 (2023-07-01). Use Resampling.BOX instead.
  'box': Image.BOX,
xxx\lib\site-packages\paddle\vision\transforms\functional_pil.py:40: DeprecationWarning: LANCZOS is deprecated and will be removed in Pillow 10 (2023-07-01). Use Resampling.LANCZOS instead.
  'lanczos': Image.LANCZOS,
xxx\lib\site-packages\paddle\vision\transforms\functional_pil.py:41: DeprecationWarning: HAMMING is deprecated and will be removed in Pillow 10 (2023-07-01). Use Resampling.HAMMING instead.
  'hamming': Image.HAMMING
xxx\lib\site-packages\onnx\helper.py:343: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3,and in 3.9 it will stop working
  is_iterable = isinstance(value, collections.Iterable)
Traceback (most recent call last):
  File "xxx\lib\site-packages\paddle2onnx\op_mapper\op_mapper.py", line 119, in mapping
    mapper_func(graph, node, **kw)
  File "xxx\lib\site-packages\paddle2onnx\op_mapper\activation.py", line 203, in opset_1
    output=node.output('Out', 0))
TypeError: clip_helper() missing 1 required positional argument: 'input'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "xxx\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "xxx\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "xxx\Scripts\paddle2onnx.exe\__main__.py", line 7, in <module>
  File "xxx\lib\site-packages\paddle2onnx\command.py", line 283, in main
    auto_update_opset=args.enable_auto_update_opset)
  File "xxx\lib\site-packages\paddle2onnx\command.py", line 210, in program2onnx
    output_names=output_names)
  File "xxx\lib\site-packages\paddle2onnx\convert.py", line 102, in program2onnx
    output_names=output_names)
  File "xxx\lib\site-packages\paddle2onnx\convert.py", line 37, in export_onnx
    auto_update_opset)
  File "xxx\lib\site-packages\paddle2onnx\graph\onnx_graph.py", line 331, in build
    onnx_graph.build_op_nodes(paddle_graph.node_map)
  File "xxx\lib\site-packages\paddle2onnx\graph\onnx_graph.py", line 209, in build_op_nodes
    OpMapper.mapping(self, node, self.operator_export_type)
  File "xxx\lib\site-packages\paddle2onnx\op_mapper\op_mapper.py", line 124, in mapping
    node.outputs) + str(e))
Exception: Error happened when mapping node ['hard_sigmoid_0'] to onnx, which op_type is 'hard_sigmoid' with inputs: {'X': ['conv2d_72.tmp_1']} and outputs: {'Out': ['hardsigmoid_0.tmp_0']}, specific error: clip_helper() missing 1 required positional argument: 'input'

请问还有什么办法可以解决这个问题?

谢谢。

jiangjiajun commented 2 years ago

Hi, 礼 @yuenshangli 上面的代码有问题,你将xxx\lib\site-packages\paddle2onnx\op_mapper\activation.py这个代码文件中的class HardSigmoid()整块代码替换为下面代码即可

@op_mapper('hard_sigmoid')
class HardSigmoid():
    support_opset_verison_range = (6, 12)

    @classmethod
    def opset_6(cls, graph, node, **kw):
        slope = node.attr('slope')
        offset = node.attr('offset')

        to_opencv = True
        if not to_opencv:
            graph.make_node(
                'HardSigmoid',
                inputs=node.input('X'),
                outputs=node.output('Out'),
                alpha=slope,
                beta=offset)
        else:
            slope_node = graph.make_node(
                'Constant', attrs={'dtype': dtypes.ONNX.FLOAT,
                                   'value': slope})
            offset_node = graph.make_node(
                'Constant',
                attrs={'dtype': dtypes.ONNX.FLOAT,
                       'value': offset})
            tmp0 = graph.make_node(
                'Div', inputs=[node.input('X')[0], slope_node])
            tmp1 = graph.make_node('Add', inputs=[tmp0, offset_node])
            graph.make_node(
                'Clip',
                inputs=[tmp1],
                min=0.0,
                max=1.0,
                outputs=node.output('Out'))

    @classmethod
    def opset_11(cls, graph, node, **kw):
        slope = node.attr('slope')
        offset = node.attr('offset')

        to_opencv = True
        if not to_opencv:
            graph.make_node(
                'HardSigmoid',
                inputs=node.input('X'),
                outputs=node.output('Out'),
                alpha=slope,
                beta=offset)
        else:
            slope_node = graph.make_node(
                'Constant', attrs={'dtype': dtypes.ONNX.FLOAT,
                                   'value': slope})
            offset_node = graph.make_node(
                'Constant',
                attrs={'dtype': dtypes.ONNX.FLOAT,
                       'value': offset})
            tmp0 = graph.make_node(
                'Mul', inputs=[node.input('X')[0], slope_node])
            tmp1 = graph.make_node('Add', inputs=[tmp0, offset_node])
            const0 = graph.make_node(
                'Constant', attrs={'dtype': dtypes.ONNX.FLOAT,
                                   'value': 0.0})
            const1 = graph.make_node(
                'Constant', attrs={'dtype': dtypes.ONNX.FLOAT,
                                   'value': 1.0})
            graph.make_node(
                'Clip',
                inputs=[tmp1, const0, const1],
                outputs=node.output('Out'))
yuenshangli commented 2 years ago

嗨,谢谢您的快速回复。真的很感激~

我尝试了您的方法,这个hard_sigmoid问题解决了。谢谢。

但是当我用opencv来执行构建的onnx文件时,又出现了其他报错:

cv2.error: OpenCV(4.5.3) C:\Users\runneradmin\AppData\Local\Temp\pip-req-build-c2l3r8zm\opencv\modules\dnn\src\onnx\onnx_importer.cpp:2146: error: (-2:Unspecified error) in function 'cv::dnn::dnn4_v20210608::ONNXImporter::handleNode'
> Node [Transpose]:(transpose_0.tmp_0) parse error: OpenCV(4.5.3) C:\Users\runneradmin\AppData\Local\Temp\pip-req-build-c2l3r8zm\opencv\modules\dnn\src\layers\permute_layer.cpp:138: error: (-215:Assertion failed) (int)_numAxes == inputs[0].size() in function 'cv::dnn::PermuteLayerImpl::getMemoryShapes'
>

xxx\lib\site-packages\numpy\_distributor_init.py:32: UserWarning: loaded more than 1 DLL from .libs:
xxx\lib\site-packages\numpy\.libs\libopenblas.NOIJJG62EMASZI6NYURL6JBKM4EVBGM7.gfortran-win_amd64.dll
xxx\lib\site-packages\numpy\.libs\libopenblas.PYQHXLVVQ7VESDPUVUADXEVJOBGHJPAY.gfortran-win_amd64.dll
xxx\lib\site-packages\numpy\.libs\libopenblas.WCDJNK7YVMPZQ2ME2ZZHJJRJ3JIKNDB7.gfortran-win_amd64.dll
  stacklevel=1)
[ERROR:0] global C:\Users\runneradmin\AppData\Local\Temp\pip-req-build-c2l3r8zm\opencv\modules\dnn\src\onnx\onnx_importer.cpp (2127) cv::dnn::dnn4_v20210608::ONNXImporter::handleNode DNN/ONNX: ERROR during processing node with 1 inputs and 1 outputs: [Transpose]:(transpose_0.tmp_0)

可以问问这个部分要怎么处理吗?

谢谢。很感激。

** 我是根据这个 https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.4/doc/doc_ch/recognition.md 来进行模块训练和生成。

GreenAvocado92 commented 2 years ago

Hi,请教一个问题,我用paddle2onnx转换完模型,然后用cv readnet的时候报下面错误,请问是怎么回事,我现在的目标是,用cv调用 (PaddleOCR的模型,因为华为昇腾310的U支持的不够多,所以通过opencv调用paddleOCR的模型的方式曲线救国) ----> 1 net = cv2.dnn.readNetFromONNX('paddle_ocr_det.onnx')

error: OpenCV(4.4.0) /tmp/pip-req-build-xgme2194/opencv/modules/dnn/src/dnn.cpp:604: error: (-2:Unspecified error) Can't create layer "hardsigmoid_0.tmp_0" of type "HardSigmoid" in function 'getLayerInstance'

升级opencv 4.6后这个问题没有了,但是有了新的报错 OpenCV(4.6.0) /io/opencv/modules/dnn/src/onnx/onnx_importer.cpp:255: error: (-5:Bad argument) Can't read ONNX file: paddle_ocr_rec.onnx in function 'ONNXImporter'