Skip to content

Commit b3121e2

Browse files
authored
Merge pull request #125 from klassen9/feature/resize_4d_conversion
Add resize to change_3d_tensors_to_4d transformation
2 parents 6d27a18 + 76bd715 commit b3121e2

File tree

4 files changed

+121
-3
lines changed

4 files changed

+121
-3
lines changed

src/qonnx/analysis/topology.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@ def all_tensors_f32(model):
5656
annotations notwithstanding.
5757
5858
Returns {"all_tensors_f32": Bool}."""
59-
all_tensors = model.make_empty_exec_context().items()
59+
exec_ctx = model.make_empty_exec_context()
60+
# remove the special empty string entry in the context since it has no tensor
61+
exec_ctx.pop("")
62+
all_tensors = exec_ctx.items()
6063
non_f32_tensors = filter(lambda x: x[1].dtype != np.float32, all_tensors)
6164
return {"all_tensors_f32": len(list(non_f32_tensors)) == 0}
6265

src/qonnx/core/modelwrapper.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,9 @@ def make_empty_exec_context(self):
510510
# fill in the constants provided by the initializers (TensorProto to npy)
511511
for t in graph.initializer:
512512
execution_context[t.name] = np_helper.to_array(t)
513+
# for nodes that use empty string as input (=default value), create a
514+
# dummy entry in the context
515+
execution_context[""] = None
513516
return execution_context
514517

515518
def check_all_tensor_shapes_specified(self, fix_missing_init_shape=False):
@@ -525,7 +528,9 @@ def check_all_tensor_shapes_specified(self, fix_missing_init_shape=False):
525528
# see https://github.com/fastmachinelearning/qonnx/issues/33
526529
for n in graph.node:
527530
for i in n.input:
528-
ret = (self.get_tensor_shape(i, fix_missing_init_shape=fix_missing_init_shape) is not None) and ret
531+
# skip tensor names with empty string (indicates defaults)
532+
if i != "":
533+
ret = (self.get_tensor_shape(i, fix_missing_init_shape=fix_missing_init_shape) is not None) and ret
529534
for o in n.output:
530535
ret = (self.get_tensor_shape(o, fix_missing_init_shape=fix_missing_init_shape) is not None) and ret
531536
return ret

src/qonnx/transformation/change_3d_tensors_to_4d.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def _find_invalid_nodes(model):
6464
"Reshape",
6565
"MaxPool",
6666
"Upsample",
67+
"Resize",
6768
]
6869
invalid_nodes = []
6970
for n in model.graph.node:
@@ -194,6 +195,43 @@ def apply(self, model):
194195
assert list(scales.shape) == [3]
195196
scales = np.append(scales, np.asarray(1.0, dtype=np.float32))
196197
model.set_initializer(n.input[1], scales)
198+
elif node_op_type == "Resize":
199+
assert "axes" not in [x.name for x in n.attribute], "%s: Axes attribute is not supported." % n.name
200+
assert not (len(n.input) in (3, 4) and model.get_initializer(n.input[1]) is not None), (
201+
"%s: ROI input is not supported." % n.name
202+
)
203+
if len(n.input) == 2:
204+
# Resize version 10
205+
scales = model.get_initializer(n.input[1])
206+
scales = np.append(scales, np.asarray(1.0, dtype=np.float32))
207+
model.set_initializer(n.input[1], scales)
208+
elif len(n.input) == 3:
209+
# Resize version 11 and up (no size input)
210+
scales = model.get_initializer(n.input[2])
211+
scales = np.append(scales, np.asarray(1.0, dtype=np.float32))
212+
model.set_initializer(n.input[2], scales)
213+
elif len(n.input) == 4:
214+
scales_exists = (model.get_initializer(n.input[2]) is not None) and (
215+
len(model.get_initializer(n.input[2])) != 0
216+
)
217+
sizes_exists = (model.get_initializer(n.input[3]) is not None) and (
218+
len(model.get_initializer(n.input[3])) != 0
219+
)
220+
assert scales_exists ^ sizes_exists, (
221+
"%s: Either scales or the target output size must "
222+
"be specified. Specifying both is prohibited." % n.name
223+
)
224+
if scales_exists:
225+
# Scales parameter is a 1d list of upsampling factors along each axis
226+
scales = model.get_initializer(n.input[2])
227+
scales = np.append(scales, np.asarray(1.0, dtype=np.float32))
228+
model.set_initializer(n.input[2], scales)
229+
else:
230+
# Size parameter is a 1d list of the target size along each axis
231+
sizes = model.get_initializer(n.input[3])
232+
sizes = np.append(sizes, np.asarray(1.0, dtype=np.int64))
233+
model.set_initializer(n.input[3], sizes)
234+
input_shape.append(1)
197235

198236
# Change format of each input/value_info/output tensor
199237
for k, v in all_tensors.items():

tests/transformation/test_4d_conversion.py

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import numpy as np
3232
import onnx
3333
import onnx.parser as oprs
34+
from onnx.helper import make_opsetid
3435

3536
import qonnx.core.onnx_exec as oxe
3637
from qonnx.core.datatype import DataType
@@ -328,7 +329,76 @@ def create_conv_upsample():
328329
return model
329330

330331

331-
@pytest.mark.parametrize("test_model", ["Quartz", "VGG", "ConvUpsample"])
332+
def create_resize(opset):
333+
"""
334+
Creates an model for testing the 3D to 4D transform of the resize node.
335+
"""
336+
resize_node1 = onnx.helper.make_node(
337+
"Resize",
338+
inputs=["in_resize1", "roi_resize1", "scales_resize1", "sizes_resize1"],
339+
outputs=["out_resize1"],
340+
name="Resize1",
341+
mode="nearest",
342+
)
343+
344+
resize_node2 = onnx.helper.make_node(
345+
"Resize",
346+
inputs=["out_resize1", "roi_resize2", "scales_resize2"],
347+
outputs=["out_resize2"],
348+
name="Resize2",
349+
mode="nearest",
350+
)
351+
352+
in_resize1 = onnx.helper.make_tensor_value_info("in_resize1", onnx.TensorProto.FLOAT, [1, 32, 4])
353+
out_resize1 = onnx.helper.make_tensor_value_info("out_resize1", onnx.TensorProto.FLOAT, [1, 32, 8])
354+
out_resize2 = onnx.helper.make_tensor_value_info("out_resize2", onnx.TensorProto.FLOAT, [1, 32, 16])
355+
356+
roi_resize1 = onnx.helper.make_tensor_value_info("roi_resize1", onnx.TensorProto.FLOAT, [4])
357+
scales_resize1 = onnx.helper.make_tensor_value_info("scales_resize1", onnx.TensorProto.FLOAT, [])
358+
sizes_resize1 = onnx.helper.make_tensor_value_info("sizes_resize1", onnx.TensorProto.INT64, [3])
359+
360+
roi_resize2 = onnx.helper.make_tensor_value_info("roi_resize2", onnx.TensorProto.FLOAT, [4])
361+
scales_resize2 = onnx.helper.make_tensor_value_info("scales_resize2", onnx.TensorProto.FLOAT, [3])
362+
363+
list_of_nodes = [
364+
resize_node1,
365+
resize_node2,
366+
]
367+
list_of_value_infos = [
368+
out_resize1,
369+
roi_resize1,
370+
sizes_resize1,
371+
scales_resize1,
372+
roi_resize2,
373+
scales_resize2,
374+
]
375+
376+
graph = onnx.helper.make_graph(
377+
nodes=list_of_nodes,
378+
name="4d_conversion_resize_test_graph",
379+
inputs=[in_resize1],
380+
outputs=[out_resize2],
381+
value_info=list_of_value_infos,
382+
)
383+
384+
onnx_model = qonnx_make_model(
385+
graph, producer_name="4d_conversion_resize_test-model", opset_imports=[make_opsetid("", opset)]
386+
)
387+
model = ModelWrapper(onnx_model)
388+
389+
model.set_initializer("sizes_resize1", np.array([1, 32, 8], dtype=np.int64))
390+
if opset == 11:
391+
model.set_initializer("scales_resize1", np.array([], dtype=np.float32))
392+
elif opset == 13:
393+
model.graph.node[0].input[2] = ""
394+
else:
395+
assert False, f"Undefined opset {opset} for Resize testcase creator"
396+
model.set_initializer("scales_resize2", np.array([1.0, 1.0, 2.0], dtype=np.float32))
397+
model = model.transform(InferShapes())
398+
return model
399+
400+
401+
@pytest.mark.parametrize("test_model", ["Quartz", "VGG", "ConvUpsample", "Resize11", "Resize13"])
332402
def test_4d_conversion(test_model):
333403
"""
334404
Test for the 3D to 4D transformation with a valid graph.
@@ -340,6 +410,8 @@ def test_4d_conversion(test_model):
340410
model = create_arbitrary_model_vgg()
341411
elif test_model == "ConvUpsample":
342412
model = create_conv_upsample()
413+
elif "Resize" in test_model:
414+
model = create_resize(opset=int(test_model.replace("Resize", "")))
343415
else:
344416
raise Exception("Unknown test_model in test_4d_conversion")
345417

0 commit comments

Comments
 (0)