From 9f64f77a3c58bdf8bd9988a1f8fbc44145e659c3 Mon Sep 17 00:00:00 2001 From: Pavel Esir Date: Wed, 20 Oct 2021 13:16:06 +0300 Subject: [PATCH] [MO] allow zero size dimensions in Slice output (#7791) * allow zero size dimensions in Slice output * updated comments regarding 0-size dimensions --- model-optimizer/mo/ops/slice.py | 2 - .../unit_tests/mo/ops/slice_test.py | 47 +++---------------- 2 files changed, 6 insertions(+), 43 deletions(-) diff --git a/model-optimizer/mo/ops/slice.py b/model-optimizer/mo/ops/slice.py index da25d1dc2f0..249c4cff638 100644 --- a/model-optimizer/mo/ops/slice.py +++ b/model-optimizer/mo/ops/slice.py @@ -142,8 +142,6 @@ class Slice(Op): slice_idx[axes[i]] = slice(starts[i], ends[i], steps[i]) if input_value is None or any(is_dynamic_slice(s) for s in slice_idx): output_shape = get_shape_from_slice(input_shape, slice_idx) - if np.ma.any(output_shape <= 0): - raise Error('Output shape: {} of node "{}" contains non-positive values'.format(output_shape, node.name)) node.out_port(0).data.set_shape(output_shape) else: node.out_port(0).data.set_value(input_value[tuple(slice_idx)]) diff --git a/model-optimizer/unit_tests/mo/ops/slice_test.py b/model-optimizer/unit_tests/mo/ops/slice_test.py index 9a2134c32a7..97fbd4a8a87 100644 --- a/model-optimizer/unit_tests/mo/ops/slice_test.py +++ b/model-optimizer/unit_tests/mo/ops/slice_test.py @@ -57,6 +57,12 @@ class TestSliceOp(unittest.TestCase): # steps are non-constant ([[4, 5, 6, 7], [2, 3, 5, 6], [5, 6, 8, 9], [5, 6, 8, 9]], [4, 4], [0, 1], [3, -2], [0, 1], None, None, [dynamic_dimension_value, dynamic_dimension_value]), + # negative steps and since after normalization starts < ends output shape has 0-size dimension + (None, [20], [1], [-1], [0], [-2], None, [0]), + # since starts == ends output shape has 0-size dimension + (None, [4], [1], [1], [0], [1], None, [0]), + # since starts > ends output shape has 0-size dimension + (None, [4], [2], [1], [0], [1], None, [0]) ]) def test_slice_infer(self, inp_value, inp_shape, starts, ends, axes, steps, expected_value, expected_shape): if inp_value is None: @@ -103,44 +109,3 @@ class TestSliceOp(unittest.TestCase): if expected_value is not None: self.assertTrue(strict_compare_tensors(slice_node.out_node().value, expected_value)) self.assertTrue(strict_compare_tensors(slice_node.out_node().shape, expected_shape)) - - # negative tests - @generate(*[ - # 1D input with negative starts - (None, [1], [-1], [0], [-2], [-6], [20]), - # case when output shape has zero elements - (None, [1], [1], [0], [1], [0], [4]) - ]) - def test_slice_infer_negative(self, inp_value, starts, ends, axes, steps, expected, inp_shape=None): - if inp_value is None: - input_node = shaped_data('data_1', int64_array(inp_shape)) - else: - input_node = valued_data('data_1', int64_array(inp_value)) - - def convert_args(val, name=''): - if val is not None: - return valued_const_with_data(name, int64_array(val)) - else: - return shaped_const_with_data(name, [0]) #fake shape - - starts = convert_args(starts, 'starts') - ends = convert_args(ends, 'ends') - axes = convert_args(axes, 'axes') - steps = convert_args(steps, 'steps') - - nodes = {**input_node, - **regular_op_with_empty_data('slice', {'op': 'Slice'}), - **starts, **ends, **axes, **steps - } - - graph = build_graph(nodes, - [('data_1', 'slice'), - *connect('starts', '1:slice'), - *connect('ends', '2:slice'), - *connect('axes', '3:slice'), - *connect('steps', '4:slice'), - *connect('slice', 'slice_d')]) - - graph.stage = 'middle' - slice_node = Node(graph, 'slice') - self.assertRaises(Error, Slice.infer, slice_node)