From 465707eba79b17a905901647bf31bf620c885066 Mon Sep 17 00:00:00 2001 From: Yegor Kruglov Date: Tue, 30 Jun 2020 22:32:13 +0300 Subject: [PATCH] [MO MXNET] Fixed spatial reshape on GluonCV models (#587) * added value propagation for slice_like op * Mark slice_lice as undead node * fixes in mark_undead_nodes and unittests update --- model-optimizer/automation/package_BOM.txt | 3 +- .../back/ConvolutionNormalizer_test.py | 8 +- .../back/FuseTransposesSequence_test.py | 8 +- .../back/InterpolateReshape_test.py | 15 +- .../back/compress_quantized_weights_test.py | 78 ++++++----- .../front/interpolate_reshape_test.py | 20 +-- .../front/mxnet/gluoncv_ssd_anchors.py | 126 +++++++++++++++++ .../front/mxnet/gluoncv_ssd_anchors_test.py | 130 ++++++++++++++++++ .../front/mxnet/ssd_anchor_reshape.py | 1 - .../mxnet/ssd_detection_output_replacer.py | 2 +- .../extensions/middle/AnchorToPriorBox.py | 71 ---------- .../middle/FakeSplitOutputs_test.py | 4 +- .../extensions/middle/ssd_anchors_to_const.py | 104 -------------- model-optimizer/extensions/ops/slice_like.py | 13 +- .../extensions/ops/slice_like_test.py | 18 ++- model-optimizer/mo/front/extractor_test.py | 22 +-- model-optimizer/mo/graph/graph.py | 2 +- model-optimizer/mo/middle/passes/eliminate.py | 16 +-- .../mo/middle/passes/eliminate_test.py | 22 +-- .../passes/fusing/decomposition_test.py | 20 +-- .../passes/fusing/fuse_linear_ops_test.py | 26 ++-- .../passes/fusing/fuse_linear_seq_test.py | 34 ++--- model-optimizer/mo/utils/unittest/graph.py | 2 +- 23 files changed, 426 insertions(+), 319 deletions(-) create mode 100644 model-optimizer/extensions/front/mxnet/gluoncv_ssd_anchors.py create mode 100644 model-optimizer/extensions/front/mxnet/gluoncv_ssd_anchors_test.py delete mode 100644 model-optimizer/extensions/middle/AnchorToPriorBox.py delete mode 100644 model-optimizer/extensions/middle/ssd_anchors_to_const.py diff --git a/model-optimizer/automation/package_BOM.txt b/model-optimizer/automation/package_BOM.txt index 73d5acc912e..1fda288d29f 100644 --- a/model-optimizer/automation/package_BOM.txt +++ b/model-optimizer/automation/package_BOM.txt @@ -178,6 +178,7 @@ extensions/front/mxnet/flatten_ext.py extensions/front/mxnet/fully_connected_ext.py extensions/front/mxnet/gather.py extensions/front/mxnet/gather_ext.py +extensions/front/mxnet/gluoncv_ssd_anchors.py extensions/front/mxnet/instance_norm_ext.py extensions/front/mxnet/leaky_relu.py extensions/front/mxnet/lrn_ext.py @@ -481,7 +482,6 @@ extensions/middle/__init__.py extensions/middle/AddFakeQuantizeFuse.py extensions/middle/AddIsCyclicAttribute.py extensions/middle/AddMeanScaleValues.py -extensions/middle/AnchorToPriorBox.py extensions/middle/ApplyNHWCtoNCHWpermutation.py extensions/middle/ApplyPermutations.py extensions/middle/ArgMaxToTopK.py @@ -556,7 +556,6 @@ extensions/middle/SliceConverter.py extensions/middle/SliceLikeToStridedSlice.py extensions/middle/sparse_reshape.py extensions/middle/SplitConcatPairToInterpolate.py -extensions/middle/ssd_anchors_to_const.py extensions/middle/SwapAxesMiddleReplacer.py extensions/middle/TensorIterator_utils.py extensions/middle/TensorIteratorBackEdge.py diff --git a/model-optimizer/extensions/back/ConvolutionNormalizer_test.py b/model-optimizer/extensions/back/ConvolutionNormalizer_test.py index 1386edfe570..302b8805925 100644 --- a/model-optimizer/extensions/back/ConvolutionNormalizer_test.py +++ b/model-optimizer/extensions/back/ConvolutionNormalizer_test.py @@ -36,12 +36,12 @@ def graph_template(weights_initial_shape, new_reshape_shape, limits_initial_shap ] core_nodes = lambda weights_shape, limit_shape, reshape_shape: { - **regular_op_with_shaped_data('input', None, {'type': 'Parameter'}), + **regular_op_with_shaped_data('input', None, {'type': 'Parameter', 'op': 'Parameter'}), **valued_const_with_data('weights', np.ones(weights_shape)), **const_with_data('dim', int64_array(reshape_shape)), - **regular_op_with_shaped_data('reshape', reshape_shape, {'type': 'Reshape', 'infer': Reshape.infer}), + **regular_op_with_shaped_data('reshape', reshape_shape, {'type': 'Reshape', 'infer': Reshape.infer, 'op': 'Reshape'}), **valued_const_with_data('il', np.ones(limit_shape)), **valued_const_with_data('ih', np.ones(limit_shape)), @@ -49,9 +49,9 @@ def graph_template(weights_initial_shape, new_reshape_shape, limits_initial_shap **valued_const_with_data('oh', np.ones(limit_shape)), **regular_op_with_shaped_data('FQ', weights_shape, {'type': 'FakeQuantize', 'infer': FakeQuantize.infer, - 'stop_value_propagation': True, 'levels': 2}), + 'stop_value_propagation': True, 'levels': 2, 'op': 'FakeQuantize'}), - **regular_op_with_shaped_data('convolution', None, {'type': 'Convolution'}), + **regular_op_with_shaped_data('convolution', None, {'type': 'Convolution', 'op': 'Convolution'}), **result(), } diff --git a/model-optimizer/extensions/back/FuseTransposesSequence_test.py b/model-optimizer/extensions/back/FuseTransposesSequence_test.py index 6dfbe941729..3d339464563 100644 --- a/model-optimizer/extensions/back/FuseTransposesSequence_test.py +++ b/model-optimizer/extensions/back/FuseTransposesSequence_test.py @@ -31,24 +31,24 @@ nodes_attributes = { 'placeholder_1_data': {'name': 'placeholder_1_data', 'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, # Transpose layers - 'const_1': {'value': None, 'kind': 'op', 'type': 'Const'}, + 'const_1': {'value': None, 'kind': 'op', 'type': 'Const', 'op': 'Const'}, 'const_1_data': {'value': None, 'shape': None, 'kind': 'data'}, 'permute_1': {'type': 'Transpose', 'value': None, 'kind': 'op', 'op': 'Transpose'}, 'permute_1_data': {'value': None, 'shape': None, 'kind': 'data'}, - 'const_2': {'value': None, 'kind': 'op', 'type': 'Const'}, + 'const_2': {'value': None, 'kind': 'op', 'type': 'Const', 'op': 'Const'}, 'const_2_data': {'value': None, 'shape': None, 'kind': 'data'}, 'permute_2': {'type': 'Transpose', 'value': None, 'kind': 'op', 'op': 'Transpose'}, 'permute_2_data': {'value': None, 'shape': None, 'kind': 'data'}, - 'const_3': {'value': None, 'kind': 'op', 'type': 'Const'}, + 'const_3': {'value': None, 'kind': 'op', 'type': 'Const', 'op': 'Const'}, 'const_3_data': {'value': None, 'shape': None, 'kind': 'data'}, 'permute_3': {'type': 'Transpose', 'value': None, 'kind': 'op', 'op': 'Transpose'}, 'permute_3_data': {'value': None, 'shape': None, 'kind': 'data'}, - 'op_output': { 'op': 'Result', 'kind': 'op'} + 'op_output': {'op': 'Result', 'kind': 'op'} } diff --git a/model-optimizer/extensions/back/InterpolateReshape_test.py b/model-optimizer/extensions/back/InterpolateReshape_test.py index f793a4b592f..cba836917b3 100644 --- a/model-optimizer/extensions/back/InterpolateReshape_test.py +++ b/model-optimizer/extensions/back/InterpolateReshape_test.py @@ -25,21 +25,22 @@ from mo.utils.unittest.graph import build_graph, result, regular_op_with_shaped_ connect_data nodes = { - **regular_op_with_shaped_data('placeholder', [1, 3, 30, 40], {'type': 'Parameter'}), + **regular_op_with_shaped_data('placeholder', [1, 3, 30, 40], {'type': 'Parameter', 'op': 'Parameter'}), **valued_const_with_data('out_shape', np.array([60, 160])), - **regular_op_with_shaped_data('interpolate', [1, 3, 60, 160], {'type': 'Interpolate', 'axes': [2, 3]}), + **regular_op_with_shaped_data('interpolate', [1, 3, 60, 160], {'type': 'Interpolate', 'axes': [2, 3], + 'op': 'Interpolate'}), - **regular_op_with_shaped_data('shape', [4], {'type': 'ShapeOf'}), + **regular_op_with_shaped_data('shape', [4], {'type': 'ShapeOf', 'op': 'ShapeOf'}), **valued_const_with_data('indices', np.array([2, 3])), **valued_const_with_data('axis', np.array(0)), - **regular_op_with_shaped_data('gather', [2], {'type': 'Gather'}), + **regular_op_with_shaped_data('gather', [2], {'type': 'Gather', 'op': 'Gather'}), **valued_const_with_data('multiplier', np.array([2, 4])), - **regular_op_with_shaped_data('mul', [2], {'type': 'Multiply'}), + **regular_op_with_shaped_data('mul', [2], {'type': 'Multiply', 'op': 'Mul'}), - **regular_op_with_shaped_data('placeholder_1', [1, 3, 60, 160], {'type': 'Parameter'}), - **regular_op_with_shaped_data('concat', [1, 7, 60, 160], {'type': 'Concat', 'axis': 1}), + **regular_op_with_shaped_data('placeholder_1', [1, 3, 60, 160], {'type': 'Parameter', 'op': 'Parameter'}), + **regular_op_with_shaped_data('concat', [1, 7, 60, 160], {'type': 'Concat', 'axis': 1, 'op': 'Concat'}), **result(), } diff --git a/model-optimizer/extensions/back/compress_quantized_weights_test.py b/model-optimizer/extensions/back/compress_quantized_weights_test.py index dedd4ea8942..8465a442c54 100644 --- a/model-optimizer/extensions/back/compress_quantized_weights_test.py +++ b/model-optimizer/extensions/back/compress_quantized_weights_test.py @@ -34,36 +34,36 @@ nodes_attributes = { 'placeholder_data': {'kind': 'data'}, # weights - 'weights_const': {'type': 'Const', 'kind': 'op', 'value': np.array([], dtype=np.float32)}, + 'weights_const': {'type': 'Const', 'kind': 'op', 'value': np.array([], dtype=np.float32), 'op': 'Const'}, 'weights_data': {'kind': 'data'}, # quantize - 'quantize1': {'type': 'FakeQuantize', 'kind': 'op', 'levels': 5}, - 'quantize2': {'type': 'FakeQuantize', 'kind': 'op', 'levels': 2}, - 'quantize3': {'type': 'FakeQuantize', 'kind': 'op', 'levels': None}, - 'quantize4': {'type': 'FakeQuantize', 'kind': 'op', 'levels': 122}, - 'quantize5': {'type': 'FakeQuantize', 'kind': 'op', 'levels': 202}, - 'quantize6': {'type': 'FakeQuantize', 'kind': 'op', 'levels': 257}, + 'quantize1': {'type': 'FakeQuantize', 'kind': 'op', 'levels': 5, 'op': 'FakeQuantize'}, + 'quantize2': {'type': 'FakeQuantize', 'kind': 'op', 'levels': 2, 'op': 'FakeQuantize'}, + 'quantize3': {'type': 'FakeQuantize', 'kind': 'op', 'levels': None, 'op': 'FakeQuantize'}, + 'quantize4': {'type': 'FakeQuantize', 'kind': 'op', 'levels': 122, 'op': 'FakeQuantize'}, + 'quantize5': {'type': 'FakeQuantize', 'kind': 'op', 'levels': 202, 'op': 'FakeQuantize'}, + 'quantize6': {'type': 'FakeQuantize', 'kind': 'op', 'levels': 257, 'op': 'FakeQuantize'}, 'quantize_data': {'kind': 'data'}, - 'new_quantize1': {'kind': 'op', 'type': 'FakeQuantize', 'levels': 5}, - 'new_quantize4': {'kind': 'op', 'type': 'FakeQuantize', 'levels': 122}, - 'new_quantize5': {'kind': 'op', 'type': 'FakeQuantize', 'levels': 202}, + 'new_quantize1': {'kind': 'op', 'type': 'FakeQuantize', 'levels': 5, 'op': 'FakeQuantize'}, + 'new_quantize4': {'kind': 'op', 'type': 'FakeQuantize', 'levels': 122, 'op': 'FakeQuantize'}, + 'new_quantize5': {'kind': 'op', 'type': 'FakeQuantize', 'levels': 202, 'op': 'FakeQuantize'}, 'new_quantize_data': {'kind': 'data'}, # quantize input/output - 'output_high_init': {'kind': 'op', 'type': 'Const'}, + 'output_high_init': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, 'output_high_init_data': {'kind': 'data', 'value': 3}, - 'output_low_init': {'kind': 'op', 'type': 'Const'}, + 'output_low_init': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, 'output_low_init_data': {'kind': 'data', 'value': -1.5}, - 'input_low': {'kind': 'op', 'type': 'Const'}, + 'input_low': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, 'input_low_data': {'kind': 'data'}, - 'input_high': {'kind': 'op', 'type': 'Const'}, + 'input_high': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, 'input_high_data': {'kind': 'data'}, - 'output_low': {'kind': 'op', 'type': 'Const'}, + 'output_low': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, 'output_low_data': {'kind': 'data'}, - 'output_high': {'kind': 'op', 'type': 'Const'}, + 'output_high': {'kind': 'op', 'type': 'Const', 'op': 'Const'}, 'output_high_data': {'kind': 'data'}, 'output_high_init_data1': {'kind': 'data', 'value': 256.1}, @@ -76,58 +76,58 @@ nodes_attributes = { 'mul': {'kind': 'op', 'op': 'Mul'}, 'add': {'kind': 'op', 'op': 'Add'}, - 'scale': {'kind': 'op', 'type': 'Const', 'value': 1.125}, - 'shift': {'kind': 'op', 'type': 'Const', 'value': -1.5}, - 'scale1': {'kind': 'op', 'type': 'Const', 'value': 1.9735537190082646}, - 'shift1': {'kind': 'op', 'type': 'Const', 'value': 17.3}, - 'scale2': {'kind': 'op', 'type': 'Const', 'value': 0.010711442786069652}, - 'shift2': {'kind': 'op', 'type': 'Const', 'value': -2.573}, + 'scale': {'kind': 'op', 'type': 'Const', 'value': 1.125, 'op': 'Const'}, + 'shift': {'kind': 'op', 'type': 'Const', 'value': -1.5, 'op': 'Const'}, + 'scale1': {'kind': 'op', 'type': 'Const', 'value': 1.9735537190082646, 'op': 'Const'}, + 'shift1': {'kind': 'op', 'type': 'Const', 'value': 17.3, 'op': 'Const'}, + 'scale2': {'kind': 'op', 'type': 'Const', 'value': 0.010711442786069652, 'op': 'Const'}, + 'shift2': {'kind': 'op', 'type': 'Const', 'value': -2.573, 'op': 'Const'}, 'shift_data': {'kind': 'data'}, 'scale_data': {'kind': 'data'}, 'mul_data': {'kind': 'data'}, 'add_data': {'kind': 'data'}, - 'convolution': {'type': 'Convolution', 'kind': 'op'}, - 'convert': {'type': 'Convert', 'kind': 'op', 'dst_type': np.float32}, + 'convolution': {'type': 'Convolution', 'kind': 'op', 'op': 'Convolution'}, + 'convert': {'type': 'Convert', 'kind': 'op', 'dst_type': np.float32, 'op': 'Cast'}, 'convert_data': {'kind': 'data'}, - 'result_data': {'kind':'data'}, + 'result_data': {'kind': 'data'}, 'result': {'kind': 'op', 'op': 'Result'}, # accuracy test 'ac_weights': {'kind': 'op', 'op': 'Const', 'shape': None, 'value': None, 'infer': Const.infer}, 'ac_weights_data': {'kind': 'data', 'shape': None, 'value': None}, - 'ac_input_low': {'kind': 'op', 'type': 'Const', 'shape': None, 'value': None, 'infer': Const.infer}, + 'ac_input_low': {'kind': 'op', 'type': 'Const', 'shape': None, 'value': None, 'infer': Const.infer, 'op': 'Const'}, 'ac_input_low_data': {'kind': 'data', 'value': None, 'shape': None}, - 'ac_input_high': {'kind': 'op', 'type': 'Const', 'shape': None, 'value': None, 'infer': Const.infer}, + 'ac_input_high': {'kind': 'op', 'type': 'Const', 'shape': None, 'value': None, 'infer': Const.infer, 'op': 'Const'}, 'ac_input_high_data': {'kind': 'data', 'value': None, 'shape': None}, - 'ac_output_low': {'kind': 'op', 'type': 'Const', 'shape': None, 'value': None, 'infer': Const.infer}, + 'ac_output_low': {'kind': 'op', 'type': 'Const', 'shape': None, 'value': None, 'infer': Const.infer, 'op': 'Const'}, 'ac_output_low_data': {'kind': 'data', 'value': None, 'shape': None}, - 'ac_output_high': {'kind': 'op', 'type': 'Const', 'shape': None, 'value': None, 'infer': Const.infer}, + 'ac_output_high': {'kind': 'op', 'type': 'Const', 'shape': None, 'value': None, 'infer': Const.infer, 'op': 'Const'}, 'ac_output_high_data': {'kind': 'data', 'value': None, 'shape': None}, - 'ac_fakeQuantize': {'kind': 'op', 'type': 'FakeQuantize', 'levels': None, 'infer': FakeQuantize.infer}, + 'ac_fakeQuantize': {'kind': 'op', 'type': 'FakeQuantize', 'levels': None, 'infer': FakeQuantize.infer, 'op': 'FakeQuantize'}, 'ac_fakeQuantize_data': {'kind': 'data', 'shape': None, 'value': None}, - 'ac_quantize': {'kind': 'op', 'type': 'fakeQuantize', 'levels': None, 'infer': FakeQuantize.infer}, + 'ac_quantize': {'kind': 'op', 'type': 'fakeQuantize', 'levels': None, 'infer': FakeQuantize.infer, 'op': 'FakeQuantize'}, 'ac_quantize_data': {'kind': 'data', 'shape': None, 'value': None}, - 'ac_convolution': {'kind': 'op', 'type': 'Convolution'}, + 'ac_convolution': {'kind': 'op', 'type': 'Convolution', 'op': 'Convolution'}, 'ac_mul': {'kind': 'op', 'op': 'Mul', 'infer': lambda node: eltwise_infer(node, lambda a, b: a * b)}, 'ac_mul_data': {'kind': 'data', 'shape': None, 'value': None}, 'ac_add': {'kind': 'op', 'op': 'Add', 'infer': lambda node: eltwise_infer(node, lambda a, b: a + b)}, 'ac_add_data': {'kind': 'data', 'shape': None, 'value': None}, - 'ac_scale': {'kind': 'op', 'type': 'Const', 'shape': None, 'value': None, 'infer': Const.infer}, + 'ac_scale': {'kind': 'op', 'type': 'Const', 'shape': None, 'value': None, 'infer': Const.infer, 'op': 'Const'}, 'ac_scale_data': {'kind': 'data', 'shape': None, 'value': None}, - 'ac_shift': {'kind': 'op', 'type': 'Const', 'shape': None, 'value': None, 'infer': Const.infer}, + 'ac_shift': {'kind': 'op', 'type': 'Const', 'shape': None, 'value': None, 'infer': Const.infer, 'op': 'Const'}, 'ac_shift_data': {'kind': 'data', 'shape': None, 'value': None}, - 'ac_output_low_ref': {'kind': 'op', 'type': 'Const', 'shape': None, 'value': None, 'infer': Const.infer}, + 'ac_output_low_ref': {'kind': 'op', 'type': 'Const', 'shape': None, 'value': None, 'infer': Const.infer, 'op': 'Const'}, 'ac_output_low_ref_data': {'kind': 'data', 'shape': None, 'value': None}, - 'ac_output_high_ref': {'kind': 'op', 'type': 'Const', 'shape': None, 'value': None, 'infer': Const.infer}, + 'ac_output_high_ref': {'kind': 'op', 'type': 'Const', 'shape': None, 'value': None, 'infer': Const.infer, 'op': 'Const'}, 'ac_output_high_ref_data': {'kind': 'data', 'shape': None, 'value': None} } @@ -838,7 +838,8 @@ class CompressionDataTypeTest(unittest.TestCase): **valued_const_with_data('weights', np.ones([1, 2, 3, 4], dtype=original)), **valued_const_with_data('int_weights', np.ones([1, 2, 3, 4], dtype=np.uint8)), - **regular_op_with_shaped_data('cast', [1, 2, 3, 4], {'type': 'Convert', 'dst_type': transformed}), + **regular_op_with_shaped_data('cast', [1, 2, 3, 4], {'type': 'Convert', 'dst_type': transformed, + 'op': 'Cast'}), **valued_const_with_data('il', np.array([0])), **valued_const_with_data('ih', np.array([254])), @@ -846,7 +847,8 @@ class CompressionDataTypeTest(unittest.TestCase): **valued_const_with_data('oh', np.array([254])), **regular_op_with_shaped_data('FQ', [1, 2, 3, 4], {'type': 'FakeQuantize', 'infer': FakeQuantize.infer, - 'stop_value_propagation': True, 'levels': 255}), + 'stop_value_propagation': True, 'levels': 255, + 'op': 'FakeQuantize'}), **result() } diff --git a/model-optimizer/extensions/front/interpolate_reshape_test.py b/model-optimizer/extensions/front/interpolate_reshape_test.py index 4f45da842da..1a23695d5de 100644 --- a/model-optimizer/extensions/front/interpolate_reshape_test.py +++ b/model-optimizer/extensions/front/interpolate_reshape_test.py @@ -26,23 +26,23 @@ from mo.utils.unittest.graph import build_graph, result, regular_op_with_shaped_ connect_data nodes = { - **regular_op_with_shaped_data('placeholder', [1, 3, 30, 40], {'type': 'Parameter'}), + **regular_op_with_shaped_data('placeholder', [1, 3, 30, 40], {'type': 'Parameter', 'op': 'Parameter'}), **valued_const_with_data('out_shape', np.array([60, 160])), **regular_op_with_shaped_data('interpolate', [1, 3, 60, 160], - {'type': 'Interpolate', 'axes': int64_array([2, 3])}), - **regular_op_with_shaped_data('identity_00', [1, 3, 60, 160], {'identity': True}), - **regular_op_with_shaped_data('identity_01', [1, 3, 60, 160], {'identity': True}), + {'type': 'Interpolate', 'axes': int64_array([2, 3]), 'op': 'Interpolate'}), + **regular_op_with_shaped_data('identity_00', [1, 3, 60, 160], {'identity': True, 'op': 'Identity'}), + **regular_op_with_shaped_data('identity_01', [1, 3, 60, 160], {'identity': True, 'op': 'Identity'}), - **regular_op_with_shaped_data('shape', [4], {'type': 'ShapeOf'}), + **regular_op_with_shaped_data('shape', [4], {'type': 'ShapeOf', 'op': 'ShapeOf'}), **valued_const_with_data('indices', np.array([2, 3])), **valued_const_with_data('axis', np.array(0)), - **regular_op_with_shaped_data('gather', [2], {'type': 'Gather'}), + **regular_op_with_shaped_data('gather', [2], {'type': 'Gather', 'op': 'Gather'}), - **regular_op_with_shaped_data('placeholder_1', [1, 3, 60, 160], {'type': 'Parameter'}), - **regular_op_with_shaped_data('identity_10', [1, 3, 60, 160], {'identity': True}), - **regular_op_with_shaped_data('identity_11', [1, 3, 60, 160], {'identity': True}), - **regular_op_with_shaped_data('concat', [1, 7, 60, 160], {'type': 'Concat', 'axis': 1}), + **regular_op_with_shaped_data('placeholder_1', [1, 3, 60, 160], {'type': 'Parameter', 'op': 'Parameter'}), + **regular_op_with_shaped_data('identity_10', [1, 3, 60, 160], {'identity': True, 'op': 'Identity'}), + **regular_op_with_shaped_data('identity_11', [1, 3, 60, 160], {'identity': True, 'op': 'Identity'}), + **regular_op_with_shaped_data('concat', [1, 7, 60, 160], {'type': 'Concat', 'axis': 1, 'op': 'Concat'}), **result(), } diff --git a/model-optimizer/extensions/front/mxnet/gluoncv_ssd_anchors.py b/model-optimizer/extensions/front/mxnet/gluoncv_ssd_anchors.py new file mode 100644 index 00000000000..e357e1c3fd6 --- /dev/null +++ b/model-optimizer/extensions/front/mxnet/gluoncv_ssd_anchors.py @@ -0,0 +1,126 @@ +""" + Copyright (C) 2018-2020 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +""" +import numpy as np + +from typing import Dict + +from extensions.front.mxnet.mx_reshape_to_reshape import MXReshapeToReshape +from extensions.front.mxnet.ssd_detection_output_replacer import SsdPatternDetectionOutputReplacer +from extensions.ops.elementwise import Div, Add, Sub +from extensions.ops.split import Split +from mo.front.common.partial_infer.utils import int64_array +from mo.front.common.replacement import FrontReplacementPattern +from mo.front.tf.graph_utils import create_op_node_with_second_input +from mo.graph.graph import Graph, Node +from mo.graph.port import Port +from mo.middle.passes.convert_data_type import data_type_str_to_np +from mo.ops.concat import Concat +from mo.ops.reshape import Reshape + + +def calculate_prior_box_value(value: Node, value_to_div: Port, value_to_add: Port): + """ + :param value: Node with value. Here is supposed the node with op='Split' + :param value_to_div: Output port with values to be divided by 2 + :param value_to_add: Output port with values to be added to values from value_to_div port + :return: Sub and Add nodes + + The sub-graph can be described by formulas: + min = value[value_to_add] - (value[value_to_div] / 2) + max = value[value_to_add] + (value[value_to_div] / 2) + """ + graph = value.graph + dtype = data_type_str_to_np(graph.graph['cmd_params'].data_type) + _min = Sub(graph, dict(name=value.name + '/Sub')).create_node() + div = create_op_node_with_second_input(graph, Div, np.array([2], dtype=dtype), op_attrs=dict(name=value.name + '/Div')) + div.in_port(0).connect(value_to_div) + _min.in_port(0).connect(value_to_add) + _min.in_port(1).connect(div.out_port(0)) + + _max = Add(graph, dict(name=value.name + '/Add')).create_node() + _max.in_port(0).connect(div.out_port(0)) + _max.in_port(1).connect(value_to_add) + + return _min, _max + + +class SsdAnchorsReplacer(FrontReplacementPattern): + """ + Replacing sub-graph with all anchors to sub-graph which calculates prior boxes values by formulas: + + value[i] = xmin = value[i] - (value[i + 2] / 2) + value[i + 1] = ymin = value[i + 1] - (value[i + 3] / 2) + value[i + 2] = xmax = value[i] + (value[i + 2] / 2) + value[i + 3] = ymax = value[i + 1] + (value[i + 3] / 2) + """ + + enabled = True + graph_condition = [lambda graph: graph.graph['cmd_params'].enable_ssd_gluoncv] + + def run_after(self): + return [SsdPatternDetectionOutputReplacer, MXReshapeToReshape] + + def pattern(self): + return dict( + nodes=[ + ('slice_like', dict(op='slice_like')), + ('reshape0', dict(op='Reshape')), + ('reshape1', dict(op='Reshape')), + ('reshape2', dict(op='Reshape')), + ('reshape3', dict(op='Reshape')), + ('concat', dict(op='Concat')), + ('detection_output', dict(op='DetectionOutput')) + ], + edges=[ + ('slice_like', 'reshape0'), + ('reshape0', 'reshape1'), + ('reshape1', 'reshape2'), + ('reshape2', 'reshape3'), + ('reshape3', 'concat', {'in': 0}), + ('concat', 'detection_output', {'in': 2}) + ]) + + def replace_pattern(self, graph: Graph, match: Dict[str, Node]): + concat_node = match['concat'] + concat_node['axis'] = 1 + concat_name = concat_node.soft_get('name', concat_node.id) + + concat_reshape = create_op_node_with_second_input(graph, Reshape, int64_array([1, 2, -1]), op_attrs=dict( + name=concat_name + '/Reshape')) + split_node = create_op_node_with_second_input(graph, Split, int64_array(1), op_attrs=dict( + name=concat_name + '/Split', num_splits=2), input_node=concat_reshape) + split_node_reshape = create_op_node_with_second_input(graph, Reshape, int64_array([-1, 4]), op_attrs=dict( + name=split_node.name + '/Reshape')) + split_node.out_port(0).connect(split_node_reshape.in_port(0)) + value = create_op_node_with_second_input(graph, Split, int64_array(1), op_attrs=dict( + name=split_node_reshape.name + '/Split', num_splits=4), input_node=split_node_reshape) + + xmin, xmax = calculate_prior_box_value(value, value_to_div=value.out_port(2), value_to_add=value.out_port(0)) + ymin, ymax = calculate_prior_box_value(value, value_to_div=value.out_port(3), value_to_add=value.out_port(1)) + + concat_slice_value = Concat(graph, dict(name=value.name + '/Concat', in_ports_count=4, axis=1)).create_node() + for ind, node in enumerate([xmin, ymin, xmax, ymax]): + concat_slice_value.in_port(ind).connect(node.out_port(0)) + + reshape_concat_values = create_op_node_with_second_input(graph, Reshape, int64_array([1, 1, -1]), + op_attrs=dict(name=concat_slice_value.name + '/Reshape'), + input_node=concat_slice_value) + concat = Concat(graph, dict(name=reshape_concat_values.name + '/Concat', in_ports_count=2, axis=1)).create_node() + concat.in_port(0).connect(reshape_concat_values.out_port(0)) + concat.in_port(1).connect(split_node.out_port(1)) + + match['detection_output'].in_port(2).get_connection().set_source(concat.out_port(0)) + concat_node.out_port(0).get_connection().set_destination(concat_reshape.in_port(0)) diff --git a/model-optimizer/extensions/front/mxnet/gluoncv_ssd_anchors_test.py b/model-optimizer/extensions/front/mxnet/gluoncv_ssd_anchors_test.py new file mode 100644 index 00000000000..c1ec5414493 --- /dev/null +++ b/model-optimizer/extensions/front/mxnet/gluoncv_ssd_anchors_test.py @@ -0,0 +1,130 @@ +""" + Copyright (C) 2018-2020 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +""" +import numpy as np +import unittest + +from extensions.front.mxnet.gluoncv_ssd_anchors import SsdAnchorsReplacer +from mo.front.common.partial_infer.utils import int64_array +from mo.utils.ir_engine.compare_graphs import compare_graphs +from mo.utils.unittest.graph import build_graph + +nodes_attributes = { + 'slice_like': {'kind': 'op', 'op': 'slice_like'}, + 'model_reshape0': {'kind': 'op', 'op': 'Reshape'}, + 'model_reshape0_const': {'kind': 'op', 'op': 'Const', 'value': int64_array([1, -1, 4])}, + 'model_reshape1': {'kind': 'op', 'op': 'Reshape'}, + 'model_reshape1_const': {'kind': 'op', 'op': 'Const', 'value': int64_array([1, -1, 4])}, + 'model_reshape2': {'kind': 'op', 'op': 'Reshape'}, + 'model_reshape2_const': {'kind': 'op', 'op': 'Const', 'value': int64_array([1, -1])}, + 'reshape0': {'kind': 'op', 'op': 'Reshape'}, + 'reshape0_const': {'kind': 'op', 'op': 'Const', 'value': int64_array([1, -1])}, + 'concat': {'kind': 'op', 'op': 'Concat'}, + 'reshape1': {'kind': 'op', 'op': 'Reshape'}, + 'reshape1_const': {'kind': 'op', 'op': 'Const', 'value': int64_array([1, 2, -1])}, + 'split': {'kind': 'op', 'op': 'Split', 'num_splits': 2}, + 'split_const': {'kind': 'op', 'op': 'Const', 'value': int64_array(1)}, + 'reshape2': {'kind': 'op', 'op': 'Reshape'}, + 'reshape2_const': {'kind': 'op', 'op': 'Const', 'value': int64_array([-1, 4])}, + 'value': {'kind': 'op', 'op': 'Split', 'num_splits': 4}, + 'value_const': {'kind': 'op', 'op': 'Const', 'value': int64_array(1)}, + 'div_1': {'kind': 'op', 'op': 'Div'}, + 'div_1_const': {'kind': 'op', 'op': 'Const', 'value': np.array([2], dtype=np.float32)}, + 'div_2': {'kind': 'op', 'op': 'Div'}, + 'div_2_const': {'kind': 'op', 'op': 'Const', 'value': np.array([2], dtype=np.float32)}, + 'xmin': {'kind': 'op', 'op': 'Sub'}, + 'ymin': {'kind': 'op', 'op': 'Sub'}, + 'xmax': {'kind': 'op', 'op': 'Add'}, + 'ymax': {'kind': 'op', 'op': 'Add'}, + 'concat_value': {'kind': 'op', 'op': 'Concat', 'axis': 1}, + 'reshape3': {'kind': 'op', 'op': 'Reshape'}, + 'reshape3_const': {'kind': 'op', 'op': 'Const', 'value': int64_array([1, 1, -1])}, + 'end_concat': {'kind': 'op', 'op': 'Concat'}, + 'detection_output': {'kind': 'op', 'op': 'DetectionOutput'} +} + + +class SsdAnchorsReplacerTest(unittest.TestCase): + + def test_replacer(self): + graph = build_graph( + nodes_attrs=nodes_attributes, + edges=[ + ('slice_like', 'model_reshape0', {'in': 0}), + ('model_reshape0_const', 'model_reshape0', {'in': 1}), + ('model_reshape0', 'model_reshape1', {'in': 0}), + ('model_reshape1_const', 'model_reshape1', {'in': 1}), + ('model_reshape1', 'model_reshape2', {'in': 0}), + ('model_reshape2_const', 'model_reshape2', {'in': 1}), + ('model_reshape2', 'reshape0', {'in': 0}), + ('reshape0_const', 'reshape0', {'in': 1}), + ('reshape0', 'concat'), + ('concat', 'detection_output', {'in': 2}) + ], + nodes_with_edges_only=True + ) + + ref_graph = build_graph( + nodes_attrs=nodes_attributes, + edges=[ + ('slice_like', 'model_reshape0', {'in': 0}), + ('model_reshape0_const', 'model_reshape0', {'in': 1}), + ('model_reshape0', 'model_reshape1', {'in': 0}), + ('model_reshape1_const', 'model_reshape1', {'in': 1}), + ('model_reshape1', 'model_reshape2', {'in': 0}), + ('model_reshape2_const', 'model_reshape2', {'in': 1}), + ('model_reshape2', 'reshape0', {'in': 0}), + ('reshape0_const', 'reshape0', {'in': 1}), + ('reshape0', 'concat'), + ('concat', 'reshape1', {'in': 0}), + ('reshape1_const', 'reshape1', {'in': 1}), + ('reshape1', 'split', {'in': 0}), + ('split_const', 'split', {'in': 1}), + ('split', 'reshape2', {'out': 0, 'in': 0}), + ('reshape2_const', 'reshape2', {'in': 1}), + ('reshape2', 'value', {'in': 0}), + ('value_const', 'value', {'in': 1}), + ('value', 'xmin', {'out': 0, 'in': 0}), + ('value', 'ymin', {'out': 1, 'in': 0}), + ('value', 'xmax', {'out': 0, 'in': 1}), + ('value', 'ymax', {'out': 1, 'in': 1}), + ('value', 'div_1', {'out': 2, 'in': 0}), + ('value', 'div_2', {'out': 3, 'in': 0}), + ('div_1_const', 'div_1', {'in': 1}), + ('div_2_const', 'div_2', {'in': 1}), + ('div_1', 'xmin', {'in': 1, 'out': 0}), + ('div_1', 'xmax', {'in': 0, 'out': 0}), + ('div_2', 'ymin', {'in': 1, 'out': 0}), + ('div_2', 'ymax', {'in': 0, 'out': 0}), + ('xmin', 'concat_value', {'in': 0}), + ('ymin', 'concat_value', {'in': 1}), + ('xmax', 'concat_value', {'in': 2}), + ('ymax', 'concat_value', {'in': 3}), + ('concat_value', 'reshape3', {'in': 0}), + ('reshape3_const', 'reshape3', {'in': 1}), + ('reshape3', 'end_concat', {'in': 0}), + ('split', 'end_concat', {'in': 1}), + ('end_concat', 'detection_output', {'in': 2}) + ], + update_attributes={ + 'concat': {'axis': 1} + }, + nodes_with_edges_only=True + ) + graph.stage = 'front' + graph.graph['cmd_params'].data_type = 'FP32' + SsdAnchorsReplacer().find_and_replace_pattern(graph) + flag, resp = compare_graphs(graph, ref_graph, 'detection_output', check_op_attrs=True) + self.assertTrue(flag, resp) diff --git a/model-optimizer/extensions/front/mxnet/ssd_anchor_reshape.py b/model-optimizer/extensions/front/mxnet/ssd_anchor_reshape.py index a1f7350f3eb..c109102b0d1 100644 --- a/model-optimizer/extensions/front/mxnet/ssd_anchor_reshape.py +++ b/model-optimizer/extensions/front/mxnet/ssd_anchor_reshape.py @@ -24,7 +24,6 @@ from mo.front.common.replacement import FrontReplacementSubgraph from mo.graph.graph import Graph, Node from mo.middle.pattern_match import find_pattern_matches from mo.ops.const import Const -from mo.ops.crop import Crop class SsdPatternAnchorReshape(FrontReplacementSubgraph): diff --git a/model-optimizer/extensions/front/mxnet/ssd_detection_output_replacer.py b/model-optimizer/extensions/front/mxnet/ssd_detection_output_replacer.py index 0033a4912cb..1bef8e9a2e9 100644 --- a/model-optimizer/extensions/front/mxnet/ssd_detection_output_replacer.py +++ b/model-optimizer/extensions/front/mxnet/ssd_detection_output_replacer.py @@ -103,7 +103,7 @@ class SsdPatternDetectionOutputReplacer(FrontReplacementSubgraph): def reshape_priorboxes(self, concat): for i, node in concat.in_nodes().items(): - reshape_node = create_op_node_with_second_input(concat.graph, Reshape, int64_array([0, 2, -1]), + reshape_node = create_op_node_with_second_input(concat.graph, Reshape, int64_array([1, -1]), dict(name=concat.name + str(i) + '/PriorBoxReshape_')) node.out_port(0).disconnect() node.out_port(0).connect(reshape_node.in_port(0)) diff --git a/model-optimizer/extensions/middle/AnchorToPriorBox.py b/model-optimizer/extensions/middle/AnchorToPriorBox.py deleted file mode 100644 index 30dbf2a181f..00000000000 --- a/model-optimizer/extensions/middle/AnchorToPriorBox.py +++ /dev/null @@ -1,71 +0,0 @@ -""" - Copyright (C) 2018-2020 Intel Corporation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -""" - -import numpy as np - -from extensions.middle.SliceLikeToStridedSlice import SliceLikeToStridedSlice -from mo.graph.graph import Graph -from mo.middle.replacement import MiddleReplacementPattern -from mo.ops.const import Const - - -class AnchorToPriorBoxes(MiddleReplacementPattern): - """ - Crop anchors consts before replacing subgraph with all anchors - """ - enabled = True - force_clean_up = True - graph_condition = [lambda graph: graph.graph['fw'] == 'mxnet' and graph.graph['cmd_params'].enable_ssd_gluoncv] - - def run_after(self): - from extensions.middle.pass_separator import MiddleStart - return [MiddleStart] - - def run_before(self): - return [SliceLikeToStridedSlice] - - def pattern(self): - return dict( - nodes=[ - ('const', dict(op='Const')), - ('const_data', dict(kind='data')), - ('slice_like', dict(op='slice_like')), - ('slice_like_out', dict(kind='data')), - ('reshape', dict(op='Reshape')), - ], - edges=[ - ('const', 'const_data'), - ('const_data', 'slice_like', {'in': 0}), - ('slice_like', 'slice_like_out'), - ('slice_like_out', 'reshape'), - ] - ) - - def replace_pattern(self, graph: Graph, match: dict): - slice_like = match['slice_like'] - anchor_node = slice_like.in_port(0).get_source().node - reshape = slice_like.out_nodes()[0].out_node() - slice_shape = slice_like.out_nodes()[0].shape - anchor_node.value = np.copy(anchor_node.value[:slice_shape[0], :slice_shape[1], - :slice_shape[2], :slice_shape[3], :slice_shape[4]]) - anchor_node.shape = slice_shape - - val_node = Const(graph, {'name': slice_like.name +'/croped_', 'value': anchor_node.value[:slice_shape[0], :slice_shape[1], - :slice_shape[2], :slice_shape[3], :slice_shape[4]], 'shape': slice_shape}).create_node_with_data() - slice_like.in_port(0).disconnect() - slice_like.in_port(1).disconnect() - slice_like.out_port(0).disconnect() - reshape.in_port(0).connect(val_node.in_node().out_port(0)) diff --git a/model-optimizer/extensions/middle/FakeSplitOutputs_test.py b/model-optimizer/extensions/middle/FakeSplitOutputs_test.py index c176e34cd23..d24e30ec229 100644 --- a/model-optimizer/extensions/middle/FakeSplitOutputs_test.py +++ b/model-optimizer/extensions/middle/FakeSplitOutputs_test.py @@ -38,9 +38,9 @@ nodes_attributes = { 'split_data_1': {'kind': 'data', 'value': None, 'shape': np.array([1, 227, 227, 1])}, 'last_data': {'kind': 'data', 'value': None, 'shape': np.array([1, 227, 227, 3])}, - 'axis_const': {'kind': 'op'}, + 'axis_const': {'kind': 'op', 'op': 'Const'}, 'axis_const_data': {'value': np.int64(1), 'shape': None, 'kind': 'data'}, - 'split_dim_const': {'kind': 'op'}, + 'split_dim_const': {'kind': 'op', 'op': 'Const'}, 'split_dim_const_data': {'value': np.array([1, 2, 3]), 'shape': None, 'kind': 'data'}, } diff --git a/model-optimizer/extensions/middle/ssd_anchors_to_const.py b/model-optimizer/extensions/middle/ssd_anchors_to_const.py deleted file mode 100644 index a6896ca93cf..00000000000 --- a/model-optimizer/extensions/middle/ssd_anchors_to_const.py +++ /dev/null @@ -1,104 +0,0 @@ -""" - Copyright (C) 2018-2020 Intel Corporation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -""" - -import numpy as np - -from extensions.middle.AnchorToPriorBox import AnchorToPriorBoxes -from extensions.middle.SliceLikeToStridedSlice import SliceLikeToStridedSlice -from mo.graph.graph import Graph -from mo.middle.replacement import MiddleReplacementPattern -from mo.ops.const import Const - - -class SsdAnchorsMiddleReplacer(MiddleReplacementPattern): - """ - Replacing subgraph with all anchors constant to constant op with pre calculated prior boxes values. - """ - enabled = True - force_clean_up = True - graph_condition = [lambda graph: graph.graph['fw'] == 'mxnet' and graph.graph['cmd_params'].enable_ssd_gluoncv] - - def run_after(self): - return [AnchorToPriorBoxes] - - def run_before(self): - return [SliceLikeToStridedSlice] - - - def pattern(self): - return dict( - nodes=[ - ('const', dict(op='Const')), - ('const_data', dict(kind='data')), - ('reshape0', dict(op='Reshape')), - ('reshape0_data', dict(kind='data')), - ('reshape1', dict(op='Reshape')), - ('reshape1_data', dict(kind='data')), - ('reshape2', dict(op='Reshape')), - ('reshape2_data', dict(kind='data')), - ('reshape3', dict(op='Reshape')), - ('reshape3_data', dict(kind='data')), - ('concat', dict(op='Concat')), - ], - edges=[ - ('const', 'const_data'), - ('const_data', 'reshape0'), - ('reshape0', 'reshape0_data'), - ('reshape0_data', 'reshape1'), - ('reshape1', 'reshape1_data'), - ('reshape1_data', 'reshape2'), - ('reshape2', 'reshape2_data'), - ('reshape2_data', 'reshape3'), - ('reshape3', 'reshape3_data'), - ('reshape3_data', 'concat'), - ]) - - def replace_pattern(self, graph: Graph, match: dict): - #self.pattern()['nodes'] - concat_node = match['concat'] - if len(concat_node.out_nodes()[0].out_nodes()) == 0: - return - const_values = [] - for in_node_index in concat_node.in_nodes(): - current_node = concat_node.in_port(in_node_index).get_source().node - for k, v in reversed(self.pattern()['nodes'][:-1]): - if 'op' in v: - assert current_node.op == v['op'] - current_node = current_node.in_port(0).get_source().node - if current_node.op == 'Const': - crop_value = current_node.value - crop_value = np.reshape(crop_value, (1, -1)) - const_values.append(crop_value) - break - concat_value = np.concatenate(tuple(const_values), axis=1) - concat_value = np.reshape(concat_value, (1, 2, -1)) - slice_value = concat_value[0][0] - for i in range(int(concat_value[0][0].size / 4)): - index = i * 4 - xmin = slice_value[index] - (slice_value[index+2] / 2) - ymin = slice_value[index + 1] - (slice_value[index + 3] / 2) - xmax = slice_value[index] + (slice_value[index + 2] / 2) - ymax = slice_value[index + 1] + (slice_value[index + 3] / 2) - slice_value[index] = xmin - slice_value[index + 1] = ymin - slice_value[index + 2] = xmax - slice_value[index + 3] = ymax - - val_node = Const(graph, {'name': concat_node.name + '/const_', - 'value': concat_value}).create_node_with_data() - out_node = concat_node.out_port(0).get_destination().node - concat_node.out_port(0).disconnect() - out_node.in_port(2).connect(val_node.in_node().out_port(0)) diff --git a/model-optimizer/extensions/ops/slice_like.py b/model-optimizer/extensions/ops/slice_like.py index ed02881c828..7d6ae78b5fc 100644 --- a/model-optimizer/extensions/ops/slice_like.py +++ b/model-optimizer/extensions/ops/slice_like.py @@ -50,5 +50,16 @@ class SliceLike(Op): 'Input shape ranks are inconsistent: {} and {}'.format(input_shape.size, shape_like.size) node.axes = int64_array(range(shape_like.size)) new_shape = np.copy(shape_like) - node.out_port(0).data.set_shape(new_shape) + + if node.in_port(0).get_connection().data.get_value() is not None: + out_value = np.copy(node.in_port(0).data.get_value()) + + slice_indexes = [] + for s in out_value.shape: + slice_indexes.append(slice(0, s)) + + for axis in node.axes: + slice_indexes[axis] = slice(0, new_shape[axis]) + out_value = out_value[tuple(slice_indexes)] + node.out_port(0).data.set_value(out_value) diff --git a/model-optimizer/extensions/ops/slice_like_test.py b/model-optimizer/extensions/ops/slice_like_test.py index dc1abd88187..156fa377117 100644 --- a/model-optimizer/extensions/ops/slice_like_test.py +++ b/model-optimizer/extensions/ops/slice_like_test.py @@ -23,14 +23,18 @@ from mo.graph.graph import Node from mo.utils.unittest.graph import build_graph nodes_attributes = { - 'input_data': {'kind': 'data', 'shape': int64_array([3, 4]), 'value': None}, + 'input': {'kind': 'op', 'op': 'Const'}, + 'input_data': {'kind': 'data', 'shape': int64_array([3, 4]), 'value': np.arange(1, 13).reshape([3, 4])}, + 'shape_like': {'kind': 'op', 'op': 'Const', 'shape': int64_array([2, 3]), 'value': None}, 'shape_like_data': {'kind': 'data', 'shape': int64_array([2, 3]), 'value': None}, 'slice_like': {'kind': 'op', 'op': 'slice_data'}, 'out_data': {'kind': 'data', 'shape': None, 'value': None} } edges = [ + ('input', 'input_data'), ('input_data', 'slice_like', {'in': 0}), + ('shape_like', 'shape_like_data'), ('shape_like_data', 'slice_like', {'in': 1}), ('slice_like', 'out_data') ] @@ -43,29 +47,41 @@ class SliceLikeTest(unittest.TestCase): slice_like = Node(graph, 'slice_like') SliceLike.infer(slice_like) ref_shape = int64_array([2, 3]) + ref_value = np.array([[1, 2, 3], [5, 6, 7]]) res_shape = graph.node['out_data']['shape'] + res_value = graph.node['out_data']['value'] self.assertTrue(np.array_equal(res_shape, ref_shape)) + self.assertTrue(np.array_equal(res_value, ref_value)) def test_2(self): graph = build_graph(nodes_attributes, edges, {'slice_like': {'axes': (0, 1)}}) slice_like = Node(graph, 'slice_like') SliceLike.infer(slice_like) ref_shape = int64_array([2, 3]) + ref_value = np.array([[1, 2, 3], [5, 6, 7]]) res_shape = graph.node['out_data']['shape'] + res_value = graph.node['out_data']['value'] self.assertTrue(np.array_equal(res_shape, ref_shape)) + self.assertTrue(np.array_equal(res_value, ref_value)) def test_3(self): graph = build_graph(nodes_attributes, edges, {'slice_like': {'axes': (0,)}}) slice_like = Node(graph, 'slice_like') SliceLike.infer(slice_like) ref_shape = int64_array([2, 4]) + ref_value = np.array([[1, 2, 3, 4], [5, 6, 7, 8]]) res_shape = graph.node['out_data']['shape'] + res_value = graph.node['out_data']['value'] self.assertTrue(np.array_equal(res_shape, ref_shape)) + self.assertTrue(np.array_equal(res_value, ref_value)) def test_4(self): graph = build_graph(nodes_attributes, edges, {'slice_like': {'axes': (-1,)}}) slice_like = Node(graph, 'slice_like') SliceLike.infer(slice_like) ref_shape = int64_array([3, 3]) + ref_value = np.array([[1, 2, 3], [5, 6, 7], [9, 10, 11]]) res_shape = graph.node['out_data']['shape'] + res_value = graph.node['out_data']['value'] self.assertTrue(np.array_equal(res_shape, ref_shape)) + self.assertTrue(np.array_equal(res_value, ref_value)) diff --git a/model-optimizer/mo/front/extractor_test.py b/model-optimizer/mo/front/extractor_test.py index 1ade5f60e68..d04107ed1e4 100644 --- a/model-optimizer/mo/front/extractor_test.py +++ b/model-optimizer/mo/front/extractor_test.py @@ -448,11 +448,11 @@ class TestOutputCut(unittest.TestCase): # {'embeddings': [{'port': None}]} @generate({'C': [{'port': None}]}, {'C': [{'out': 0}]}, {'C': [{'out': 1}]}) def test_output_port_cut(self, output): - nodes = {'A': {'type': 'Identity', 'kind': 'op'}, - 'B': {'type': 'Identity', 'kind': 'op'}, - 'C': {'type': 'Identity', 'kind': 'op'}, - 'D': {'type': 'Identity', 'kind': 'op'}, - 'E': {'type': 'Identity', 'kind': 'op'}, + nodes = {'A': {'type': 'Identity', 'kind': 'op', 'op': 'Identity'}, + 'B': {'type': 'Identity', 'kind': 'op', 'op': 'Identity'}, + 'C': {'type': 'Identity', 'kind': 'op', 'op': 'Identity'}, + 'D': {'type': 'Identity', 'kind': 'op', 'op': 'Identity'}, + 'E': {'type': 'Identity', 'kind': 'op', 'op': 'Identity'}, } edges = [ ('A', 'C', {'in': 0, 'out': 0}), @@ -470,9 +470,9 @@ class TestOutputCut(unittest.TestCase): def test_output_port_cut(self, output): nodes = {'A': {'op': 'Parameter', 'kind': 'op'}, 'B': {'op': 'Parameter', 'kind': 'op'}, - 'C': {'type': 'Identity', 'kind': 'op'}, - 'D': {'type': 'Identity', 'kind': 'op'}, - 'E': {'type': 'Identity', 'kind': 'op'}, + 'C': {'type': 'Identity', 'kind': 'op', 'op': 'Identity'}, + 'D': {'type': 'Identity', 'kind': 'op', 'op': 'Identity'}, + 'E': {'type': 'Identity', 'kind': 'op', 'op': 'Identity'}, } edges = [ ('A', 'C', {'in': 0, 'out': 0}), @@ -489,9 +489,9 @@ class TestOutputCut(unittest.TestCase): class TestUserDataRepack(unittest.TestCase): nodes = {'A': {'name': 'Aa', 'op': 'Parameter', 'kind': 'op'}, 'B': {'name': 'Bb', 'op': 'Parameter', 'kind': 'op'}, - 'C': {'name': 'Cc', 'type': 'Identity', 'value': None, 'kind': 'op'}, - 'D': {'name': 'Dd', 'type': 'Identity', 'value': None, 'kind': 'op'}, - 'E': {'name': 'Ee', 'type': 'Identity', 'value': None, 'kind': 'op'}, + 'C': {'name': 'Cc', 'type': 'Identity', 'value': None, 'kind': 'op', 'op': 'Identity'}, + 'D': {'name': 'Dd', 'type': 'Identity', 'value': None, 'kind': 'op', 'op': 'Identity'}, + 'E': {'name': 'Ee', 'type': 'Identity', 'value': None, 'kind': 'op', 'op': 'Identity'}, } edges = [ ('A', 'C', {'in': 0, 'out': 0}), diff --git a/model-optimizer/mo/graph/graph.py b/model-optimizer/mo/graph/graph.py index e79eb127726..3481180fe53 100644 --- a/model-optimizer/mo/graph/graph.py +++ b/model-optimizer/mo/graph/graph.py @@ -979,7 +979,7 @@ class Graph(nx.MultiDiGraph): undead_node_types.append('TFCustomSubgraphCall') if 'cmd_params' in self.graph and getattr(self.graph['cmd_params'], 'keep_shape_ops'): - undead_node_types.extend(['ShapeOf', 'Shape']) + undead_node_types.extend(['ShapeOf', 'Shape', 'slice_like']) mark_output_reachable_nodes(self) shape_inference(self) diff --git a/model-optimizer/mo/middle/passes/eliminate.py b/model-optimizer/mo/middle/passes/eliminate.py index a2ead944a07..f0b373b5b2d 100644 --- a/model-optimizer/mo/middle/passes/eliminate.py +++ b/model-optimizer/mo/middle/passes/eliminate.py @@ -83,16 +83,14 @@ def mark_undead_nodes(graph, undead_types: list): nx.set_node_attributes(G=graph, name='is_undead', values=False) - # mark output nodes as undead - outputs = graph.get_nodes_with_attributes(op='Result') - nx.set_node_attributes(G=graph, name='is_undead', values={n: True for n in outputs}) + undead_types_with_result = undead_types + ['Result'] + undead_nodes = [] + for node in graph.get_op_nodes(): + node_type = node.soft_get('type', node.op) + if node_type in undead_types_with_result: + undead_nodes.append(node.id) - # mark specifically defined with node type set of nodes - for type in undead_types: - node_of_specific_type = graph.get_nodes_with_attributes(type=type) - nx.set_node_attributes(G=graph, name='is_undead', values={n: True for n in node_of_specific_type}) - - undead_nodes = graph.get_nodes_with_attributes(is_undead=True) + nx.set_node_attributes(G=graph, name='is_undead', values={n: True for n in undead_nodes}) # propagate 'undead' attribute to children nodes of undead nodes if the node produces constant value for node_name in bfs_search(graph, undead_nodes): if graph.node[node_name]['is_undead']: diff --git a/model-optimizer/mo/middle/passes/eliminate_test.py b/model-optimizer/mo/middle/passes/eliminate_test.py index 0b0159a48b9..693c8fdece1 100644 --- a/model-optimizer/mo/middle/passes/eliminate_test.py +++ b/model-optimizer/mo/middle/passes/eliminate_test.py @@ -22,14 +22,14 @@ from mo.graph.graph import Node from mo.middle.passes.eliminate import mark_output_reachable_nodes, mark_const_producer_nodes from mo.utils.unittest.graph import build_graph -nodes_attributes = {'placeholder_1': {'type': 'Parameter', 'kind': 'op'}, - 'placeholder_2': {'type': 'Parameter', 'kind': 'op'}, - 'node_1': {'type': 'Identity', 'value': None, 'kind': 'op'}, - 'node_2': {'type': 'Identity', 'value': None, 'kind': 'op'}, - 'node_3': {'type': 'Identity', 'value': None, 'kind': 'op'}, - 'node_4': {'type': 'Identity', 'value': None, 'kind': 'op'}, - 'node_5': {'type': 'Identity', 'value': None, 'kind': 'op'}, - 'node_6': {'type': 'Identity', 'value': None, 'kind': 'op'}, +nodes_attributes = {'placeholder_1': {'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'}, + 'placeholder_2': {'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'}, + 'node_1': {'type': 'Identity', 'value': None, 'kind': 'op', 'op': 'Identity'}, + 'node_2': {'type': 'Identity', 'value': None, 'kind': 'op', 'op': 'Identity'}, + 'node_3': {'type': 'Identity', 'value': None, 'kind': 'op', 'op': 'Identity'}, + 'node_4': {'type': 'Identity', 'value': None, 'kind': 'op', 'op': 'Identity'}, + 'node_5': {'type': 'Identity', 'value': None, 'kind': 'op', 'op': 'Identity'}, + 'node_6': {'type': 'Identity', 'value': None, 'kind': 'op', 'op': 'Identity'}, 'placeholder_1_data_node': {'value': None, 'kind': 'data'}, 'placeholder_2_data_node': {'value': None, 'kind': 'data'}, 'data_node_1': {'value': None, 'kind': 'data'}, @@ -39,9 +39,9 @@ nodes_attributes = {'placeholder_1': {'type': 'Parameter', 'kind': 'op'}, 'data_node_4': {'value': None, 'kind': 'data'}, 'data_node_5': {'value': None, 'shape': None, 'kind': 'data'}, 'data_node_6': {'value': None, 'shape': None, 'kind': 'data'}, - 'tf_call_1': {'type': 'TFCustomSubgraphCall', 'kind': 'op'}, - 'tf_call_2': {'type': 'TFCustomSubgraphCall', 'kind': 'op'}, - 'tf_call_3': {'type': 'TFCustomSubgraphCall', 'kind': 'op'}, + 'tf_call_1': {'type': 'TFCustomSubgraphCall', 'kind': 'op', 'op': 'TFCustomSubgraphCall'}, + 'tf_call_2': {'type': 'TFCustomSubgraphCall', 'kind': 'op', 'op': 'TFCustomSubgraphCall'}, + 'tf_call_3': {'type': 'TFCustomSubgraphCall', 'kind': 'op', 'op': 'TFCustomSubgraphCall'}, 'op_output': {'kind': 'op', 'op': 'Result'}, 'op_output_1': {'kind': 'op', 'op': 'Result'}, 'op_output_2': {'kind': 'op', 'op': 'Result'} diff --git a/model-optimizer/mo/middle/passes/fusing/decomposition_test.py b/model-optimizer/mo/middle/passes/fusing/decomposition_test.py index f72f653e327..5f32105703d 100644 --- a/model-optimizer/mo/middle/passes/fusing/decomposition_test.py +++ b/model-optimizer/mo/middle/passes/fusing/decomposition_test.py @@ -29,27 +29,27 @@ nodes_attributes = { 'placeholder_2_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, # ScaleShift layer 'scaleshift_1': {'type': 'ScaleShift', 'kind': 'op', 'op': 'ScaleShift', 'axis': 0}, - 'const_scaleshift_1_w': {'value': None, 'shape': None, 'kind': 'op'}, + 'const_scaleshift_1_w': {'value': None, 'shape': None, 'kind': 'op', 'op': 'Const'}, 'scaleshift_1_w': {'value': None, 'shape': None, 'kind': 'data'}, - 'const_scaleshift_1_b': {'value': None, 'shape': None, 'kind': 'op'}, + 'const_scaleshift_1_b': {'value': None, 'shape': None, 'kind': 'op', 'op': 'Const'}, 'scaleshift_1_b': {'value': None, 'shape': None, 'kind': 'data'}, 'scaleshift_1_data': {'value': None, 'shape': None, 'kind': 'data'}, # Mul and Add operations 'mul_1': {'type': None, 'value': None, 'kind': 'op', 'op': 'Mul'}, - 'const_mul_1_w': {'value': None, 'shape': None, 'kind': 'op'}, + 'const_mul_1_w': {'value': None, 'shape': None, 'kind': 'op', 'op': 'Const'}, 'mul_1_w': {'value': None, 'shape': None, 'kind': 'data'}, 'mul_1_data': {'value': None, 'shape': None, 'kind': 'data'}, 'add_1': {'type': None, 'kind': 'op', 'op': 'Add'}, - 'const_add_1_w': {'value': None, 'shape': None, 'kind': 'op'}, + 'const_add_1_w': {'value': None, 'shape': None, 'kind': 'op', 'op': 'Const'}, 'add_1_w': {'value': None, 'shape': None, 'kind': 'data'}, 'add_1_data': {'value': None, 'shape': None, 'kind': 'data'}, # Mul and Add operations 'mul_2': {'type': None, 'kind': 'op', 'op': 'Mul'}, - 'const_mul_2_w': {'value': None, 'shape': None, 'kind': 'op'}, + 'const_mul_2_w': {'value': None, 'shape': None, 'kind': 'op', 'op': 'Const'}, 'mul_2_w': {'value': None, 'shape': None, 'kind': 'data'}, 'mul_2_data': {'value': None, 'shape': None, 'kind': 'data'}, 'add_2': {'type': None, 'kind': 'op', 'op': 'Add'}, - 'const_add_2_w': {'value': None, 'shape': None, 'kind': 'op'}, + 'const_add_2_w': {'value': None, 'shape': None, 'kind': 'op', 'op': 'Const'}, 'add_2_w': {'value': None, 'shape': None, 'kind': 'data'}, 'add_2_data': {'value': None, 'shape': None, 'kind': 'data'}, # Reshape @@ -59,13 +59,13 @@ nodes_attributes = { 'placeholder_2/Reshape_const_data': {'kind': 'data', 'value': None, 'shape': None}, # BatchNorm operation 'bn_op': {'type': None, 'kind': 'op', 'op': 'BatchNorm', 'can_be_fused': True}, - 'const_bn_const': {'value': None, 'shape': None, 'kind': 'op'}, + 'const_bn_const': {'value': None, 'shape': None, 'kind': 'op', 'op': 'Const'}, 'bn_const': {'value': None, 'shape': None, 'kind': 'data'}, - 'const_bn_beta': {'value': None, 'shape': None, 'kind': 'op'}, + 'const_bn_beta': {'value': None, 'shape': None, 'kind': 'op', 'op': 'Const'}, 'bn_beta': {'value': None, 'shape': None, 'kind': 'data'}, - 'const_bn_mean': {'value': None, 'shape': None, 'kind': 'op'}, + 'const_bn_mean': {'value': None, 'shape': None, 'kind': 'op', 'op': 'Const'}, 'bn_mean': {'value': None, 'shape': None, 'kind': 'data'}, - 'const_bn_var': {'value': None, 'shape': None, 'kind': 'op'}, + 'const_bn_var': {'value': None, 'shape': None, 'kind': 'op', 'op': 'Const'}, 'bn_var': {'value': None, 'shape': None, 'kind': 'data'}, 'bn_data': {'value': None, 'shape': None, 'kind': 'data'}, # Concat1 operation diff --git a/model-optimizer/mo/middle/passes/fusing/fuse_linear_ops_test.py b/model-optimizer/mo/middle/passes/fusing/fuse_linear_ops_test.py index 5bc4f3301ad..23b8d071638 100644 --- a/model-optimizer/mo/middle/passes/fusing/fuse_linear_ops_test.py +++ b/model-optimizer/mo/middle/passes/fusing/fuse_linear_ops_test.py @@ -31,27 +31,27 @@ nodes_attributes = { 'scaleshift_1': {'type': 'ScaleShift', 'kind': 'op', 'op': 'ScaleShift'}, 'scaleshift_1_w': {'value': None, 'shape': None, 'kind': 'data'}, 'scaleshift_1_b': {'value': None, 'shape': None, 'kind': 'data'}, - 'const_scaleshift_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, - 'const_scaleshift_1_b': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_scaleshift_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, + 'const_scaleshift_1_b': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'scaleshift_1_data': {'value': None, 'shape': None, 'kind': 'data'}, # Mul and Add operations 'mul_1': {'type': 'Mul', 'kind': 'op', 'op': 'Mul', 'can_be_fused': True, 'infer': lambda node: eltwise_infer(node, lambda a, b: a*b)}, 'mul_1_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, - 'const_mul_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_mul_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'mul_1_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, 'add_1': {'type': 'Add', 'kind': 'op', 'op': 'Add', 'can_be_fused': True}, 'add_1_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, - 'const_add_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_add_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'add_1_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, # Mul2 and Add2 operations 'mul_2': {'type': 'Mul', 'kind': 'op', 'op': 'Mul', 'can_be_fused': True}, 'mul_2_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, - 'const_mul_2_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_mul_2_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'mul_2_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, 'add_2': {'type': 'Add', 'kind': 'op', 'op': 'Add', 'can_be_fused': True}, 'add_2_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, - 'const_add_2_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_add_2_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'add_2_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, # Concat1 operation 'concat_1': {'type': 'Concat', 'kind': 'op', 'op': 'Concat'}, @@ -60,21 +60,21 @@ nodes_attributes = { 'conv_1': {'type': 'Convolution', 'kind': 'op', 'op': 'Conv2D', 'layout': 'NHWC'}, 'conv_1_w': {'value': None, 'shape': None, 'kind': 'data'}, 'conv_1_b': {'value': None, 'shape': None, 'kind': 'data'}, - 'const_conv_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, - 'const_conv_1_b': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_conv_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, + 'const_conv_1_b': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'conv_1_data': {'value': None, 'shape': None, 'kind': 'data'}, 'conv_2': {'type': 'Convolution', 'kind': 'op', 'op': 'Conv2D', 'layout': 'NHWC'}, 'conv_2_w': {'value': None, 'shape': None, 'kind': 'data'}, 'conv_2_b': {'value': None, 'shape': None, 'kind': 'data'}, - 'const_conv_2_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, - 'const_conv_2_b': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_conv_2_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, + 'const_conv_2_b': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'conv_2_data': {'value': None, 'shape': None, 'kind': 'data'}, # MatMul - 'fc_1': {'type': 'MatMul', 'kind': 'op', 'layout': 'NHWC'}, + 'fc_1': {'type': 'MatMul', 'kind': 'op', 'layout': 'NHWC', 'op': 'MatMul'}, 'fc_1_w': {'value': None, 'shape': None, 'kind': 'data'}, 'fc_1_b': {'value': None, 'shape': None, 'kind': 'data'}, - 'const_fc_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, - 'const_fc_1_b': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_fc_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, + 'const_fc_1_b': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'fc_1_data': {'value': None, 'shape': None, 'kind': 'data'}, # Placeholders 'placeholder_2': {'shape': None, 'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'}, diff --git a/model-optimizer/mo/middle/passes/fusing/fuse_linear_seq_test.py b/model-optimizer/mo/middle/passes/fusing/fuse_linear_seq_test.py index afa4a899d48..e256553347d 100644 --- a/model-optimizer/mo/middle/passes/fusing/fuse_linear_seq_test.py +++ b/model-optimizer/mo/middle/passes/fusing/fuse_linear_seq_test.py @@ -27,45 +27,45 @@ nodes_attributes = { 'placeholder_1_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, # ScaleShift layer 'scaleshift_1': {'type': 'ScaleShift', 'kind': 'op', 'op': 'ScaleShift'}, - 'const_scaleshift_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_scaleshift_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'scaleshift_1_w': {'value': None, 'shape': None, 'kind': 'data'}, - 'const_scaleshift_1_b': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_scaleshift_1_b': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'scaleshift_1_b': {'value': None, 'shape': None, 'kind': 'data'}, 'scaleshift_1_data': {'value': None, 'shape': None, 'kind': 'data'}, # Mul and Add operations 'mul_1': {'type': 'Mul', 'kind': 'op', 'op': 'Mul', 'can_be_fused': True}, - 'const_mul_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_mul_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'mul_1_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, 'mul_1_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, 'add_1': {'type': 'Add', 'kind': 'op', 'op': 'Add', 'can_be_fused': True}, - 'const_add_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_add_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'add_1_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, 'add_1_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, # Mul2 and Add2 operations 'mul_2': {'type': 'Mul', 'kind': 'op', 'op': 'Mul', 'can_be_fused': True}, - 'const_mul_2_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_mul_2_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'mul_2_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, 'mul_2_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, 'add_2': {'type': 'Add', 'kind': 'op', 'op': 'Add', 'can_be_fused': True}, - 'const_add_2_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_add_2_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'add_2_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, 'add_2_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, # Mul3 and Add3 operations 'mul_3': {'type': 'Mul', 'kind': 'op', 'op': 'Mul', 'can_be_fused': True}, - 'const_mul_3_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_mul_3_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'mul_3_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, 'mul_3_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, 'add_3': {'type': 'Add', 'kind': 'op', 'op': 'Add', 'can_be_fused': True}, - 'const_add_3_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_add_3_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'add_3_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, 'add_3_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, # Mul4 and Add4 operations 'mul_4': {'type': 'Mul', 'kind': 'op', 'op': 'Mul', 'can_be_fused': True}, - 'const_mul_4_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_mul_4_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'mul_4_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, 'mul_4_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, 'add_4': {'type': 'Add', 'kind': 'op', 'op': 'Add', 'can_be_fused': True}, - 'const_add_4_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_add_4_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'add_4_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, 'add_4_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, # Concat1 operation @@ -73,22 +73,22 @@ nodes_attributes = { 'concat_1_data': {'value': None, 'shape': None, 'kind': 'data'}, # Convolutions 'conv_1': {'type': 'Convolution', 'kind': 'op', 'op': 'Conv2D', 'layout': 'NHWC'}, - 'const_conv_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_conv_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'conv_1_w': {'value': None, 'shape': None, 'kind': 'data'}, - 'const_conv_1_b': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_conv_1_b': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'conv_1_b': {'value': None, 'shape': None, 'kind': 'data'}, 'conv_1_data': {'value': None, 'shape': None, 'kind': 'data'}, 'conv_2': {'type': 'Convolution', 'kind': 'op', 'op': 'Conv2D', 'layout': 'NHWC'}, - 'const_conv_2_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_conv_2_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'conv_2_w': {'value': None, 'shape': None, 'kind': 'data'}, - 'const_conv_2_b': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_conv_2_b': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'conv_2_b': {'value': None, 'shape': None, 'kind': 'data'}, 'conv_2_data': {'value': None, 'shape': None, 'kind': 'data'}, # FullyConnected 'fc_1': {'type': 'MatMul', 'kind': 'op', 'op': 'FullyConnected', 'layout': 'NHWC'}, - 'const_fc_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_fc_1_w': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'fc_1_w': {'value': None, 'shape': None, 'kind': 'data'}, - 'const_fc_1_b': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None}, + 'const_fc_1_b': {'value': None, 'shape': None, 'kind': 'op', 'data_type': None, 'op': 'Const'}, 'fc_1_b': {'value': None, 'shape': None, 'kind': 'data'}, 'fc_1_data': {'value': None, 'shape': None, 'kind': 'data'}, # Placeholders @@ -96,7 +96,7 @@ nodes_attributes = { 'placeholder_2_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, 'placeholder_3': {'shape': None, 'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'}, 'placeholder_3_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None}, - 'op_output': { 'kind': 'op', 'op': 'Result'} + 'op_output': {'kind': 'op', 'op': 'Result'} } diff --git a/model-optimizer/mo/utils/unittest/graph.py b/model-optimizer/mo/utils/unittest/graph.py index fd7d8468898..f76ca0d439a 100644 --- a/model-optimizer/mo/utils/unittest/graph.py +++ b/model-optimizer/mo/utils/unittest/graph.py @@ -277,7 +277,7 @@ regular_op_with_empty_data = lambda name, kwargs: {**regular_op(name, kwargs), * # constants const = lambda name, value: {name: {'kind': 'op', 'value': value, 'shape': int64_array(value.shape), - 'type': 'Const', 'infer': Const.infer}} + 'type': 'Const', 'infer': Const.infer, 'op': 'Const'}} fake_const = lambda name, shape: {name: {'kind': 'op', 'value': None, 'infer': Const.infer, 'shape': int64_array(shape) if shape is not None else None}} shaped_const_with_data = lambda name, shape: {**fake_const(name, shape), **shaped_data(name + '_d', shape)}