Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【PaddlePaddle Hackathon】在Paddle2ONNX 新增11个 Paddle 2.0 API 支持 #363

Merged
merged 27 commits into from Oct 26, 2021
Merged

Conversation

AndPuQing
Copy link
Contributor

PR types :New features

Describe:

Task: #343

在Paddle2ONNX 新增11个 Paddle 2.0 API 支持

11个 API 具体为:

  • paddle.argsort(x, axis=- 1, descending=False, name=None)
  • paddle.nn.functional.hardtanh(x, min=-1.0, max=1.0, name=None)
  • paddle.dist(x, y, p=2)
  • paddle.dot(x, y, name=None)
  • paddle.index_select(x, index, axis=0, name=None)
  • paddle.nn.functional.log_softmax(x, axis=- 1, dtype=None, name=None)
  • paddle.mv(x, vec, name=None)
  • paddle.nn.Pad1D(padding, mode='constant', value=0.0, data_format='NCL', name=None)
  • paddle.sinh(x, name=None)
  • paddle.numel(x)
  • paddle.nn.functional.softsign(x, name=None)

paddle2onnx/op_mapper/nn.py Outdated Show resolved Hide resolved
paddle2onnx/op_mapper/nn.py Outdated Show resolved Hide resolved
paddle2onnx/op_mapper/search.py Outdated Show resolved Hide resolved
@yeliang2258
Copy link
Collaborator

另外解决一下merge冲突,更新一下op_list

paddle2onnx/op_mapper/math.py Outdated Show resolved Hide resolved
paddle2onnx/op_mapper/math.py Outdated Show resolved Hide resolved
paddle2onnx/op_mapper/math.py Show resolved Hide resolved
tests/test_dot.py Show resolved Hide resolved
super(Net, self).__init__()
self._pad = paddle.nn.Pad1D(padding=1, mode='constant')
self.mode = mode
self._pad = paddle.nn.Pad1D(padding=1, mode=self.mode)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里组网仅测试了padding为常数值的情况,需包含以下几种情况

  1. padding=1
  2. padding=[1, 2]
  3. padding=Tensor([1])
  4. padding=Tensor([1, 2])

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tensor输入的支持似乎是一个遗留问题,见如下TODO

#TODO support pads is Variable

在转换中发现,是paddle源码中判断当padVariable时,将pad放入inputs中,如下代码

https://github.com/PaddlePaddle/Paddle/blob/06d47ff7e2dff1d2daa96eaff525d81ef7c013eb/python/paddle/nn/functional/common.py#L1325

这样在转换成onnx后需要网络输入padding,但是这个pad在paddle中是由attr输入的,使得onnx网络不能拿到该节点。但若写成输入padding形式,如下

obj.set_input_data(
    "input_data",
    paddle.to_tensor(
        randtool("float", -1, 1, [3, 1, 10]).astype('float32')),
    paddle.to_tensor([1, 2]).astype('int32'))

在paddle这边会遇到动转静类型问题

>   ???
E   TypeError: In transformed code:
E
E       File "/home/ray/workspace/PuQing/Paddle2ONNX/tests/test_nn_Pad1D.py", line 38, in forward
E           print(padding)
E           self._pad = paddle.nn.Pad1D(padding=padding, mode=self.mode)
E           x = self._pad(inputs)
E           ~~~~~~~~~~~~~~~~~~~~~ <--- HERE
E           return x
E
E       TypeError: _set_attr(): incompatible function arguments. The following argument types are supported:
E       1. (self: paddle.fluid.core_avx.OpDesc, arg0: str, arg1: Variant) -> None
E
E   Invoked with: <paddle.fluid.core_avx.OpDesc object at 0x7fb2b3f12d30>, 'paddings', [0, 0, 0, 0, var 1 : LOD_TENSOR.shape(2,).dtype(int32).stop_gradient(False), var 1 : LOD_TENSOR.shape(2,).dtype(int32).stop_gradient(False)]

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image
尝试这样写单测?你在看看能否改改pad的OP转换,将其转成功

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

emm,就像这样写吗?

def test_Pad1D_paddingTensor():
    """
    api: paddle.nn.Pad1D
    op version: 12
    """
    op = Net(padding=paddle.to_tensor(np.array([1, 2])).astype('int32'))
    op.eval()
    # net, name, ver_list, delta=1e-6, rtol=1e-5
    obj = APIOnnx(op, 'nn_Pad1D', [12])
    obj.set_input_data(
        "input_data",
        paddle.to_tensor(
            randtool("float", -1, 1, [3, 1, 10]).astype('float32')))
    obj.run()

pad代码并未改动,报错发生在

        elif node.attr('data_format') == 'NCDHW':
            onnx_paddings = [
>               0, 0, paddings[4], paddings[2], paddings[0], 0, 0, paddings[5],
                paddings[3], paddings[1]
E               IndexError: list index out of range

打印该结点

    def convert_padding(cls, node, **kw):
        x_shape = node.input_shape('X', 0)
        paddings = node.attr('paddings')
>       raise NameError(paddings)
E       NameError: []

若打印node_inputs

    @classmethod
    def convert_padding(cls, node, **kw):
        x_shape = node.input_shape('X', 0)
        paddings = node.attr('paddings')
>       raise NameError(node.input('Paddings'))
E       NameError: ['concat_0.tmp_0']

就像上面说的,paddings如果是tensor将会在input中

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

上面单测报错应该是pad使用tensor作为输入的时候对size有要求,你按照我的那个实例的参数设置一下。你看看之前的开发例子,看能否将这个convert_padding修改符合要求。

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

确实这个padding为tensor的输入比较复杂,那暂时先不实现这个例子吧,padding为tensor输入的情况先不实现。

@jiangjiajun
Copy link
Collaborator

注意到当前代码已经出现了冲突 @AndPuQing

@jiangjiajun
Copy link
Collaborator

@AndPuQing CI中有部分单测没过,可点进去(login as guest)看下build_log,在里面可以找到具体出错的原因

@AndPuQing
Copy link
Contributor Author

@AndPuQing CI中有部分单测没过,可点进去(login as guest)看下build_log,在里面可以找到具体出错的原因

提示访问错误,正在请交流群群主看看,周一回复

@AndPuQing
Copy link
Contributor Author

@AndPuQing CI中有部分单测没过,可点进去(login as guest)看下build_log,在里面可以找到具体出错的原因

CI似乎通过了

@AndPuQing
Copy link
Contributor Author

最新push版本是能支持Tensor的paddings动态输入,但是还不完善,以下是我目前知道该OP的信息

Padddle部分的计算图

在进入Pad3D算子之前,Paddings会Concat一下。而在转化时,node只能拿到Concat之后的节点名称concat_1.tmp_0,在转化为onnx模型后,如下图:

网络需要一个命名为auto_25_的输入,但是矛盾的是该输入是在Concat节点中输入的,所以我添加了一个名为auto_25_的节点输入,如下

# tensor.py
graph.add_input_node('auto_25_', [2],
                                 dtypes.DTYPE_ONNX_STR_MAP['float64'])

这样修改后,在onnx推理阶段就不能使用onnxbase.py中的API进行推理了,只能自定义输入名,如下

# test_nn_Pad1D.py
sess = InferenceSession(
        os.path.join(os.getcwd(), 'nn_Pad1D', 'nn_Pad1D' + '12' + '.onnx'))
x = np.random.random([3, 1, 10]).astype('float32')
y = np.array([1, 2]).astype('int32')
ort_inputs = {sess.get_inputs()[0].name: x, sess.get_inputs()[1].name: y}

在本地测试中,以上写法是能达到精度的,但是问题很明显,auto_25_输入名是不定的,所以我修改了输入进paddings的名字,并且进输入pad名固定为pad,如下

# tensor.py
graph.add_input_node('pad', [2],dtypes.DTYPE_ONNX_STR_MAP['float64'])
# test_nn_Pad1D.py
paddings = paddle.to_tensor([1, 2]).astype('int32')
paddings.name = 'pad'
op = Net(padding=paddings)
op.eval()
# net, name, ver_list, delta=1e-6, rtol=1e-5
obj = APIOnnx(op, 'nn_Pad1D', [12])

以上我的实现,希望有所用。 @yeliang2258 @jiangjiajun

@jiangjiajun jiangjiajun merged commit b9bc3c5 into PaddlePaddle:develop Oct 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants