Skip to content

Commit 91eabc3

Browse files
committed
add depthtospace converter
1 parent 29158ff commit 91eabc3

File tree

3 files changed

+163
-1
lines changed

3 files changed

+163
-1
lines changed

tests/test_subpixelconv.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#! /usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
import os
4+
# os.environ["TL_BACKEND"] = 'tensorflow'
5+
# os.environ["TL_BACKEND"] = 'paddle'
6+
os.environ["TL_BACKEND"] = 'torch'
7+
# os.environ["TL_BACKEND"] = 'mindspore'
8+
import tensorlayerx as tlx
9+
from tensorlayerx.nn import Module
10+
from tensorlayerx.nn import SubpixelConv2d
11+
from tlx2onnx.main import export
12+
import onnxruntime as rt
13+
import numpy as np
14+
tlx.set_seed(42)
15+
16+
class conv(Module):
17+
18+
def __init__(self):
19+
super(conv, self).__init__()
20+
self.conv = SubpixelConv2d(scale=2, data_format="channels_last")
21+
22+
def forward(self, x):
23+
24+
x = self.conv(x)
25+
return x
26+
27+
model = conv()
28+
input = tlx.nn.Input(shape= (1, 2, 2, 8), init=tlx.nn.initializers.HeUniform())
29+
model.set_eval()
30+
output = model(input)
31+
print("SubpixelConv2d tlx output", output)
32+
onnx_model = export(model, input_spec=input, path='SubpixelConv2d.onnx', opset_version = 11)
33+
34+
sess = rt.InferenceSession('SubpixelConv2d.onnx')
35+
input_name = sess.get_inputs()[0].name
36+
output_name = sess.get_outputs()[0].name
37+
38+
input_data = np.array(input, dtype=np.float32)
39+
result = sess.run([output_name], {input_name: input_data})
40+
print("SubpixelConv2d onnx output", result)

tlx2onnx/op_mapper/nn/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@
2020
from .noise import *
2121
from .padding import *
2222
from .scale import *
23-
from .stack import *
23+
from .stack import *
24+
from .subpixelconv import *
25+
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#! /usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
import numpy as np
4+
import onnx
5+
from onnx import helper, numpy_helper
6+
from collections import OrderedDict
7+
import tensorlayerx as tlx
8+
from tlx2onnx.op_mapper.datatype_mapping import NP_TYPE_TO_TENSOR_TYPE
9+
from tlx2onnx.op_mapper.op_mapper import OpMapper
10+
from tlx2onnx.common import make_node
11+
from tlx2onnx.common import make_shape_channels_first, get_channels_first_permutation,get_channels_last_permutation
12+
13+
@OpMapper(["SubpixelConv2d"])
14+
class SubpixelConv():
15+
16+
@classmethod
17+
def version_1(cls, node, **kwargs):
18+
onnx_node = []
19+
onnx_value = []
20+
onnx_init = []
21+
22+
op_type = "DepthToSpace"
23+
attr_dict = OrderedDict()
24+
# get in_node_name out_node_nmae
25+
x_name = node['in_nodes_name'][0]
26+
out_name = node['out_nodes_name'][0]
27+
x_shape = node['in_tensors'][0]
28+
out_shape = node['out_tensors'][0]
29+
30+
# get data_type
31+
data_type = node['dtype']
32+
tensor_type = NP_TYPE_TO_TENSOR_TYPE[data_type]
33+
34+
# get cur_node_layer node_index
35+
layer = node['node'].layer
36+
layer_name = layer.__class__.__name__
37+
spatial = int(layer_name[-2])
38+
39+
# get layer attr
40+
scale = layer.scale
41+
data_format = layer.data_format
42+
attr_dict["blocksize"] = scale
43+
44+
if data_format == "channels_last":
45+
permutation = get_channels_first_permutation(spatial)
46+
x_shape_t = make_shape_channels_first(x_shape)
47+
transpose_value = helper.make_tensor_value_info(x_name + '_t', tensor_type, shape=x_shape_t)
48+
onnx_value.append(transpose_value)
49+
transpose_node, out = make_node('Transpose', inputs=[x_name], outputs=[x_name + '_t'], perm=permutation)
50+
onnx_node.append(transpose_node)
51+
depth_to_space, out = make_node(op_type, inputs=[out], outputs=[out + '_t'], **attr_dict)
52+
onnx_node.append(depth_to_space)
53+
permutation = get_channels_last_permutation(spatial)
54+
transpose_node, out = make_node('Transpose', inputs=[out], outputs=[out_name], perm=permutation)
55+
onnx_node.append(transpose_node)
56+
return onnx_node, onnx_value, onnx_init
57+
58+
elif data_format == 'channels_first':
59+
60+
depth_to_space, out = make_node(op_type, inputs=[x_name], outputs=[out_name], **attr_dict)
61+
onnx_node.append(depth_to_space)
62+
return onnx_node, onnx_value, onnx_init
63+
else:
64+
raise ValueError(
65+
"Only support 'channels_first' or 'channels_last' data_format mode, but got {}.".format(data_format))
66+
67+
@classmethod
68+
def version_11(cls, node, **kwargs):
69+
onnx_node = []
70+
onnx_value = []
71+
onnx_init = []
72+
73+
op_type = "DepthToSpace"
74+
attr_dict = OrderedDict()
75+
# get in_node_name out_node_nmae
76+
x_name = node['in_nodes_name'][0]
77+
out_name = node['out_nodes_name'][0]
78+
x_shape = node['in_tensors'][0]
79+
out_shape = node['out_tensors'][0]
80+
81+
# get data_type
82+
data_type = node['dtype']
83+
tensor_type = NP_TYPE_TO_TENSOR_TYPE[data_type]
84+
85+
# get cur_node_layer node_index
86+
layer = node['node'].layer
87+
layer_name = layer.__class__.__name__
88+
spatial = int(layer_name[-2])
89+
90+
# get layer attr
91+
scale = layer.scale
92+
data_format = layer.data_format
93+
attr_dict["blocksize"] = scale
94+
if tlx.BACKEND in ["tensorflow", "mindspore"]:
95+
attr_dict["mode"] = "DCR"
96+
elif tlx.BACKEND in ["torch", "paddle"]:
97+
attr_dict["mode"] = "CRD"
98+
99+
if data_format == "channels_last":
100+
permutation = get_channels_first_permutation(spatial)
101+
x_shape_t = make_shape_channels_first(x_shape)
102+
transpose_value = helper.make_tensor_value_info(x_name + '_t', tensor_type, shape=x_shape_t)
103+
onnx_value.append(transpose_value)
104+
transpose_node, out = make_node('Transpose', inputs=[x_name], outputs=[x_name + '_t'], perm=permutation)
105+
onnx_node.append(transpose_node)
106+
depth_to_space, out = make_node(op_type, inputs=[out], outputs=[out + '_t'], **attr_dict)
107+
onnx_node.append(depth_to_space)
108+
permutation = get_channels_last_permutation(spatial)
109+
transpose_node, out = make_node('Transpose', inputs=[out], outputs=[out_name], perm=permutation)
110+
onnx_node.append(transpose_node)
111+
return onnx_node, onnx_value, onnx_init
112+
113+
elif data_format == 'channels_first':
114+
115+
depth_to_space, out = make_node(op_type, inputs=[x_name], outputs=[out_name], **attr_dict)
116+
onnx_node.append(depth_to_space)
117+
return onnx_node, onnx_value, onnx_init
118+
else:
119+
raise ValueError(
120+
"Only support 'channels_first' or 'channels_last' data_format mode, but got {}.".format(data_format))

0 commit comments

Comments
 (0)