Fix pad op with int input (#4438)
* Added operation ConvertLike to the MO * Fixed transformations with Pad which insert Const with pad value of incorrect type * Added constant folding to ConvertLike operation * Fixed unit tests for Pad transformations to include ConverLike operations * Update copyright year * nGraph code style fix * Added OV_ITT_SCOPED_TASK for ConvertLike constant folding
This commit is contained in:
@@ -639,6 +639,7 @@ extensions/ops/box_nms.py
|
||||
extensions/ops/bucketize.py
|
||||
extensions/ops/Cast.py
|
||||
extensions/ops/constant_fill.py
|
||||
extensions/ops/ConvertLike.py
|
||||
extensions/ops/copyop.py
|
||||
extensions/ops/correlation.py
|
||||
extensions/ops/ctc_greedy_decoder.py
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Copyright (C) 2020 Intel Corporation
|
||||
Copyright (C) 2018-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -14,7 +14,9 @@
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from extensions.ops.ConvertLike import ConvertLike
|
||||
from mo.front.common.replacement import FrontReplacementPattern
|
||||
from mo.front.tf.graph_utils import create_op_with_const_inputs
|
||||
from mo.graph.graph import Graph, rename_nodes
|
||||
from mo.ops.const import Const
|
||||
from mo.ops.pad import Pad
|
||||
@@ -39,7 +41,11 @@ class AttributedPadToPad(FrontReplacementPattern):
|
||||
new_pad.in_port(1).connect(Const(graph, {'value': attr_pad.pads[:, 0]}).create_node().out_port(0))
|
||||
new_pad.in_port(2).connect(Const(graph, {'value': attr_pad.pads[:, 1]}).create_node().out_port(0))
|
||||
if attr_pad.soft_get('mode') == 'constant':
|
||||
new_pad.in_port(3).connect(Const(graph, {'value': attr_pad.fill_value}).create_node().out_port(0))
|
||||
# create Constant node of proper data type (equal to the data type of the Pad first input)
|
||||
convert_pad_value = create_op_with_const_inputs(graph, ConvertLike, {0: attr_pad.fill_value},
|
||||
{'name': original_name + '/pad_value_convert'})
|
||||
convert_pad_value.in_port(1).connect(new_pad.in_port(0).get_source())
|
||||
new_pad.in_port(3).connect(convert_pad_value.out_port(0))
|
||||
|
||||
attr_pad.out_port(0).get_connection().set_source(new_pad.out_port(0))
|
||||
graph.remove_node(attr_pad.id)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Copyright (C) 2018-2020 Intel Corporation
|
||||
Copyright (C) 2018-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -31,6 +31,7 @@ nodes_attributes = {
|
||||
|
||||
# new Pad layer and inputs
|
||||
'pad': {'type': 'Pad', 'kind': 'op', 'op': 'Pad', 'mode': 'constant'},
|
||||
'convert_like': {'type': 'ConvertLike', 'kind': 'op', 'op': 'ConvertLike'},
|
||||
**const('pad_begin', int64_array([1, 3, 5])),
|
||||
**const('pad_end', int64_array([2, 4, 6])),
|
||||
**const('pad_fill', np.array(0.75)),
|
||||
@@ -49,7 +50,9 @@ class AttributedPadToPadTest(unittest.TestCase):
|
||||
[('placeholder', 'pad', {'in': 0, 'out': 0}),
|
||||
('pad_begin', 'pad', {'in': 1, 'out': 0}),
|
||||
('pad_end', 'pad', {'in': 2, 'out': 0}),
|
||||
('pad_fill', 'pad', {'in': 3, 'out': 0}),
|
||||
('pad_fill', 'convert_like', {'in': 0, 'out': 0}),
|
||||
('placeholder', 'convert_like', {'in': 1, 'out': 0}),
|
||||
('convert_like', 'pad', {'in': 3, 'out': 0}),
|
||||
('pad', 'result')
|
||||
],
|
||||
{}, nodes_with_edges_only=True)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Copyright (C) 2020 Intel Corporation
|
||||
Copyright (C) 2018-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -13,13 +13,13 @@
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
from extensions.ops.ConvertLike import ConvertLike
|
||||
from extensions.ops.split import Split
|
||||
from extensions.ops.transpose import Transpose
|
||||
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_with_const_inputs
|
||||
from mo.graph.graph import Graph, rename_node
|
||||
from mo.ops.const import Const
|
||||
from mo.ops.pad import Pad
|
||||
from mo.ops.squeeze import Squeeze
|
||||
|
||||
@@ -47,8 +47,11 @@ class PadTFToPad(FrontReplacementPattern):
|
||||
if not tfpad.in_port(2).disconnected():
|
||||
tfpad.in_port(2).get_connection().set_destination(new_pad.in_port(3))
|
||||
else:
|
||||
new_pad.in_port(3).connect(Const(graph, {'value': 0.0, 'name': new_pad.name + '/value'}
|
||||
).create_node().out_port(0))
|
||||
# create Constant node of proper data type (equal to the data type of the Pad first input)
|
||||
convert_pad_value = create_op_with_const_inputs(graph, ConvertLike, {0: 0.0},
|
||||
{'name': original_name + '/pad_value_convert'})
|
||||
convert_pad_value.in_port(1).connect(new_pad.in_port(0).get_source())
|
||||
new_pad.in_port(3).connect(convert_pad_value.out_port(0))
|
||||
|
||||
# convert TF representation of the pads as [N, 2] to MO representation: [N] and [N]
|
||||
transposed_pads = create_op_with_const_inputs(graph, Transpose, {1: int64_array([1, 0])})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Copyright (C) 2018-2020 Intel Corporation
|
||||
Copyright (C) 2018-2021 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,7 @@ import unittest
|
||||
import numpy as np
|
||||
|
||||
from extensions.front.tf.pad_tf_to_pad import PadTFToPad
|
||||
from mo.front.common.partial_infer.utils import int64_array
|
||||
from mo.front.common.partial_infer.utils import int64_array, float_array
|
||||
from mo.utils.ir_engine.compare_graphs import compare_graphs
|
||||
from mo.utils.unittest.graph import build_graph, const
|
||||
|
||||
@@ -27,7 +27,7 @@ nodes_attributes = {
|
||||
'placeholder': {'shape': None, 'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'},
|
||||
'tfpad': {'type': None, 'kind': 'op', 'op': 'TFPad', 'mode': 'constant', 'name': 'tfpad_name'},
|
||||
**const('paddings', int64_array([1, 2, 3, 4, 5, 6]).reshape([3, 2])),
|
||||
**const('fill', int64_array(5.75)),
|
||||
**const('fill', float_array(5.75)),
|
||||
'result': {'type': 'Result', 'value': None, 'kind': 'op', 'op': 'Result'},
|
||||
|
||||
# new Pad layer and sub-graph
|
||||
@@ -40,6 +40,7 @@ nodes_attributes = {
|
||||
**const('squeeze_1_axis', int64_array([0])),
|
||||
'squeeze_2': {'type': 'Squeeze', 'kind': 'op', 'op': 'Squeeze'},
|
||||
**const('squeeze_2_axis', int64_array([0])),
|
||||
'convert_like': {'type': 'ConvertLike', 'kind': 'op', 'op': 'ConvertLike'},
|
||||
|
||||
**const('pad_fill', np.array(0.0)),
|
||||
}
|
||||
@@ -86,7 +87,9 @@ class PadTFToPadTest(unittest.TestCase):
|
||||
{}, nodes_with_edges_only=True)
|
||||
graph.get_op_nodes(op='TFPad')[0].add_input_port(2)
|
||||
|
||||
graph_ref = build_graph(nodes_attributes, common_edges + [('pad_fill', 'pad', {'in': 3, 'out': 0})],
|
||||
graph_ref = build_graph(nodes_attributes, common_edges + [('pad_fill', 'convert_like', {'in': 0, 'out': 0}),
|
||||
('placeholder', 'convert_like', {'in': 1, 'out': 0}),
|
||||
('convert_like', 'pad', {'in': 3, 'out': 0})],
|
||||
{}, nodes_with_edges_only=True)
|
||||
self._run_test(graph, graph_ref)
|
||||
|
||||
|
||||
44
model-optimizer/extensions/ops/ConvertLike.py
Normal file
44
model-optimizer/extensions/ops/ConvertLike.py
Normal file
@@ -0,0 +1,44 @@
|
||||
"""
|
||||
Copyright (C) 2018-2021 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.
|
||||
"""
|
||||
|
||||
from mo.front.common.partial_infer.elemental import copy_shape_infer
|
||||
from mo.graph.graph import Node, Graph
|
||||
from mo.ops.op import Op
|
||||
|
||||
|
||||
class ConvertLike(Op):
|
||||
op = 'ConvertLike'
|
||||
enabled = False
|
||||
|
||||
def __init__(self, graph: Graph, attrs: dict):
|
||||
mandatory_props = {
|
||||
'op': self.op,
|
||||
'type': self.op,
|
||||
'version': 'opset1',
|
||||
|
||||
'infer': copy_shape_infer,
|
||||
'type_infer': self.type_infer,
|
||||
|
||||
'in_ports_count': 2,
|
||||
'out_ports_count': 1,
|
||||
}
|
||||
super().__init__(graph, mandatory_props, attrs)
|
||||
|
||||
@staticmethod
|
||||
def type_infer(node: Node):
|
||||
assert node.is_in_port_connected(1), 'The second input is not connected for a node {}.' \
|
||||
''.format(node.soft_get('name'), node.id)
|
||||
node.out_port(0).set_data_type(node.in_port(1).get_data_type())
|
||||
@@ -42,6 +42,9 @@ namespace ngraph
|
||||
|
||||
virtual std::shared_ptr<Node>
|
||||
clone_with_new_inputs(const OutputVector& new_args) const override;
|
||||
|
||||
bool constant_fold(OutputVector& output_values,
|
||||
const OutputVector& input_values) override;
|
||||
};
|
||||
|
||||
} // namespace v1
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include <memory>
|
||||
#include "itt.hpp"
|
||||
|
||||
#include "ngraph/op/constant.hpp"
|
||||
#include "ngraph/op/convert.hpp"
|
||||
#include "ngraph/op/convert_like.hpp"
|
||||
|
||||
using namespace std;
|
||||
@@ -48,3 +50,17 @@ shared_ptr<Node> op::v1::ConvertLike::clone_with_new_inputs(const OutputVector&
|
||||
check_new_args_count(this, new_args);
|
||||
return make_shared<ConvertLike>(new_args.at(0), new_args.at(1));
|
||||
}
|
||||
|
||||
bool op::v1::ConvertLike::constant_fold(OutputVector& output_values,
|
||||
const OutputVector& input_values)
|
||||
{
|
||||
OV_ITT_SCOPED_TASK(itt::domains::nGraph, "op::v1::ConvertLike::constant_fold");
|
||||
if (auto data_const =
|
||||
std::dynamic_pointer_cast<op::Constant>(input_values[0].get_node_shared_ptr()))
|
||||
{
|
||||
auto convert = make_shared<Convert>(input_values[0], input_values[1].get_element_type());
|
||||
convert->constant_fold(output_values, OutputVector{data_const});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user