XLNET models bugs (#1199)
* Started to write equality comparator for StridedSlice layers. * Now considered only unique StridedSlice consumers of non-constant data nodes. * Fixed test for the transformation ConvertGroupedStridedSlice. * Deleted commented code. * Small fixes. * Moved functions unique_by and group_by_with_binary_predicate to mo/utils/utils.py. * Deleted function collect_sequences. * Added asserts into the constructor of StridedSlice. * Written test for the case when 1) there are 4 StridedSlice operations; 2) 2 of StridedSlice have the same data; 3) 2 others StridedSlice have the same data; 4) all StridedSlice operations outputs are consumed by different operations. * Added some comments.
This commit is contained in:
1 parent
2ec0904d40
commit
3aed19a46a
5 files changed
+258
-91
No files matched your search
@@ -16,6 +16,7 @@
|
||||
|
||||
import logging as log
|
||||
from copy import deepcopy
|
||||
from typing import Callable
|
||||
|
||||
import numpy as np
|
||||
|
||||
@@ -28,6 +29,21 @@ from mo.ops.const import Const
|
||||
from mo.ops.op import Op
|
||||
from mo.ops.squeeze import Squeeze
|
||||
from mo.ops.unsqueeze import Unsqueeze
|
||||
from mo.utils.utils import unique_by
|
||||
|
||||
|
||||
def strided_slices_equality(lhs: Node, rhs: Node) -> bool:
|
||||
"""
|
||||
Equality criterion for StridedSlice layers.
|
||||
:param lhs: the first StridedSlice layer
|
||||
:param rhs: the second StridedSlice layer
|
||||
:return: True, if lhs and rhs have identical attributes 'slices', 'begin_mask', 'end_mask', 'ellipsis_mask',
|
||||
'new_axis_mask', 'shrink_axis_mask', and False otherwise.
|
||||
"""
|
||||
for attr in ['slices', 'new_axis_mask', 'shrink_axis_mask', 'begin_mask', 'end_mask', 'ellipsis_mask']:
|
||||
if not np.array_equal(lhs[attr], rhs[attr]):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
class ConvertGroupedStridedSlice(MiddleReplacementPattern):
|
||||
@@ -68,8 +84,10 @@ class ConvertGroupedStridedSlice(MiddleReplacementPattern):
|
||||
|
||||
input_shape = np.array(input_data.shape)
|
||||
|
||||
# Get all StridedSlice consumers
|
||||
# Get all unique StridedSlice consumers
|
||||
out_nodes = [node for node in input_data.out_nodes() if node.op == 'StridedSlice' and node.in_node(0).name == input_data.name]
|
||||
sorted_out_nodes = sorted(out_nodes, key=lambda n: list(n.slices))
|
||||
out_nodes = unique_by(sorted_out_nodes, strided_slices_equality)
|
||||
if len(out_nodes) <= 1:
|
||||
continue
|
||||
|
||||
|
||||
@@ -36,14 +36,25 @@ nodes_attributes = {
|
||||
|
||||
# StridedSlice layers
|
||||
'sslice_1': {'type': None, 'kind': 'op', 'op': 'StridedSlice', 'slices': None,
|
||||
'shrink_axis_mask': np.array([0, 0, 0, 0])},
|
||||
'shrink_axis_mask': np.array([0, 0, 0, 0]), 'begin_mask': int64_array([1, 1, 1, 1]),
|
||||
'end_mask': int64_array([1, 1, 1, 1]), 'new_axis_mask': int64_array([0, 0, 0, 0]),
|
||||
'ellipsis_mask': int64_array([0])},
|
||||
'sslice_1_data': {'value': None, 'shape': None, 'kind': 'data'},
|
||||
'sslice_2': {'type': None, 'kind': 'op', 'op': 'StridedSlice', 'slices': None,
|
||||
'shrink_axis_mask': np.array([0, 0, 0, 0])},
|
||||
'shrink_axis_mask': np.array([0, 0, 0, 0]), 'begin_mask': int64_array([1, 1, 1, 1]),
|
||||
'end_mask': int64_array([1, 1, 1, 1]), 'new_axis_mask': int64_array([0, 0, 0, 0]),
|
||||
'ellipsis_mask': int64_array([0])},
|
||||
'sslice_2_data': {'value': None, 'shape': None, 'kind': 'data'},
|
||||
'sslice_3': {'type': None, 'kind': 'op', 'op': 'StridedSlice', 'slices': None,
|
||||
'shrink_axis_mask': np.array([0, 0, 0, 0])},
|
||||
'shrink_axis_mask': np.array([0, 0, 0, 0]), 'begin_mask': int64_array([1, 1, 1, 1]),
|
||||
'end_mask': int64_array([1, 1, 1, 1]), 'new_axis_mask': int64_array([0, 0, 0, 0]),
|
||||
'ellipsis_mask': int64_array([0])},
|
||||
'sslice_3_data': {'value': None, 'shape': None, 'kind': 'data'},
|
||||
'sslice_4': {'type': None, 'kind': 'op', 'op': 'StridedSlice', 'slices': None,
|
||||
'shrink_axis_mask': np.array([0, 0, 0, 0]), 'begin_mask': int64_array([1, 1, 1, 1]),
|
||||
'end_mask': int64_array([1, 1, 1, 1]), 'new_axis_mask': int64_array([0, 0, 0, 0]),
|
||||
'ellipsis_mask': int64_array([0])},
|
||||
'sslice_4_data': {'value': None, 'shape': None, 'kind': 'data'},
|
||||
|
||||
# Split layer
|
||||
'axis_const': {'kind': 'op'},
|
||||
@@ -81,6 +92,16 @@ nodes_attributes = {
|
||||
'sslice_2/Unsqueeze_new_data': {'value': None, 'shape': None, 'kind': 'data'},
|
||||
'sslice_2/unsqueeze_const': {'type': 'Const', 'kind': 'op', 'op': 'Const', 'value': int64_array([2])},
|
||||
'sslice_2/unsqueeze_const_data': {'kind': 'data', 'value': None, 'shape': None},
|
||||
|
||||
# Activations
|
||||
'abs': {'type': None, 'value': None, 'kind': 'op', 'op': 'Abs'},
|
||||
'abs_data': {'value': None, 'shape': None, 'kind': 'data'},
|
||||
'relu': {'type': None, 'value': None, 'kind': 'op', 'op': 'ReLU'},
|
||||
'relu_data': {'value': None, 'shape': None, 'kind': 'data'},
|
||||
'erf': {'type': None, 'value': None, 'kind': 'op', 'op': 'Erf'},
|
||||
'erf_data': {'value': None, 'shape': None, 'kind': 'data'},
|
||||
'gelu': {'type': None, 'value': None, 'kind': 'op', 'op': 'Gelu'},
|
||||
'gelu_data': {'value': None, 'shape': None, 'kind': 'data'},
|
||||
}
|
||||
|
||||
one_strided_slice_case_node_attributes = {
|
||||
@@ -653,6 +674,110 @@ class ConvertGroupedStridedSliceTests(unittest.TestCase):
|
||||
(flag, resp) = compare_graphs(graph, graph_ref, 'op_output', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
|
||||
# Test for case when
|
||||
# 1) There are 4 StridedSlice operations.
|
||||
# 2) 2 of StridedSlice have the same data.
|
||||
# 3) 2 others StridedSlice have the same data.
|
||||
# 4) All StridedSlice operations outputs are consumed by different operations.
|
||||
def test_10(self):
|
||||
graph = build_graph(nodes_attributes,
|
||||
[('placeholder_1', 'placeholder_1_data'),
|
||||
('placeholder_1_data', 'sslice_1'),
|
||||
('sslice_1', 'sslice_1_data'),
|
||||
('placeholder_1_data', 'sslice_2'),
|
||||
('sslice_2', 'sslice_2_data'),
|
||||
('placeholder_1_data', 'sslice_3'),
|
||||
('sslice_3', 'sslice_3_data'),
|
||||
('placeholder_1_data', 'sslice_4'),
|
||||
('sslice_4', 'sslice_4_data'),
|
||||
('sslice_1_data', 'abs'),
|
||||
('abs', 'abs_data'),
|
||||
('sslice_2_data', 'relu'),
|
||||
('relu', 'relu_data'),
|
||||
('sslice_3_data', 'erf'),
|
||||
('erf', 'erf_data'),
|
||||
('sslice_4_data', 'gelu'),
|
||||
('gelu', 'gelu_data'),
|
||||
('abs_data', 'concat_1'),
|
||||
('relu_data', 'concat_1'),
|
||||
('erf_data', 'concat_1'),
|
||||
('gelu_data', 'concat_1'),
|
||||
('concat_1', 'concat_1_data'),
|
||||
('concat_1_data', 'op_output')
|
||||
],
|
||||
{'placeholder_1_data': {'shape': np.array([1, 54, 54, 3])},
|
||||
'sslice_1': {'slices': np.array(
|
||||
[slice(0, 1, 1), slice(0, 30, 1), slice(0, 54, 1), slice(0, 3, 1)])},
|
||||
'sslice_1_data': {'shape': np.array([1, 30, 54, 3])},
|
||||
'sslice_2': {'slices': np.array(
|
||||
[slice(0, 1, 1), slice(30, 54, 1), slice(0, 54, 1), slice(0, 3, 1)])},
|
||||
'sslice_2_data': {'shape': np.array([1, 24, 54, 3])},
|
||||
'sslice_3': {'slices': np.array(
|
||||
[slice(0, 1, 1), slice(0, 30, 1), slice(0, 54, 1), slice(0, 3, 1)])},
|
||||
'sslice_3_data': {'shape': np.array([1, 30, 54, 3])},
|
||||
'sslice_4': {'slices': np.array(
|
||||
[slice(0, 1, 1), slice(30, 54, 1), slice(0, 54, 1), slice(0, 3, 1)])},
|
||||
'sslice_4_data': {'shape': np.array([1, 24, 54, 3])},
|
||||
'concat_1_data': {'shape': np.array([1, 108, 54, 3])},
|
||||
'abs_data': {'shape': np.array([1, 30, 54, 3])},
|
||||
'relu_data': {'shape': np.array([1, 24, 54, 3])},
|
||||
'erf_data': {'shape': np.array([1, 30, 54, 3])},
|
||||
'gelu_data': {'shape': np.array([1, 24, 54, 3])},
|
||||
})
|
||||
graph.graph['layout'] = 'NHWC'
|
||||
|
||||
graph_ref = build_graph(nodes_attributes,
|
||||
[('placeholder_1', 'placeholder_1_data'),
|
||||
('placeholder_1_data', 'split_1'),
|
||||
('split_1', 'split_1_data'),
|
||||
('split_1', 'split_2_data'),
|
||||
('placeholder_1_data', 'sslice_3'),
|
||||
('sslice_3', 'sslice_3_data'),
|
||||
('placeholder_1_data', 'sslice_4'),
|
||||
('sslice_4', 'sslice_4_data'),
|
||||
('split_1_data', 'abs'),
|
||||
('abs', 'abs_data'),
|
||||
('split_2_data', 'relu'),
|
||||
('relu', 'relu_data'),
|
||||
('sslice_3_data', 'erf'),
|
||||
('erf', 'erf_data'),
|
||||
('sslice_4_data', 'gelu'),
|
||||
('gelu', 'gelu_data'),
|
||||
('abs_data', 'concat_1'),
|
||||
('relu_data', 'concat_1'),
|
||||
('erf_data', 'concat_1'),
|
||||
('gelu_data', 'concat_1'),
|
||||
('concat_1', 'concat_1_data'),
|
||||
|
||||
('axis_const', 'axis_const_data'),
|
||||
('split_dim_const', 'split_dim_const_data'),
|
||||
('axis_const_data', 'split_1', {'in': 1}),
|
||||
('split_dim_const_data', 'split_1', {'in': 2}),
|
||||
|
||||
('concat_1_data', 'op_output')
|
||||
],
|
||||
{'placeholder_1_data': {'shape': np.array([1, 54, 54, 3])},
|
||||
'split_1_data': {'shape': np.array([1, 30, 54, 3])},
|
||||
'split_2_data': {'shape': np.array([1, 24, 54, 3])},
|
||||
'sslice_3': {'slices': np.array(
|
||||
[slice(0, 1, 1), slice(0, 30, 1), slice(0, 54, 1), slice(0, 3, 1)])},
|
||||
'sslice_3_data': {'shape': np.array([1, 30, 54, 3])},
|
||||
'sslice_4': {'slices': np.array(
|
||||
[slice(0, 1, 1), slice(30, 54, 1), slice(0, 54, 1), slice(0, 3, 1)])},
|
||||
'sslice_4_data': {'shape': np.array([1, 24, 54, 3])},
|
||||
'abs_data': {'shape': np.array([1, 30, 54, 3])},
|
||||
'relu_data': {'shape': np.array([1, 24, 54, 3])},
|
||||
'erf_data': {'shape': np.array([1, 30, 54, 3])},
|
||||
'gelu_data': {'shape': np.array([1, 24, 54, 3])},
|
||||
'axis_const': {'value': 1},
|
||||
'concat_1_data': {'shape': np.array([1, 108, 54, 3])},
|
||||
})
|
||||
|
||||
pattern = ConvertGroupedStridedSlice()
|
||||
pattern.find_and_replace_pattern(graph)
|
||||
(flag, resp) = compare_graphs(graph, graph_ref, 'concat_1_data', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
|
||||
|
||||
class AddReshapeAfterStridedSliceTests(unittest.TestCase):
|
||||
def test_ss_1_shrink_last(self):
|
||||
@@ -987,69 +1112,75 @@ class AddReshapeAfterStridedSliceTests(unittest.TestCase):
|
||||
(flag, resp) = compare_graphs(graph, graph_ref, 'sslice_2_data', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
|
||||
# test case with 2 strided slices with the same parameters but different outputs
|
||||
# test case when
|
||||
# 1) There are 3 StridedSlice operations;
|
||||
# 2) 2 of StridedSlice have the same attributes;
|
||||
# 3) other StridedSlice have different attributes;
|
||||
# 4) pair (some StridedSlice from the item 2, StridedSlice from the item 3) can be replaced by VariadicSplit.
|
||||
def test_1(self):
|
||||
graph = build_graph(nodes_attributes,
|
||||
[('placeholder_1', 'placeholder_1_data'),
|
||||
('placeholder_1_data', 'sslice_1'),
|
||||
('sslice_1', 'sslice_1_data'),
|
||||
('placeholder_1_data', 'sslice_2'),
|
||||
('sslice_2', 'sslice_2_data'),
|
||||
('placeholder_1_data', 'sslice_3'),
|
||||
('sslice_3', 'sslice_3_data'),
|
||||
('sslice_1_data', 'concat_1'),
|
||||
('sslice_2_data', 'concat_1'),
|
||||
('sslice_3_data', 'placeholder_2'),
|
||||
('placeholder_2', 'placeholder_2_data'),
|
||||
('concat_1', 'concat_1_data'),
|
||||
('concat_1_data', 'op_output'),
|
||||
('placeholder_2_data', 'op_output')
|
||||
],
|
||||
{'placeholder_1_data': {'shape': np.array([1, 227, 227, 54])},
|
||||
|
||||
'sslice_1': {'slices': np.array(
|
||||
[slice(0, 1, 1), slice(0, 227, 1), slice(0, 227, 1), slice(0, 27, 1)])},
|
||||
'sslice_1_data': {'shape': np.array([1, 227, 227, 27])},
|
||||
|
||||
'sslice_2': {'slices': np.array(
|
||||
[slice(0, 1, 1), slice(0, 227, 1), slice(0, 227, 1), slice(27, 54, 1)])},
|
||||
'sslice_2_data': {'shape': np.array([1, 227, 227, 27])},
|
||||
|
||||
'sslice_3': {'slices': np.array(
|
||||
[slice(0, 1, 1), slice(0, 227, 1), slice(0, 227, 1), slice(0, 27, 1)])},
|
||||
'sslice_3_data': {'shape': np.array([1, 227, 227, 27])},
|
||||
|
||||
'concat_1_data': {'shape': np.array([1, 227, 227, 54])},
|
||||
}, nodes_with_edges_only=True)
|
||||
[
|
||||
('placeholder_1', 'placeholder_1_data'),
|
||||
('placeholder_1_data', 'sslice_1'),
|
||||
('sslice_1', 'sslice_1_data'),
|
||||
('placeholder_1_data', 'sslice_2'),
|
||||
('sslice_2', 'sslice_2_data'),
|
||||
('placeholder_1_data', 'sslice_3'),
|
||||
('sslice_3', 'sslice_3_data'),
|
||||
('sslice_1_data', 'concat_1'),
|
||||
('sslice_2_data', 'concat_1'),
|
||||
('sslice_3_data', 'concat_1'),
|
||||
('concat_1', 'concat_1_data'),
|
||||
('concat_1_data', 'op_output'),
|
||||
],
|
||||
{
|
||||
'placeholder_1_data': {'shape': np.array([1, 227, 227, 54])},
|
||||
'sslice_1': {'slices': np.array([slice(0, 1, 1), slice(0, 227, 1), slice(0, 227, 1),
|
||||
slice(0, 27, 1)])},
|
||||
'sslice_1_data': {'shape': np.array([1, 227, 227, 27])},
|
||||
'sslice_2': {'slices': np.array([slice(0, 1, 1), slice(0, 227, 1), slice(0, 227, 1),
|
||||
slice(27, 54, 1)])},
|
||||
'sslice_2_data': {'shape': np.array([1, 227, 227, 27])},
|
||||
'sslice_3': {'slices': np.array([slice(0, 1, 1), slice(0, 227, 1), slice(0, 227, 1),
|
||||
slice(0, 27, 1)])},
|
||||
'sslice_3_data': {'shape': np.array([1, 227, 227, 27])},
|
||||
'concat_1': {'axis': 3},
|
||||
'concat_1_data': {'shape': np.array([1, 227, 227, 81])},
|
||||
})
|
||||
graph.graph['layout'] = 'NHWC'
|
||||
|
||||
graph_ref = build_graph(nodes_attributes,
|
||||
[('placeholder_1', 'placeholder_1_data'),
|
||||
('placeholder_1_data', 'split_1'),
|
||||
('split_1', 'split_1_data'),
|
||||
('split_1', 'split_2_data'),
|
||||
('split_1_data', 'concat_1'),
|
||||
('split_2_data', 'concat_1'),
|
||||
('split_1_data', 'placeholder_2'),
|
||||
('placeholder_2', 'placeholder_2_data'),
|
||||
('concat_1', 'concat_1_data'),
|
||||
('concat_1_data', 'op_output'),
|
||||
('placeholder_2_data', 'op_output'),
|
||||
|
||||
('axis_const', 'axis_const_data'),
|
||||
('split_dim_const', 'split_dim_const_data'),
|
||||
('axis_const_data', 'split_1', {'in': 1}),
|
||||
('split_dim_const_data', 'split_1', {'in': 2}),
|
||||
],
|
||||
{'placeholder_1_data': {'shape': np.array([1, 227, 227, 54])},
|
||||
'axis_const': {'value': 3},
|
||||
'split_1_data': {'shape': np.array([1, 227, 227, 27])},
|
||||
'split_2_data': {'shape': np.array([1, 227, 227, 27])},
|
||||
'concat_1_data': {'shape': np.array([1, 227, 227, 54])},
|
||||
}, nodes_with_edges_only=True)
|
||||
|
||||
[
|
||||
('placeholder_1', 'placeholder_1_data'),
|
||||
('placeholder_1_data', 'sslice_3'),
|
||||
('sslice_3', 'sslice_3_data'),
|
||||
('placeholder_1_data', 'split_1'),
|
||||
('split_1', 'split_1_data'),
|
||||
('split_1', 'split_2_data'),
|
||||
('axis_const', 'axis_const_data'),
|
||||
('split_dim_const', 'split_dim_const_data'),
|
||||
('axis_const_data', 'split_1', {'in': 1}),
|
||||
('split_dim_const_data', 'split_1', {'in': 2}),
|
||||
('split_1_data', 'concat_1'),
|
||||
('split_2_data', 'concat_1'),
|
||||
('sslice_3_data', 'concat_1'),
|
||||
('concat_1', 'concat_1_data'),
|
||||
('concat_1_data', 'op_output')
|
||||
],
|
||||
{
|
||||
'placeholder_1_data': {'shape': np.array([1, 227, 227, 54])},
|
||||
'sslice_3': {'slices': np.array([slice(0, 1, 1), slice(0, 227, 1), slice(0, 227, 1),
|
||||
slice(0, 27, 1)])},
|
||||
'sslice_3_data': {'shape': np.array([1, 227, 227, 27])},
|
||||
'split_1_data': {'shape': np.array([1, 227, 227, 27])},
|
||||
'split_2_data': {'shape': np.array([1, 227, 227, 27])},
|
||||
'axis_const': {'op': 'Const', 'type': 'Const', 'value': 3, 'shape': []},
|
||||
'axis_const_data': {'value': 3, 'shape': []},
|
||||
'split_dim_const': {'op': 'Const', 'type': 'Const', 'value': np.array([27, 27])},
|
||||
'split_dim_const_data': {'value': np.array([27, 27])},
|
||||
'concat_1': {'axis': 3},
|
||||
'concat_1_data': {'shape': np.array([1, 227, 227, 81])}
|
||||
})
|
||||
ConvertGroupedStridedSlice().find_and_replace_pattern(graph)
|
||||
|
||||
(flag, resp) = compare_graphs(graph, graph_ref, 'concat_1_data', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ from mo.front.tf.graph_utils import create_op_with_const_inputs
|
||||
from mo.graph.graph import Graph, Node, rename_nodes
|
||||
from mo.middle.replacement import MiddleReplacementPattern
|
||||
from mo.utils.error import Error
|
||||
from mo.utils.utils import group_by_with_binary_predicate
|
||||
|
||||
|
||||
def node_has_one_consumer(node: Node) -> bool:
|
||||
@@ -148,34 +149,6 @@ class CanBeFused:
|
||||
return False
|
||||
|
||||
|
||||
def collect_sequences(xs: List[Node]) -> List[List[Node]]:
|
||||
"""
|
||||
This function receive a list of Interpolate layers, and returns a list of sequences
|
||||
of Interpolate layers. Two Interpolate layers, 'first' and 'second' are called to be
|
||||
a consecutive, if an output of 'first' is an input of 'second', and number of destinations
|
||||
of 'first' is equal to 1.
|
||||
:param xs: list of Interpolate layers
|
||||
:return: list of sequences of consecutive Interpolate layers
|
||||
"""
|
||||
fuser = CanBeFused()
|
||||
if not xs:
|
||||
return []
|
||||
|
||||
prev = xs[0]
|
||||
sequence = [prev]
|
||||
result = []
|
||||
for x in xs[1:]:
|
||||
if is_next(prev, x) and fuser(prev, x):
|
||||
sequence.append(x)
|
||||
prev = x
|
||||
else:
|
||||
result.append(sequence)
|
||||
prev = x
|
||||
sequence = [prev]
|
||||
result.append(sequence)
|
||||
return result
|
||||
|
||||
|
||||
def get_interpolate_attributes(node: Node) -> dict:
|
||||
opset_to_default_values = {
|
||||
'opset1': {
|
||||
@@ -293,6 +266,7 @@ class InterpolateSequenceToInterpolate(MiddleReplacementPattern):
|
||||
def find_and_replace_pattern(self, graph: Graph):
|
||||
log.debug('Enabled replacement of a sequence of Interpolate layers with one Interpolate layer.')
|
||||
interps = [n for n in graph.pseudo_topological_sort() if n.kind == 'op' and n.op == 'Interpolate']
|
||||
sequences = collect_sequences(interps)
|
||||
fuser = CanBeFused()
|
||||
sequences = group_by_with_binary_predicate(interps, lambda prev, x: is_next(prev, x) and fuser(prev, x))
|
||||
for seq in sequences:
|
||||
replace_sequence(seq, graph)
|
||||
Reference in new issue
Block a user