Fixed L2NormFusing transformation (#4526)

* Fixed L2NormFusing transformastion

* Refactor L2NormFusing transformation
This commit is contained in:
Evgeny Lazarev authored and GitHub committed 2021-03-01 12:13:25 +03:00
1 parent 62fb80aa43
commit e065cf554a
3 files changed
+86 -315

No files matched your search

@@ -19,13 +19,19 @@ import logging as log
import numpy as np
from extensions.ops.normalize_l2 import NormalizeL2Op
from mo.front.common.layout import get_features_dim
from mo.front.common.partial_infer.utils import int64_array
from mo.front.tf.graph_utils import create_op_node_with_second_input
from mo.graph.graph import Graph, rename_node
from mo.graph.graph import Graph, rename_nodes
from mo.middle.replacement import MiddleReplacementPattern
class L2NormToNorm(MiddleReplacementPattern):
"""
Transformation fuses sub-graph performing l2 normalization into the NormalizeL2 operation. IE plugins do not support
NormalizeL2 operation and there is a nGraph transformation which converts NormalizeL2 to NormalizeIE. The latter one
allows to normalize over just channel dimension or "channel + all spatial" dimensions for 2D, 3D or 4D cases.
"""
enabled = True
force_clean_up = True
@@ -86,29 +92,33 @@ class L2NormToNorm(MiddleReplacementPattern):
# reduction only along spatial and channel dimensions.
input_rank = len(match['sum'].in_port(0).data.get_shape())
if input_rank not in [2, 3, 4]:
log.debug('IE supports L2 normalization only for 2D, 3D and 4D tensors, skip fusing transformation.')
log.debug('IE supports L2 normalization only for 2D, 3D and 4D tensors.')
return
axes = match['sum'].in_port(1).data.get_value()
axes = int64_array(axes)
if axes.shape == ():
axes = int64_array([axes])
axes = int64_array([axis if axis >= 0 else axis + input_rank for axis in axes])
axes.sort()
if not np.array_equal(axes, int64_array(np.arange(start=1, stop=input_rank))):
log.debug('IE doesn\'t support l2 normalization with reduction along axes {}, skip fusing transformation.'
''.format(axes))
transformation_applicable = False
# check for case C + all spatial dims. Works for 2D (NC), 3D (NCH) and 4D (NCHW and NHWC)
if len(axes) + 1 == input_rank and np.array_equal(axes, int64_array(np.arange(start=1, stop=input_rank))):
transformation_applicable = True
# check for pure C channel normalization
if len(axes) == 1 and ((input_rank == 4 and get_features_dim(graph.graph['layout'], input_rank) == axes[0]) or
(input_rank != 4 and axes[0] == 1)):
transformation_applicable = True
if not transformation_applicable:
log.debug('IE doesn\'t support l2 normalization with reduction along axes {}.'.format(axes))
return
# rename l2_normalize node since it will be no longer output after the transformation
output_name = match['l2_normalize'].soft_get('name', match['l2_normalize'].id)
normalizel2_name = output_name + '/normalizel2'
rename_node(match['l2_normalize'], normalizel2_name)
normalize_node = create_op_node_with_second_input(graph, NormalizeL2Op, axes, {'name': output_name,
'eps_mode': 'max', 'eps': y})
rename_node(normalize_node, output_name)
match['square'].in_port(0).get_source().connect(normalize_node.in_port(0))
match['square'].in_port(0).disconnect()
@@ -118,3 +128,4 @@ class L2NormToNorm(MiddleReplacementPattern):
match['l2_normalize'].in_port(0).disconnect()
match['l2_normalize'].out_port(0).get_connection().set_source(normalize_node.out_port(0))
rename_nodes([(match['l2_normalize'], output_name + "/TBR"), (normalize_node, output_name)])
@@ -17,6 +17,7 @@
import unittest
import numpy as np
from generator import generator, generate
from extensions.middle.L2NormFusing import L2NormToNorm
from mo.front.common.partial_infer.utils import int64_array
@@ -79,18 +80,31 @@ edges_after_replacement = [
]
@generator
class L2NormToNormTest(unittest.TestCase):
def test_2D(self):
input_shape = int64_array([1, 300])
axes = int64_array([1])
@generate(*[(int64_array([2, 3]), int64_array([1]), 'NCHW'), # NC layout, normalize C dimension
(int64_array([2, 3]), int64_array([1]), 'NHWC'), # NC layout, normalize C dimension
(int64_array([2, 3, 5]), int64_array([1]), 'NCHW'), # NCH layout, normalize C dimension
(int64_array([2, 3, 5]), int64_array([1]), 'NHWC'), # NCH layout, normalize C dimension
(int64_array([2, 3, 5]), int64_array([-1, -2]), 'NHWC'), # NCH layout, normalize CH dimensions
(int64_array([2, 3, 5]), int64_array([-1, -2]), 'NCHW'), # NCH layout, normalize CH dimensions
(int64_array([2, 3, 5]), int64_array([1, 2]), 'NCHW'), # NCH layout, normalize CH dimensions
(int64_array([2, 3, 5]), int64_array([1, 2]), 'NHWC'), # NCH layout, normalize CH dimensions
(int64_array([2, 3, 5, 7]), int64_array([1]), 'NCHW'), # NCHW layout, normalize C dimension
(int64_array([2, 3, 5, 7]), int64_array([-1]), 'NHWC'), # NHWC layout, normalize C dimension
(int64_array([2, 3, 5, 7]), int64_array([3]), 'NHWC'), # NCHW layout, normalize C dimension
(int64_array([2, 3, 5, 7]), int64_array([-1, 1, 2]), 'NCHW'), # NCHW layout, normalize CHW dimensions
(int64_array([2, 3, 5, 7]), int64_array([-3, -2, -1]), 'NHWC'), # NCHW layout, normalize HWC dimensions
])
def test_positive(self, input_shape, axes, layout):
graph = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=axes.shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
graph.stage = 'middle'
graph.graph['layout'] = layout
L2NormToNorm().find_and_replace_pattern(graph)
@@ -104,301 +118,43 @@ class L2NormToNormTest(unittest.TestCase):
self.assertTrue(graph.node[graph.get_nodes_with_attributes(type='NormalizeL2')[0]]['name'] == 'l2_norm_name')
self.assertTrue(flag, resp)
def test_2D_scalar_axis(self):
input_shape = int64_array([1, 300])
axes = int64_array(1)
graph = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
graph.stage = 'middle'
L2NormToNorm().find_and_replace_pattern(graph)
graph_ref = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('weights_node_data', dict(kind='data', value=int64_array([axes]).sort())),
], edges_after_replacement, nodes_with_edges_only=True)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(graph.node[graph.get_nodes_with_attributes(type='NormalizeL2')[0]]['name'] == 'l2_norm_name')
self.assertTrue(flag, resp)
def test_3D(self):
input_shape = int64_array([1, 300, 300])
axes = int64_array([1, 2])
graph = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
graph.stage = 'middle'
L2NormToNorm().find_and_replace_pattern(graph)
graph_ref = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('weights_node_data', dict(kind='data', value=axes.sort())),
], edges_after_replacement, nodes_with_edges_only=True)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(graph.node[graph.get_nodes_with_attributes(type='NormalizeL2')[0]]['name'] == 'l2_norm_name')
self.assertTrue(flag, resp)
def test_4D(self):
input_shape = int64_array([1, 300, 300, 3])
axes = int64_array([1, 2, 3])
graph = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
graph.stage = 'middle'
L2NormToNorm().find_and_replace_pattern(graph)
graph_ref = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('weights_node_data', dict(kind='data', value=axes.sort())),
], edges_after_replacement, nodes_with_edges_only=True)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(graph.node[graph.get_nodes_with_attributes(type='NormalizeL2')[0]]['name'] == 'l2_norm_name')
self.assertTrue(flag, resp)
def test_4D_mixed_axes(self):
input_shape = int64_array([1, 300, 300, 3])
axes = int64_array([3, 1, 2])
graph = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
graph.stage = 'middle'
L2NormToNorm().find_and_replace_pattern(graph)
graph_ref = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('weights_node_data', dict(kind='data', value=axes.sort())),
], edges_after_replacement, nodes_with_edges_only=True)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(graph.node[graph.get_nodes_with_attributes(type='NormalizeL2')[0]]['name'] == 'l2_norm_name')
self.assertTrue(flag, resp)
def test_4D_multiple_consumers(self):
input_shape = int64_array([1, 300, 300, 3])
axes = int64_array([1, 2, 3])
weights_value = np.ones(shape=int64_array([input_shape[-1]]), dtype=np.float32)
graph = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
('result_2', dict(kind='op', op='Result'))
], edges + [('input_data', 'result_2')], nodes_with_edges_only=True)
graph.stage = 'middle'
L2NormToNorm().find_and_replace_pattern(graph)
graph_ref = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('weights_node_data', dict(kind='data', value=axes.sort())),
('result_2', dict(kind='op', op='Result'))
], edges_after_replacement + [('input_data', 'result_2')], nodes_with_edges_only=True)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(graph.node[graph.get_nodes_with_attributes(type='NormalizeL2')[0]]['name'] == 'l2_norm_name')
self.assertTrue(flag, resp)
def test_1D_negative(self):
input_shape = int64_array([300])
axes = int64_array([0])
graph = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
graph.stage = 'middle'
L2NormToNorm().find_and_replace_pattern(graph)
graph_ref = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(flag, resp)
def test_2D_negative(self):
input_shape = int64_array([1, 300])
axes = int64_array([0])
graph = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
graph.stage = 'middle'
L2NormToNorm().find_and_replace_pattern(graph)
graph_ref = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(flag, resp)
def test_3D_negative(self):
input_shape = int64_array([1, 300, 300])
axes = int64_array([2])
graph = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
graph.stage = 'middle'
L2NormToNorm().find_and_replace_pattern(graph)
graph_ref = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(flag, resp)
def test_4D_negative_1(self):
input_shape = int64_array([1, 300, 300, 3])
axes = int64_array([0, 1, 2])
graph = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
graph.stage = 'middle'
L2NormToNorm().find_and_replace_pattern(graph)
graph_ref = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(flag, resp)
def test_4D_negative_2(self):
input_shape = int64_array([1, 300, 300, 3])
axes = int64_array([2])
graph = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
graph.stage = 'middle'
L2NormToNorm().find_and_replace_pattern(graph)
graph_ref = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(flag, resp)
def test_4D_negative_3(self):
input_shape = int64_array([1, 300, 300, 3])
axes = int64_array([2, 1])
graph = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
graph.stage = 'middle'
L2NormToNorm().find_and_replace_pattern(graph)
graph_ref = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(flag, resp)
def test_4D_negative_4(self):
input_shape = int64_array([1, 300, 300, 3])
axes = int64_array([2, 0])
graph = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
graph.stage = 'middle'
L2NormToNorm().find_and_replace_pattern(graph)
graph_ref = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
('square_data', dict(kind='data', shape=input_shape)),
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(flag, resp)
def test_5D_negative(self):
input_shape = int64_array([1, 300, 300, 300, 3])
axes = int64_array([1, 2, 3, 4])
@generate(*[(int64_array([2]), int64_array([0]), 'NCHW'),
(int64_array([2, 3]), int64_array([0]), 'NCHW'),
(int64_array([2, 3]), int64_array([0]), 'NHWC'),
(int64_array([2, 3]), int64_array([0, 1]), 'NCHW'),
(int64_array([2, 3]), int64_array([0, 1]), 'NHWC'),
(int64_array([2, 3, 5]), int64_array([0]), 'NCHW'),
(int64_array([2, 3, 5]), int64_array([0]), 'NHWC'),
(int64_array([2, 3, 5]), int64_array([-1]), 'NCHW'),
(int64_array([2, 3, 5]), int64_array([-1]), 'NHWC'),
(int64_array([2, 3, 5]), int64_array([0, 1]), 'NCHW'),
(int64_array([2, 3, 5]), int64_array([0, 1]), 'NHWC'),
(int64_array([2, 3, 5]), int64_array([0, 2]), 'NCHW'),
(int64_array([2, 3, 5]), int64_array([0, 2]), 'NHWC'),
(int64_array([2, 3, 5, 7]), int64_array([0]), 'NCHW'),
(int64_array([2, 3, 5, 7]), int64_array([0]), 'NHWC'),
(int64_array([2, 3, 5, 7]), int64_array([2]), 'NCHW'),
(int64_array([2, 3, 5, 7]), int64_array([2]), 'NHWC'),
(int64_array([2, 3, 5, 7]), int64_array([3]), 'NCHW'),
(int64_array([2, 3, 5, 7]), int64_array([1]), 'NHWC'),
(int64_array([2, 3, 5, 7]), int64_array([1, 2]), 'NCHW'),
(int64_array([2, 3, 5, 7]), int64_array([1, -1]), 'NHWC'),
(int64_array([2, 3, 5, 7]), int64_array([1, -1]), 'NCHW'),
(int64_array([2, 3, 5, 7]), int64_array([-2, -1]), 'NHWC'),
(int64_array([2, 3, 5, 7]), int64_array([1, 3]), 'NCHW'),
(int64_array([2, 3, 5, 7]), int64_array([2, 3]), 'NHWC'),
(int64_array([2, 3, 5, 7]), int64_array([0, 1, 2]), 'NCHW'),
(int64_array([2, 3, 5, 7]), int64_array([0, 1, 2]), 'NHWC'),
(int64_array([2, 3, 5, 7]), int64_array([0, 2, 3]), 'NCHW'),
(int64_array([2, 3, 5, 7]), int64_array([0, 2, 3]), 'NHWC'),
(int64_array([2, 3, 5, 7]), int64_array([0, 1, 2, 3]), 'NCHW'),
(int64_array([2, 3, 5, 7]), int64_array([0, 1, 2, 3]), 'NHWC'),
(int64_array([2, 3, 5, 7, 9]), int64_array([1]), 'NCHW'),
(int64_array([2, 3, 5, 7, 9]), int64_array([-1]), 'NHWC'),
(int64_array([2, 3, 5, 7, 9]), int64_array([1, 2, 3, 4]), 'NCHW'),
(int64_array([2, 3, 5, 7, 9]), int64_array([-1, -2, -3, -4]), 'NHWC'),
])
def test_negative(self, input_shape, axes, layout):
graph = build_graph_with_attrs(nodes + [
('input', dict(kind='op', shape=input_shape, op='Parameter', data_type=np.float32)),
('input_data', dict(kind='data', shape=input_shape, data_type=np.float32)),
@@ -406,6 +162,7 @@ class L2NormToNormTest(unittest.TestCase):
('sum_axes_data', dict(kind='data', value=axes, shape=None)),
], edges, nodes_with_edges_only=True)
graph.stage = 'middle'
graph.graph['layout'] = layout
L2NormToNorm().find_and_replace_pattern(graph)
@@ -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.
@@ -16,6 +16,7 @@
import numpy as np
from mo.graph.graph import Graph, Node
from mo.graph.perm_inputs import PermuteInputs
from mo.ops.op import Op
@@ -25,15 +26,15 @@ class NormalizeL2Op(Op):
def __init__(self, graph: Graph, attrs: dict):
super().__init__(graph, {
'type': __class__.op,
'op': __class__.op,
'type': self.op,
'op': self.op,
'version': 'opset1',
'eps': None,
'p': None,
'eps_mode': None,
'in_ports_count': 2,
'out_ports_count': 1,
'infer': __class__.infer
'infer': self.infer
}, attrs)
def supported_attrs(self):
@@ -58,3 +59,5 @@ class NormalizeL2Op(Op):
node.out_port(0).data.set_value(input_value / norm_value)
else:
node.out_port(0).data.set_shape(input_shape)
PermuteInputs().set_input_permutation(node.in_node(1), node, 'input:0', 'axis')