[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
This commit is contained in:
Yegor Kruglov authored and GitHub committed 2020-06-30 22:32:13 +03:00
1 parent c9d4e6b934
commit 465707eba7
23 files changed
+426 -319

No files matched your search

+1 -2
View File
@@ -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
@@ -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(),
}
@@ -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'}
}
@@ -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(),
}
@@ -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()
}
@@ -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(),
}
@@ -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))
@@ -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)
@@ -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):
@@ -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))
@@ -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))
@@ -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'},
}
@@ -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))
+12 -1
View File
@@ -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)
@@ -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))
+11 -11
View File
@@ -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}),
+1 -1
View File
@@ -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)
@@ -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']:
@@ -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'}
@@ -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
@@ -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'},
@@ -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'}
}
+1 -1
View File
@@ -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)}