Add axis support (#5242)

* Add axis support

* Update dequant extractor

* Update qdeq ops

* Refactoring quantize

* Update dequantize resolver

* Update dequantize op

* Refactoring dequantize

* Some fixes for quantize and dequantize

* Update unit tests

* Reafctoring quantize/dequantize axis support

* Move quantize/dequantize resolvers to middle

* hot fix

* Fix unit tests

* Fix unit tests

* Update quintize resolver comment

* Refactoring code according to code review

* Fix according to review

* Change order for transforms quantize pipline
This commit is contained in:
iliya mironov authored and GitHub committed 2021-05-17 15:03:22 +03:00
1 parent c029b07d34
commit 642a62d0e2
15 files changed
+790 -348

No files matched your search

+2 -2
View File
@@ -276,7 +276,6 @@ extensions/front/onnx/cumsum_ext.py
extensions/front/onnx/deformable_conv_ext.py
extensions/front/onnx/depth_to_space_ext.py
extensions/front/onnx/dequantize_linear_ext.py
extensions/front/onnx/dequantize_linear_resolver.py
extensions/front/onnx/detection_output.py
extensions/front/onnx/detectionoutput_ext.py
extensions/front/onnx/dropout_ext.py
@@ -328,7 +327,6 @@ extensions/front/onnx/proposal_ext.py
extensions/front/onnx/quantize_dequantize_linear.py
extensions/front/onnx/quantize_ext.py
extensions/front/onnx/quantize_linear_ext.py
extensions/front/onnx/quantize_linear_resolver.py
extensions/front/onnx/range_ext.py
extensions/front/onnx/reduce_ext.py
extensions/front/onnx/remove_filtering_boxes_by_size.py
@@ -580,6 +578,7 @@ extensions/middle/DecomposeBidirectionalRNNSequence.py
extensions/middle/Deconvolution3rdInputNormalization.py
extensions/middle/DeleteControlFlowEdges.py
extensions/middle/DeleteNotExecutable.py
extensions/middle/dequantize_linear_resolver.py
extensions/middle/DilatedConvolution.py
extensions/middle/EltwiseChecker.py
extensions/middle/EltwiseInputReshape.py
@@ -614,6 +613,7 @@ extensions/middle/permute_tensor_iterator.py
extensions/middle/PoolV2ToAttributedPool.py
extensions/middle/preprocessing.py
extensions/middle/quantize_fuses.py
extensions/middle/quantize_linear_resolver.py
extensions/middle/ReluQuantizeFuse.py
extensions/middle/RemoveDuplicationMemory.py
extensions/middle/RemoveIdentity.py
@@ -14,8 +14,9 @@ class DequantizeLinearFrontExtractor(FrontExtractorOp):
@classmethod
def extract(cls, node):
attrs = {}
if get_onnx_opset_version(node) >= 13:
log.warning('Ignoring "axis" attribute for DequantizeLinear-{} node, inference might be incorrect.'.format(
get_onnx_opset_version(node)))
DequantizeLinear.update_node_stat(node)
axis = onnx_attr(node, 'axis', 'i', default=None)
attrs.update(axis=axis)
DequantizeLinear.update_node_stat(node, attrs)
return cls.enabled
@@ -1,40 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
from extensions.front.onnx.quantize_dequantize_linear import QuantizeDequantizeLinear
from extensions.ops.Cast import Cast
from extensions.ops.elementwise import Mul, Sub
from mo.front.common.replacement import FrontReplacementOp
from mo.graph.graph import Graph, Node, rename_nodes
from mo.middle.passes.convert_data_type import data_type_str_to_np
class DequantizeLinearResolver(FrontReplacementOp):
"""
DequantizeLinear can be replace with the following formula: y = (x - x_zero_point) * x_scale
"""
op = "DequantizeLinear"
enabled = True
def run_after(self):
return [QuantizeDequantizeLinear]
def replace_op(self, graph: Graph, node: Node):
node_name = node.soft_get('name', node.id)
model_data_type = data_type_str_to_np(graph.graph['cmd_params'].data_type)
cast = Cast(graph, {'dst_type': model_data_type, 'name': node_name + '/Cast'}).create_node()
node.in_port(0).get_connection().set_destination(cast.in_port(0))
mul = Mul(graph, {}).create_node()
if node.is_in_port_connected(2):
sub = Sub(graph, {'name': node_name + '/Sub'}).create_node()
cast.out_port(0).connect(sub.in_port(0))
node.in_port(2).get_connection().set_destination(sub.in_port(1))
sub.out_port(0).connect(mul.in_port(0))
else:
cast.out_port(0).connect(mul.in_port(0))
node.in_port(1).get_connection().set_destination(mul.in_port(1))
rename_nodes([(node, node_name + '/TBD'), (mul, node_name)])
return [mul.id]
@@ -14,7 +14,7 @@ class QuantizeLinearFrontExtractor(FrontExtractorOp):
def extract(cls, node):
attrs = {}
if get_onnx_opset_version(node) >= 13:
axis = onnx_attr(node, 'axis', 'i', default=1)
axis = onnx_attr(node, 'axis', 'i', default=None)
attrs.update(axis=axis)
QuantizeLinear.update_node_stat(node, attrs)
return cls.enabled
@@ -1,69 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import numpy as np
from extensions.front.onnx.quantize_dequantize_linear import QuantizeDequantizeLinear
from extensions.ops.Cast import Cast
from extensions.ops.elementwise import Mul
from extensions.ops.fakequantize import FakeQuantize
from mo.front.common.partial_infer.utils import float_array
from mo.front.common.replacement import FrontReplacementOp
from mo.front.tf.graph_utils import create_op_with_const_inputs
from mo.graph.graph import Graph, Node, rename_nodes
from mo.ops.const import Const
from mo.utils.error import Error
class QuantizeLinearResolver(FrontReplacementOp):
"""
Replaces QuantizeLinear with FakeQuantize
"""
op = "QuantizeLinear"
enabled = True
def run_after(self):
return [QuantizeDequantizeLinear]
def replace_op(self, graph: Graph, node: Node):
node_name = node.soft_get('name', node.id)
if node.is_in_port_connected(2):
zerop = node.in_port(2).get_source().node
else:
zerop = Const(graph, {'value': np.array(0, dtype=np.uint8), 'name': node_name + '/ZeroPoint'}).create_node()
assert zerop.soft_get('type') == 'Const', 'only constant for zero_point is supported for QuantizeLinear'
zero_point_type = zerop.value.dtype
# data type affects range of output values: [-128..127] or [0..255]
if zero_point_type == np.int8:
output_low_value = -128.0
output_high_value = 127.0
elif zero_point_type == np.uint8:
output_low_value = 0.0
output_high_value = 255.0
else:
raise Error('Not expected type {} for zero point value in node {}'.format(
zero_point_type, zerop.soft_get('name')))
fake_quantize = create_op_with_const_inputs(graph, FakeQuantize, {3: float_array(output_low_value),
4: float_array(output_high_value)},
{'levels': 256, 'name': node_name + '/FakeQuantize'})
node.in_port(0).get_connection().set_destination(fake_quantize.in_port(0))
# Calculate input_low value
mul_low = create_op_with_const_inputs(graph, Mul, {1: float_array(output_low_value - zerop.value)},
{'name': node_name + '/Mul/Low'})
node.in_port(1).get_connection().set_destination(mul_low.in_port(0))
mul_low.out_port(0).connect(fake_quantize.in_port(1))
# Calculate input_high value
mul_high = create_op_with_const_inputs(graph, Mul, {1: float_array(output_high_value - zerop.value)},
{'name': node_name + '/Mul/High'})
mul_low.in_port(0).get_connection().add_destination(mul_high.in_port(0))
mul_high.out_port(0).connect(fake_quantize.in_port(2))
cast = Cast(graph, {'dst_type': zero_point_type, 'name': node_name + '/Cast'}).create_node()
rename_nodes([(node, node_name + '/TBD'), (cast, node_name)])
fake_quantize.out_port(0).connect(cast.in_port(0))
return [cast.id]
@@ -0,0 +1,66 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import numpy as np
from extensions.ops.Cast import Cast
from extensions.ops.elementwise import Mul, Sub
from mo.front.common.partial_infer.utils import int64_array
from mo.front.tf.graph_utils import create_op_with_const_inputs
from mo.graph.graph import Graph, rename_nodes
from mo.middle.passes.convert_data_type import data_type_str_to_np
from mo.middle.replacement import MiddleReplacementPattern
from mo.ops.reshape import Reshape
class DequantizeLinearResolver(MiddleReplacementPattern):
"""
Transformation result depends on the axis value.
If the axis is not set or x_scale input is scalar or 1D tensor with one element then DequantizeLinear is
replaced with the sub-graph which can be expressed with the following formula:
y = (x - x_zero_point) * x_scale
In other cases DequantizeLinear can be replace to formula with addition reshape x_zero_point and x_scale.
Target shape for reshape depend on axis.
"""
enabled = True
graph_condition = [lambda graph: graph.graph['layout'] == 'NCHW']
def find_and_replace_pattern(self, graph: Graph):
for dequantize_node in graph.get_op_nodes(op='DequantizeLinear'):
node_name = dequantize_node.soft_get('name', dequantize_node.id)
axis = dequantize_node.soft_get('axis', None)
scale_y_shape = dequantize_node.in_port(1).data.get_shape()
model_data_type = data_type_str_to_np(graph.graph['cmd_params'].data_type)
cast = Cast(graph, {'dst_type': model_data_type, 'name': node_name + '/Cast'}).create_node()
dequantize_node.in_port(0).get_connection().set_destination(cast.in_port(0))
mul = Mul(graph, {}).create_node()
is_second_port_connected = dequantize_node.is_in_port_connected(2)
if is_second_port_connected:
sub = Sub(graph, {'name': node_name + '/Sub'}).create_node()
cast.out_port(0).connect(sub.in_port(0))
dequantize_node.in_port(2).get_connection().set_destination(sub.in_port(1))
sub.out_port(0).connect(mul.in_port(0))
else:
cast.out_port(0).connect(mul.in_port(0))
dequantize_node.in_port(1).get_connection().set_destination(mul.in_port(1))
dequantize_node.out_port(0).get_connection().set_source(mul.out_port(0))
rename_nodes([(dequantize_node, node_name + '/TBD'), (mul, node_name)])
assert scale_y_shape is not None
if axis is not None and len(scale_y_shape) > 0 and scale_y_shape[0] > 1:
input_shape = cast.in_port(0).data.get_shape()
target_shape = np.ones(len(input_shape), np.int64)
target_shape[axis] = input_shape[axis]
mul_reshape = create_op_with_const_inputs(graph, Reshape, {1: int64_array(target_shape)},
{'name': node_name + '/Reshape/Mul'})
mul.in_port(1).get_connection().set_destination(mul_reshape.in_port(0))
mul_reshape.out_port(0).connect(mul.in_port(1))
if is_second_port_connected:
sub_reshape = create_op_with_const_inputs(graph, Reshape, {1: int64_array(target_shape)},
{'name': node_name + '/Reshape/Sub'})
sub.in_port(1).get_connection().set_destination(sub_reshape.in_port(0))
sub_reshape.out_port(0).connect(sub.in_port(1))
@@ -6,6 +6,7 @@ import numpy as np
from extensions.middle.BinarizeWeightsM1P1 import BinarizeWeightsM1P1
from extensions.middle.DeleteControlFlowEdges import DeleteControlFlowEdges
from extensions.middle.EltwiseChecker import EltwiseChecker
from extensions.middle.quantize_linear_resolver import QuantizeLinearResolver
from mo.graph.graph import Graph
from mo.middle.passes.fusing.helpers import get_value_in_port
from mo.middle.replacement import MiddleReplacementPattern
@@ -75,7 +76,7 @@ class FakeQuantizeFuse(MiddleReplacementPattern):
graph_condition = [lambda graph: not graph.graph['cmd_params'].disable_fusing]
def run_after(self):
return [MarkNodesToFuseUpToFakeQuantize]
return [QuantizeLinearResolver]
def run_before(self):
return [BinarizeWeightsM1P1]
@@ -0,0 +1,101 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import numpy as np
from extensions.ops.Cast import Cast
from extensions.ops.elementwise import Mul
from extensions.ops.fakequantize import FakeQuantize
from mo.front.common.partial_infer.utils import float_array, int64_array
from mo.front.tf.graph_utils import create_op_with_const_inputs
from mo.graph.graph import Graph, rename_nodes
from mo.middle.replacement import MiddleReplacementPattern
from mo.ops.const import Const
from mo.ops.reshape import Reshape
from mo.utils.error import Error
class QuantizeLinearResolver(MiddleReplacementPattern):
"""
Replaces QuantizeLinear with FakeQuantize
Transformation result depends on the axis value.
If the axis is not set or x_scale input is scalar or 1D tensor with one element then QuantizeLinear is
replaced with the sub-graph which can be expressed with the following formula:
QuantizeLinear -> FakeQuantize(input
Mul(y_scale, Const(low_value))
Mul(y_scale, Const(high_value))
Const(low_value)
Const(high_value))
low_value and high_value depend on from y_zero_point type
In other cases y_scale and y_zero_point can be transform with addition reshape.
Target shape for y_scale and y_zero_point depend on axis value.
"""
enabled = True
graph_condition = [lambda graph: graph.graph['layout'] == 'NCHW']
def run_after(self):
from extensions.middle.quantize_fuses import MarkNodesToFuseUpToFakeQuantize
return [MarkNodesToFuseUpToFakeQuantize]
def find_and_replace_pattern(self, graph: Graph):
for quantize_node in graph.get_op_nodes(op='QuantizeLinear'):
node_name = quantize_node.soft_get('name', quantize_node.id)
axis = quantize_node.soft_get('axis', None)
scale_y_shape = quantize_node.in_port(1).data.get_shape()
if quantize_node.is_in_port_connected(2):
zerop = quantize_node.in_port(2).get_source().node
else:
zerop = Const(graph,
{'value': np.array(0, dtype=np.uint8), 'name': node_name + '/ZeroPoint'}).create_node()
assert zerop.soft_get('type') == 'Const', 'only constant for zero_point is supported for QuantizeLinear'
zero_point_type = zerop.value.dtype
# data type affects range of output values: [-128..127] or [0..255]
if zero_point_type == np.int8:
output_low_value = -128.0
output_high_value = 127.0
elif zero_point_type == np.uint8:
output_low_value = 0.0
output_high_value = 255.0
else:
raise Error('Not expected type {} for zero point value in node {}'.format(
zero_point_type, zerop.soft_get('name')))
fake_quantize = create_op_with_const_inputs(graph, FakeQuantize, {3: float_array(output_low_value),
4: float_array(output_high_value)},
{'levels': 256, 'name': node_name + '/FakeQuantize'})
quantize_node.in_port(0).get_connection().set_destination(fake_quantize.in_port(0))
# Calculate input_low value
mul_low = create_op_with_const_inputs(graph, Mul, {1: float_array(output_low_value - zerop.value)},
{'name': node_name + '/Mul/Low'})
quantize_node.in_port(1).get_connection().set_destination(mul_low.in_port(0))
mul_low.out_port(0).connect(fake_quantize.in_port(1))
# Calculate input_high value
mul_high = create_op_with_const_inputs(graph, Mul, {1: float_array(output_high_value - zerop.value)},
{'name': node_name + '/Mul/High'})
mul_low.in_port(0).get_connection().add_destination(mul_high.in_port(0))
mul_high.out_port(0).connect(fake_quantize.in_port(2))
cast = Cast(graph, {'dst_type': zero_point_type, 'name': node_name + '/Cast'}).create_node()
fake_quantize.out_port(0).connect(cast.in_port(0))
quantize_node.out_port(0).get_connection().set_source(cast.out_port(0))
rename_nodes([(quantize_node, node_name + '/TBD'), (cast, node_name)])
assert scale_y_shape is not None
if axis is not None and len(scale_y_shape) > 0 and scale_y_shape[0] > 1:
input_shape = fake_quantize.in_port(0).data.get_shape()
target_shape = np.ones(len(input_shape), np.int)
target_shape[axis] = input_shape[axis]
mul_low_reshape = create_op_with_const_inputs(graph, Reshape, {1: int64_array(target_shape)},
{'name': node_name + '/Reshape/Mul/Low'})
mul_high_reshape = create_op_with_const_inputs(graph, Reshape, {1: int64_array(target_shape)},
{'name': node_name + '/Reshape/Mul/high'})
fake_quantize.in_port(1).get_connection().set_destination(mul_low_reshape.in_port(0))
fake_quantize.in_port(2).get_connection().set_destination(mul_high_reshape.in_port(0))
mul_low_reshape.out_port(0).connect(fake_quantize.in_port(1))
mul_high_reshape.out_port(0).connect(fake_quantize.in_port(2))
@@ -1,6 +1,7 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
from mo.front.common.partial_infer.elemental import copy_shape_infer
from mo.graph.graph import Graph
from mo.ops.op import Op
@@ -13,8 +14,9 @@ class DequantizeLinear(Op):
mandatory_props = {
'type': None,
'op': self.op,
'axis': None,
'version': None,
'infer': None,
'infer': copy_shape_infer,
'out_ports_count': 1,
'in_ports_count': 3,
}
@@ -1,6 +1,7 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
from mo.front.common.partial_infer.elemental import copy_shape_infer
from mo.graph.graph import Graph
from mo.ops.op import Op
@@ -13,8 +14,9 @@ class QuantizeLinear(Op):
mandatory_props = {
'type': None,
'op': self.op,
'axis': None,
'version': None,
'infer': None,
'infer': copy_shape_infer,
'out_ports_count': 1,
'in_ports_count': 3,
}
+2 -2
View File
@@ -58,8 +58,8 @@ class Broadcast(Op):
node.out_port(0).data.set_value(bi_directional_broadcasting(input_value, target_shape))
elif node.mode == 'explicit':
axes_mapping = node.in_port(2).data.get_value()
assert axes_mapping is not None, 'Broadcast(mode="explicit") with dynamic axes_mapping input ' \
'is not supported. Node: `{}`'.format(node_name)
assert axes_mapping is not None, 'Broadcast(mode="explicit") with dynamic axes_mapping input ' \
'is not supported. Node: `{}`'.format(node_name)
PermuteInputs().set_input_permutation(node.in_node(2), node, 'output:0', 'axis')
axes_mapping = node.in_port(2).data.get_value()
node.out_port(0).data.set_value(explicit_broadcasting(input_value, target_shape, axes_mapping))
@@ -1,84 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import unittest
import numpy as np
from extensions.front.onnx.dequantize_linear_resolver import DequantizeLinearResolver
from mo.utils.ir_engine.compare_graphs import compare_graphs
from unit_tests.utils.graph import build_graph
nodes1_attributes = {
'input': {'kind': 'op', 'op': 'AnyOp'},
'dequantize': {'kind': 'op', 'op': 'DequantizeLinear'},
'scale_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'zerop_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'out': {'kind': 'op', 'op': 'AnyOp'},
}
nodes_ref_attributes = {
'input': {'kind': 'op', 'op': 'AnyOp'},
'cast': {'kind': 'op', 'op': 'Cast', 'type': 'Convert'},
'sub': {'kind': 'op', 'op': 'Sub', 'type': 'Subtract'},
'mul': {'kind': 'op', 'op': 'Mul', 'type': 'Multiply'},
'scale_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'zerop_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'out': {'kind': 'op', 'op': 'AnyOp'},
}
class TestDequantizeLinearResolver(unittest.TestCase):
def test_dequantize(self):
graph = build_graph(nodes1_attributes,
[('input', 'dequantize'),
('scale_param_dq', 'dequantize'),
('zerop_param_dq', 'dequantize'),
('dequantize', 'out'),
],
{'scale_param_dq': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
'zerop_param_dq': {'shape': np.array([]), 'value': np.uint8(0)},
}, nodes_with_edges_only=True)
graph_ref = build_graph(nodes_ref_attributes,
[('input', 'cast'),
('cast', 'sub'),
('zerop_param_dq', 'sub'),
('sub', 'mul'),
('scale_param_dq', 'mul'),
('mul', 'out'),
],
{'scale_param_dq': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
'zerop_param_dq': {'shape': np.array([]), 'value': np.uint8(0)}
}, nodes_with_edges_only=True)
graph.stage = 'front'
DequantizeLinearResolver().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True)
self.assertTrue(flag, resp)
def test_dequantize_no_zerop(self):
graph = build_graph(nodes1_attributes,
[('input', 'dequantize'),
('scale_param_dq', 'dequantize'),
('dequantize', 'out'),
],
{'scale_param_dq': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
}, nodes_with_edges_only=True)
graph_ref = build_graph(nodes_ref_attributes,
[('input', 'cast'),
('cast', 'mul'),
('scale_param_dq', 'mul'),
('mul', 'out'),
],
{'scale_param_dq': {'shape': np.array([]), 'value': np.float32(1.0 / 255)}
}, nodes_with_edges_only=True)
graph.stage = 'front'
DequantizeLinearResolver().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True)
self.assertTrue(flag, resp)
@@ -1,144 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import unittest
import numpy as np
from extensions.front.onnx.quantize_linear_resolver import QuantizeLinearResolver
from mo.utils.ir_engine.compare_graphs import compare_graphs
from unit_tests.utils.graph import build_graph
nodes1_attributes = {
'input': {'kind': 'op', 'op': 'AnyOp'},
'quantize': {'kind': 'op', 'op': 'QuantizeLinear'},
'scale_param_q': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'zerop_param_q': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'out': {'kind': 'op', 'op': 'AnyOp'},
}
nodes_ref_attributes = {
'input': {'kind': 'op', 'op': 'AnyOp'},
'cast': {'kind': 'op', 'op': 'Cast', 'type': 'Convert'},
'f_quantize': {'kind': 'op', 'op': 'FakeQuantize', 'type': 'FakeQuantize'},
'mul1': {'kind': 'op', 'op': 'Mul', 'type': 'Multiply'},
'mul2': {'kind': 'op', 'op': 'Mul', 'type': 'Multiply'},
'scale_param_q': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'in_low': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'in_high': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'out_low': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'out_high': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'out': {'kind': 'op', 'op': 'AnyOp'},
}
class TestQuantizeLinearResolver(unittest.TestCase):
def test_quantize_uint8(self):
graph = build_graph(nodes1_attributes,
[('input', 'quantize'),
('scale_param_q', 'quantize'),
('zerop_param_q', 'quantize'),
('quantize', 'out'),
],
{'scale_param_q': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
'zerop_param_q': {'shape': np.array([]), 'value': np.uint8(128)},
}, nodes_with_edges_only=True)
graph_ref = build_graph(nodes_ref_attributes,
[('input', 'f_quantize'),
('scale_param_q', 'mul1', {'out': 0}),
('in_low', 'mul1'),
('mul1', 'f_quantize'),
('scale_param_q', 'mul2', {'out': 0}),
('in_high', 'mul2'),
('mul2', 'f_quantize'),
('out_low', 'f_quantize'),
('out_high', 'f_quantize'),
('f_quantize', 'cast'),
('cast', 'out'),
],
{'in_low': {'shape': np.array([]), 'value': -128},
'in_high': {'shape': np.array([]), 'value': 127},
'out_low': {'shape': np.array([]), 'value': 0},
'out_high': {'shape': np.array([]), 'value': 255},
'cast': {'dst_type': np.uint8}
}, nodes_with_edges_only=True)
graph.stage = 'front'
QuantizeLinearResolver().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True)
self.assertTrue(flag, resp)
def test_quantize_int8(self):
graph = build_graph(nodes1_attributes,
[('input', 'quantize'),
('scale_param_q', 'quantize'),
('zerop_param_q', 'quantize'),
('quantize', 'out'),
],
{'scale_param_q': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
'zerop_param_q': {'shape': np.array([]), 'value': np.int8(0)},
}, nodes_with_edges_only=True)
graph_ref = build_graph(nodes_ref_attributes,
[('input', 'f_quantize'),
('scale_param_q', 'mul1', {'out': 0}),
('in_low', 'mul1'),
('mul1', 'f_quantize'),
('scale_param_q', 'mul2', {'out': 0}),
('in_high', 'mul2'),
('mul2', 'f_quantize'),
('out_low', 'f_quantize'),
('out_high', 'f_quantize'),
('f_quantize', 'cast'),
('cast', 'out'),
],
{'in_low': {'shape': np.array([]), 'value': -128},
'in_high': {'shape': np.array([]), 'value': 127},
'out_low': {'shape': np.array([]), 'value': -128},
'out_high': {'shape': np.array([]), 'value': 127},
'cast': {'dst_type': np.int8}
}, nodes_with_edges_only=True)
graph.stage = 'front'
QuantizeLinearResolver().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True)
self.assertTrue(flag, resp)
def test_quantize_no_zerop(self):
graph = build_graph(nodes1_attributes,
[('input', 'quantize'),
('scale_param_q', 'quantize'),
('quantize', 'out'),
],
{'scale_param_q': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
}, nodes_with_edges_only=True)
graph_ref = build_graph(nodes_ref_attributes,
[('input', 'f_quantize'),
('scale_param_q', 'mul1', {'out': 0}),
('in_low', 'mul1'),
('mul1', 'f_quantize'),
('scale_param_q', 'mul2', {'out': 0}),
('in_high', 'mul2'),
('mul2', 'f_quantize'),
('out_low', 'f_quantize'),
('out_high', 'f_quantize'),
('f_quantize', 'cast'),
('cast', 'out'),
],
{'in_low': {'shape': np.array([]), 'value': 0},
'in_high': {'shape': np.array([]), 'value': 255},
'out_low': {'shape': np.array([]), 'value': 0},
'out_high': {'shape': np.array([]), 'value': 255},
'cast': {'dst_type': np.uint8}
}, nodes_with_edges_only=True)
graph.stage = 'front'
QuantizeLinearResolver().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True)
self.assertTrue(flag, resp)
@@ -0,0 +1,237 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import unittest
import numpy as np
from extensions.middle.dequantize_linear_resolver import DequantizeLinearResolver
from mo.front.common.partial_infer.utils import int64_array
from mo.utils.ir_engine.compare_graphs import compare_graphs
from unit_tests.utils.graph import build_graph
from generator import generator, generate
nodes1_attributes = {
'input': {'kind': 'op', 'op': 'AnyOp'},
'input_data': {'kind': 'data', 'shape': None},
'dequantize': {'kind': 'op', 'op': 'DequantizeLinear', 'axis': 1},
'dequantize_data': {'kind': 'data', 'shape': None},
'scale_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'scale_param_dq_data': {'kind': 'data', 'shape': None},
'zerop_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'zerop_param_dq_data': {'kind': 'data', 'shape': None},
'out': {'kind': 'op', 'op': 'AnyOp'},
'out_data': {'kind': 'data', 'shape': None},
'result': {'kind': 'op', 'op': 'Result'},
}
nodes_ref_attributes = {
'input': {'kind': 'op', 'op': 'AnyOp'},
'input_data': {'kind': 'data', 'shape': None},
'cast': {'kind': 'op', 'op': 'Cast', 'type': 'Convert'},
'cast_data': {'kind': 'data', 'shape': None},
'sub': {'kind': 'op', 'op': 'Sub', 'type': 'Subtract'},
'sub_data': {'kind': 'data', 'shape': None},
'mul': {'kind': 'op', 'op': 'Mul', 'type': 'Multiply'},
'mul_data': {'kind': 'data', 'shape': None},
'scale_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'scale_param_dq_data': {'kind': 'data', 'shape': None},
'zerop_param_dq': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'zerop_param_dq_data': {'kind': 'data', 'shape': None},
'out': {'kind': 'op', 'op': 'AnyOp'},
'out_data': {'kind': 'data', 'shape': None},
'result': {'kind': 'op', 'op': 'Result'},
'sub_reshape_const': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'sub_reshape_const_data': {'kind': 'data', 'shape': None},
'sub_reshape': {'kind': 'op', 'type': 'Reshape', 'op': 'Reshape'},
'sub_reshape_data': {'kind': 'data', 'shape': None},
'mul_reshape_const': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'mul_reshape_const_data': {'kind': 'data', 'shape': None},
'mul_reshape': {'kind': 'op', 'type': 'Reshape', 'op': 'Reshape'},
'mul_reshape_data': {'kind': 'data', 'shape': None},
}
class TestDequantizeLinearResolver(unittest.TestCase):
def test_dequantize(self):
graph = build_graph(nodes1_attributes,
[('input', 'input_data'),
('input_data', 'dequantize'),
('dequantize', 'dequantize_data'),
('scale_param_dq', 'scale_param_dq_data'),
('zerop_param_dq', 'zerop_param_dq_data'),
('scale_param_dq_data', 'dequantize'),
('zerop_param_dq_data', 'dequantize'),
('dequantize_data', 'out'),
('out', 'out_data'),
('out_data', 'result'),
],
{'input_data': {'shape': int64_array([1, 3, 224, 224])},
'scale_param_dq': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
'scale_param_dq_data': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
'zerop_param_dq': {'shape': np.array([]), 'value': np.uint8(0)},
'zerop_param_dq_data': {'shape': np.array([]), 'value': np.uint8(0)},
}, nodes_with_edges_only=True)
graph_ref = build_graph(nodes_ref_attributes,
[('input', 'input_data'),
('input_data', 'cast'),
('cast', 'cast_data'),
('cast_data', 'sub'),
('zerop_param_dq', 'zerop_param_dq_data'),
('zerop_param_dq_data', 'sub'),
('sub', 'sub_data'),
('sub_data', 'mul'),
('scale_param_dq', 'scale_param_dq_data'),
('scale_param_dq_data', 'mul'),
('mul', 'mul_data'),
('mul_data', 'out'),
('out', 'out_data'),
('out_data', 'result'),
],
{'input_data': {'shape': int64_array([1, 3, 224, 224])},
'scale_param_dq': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
'scale_param_dq_data': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
'zerop_param_dq': {'shape': np.array([]), 'value': np.uint8(0)},
'zerop_param_dq_data': {'shape': np.array([]), 'value': np.uint8(0)},
}, nodes_with_edges_only=True)
graph.stage = 'middle'
DequantizeLinearResolver().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True)
self.assertTrue(flag, resp)
def test_dequantize_no_zerop(self):
graph = build_graph(nodes1_attributes,
[('input', 'input_data'),
('input_data', 'dequantize'),
('dequantize', 'dequantize_data'),
('scale_param_dq', 'scale_param_dq_data'),
('scale_param_dq_data', 'dequantize'),
('dequantize', 'dequantize_data'),
('dequantize_data', 'out'),
('out', 'out_data'),
('out_data', 'result'),
],
{'input_data': {'shape': int64_array([1, 3, 224, 224])},
'scale_param_dq': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
'scale_param_dq_data': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
}, nodes_with_edges_only=True)
graph_ref = build_graph(nodes_ref_attributes,
[('input', 'input_data'),
('input_data', 'cast'),
('cast', 'cast_data'),
('cast_data', 'mul'),
('scale_param_dq', 'scale_param_dq_data'),
('scale_param_dq_data', 'mul'),
('mul', 'mul_data'),
('mul_data', 'out'),
('out', 'out_data'),
('out_data', 'result'),
],
{'input_data': {'shape': int64_array([1, 3, 224, 224])},
'scale_param_dq': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
'scale_param_dq_data': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
}, nodes_with_edges_only=True)
graph.stage = 'middle'
DequantizeLinearResolver().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True)
self.assertTrue(flag, resp)
@generator
class TestDequantizeWithAxis(unittest.TestCase):
@generate(*[(int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32),
np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([1, 1, 4, 1]), 2),
(int64_array([1, 3, 4, 4]), int64_array([2, 3, 4, 5]),
np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([1, 3, 1, 1]), 1),
(int64_array([2, 3, 4, 4]), int64_array([2, 3, 4, 5]),
np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([2, 1, 1, 1]), 0),
(int64_array([1, 3, 4, 4]), int64_array([2, 3, 4, 5]),
np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([1, 1, 4, 1]), -2),
(int64_array([1, 3, 4, 4]), int64_array([2, 3, 4, 5]),
np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([1, 1, 1, 4]), -1),
(int64_array([1, 3, 4, 4]), int64_array([2, 3, 4, 5]),
np.array([2, 3, 4, 5], dtype=np.int32), int64_array([1, 1, 4, 1]), 2),
(int64_array([1, 3, 4, 4]), int64_array([2, 3, 4, 5]),
np.array([2, 3, 4, 5], dtype=np.int32), int64_array([1, 3, 1, 1]), 1),
(int64_array([2, 3, 4, 4]), int64_array([2, 3, 4, 5]),
np.array([2, 3, 4, 5], dtype=np.int32), int64_array([2, 1, 1, 1]), 0),
])
def test_dequantize_with_axis(self, input_shape, scale_param_value, zero_param_value, target_shape, axis):
graph = build_graph(nodes1_attributes,
[('input', 'input_data'),
('input_data', 'dequantize'),
('dequantize', 'dequantize_data'),
('scale_param_dq', 'scale_param_dq_data'),
('zerop_param_dq', 'zerop_param_dq_data'),
('scale_param_dq_data', 'dequantize'),
('zerop_param_dq_data', 'dequantize'),
('dequantize_data', 'out'),
('out', 'out_data'),
('out_data', 'result'),
],
{'input_data': {'shape': input_shape},
'dequantize': {'axis': axis},
'scale_param_dq': {'shape': scale_param_value.shape,
'value': scale_param_value},
'scale_param_dq_data': {'shape': scale_param_value.shape,
'value': scale_param_value},
'zerop_param_dq': {'shape': zero_param_value.shape,
'value': zero_param_value},
'zerop_param_dq_data': {'shape': zero_param_value.shape,
'value': zero_param_value},
}, nodes_with_edges_only=True)
graph_ref = build_graph(nodes_ref_attributes,
[('input', 'input_data'),
('input_data', 'cast'),
('cast', 'cast_data'),
('cast_data', 'sub'),
('zerop_param_dq', 'zerop_param_dq_data'),
('zerop_param_dq_data', 'sub_reshape'),
('sub_reshape_const', 'sub_reshape_const_data'),
('sub_reshape_const_data', 'sub_reshape'),
('sub_reshape', 'sub_reshape_data'),
('sub_reshape_data', 'sub'),
('sub', 'sub_data'),
('sub_data', 'mul'),
('scale_param_dq', 'scale_param_dq_data'),
('scale_param_dq_data', 'mul_reshape'),
('mul_reshape_const', 'mul_reshape_const_data'),
('mul_reshape_const_data', 'mul_reshape'),
('mul_reshape', 'mul_reshape_data'),
('mul_reshape_data', 'mul'),
('mul', 'mul_data'),
('mul_data', 'out'),
('out', 'out_data'),
('out_data', 'result'),
],
{'input_data': {'shape': input_shape},
'scale_param_dq': {'shape': scale_param_value.shape,
'value': scale_param_value},
'scale_param_dq_data': {'shape': scale_param_value.shape,
'value': scale_param_value},
'zerop_param_dq': {'shape': zero_param_value.shape,
'value': zero_param_value},
'zerop_param_dq_data': {'shape': zero_param_value.shape,
'value': zero_param_value},
'sub_reshape_const_data': {'shape': target_shape.shape, 'value': target_shape},
'mul_reshape_const_data': {'shape': target_shape.shape, 'value': target_shape},
}, nodes_with_edges_only=True)
graph.stage = 'middle'
DequantizeLinearResolver().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'out', check_op_attrs=True)
self.assertTrue(flag, resp)
@@ -0,0 +1,369 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import unittest
import numpy as np
from extensions.middle.quantize_linear_resolver import QuantizeLinearResolver
from mo.front.common.partial_infer.utils import int64_array
from mo.utils.ir_engine.compare_graphs import compare_graphs
from unit_tests.utils.graph import build_graph
from generator import generator, generate
nodes1_attributes = {
'input': {'kind': 'op', 'op': 'AnyOp'},
'input_data': {'kind': 'data', 'shape': None},
'quantize': {'kind': 'op', 'op': 'QuantizeLinear', 'axis': 1},
'quantize_data': {'kind': 'data', 'shape': None},
'scale_param_q': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'scale_param_q_data': {'kind': 'data', 'shape': None},
'zerop_param_q': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'zerop_param_q_data': {'kind': 'data', 'shape': None},
'out': {'kind': 'op', 'op': 'AnyOp'},
'out_data': {'kind': 'data', 'shape': None},
'result': {'kind': 'op', 'op': 'Result'},
}
nodes_ref_attributes = {
'input': {'kind': 'op', 'op': 'AnyOp'},
'input_data': {'kind': 'data', 'shape': None},
'cast': {'kind': 'op', 'op': 'Cast', 'type': 'Convert'},
'cast_data': {'kind': 'data', 'shape': None},
'f_quantize': {'kind': 'op', 'op': 'FakeQuantize', 'type': 'FakeQuantize'},
'f_quantize_data': {'kind': 'data', 'shape': None},
'mul1': {'kind': 'op', 'op': 'Mul', 'type': 'Multiply'},
'mul1_data': {'kind': 'data', 'shape': None},
'mul2': {'kind': 'op', 'op': 'Mul', 'type': 'Multiply'},
'mul2_data': {'kind': 'data', 'shape': None},
'scale_param_q': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'scale_param_q_data': {'kind': 'data', 'shape': None},
'in_low': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'in_low_data': {'kind': 'data', 'shape': None},
'in_high': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'in_high_data': {'kind': 'data', 'shape': None},
'out_low': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'out_low_data': {'kind': 'data', 'shape': None},
'out_high': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'out_high_data': {'kind': 'data', 'shape': None},
'out': {'kind': 'op', 'op': 'AnyOp'},
'out_data': {'kind': 'data', 'shape': None},
'result': {'kind': 'op', 'op': 'Result'},
'high_reshape_const': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'high_reshape_const_data': {'kind': 'data', 'shape': None},
'high_reshape': {'kind': 'op', 'type': 'Reshape', 'op': 'Reshape'},
'high_reshape_data': {'kind': 'data', 'shape': None},
'low_reshape_const': {'kind': 'op', 'type': 'Const', 'op': 'Const'},
'low_reshape_const_data': {'kind': 'data', 'shape': None},
'low_reshape': {'kind': 'op', 'type': 'Reshape', 'op': 'Reshape'},
'low_reshape_data': {'kind': 'data', 'shape': None},
}
class TestQuantizeLinearResolver(unittest.TestCase):
def test_quantize_uint8(self):
graph = build_graph(nodes1_attributes,
[('input', 'input_data'),
('input_data', 'quantize'),
('scale_param_q', 'scale_param_q_data'),
('scale_param_q_data', 'quantize'),
('zerop_param_q', 'zerop_param_q_data'),
('zerop_param_q_data', 'quantize'),
('quantize', 'quantize_data'),
('quantize_data', 'out'),
('out', 'out_data'),
('out_data', 'result'),
],
{
'quantize': {'axis': 2},
'scale_param_q': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
'scale_param_q_data': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
'zerop_param_q': {'shape': np.array([]), 'value': np.uint8(128)},
'zerop_param_q_data': {'shape': np.array([]), 'value': np.uint8(128)},
}, nodes_with_edges_only=True)
graph_ref = build_graph(nodes_ref_attributes,
[('input', 'input_data'),
('input_data', 'f_quantize'),
('scale_param_q', 'scale_param_q_data'),
('scale_param_q_data', 'mul1', {'out': 0}),
('in_low', 'in_low_data'),
('in_low_data', 'mul1'),
('mul1', 'mul1_data'),
('mul1_data', 'f_quantize'),
('f_quantize', 'f_quantize_data'),
('scale_param_q_data', 'mul2', {'out': 0}),
('in_high', 'in_high_data'),
('in_high_data', 'mul2'),
('mul2', 'mul2_data'),
('mul2_data', 'f_quantize'),
('out_low', 'out_low_data'),
('out_low_data', 'f_quantize'),
('out_high', 'out_high_data'),
('out_high_data', 'f_quantize'),
('f_quantize_data', 'cast'),
('cast', 'cast_data'),
('cast_data', 'out'),
('out', 'out_data'),
('out_data', 'result'),
],
{'in_low': {'shape': np.array([]), 'value': -128},
'in_low_data': {'shape': np.array([]), 'value': -128},
'in_high': {'shape': np.array([]), 'value': 127},
'in_high_data': {'shape': np.array([]), 'value': 127},
'out_low': {'shape': np.array([]), 'value': 0},
'out_low_data': {'shape': np.array([]), 'value': 0},
'out_high': {'shape': np.array([]), 'value': 255},
'out_high_data': {'shape': np.array([]), 'value': 255},
'cast': {'dst_type': np.uint8}
}, nodes_with_edges_only=True)
graph.stage = 'middle'
QuantizeLinearResolver().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(flag, resp)
def test_quantize_int8(self):
graph = build_graph(nodes1_attributes,
[('input', 'input_data'),
('input_data', 'quantize'),
('scale_param_q', 'scale_param_q_data'),
('scale_param_q_data', 'quantize'),
('zerop_param_q', 'zerop_param_q_data'),
('zerop_param_q_data', 'quantize'),
('quantize', 'quantize_data'),
('quantize_data', 'out'),
('out', 'out_data'),
('out_data', 'result'),
],
{'scale_param_q': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
'scale_param_q_data': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
'zerop_param_q': {'shape': np.array([]), 'value': np.int8(0)},
'zerop_param_q_data': {'shape': np.array([]), 'value': np.int8(0)},
}, nodes_with_edges_only=True)
graph_ref = build_graph(nodes_ref_attributes,
[('input', 'input_data'),
('input_data', 'f_quantize'),
('scale_param_q', 'scale_param_q_data'),
('scale_param_q_data', 'mul1', {'out': 0}),
('in_low', 'in_low_data'),
('in_low_data', 'mul1'),
('mul1', 'mul1_data'),
('mul1_data', 'f_quantize'),
('f_quantize', 'f_quantize_data'),
('scale_param_q_data', 'mul2', {'out': 0}),
('in_high', 'in_high_data'),
('in_high_data', 'mul2'),
('mul2', 'mul2_data'),
('mul2_data', 'f_quantize'),
('out_low', 'out_low_data'),
('out_low_data', 'f_quantize'),
('out_high', 'out_high_data'),
('out_high_data', 'f_quantize'),
('f_quantize_data', 'cast'),
('cast', 'cast_data'),
('cast_data', 'out'),
('out', 'out_data'),
('out_data', 'result'),
],
{'in_low': {'shape': np.array([]), 'value': -128},
'in_low_data': {'shape': np.array([]), 'value': -128},
'in_high': {'shape': np.array([]), 'value': 127},
'in_high_data': {'shape': np.array([]), 'value': 127},
'out_low': {'shape': np.array([]), 'value': -128},
'out_low_data': {'shape': np.array([]), 'value': -128},
'out_high': {'shape': np.array([]), 'value': 127},
'out_high_data': {'shape': np.array([]), 'value': 127},
'cast': {'dst_type': np.int8}
}, nodes_with_edges_only=True)
graph.stage = 'middle'
QuantizeLinearResolver().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(flag, resp)
def test_quantize_no_zerop(self):
graph = build_graph(nodes1_attributes,
[('input', 'input_data'),
('input_data', 'quantize'),
('quantize', 'quantize_data'),
('scale_param_q', 'scale_param_q_data'),
('scale_param_q_data', 'quantize'),
('quantize', 'quantize_data'),
('quantize_data', 'out'),
('out', 'out_data'),
('out_data', 'result'),
],
{'scale_param_q': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
'scale_param_q_data': {'shape': np.array([]), 'value': np.float32(1.0 / 255)},
}, nodes_with_edges_only=True)
graph_ref = build_graph(nodes_ref_attributes,
[('input', 'input_data'),
('input_data', 'f_quantize'),
('scale_param_q', 'scale_param_q_data'),
('scale_param_q_data', 'mul1', {'out': 0}),
('in_low', 'in_low_data'),
('in_low_data', 'mul1'),
('mul1', 'mul1_data'),
('mul1_data', 'f_quantize'),
('f_quantize', 'f_quantize_data'),
('scale_param_q_data', 'mul2', {'out': 0}),
('in_high', 'in_high_data'),
('in_high_data', 'mul2'),
('mul2', 'mul2_data'),
('mul2_data', 'f_quantize'),
('out_low', 'out_low_data'),
('out_low_data', 'f_quantize'),
('out_high', 'out_high_data'),
('out_high_data', 'f_quantize'),
('f_quantize_data', 'cast'),
('cast', 'cast_data'),
('cast_data', 'out'),
('out', 'out_data'),
('out_data', 'result'),
],
{'in_low': {'shape': np.array([]), 'value': 0},
'in_low_data': {'shape': np.array([]), 'value': 0},
'in_high': {'shape': np.array([]), 'value': 255},
'in_high_data': {'shape': np.array([]), 'value': 255},
'out_low': {'shape': np.array([]), 'value': 0},
'out_low_data': {'shape': np.array([]), 'value': 0},
'out_high': {'shape': np.array([]), 'value': 255},
'out_high_data': {'shape': np.array([]), 'value': 255},
'cast': {'dst_type': np.uint8}
}, nodes_with_edges_only=True)
graph.stage = 'middle'
QuantizeLinearResolver().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(flag, resp)
@generator
class TestQuantizeWithAxis(unittest.TestCase):
@generate(*[(int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32),
np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([1, 1, 4, 1]),
np.array([-2., -3., -4., -5.]), np.array([253., 252., 251., 250.]),
0, 255, 2),
(int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32),
np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([1, 3, 1, 1]),
np.array([-2., -3., -4., -5.]), np.array([253., 252., 251., 250.]),
0, 255, 1),
(int64_array([2, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32),
np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([2, 1, 1, 1]),
np.array([-2., -3., -4., -5.]), np.array([253., 252., 251., 250.]),
0, 255, 0),
(int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32),
np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([1, 1, 1, 4]),
np.array([-2., -3., -4., -5.]), np.array([253., 252., 251., 250.]),
0, 255, -1),
(int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32),
np.array([2, 3, 4, 5], dtype=np.uint8), int64_array([1, 1, 4, 1]),
np.array([-2., -3., -4., -5.]), np.array([253., 252., 251., 250.]),
0, 255, -2),
(int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32),
np.array([2, 3, 4, 5], dtype=np.int8), int64_array([1, 1, 4, 1]),
np.array([-130., -131., -132., -133.]), np.array([125., 124., 123., 122.]),
-128.0, 127.0, 2),
(int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32),
np.array([2, 3, 4, 5], dtype=np.int8), int64_array([1, 3, 1, 1]),
np.array([-130., -131., -132., -133.]), np.array([125., 124., 123., 122.]),
-128.0, 127.0, 1),
(int64_array([2, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32),
np.array([2, 3, 4, 5], dtype=np.int8), int64_array([2, 1, 1, 1]),
np.array([-130., -131., -132., -133.]), np.array([125., 124., 123., 122.]),
-128.0, 127.0, 0),
(int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32),
np.array([2, 3, 4, 5], dtype=np.int8), int64_array([1, 1, 1, 4]),
np.array([-130., -131., -132., -133.]), np.array([125., 124., 123., 122.]),
-128.0, 127.0, -1),
(int64_array([1, 3, 4, 4]), np.array([2, 3, 4, 5], dtype=np.float32),
np.array([2, 3, 4, 5], dtype=np.int8), int64_array([1, 1, 4, 1]),
np.array([-130., -131., -132., -133.]), np.array([125., 124., 123., 122.]),
-128.0, 127.0, -2),
])
def test_quantize_with_axis(self, input_shape, scale_param_value, zero_param_value,
target_shape, in_low, in_high, out_low, out_high, axis):
graph = build_graph(nodes1_attributes,
[('input', 'input_data'),
('input_data', 'quantize'),
('scale_param_q', 'scale_param_q_data'),
('scale_param_q_data', 'quantize'),
('zerop_param_q', 'zerop_param_q_data'),
('zerop_param_q_data', 'quantize'),
('quantize', 'quantize_data'),
('quantize_data', 'out'),
('out', 'out_data'),
('out_data', 'result'),
],
{
'quantize': {'axis': axis},
'input': {'shape': input_shape},
'input_data': {'shape': input_shape},
'scale_param_q': {'shape': scale_param_value.shape, 'value': scale_param_value},
'scale_param_q_data': {'shape': scale_param_value.shape, 'value': scale_param_value},
'zerop_param_q': {'shape': zero_param_value.shape, 'value': zero_param_value},
'zerop_param_q_data': {'shape': zero_param_value.shape, 'value': zero_param_value},
}, nodes_with_edges_only=True)
graph_ref = build_graph(nodes_ref_attributes,
[('input', 'input_data'),
('input_data', 'f_quantize'),
('scale_param_q', 'scale_param_q_data'),
('scale_param_q_data', 'mul1', {'out': 0}),
('in_low', 'in_low_data'),
('in_low_data', 'mul1'),
('mul1', 'mul1_data'),
('mul1_data', 'high_reshape'),
('high_reshape_const', 'high_reshape_const_data'),
('high_reshape_const_data', 'high_reshape'),
('high_reshape', 'high_reshape_data'),
('high_reshape_data', 'f_quantize'),
('f_quantize', 'f_quantize_data'),
('scale_param_q_data', 'mul2', {'out': 0}),
('in_high', 'in_high_data'),
('in_high_data', 'mul2'),
('mul2', 'mul2_data'),
('mul2_data', 'low_reshape'),
('low_reshape', 'low_reshape_data'),
('low_reshape_data', 'f_quantize'),
('low_reshape_const', 'low_reshape_const_data'),
('low_reshape_const_data', 'low_reshape'),
('out_low', 'out_low_data'),
('out_low_data', 'f_quantize'),
('out_high', 'out_high_data'),
('out_high_data', 'f_quantize'),
('f_quantize_data', 'cast'),
('cast', 'cast_data'),
('cast_data', 'out'),
('out', 'out_data'),
('out_data', 'result'),
],
{'in_low': {'shape': in_low.shape, 'value': in_low},
'in_low_data': {'shape': in_low.shape, 'value': in_low},
'in_high': {'shape': in_high.shape, 'value': in_high},
'in_high_data': {'shape': in_high.shape, 'value': in_high},
'out_low': {'shape': np.array([]), 'value': out_low},
'out_low_data': {'shape': np.array([]), 'value': out_low},
'out_high': {'shape': np.array([]), 'value': out_high},
'out_high_data': {'shape': np.array([]), 'value': out_high},
'cast': {'dst_type': zero_param_value.dtype},
'low_reshape_const_data': {'shape': target_shape.shape, 'value': target_shape},
'high_reshape_const_data': {'shape': target_shape.shape, 'value': target_shape},
}, nodes_with_edges_only=True)
graph.stage = 'middle'
QuantizeLinearResolver().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(flag, resp)