[MO] Add transformation for single CTCGreedyDecoder operation (#7023)
* Add transformation for single CTCGreedyDecoder operation * Fix style in op specification * Update transformation logic * refactor old tests and add tests for new transformation * Move tf specific front transformations to tf folder * Update transformation logic and comments * Add run_after function and update comments * Add output_sparse_format attribute to extractor * Update transformation conditions and tests * Fix incorrect comment * Move sparse_to_dense_replacer to front/tf folder to fix problems with class registration * Update import * Update output ports handling in transformation * Update test * Fix BOM file * Update pattern for ctcloss transformation * Fix and refactor tests for ctcloss transform * Update transformation conditions
This commit is contained in:
1 parent
83e1359c9e
commit
f8e90f0c56
12 files changed
+422
-311
No files matched your search
@@ -74,7 +74,8 @@ The main difference between [CTCGreedyDecoder](CTCGreedyDecoder_1.md) and CTCGre
|
||||
**Example**
|
||||
|
||||
```xml
|
||||
<layer type="CTCGreedyDecoderSeqLen" merge_repeated="true" classes_index_type="i64" sequence_length_type="i64">
|
||||
<layer ... type="CTCGreedyDecoderSeqLen" version="opset6">
|
||||
<data merge_repeated="true" classes_index_type="i64" sequence_length_type="i64"/>
|
||||
<input>
|
||||
<port id="0">
|
||||
<dim>8</dim>
|
||||
|
||||
@@ -133,8 +133,6 @@ extensions/front/caffe/split_to_identity.py
|
||||
extensions/front/caffe/tanh.py
|
||||
extensions/front/ChangePlaceholderTypes.py
|
||||
extensions/front/create_tensor_nodes.py
|
||||
extensions/front/CTCGreedyDecoderReplacement.py
|
||||
extensions/front/CTCLossReplacement.py
|
||||
extensions/front/disable_weights_quantize_value_propagation.py
|
||||
extensions/front/div.py
|
||||
extensions/front/DropoutWithRandomUniformReplacer.py
|
||||
@@ -370,7 +368,6 @@ extensions/front/scatter_normalizer.py
|
||||
extensions/front/SizeReplacer.py
|
||||
extensions/front/softmax.py
|
||||
extensions/front/softsign_replacer.py
|
||||
extensions/front/sparse_to_dense_replacer.py
|
||||
extensions/front/split_normalizer.py
|
||||
extensions/front/SqueezeNormalize.py
|
||||
extensions/front/sub.py
|
||||
@@ -401,7 +398,9 @@ extensions/front/tf/CorrectRollAxes.py
|
||||
extensions/front/tf/crop_and_resize_ext.py
|
||||
extensions/front/tf/CropAndResizeReplacement.py
|
||||
extensions/front/tf/CTCGreedyDecoder_ext.py
|
||||
extensions/front/tf/CTCGreedyDecoderReplacement.py
|
||||
extensions/front/tf/CTCLoss_ext.py
|
||||
extensions/front/tf/CTCLossReplacement.py
|
||||
extensions/front/tf/cumsum_ext.py
|
||||
extensions/front/tf/deconv_ext.py
|
||||
extensions/front/tf/depth_to_space.py
|
||||
@@ -496,6 +495,7 @@ extensions/front/tf/sparse_fill_empty_rows_ext.py
|
||||
extensions/front/tf/sparse_segment_mean_ext.py
|
||||
extensions/front/tf/sparse_segment_sqrtn_ext.py
|
||||
extensions/front/tf/sparse_segment_sum_ext.py
|
||||
extensions/front/tf/sparse_to_dense_replacer.py
|
||||
extensions/front/tf/split_ext.py
|
||||
extensions/front/tf/ssd_support.json
|
||||
extensions/front/tf/ssd_support_api_v1.14.json
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
from extensions.ops.ctc_greedy_decoder_seq_len import CTCGreedyDecoderSeqLenOp
|
||||
from extensions.ops.transpose import Transpose
|
||||
from mo.front.common.partial_infer.utils import int64_array
|
||||
from mo.front.common.replacement import FrontReplacementSubgraph
|
||||
from mo.front.tf.graph_utils import create_op_with_const_inputs
|
||||
from mo.graph.graph import Graph, rename_nodes
|
||||
|
||||
|
||||
def replace_ctc_greedy_decoder(graph: Graph, match: dict):
|
||||
ctc_greedy_decoder_tf = match['decoder']
|
||||
cast = match['cast']
|
||||
sparse_to_dense = match['sparse_to_dense']
|
||||
sparse_to_dense_name = sparse_to_dense.soft_get('name', sparse_to_dense.id)
|
||||
ctc_greedy_decoder_tf_name = ctc_greedy_decoder_tf.soft_get('name', ctc_greedy_decoder_tf.id)
|
||||
|
||||
# for normalizing input chanel need to transpose input data from [T, N, C] to [N, T, C]
|
||||
# which supported CTCGreedyDecoderSeqLen op.
|
||||
ctc_data_permute = create_op_with_const_inputs(graph, Transpose, {1: int64_array([1, 0, 2])},
|
||||
{'name': ctc_greedy_decoder_tf_name + '/ctc_data_permute'})
|
||||
|
||||
assert ctc_greedy_decoder_tf.has_valid('merge_repeated'), \
|
||||
'The CTCGreedyDecoderSeqLen node "{}" misses "merge_repeated" attribute'.format(ctc_greedy_decoder_tf_name)
|
||||
|
||||
ctc_greedy_decoder_tf.in_port(0).get_source().connect(ctc_data_permute.in_port(0))
|
||||
merge_repeated_tf = ctc_greedy_decoder_tf.merge_repeated
|
||||
ctc_greedy_decoder = CTCGreedyDecoderSeqLenOp(graph, {'name': sparse_to_dense_name,
|
||||
'merge_repeated': merge_repeated_tf}).create_node()
|
||||
rename_nodes(
|
||||
[(sparse_to_dense, sparse_to_dense_name + '/AbandonedName'), (ctc_greedy_decoder, sparse_to_dense_name)])
|
||||
ctc_greedy_decoder.in_port(0).connect(ctc_data_permute.out_port(0))
|
||||
ctc_greedy_decoder_tf.in_port(1).get_source().connect(ctc_greedy_decoder.in_port(1))
|
||||
|
||||
# set output of the new sub-graph as a source for SparseToDense consumer
|
||||
sparse_to_dense.out_port(0).get_connection().set_source(ctc_greedy_decoder.out_port(0))
|
||||
|
||||
# remove no longer needed nodes
|
||||
graph.remove_nodes_from([sparse_to_dense.id, cast.id, ctc_greedy_decoder_tf.id])
|
||||
|
||||
|
||||
class CTCGreedyDecoderReplacement(FrontReplacementSubgraph):
|
||||
"""
|
||||
TensorFlow CTCGreedyDecoder produces output in a sparse tensor that is not supported by Inference Engine and
|
||||
Inference Engine's CTCGreedyDecoderSeqLen has different output that is in a dense format. So this transformation
|
||||
intents to replace TF CTCGreedyDecoder+SparseToDense where SparseToDense third input get from input parameter
|
||||
to CTCGreedyDecoderSeqLen which compatible with IE.
|
||||
"""
|
||||
enabled = True
|
||||
|
||||
@staticmethod
|
||||
def pattern(**kwargs):
|
||||
return dict(
|
||||
nodes=[('decoder', dict(op='CTCGreedyDecoderSeqLen')),
|
||||
('cast', dict(op='Cast')),
|
||||
('sparse_to_dense', dict(op='SparseToDense'))
|
||||
],
|
||||
edges=[('decoder', 'sparse_to_dense', {'out': 0}),
|
||||
('decoder', 'cast', {'out': 1}),
|
||||
('cast', 'sparse_to_dense', {'out': 0})]
|
||||
)
|
||||
|
||||
def replace_sub_graph(self, graph: Graph, match: dict):
|
||||
replace_ctc_greedy_decoder(graph, match)
|
||||
|
||||
|
||||
class CTCGreedyDecoderWithSparseToDenseShapeReplacement(FrontReplacementSubgraph):
|
||||
"""
|
||||
TensorFlow CTCGreedyDecoder produces output in a sparse tensor that is not supported by Inference Engine and
|
||||
Inference Engine's CTCGreedyDecoderSeqLen has different output that is in a dense format. So this transformation
|
||||
intents to replace TF CTCGreedyDecoder+SparseToDense where SparseToDense third input get from CTCGreedyDecoder
|
||||
second output to CTCGreedyDecoderSeqLen which compatible with IE.
|
||||
"""
|
||||
enabled = True
|
||||
|
||||
@staticmethod
|
||||
def pattern(**kwargs):
|
||||
return dict(
|
||||
nodes=[('decoder', dict(op='CTCGreedyDecoderSeqLen')),
|
||||
('cast', dict(op='Cast')),
|
||||
('sparse_to_dense', dict(op='SparseToDense'))
|
||||
],
|
||||
edges=[('decoder', 'sparse_to_dense', {'out': 0}),
|
||||
('decoder', 'cast', {'out': 1}),
|
||||
('decoder', 'sparse_to_dense', {'out': 2}),
|
||||
('cast', 'sparse_to_dense', {'out': 0})]
|
||||
)
|
||||
|
||||
def replace_sub_graph(self, graph: Graph, match: dict):
|
||||
replace_ctc_greedy_decoder(graph, match)
|
||||
@@ -0,0 +1,155 @@
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import logging as log
|
||||
|
||||
from extensions.ops.ctc_greedy_decoder_seq_len import CTCGreedyDecoderSeqLenOp
|
||||
from extensions.ops.transpose import Transpose
|
||||
from mo.front.common.partial_infer.utils import int64_array
|
||||
from mo.front.common.replacement import FrontReplacementSubgraph, FrontReplacementPattern
|
||||
from mo.front.tf.graph_utils import create_op_with_const_inputs
|
||||
from mo.graph.graph import Graph, rename_nodes
|
||||
from mo.ops.result import Result
|
||||
|
||||
|
||||
def replace_ctc_greedy_decoder(graph: Graph, match: dict):
|
||||
ctc_greedy_decoder_tf = match['decoder']
|
||||
cast = match['cast']
|
||||
sparse_to_dense = match['sparse_to_dense']
|
||||
sparse_to_dense_name = sparse_to_dense.soft_get('name', sparse_to_dense.id)
|
||||
ctc_greedy_decoder_tf_name = ctc_greedy_decoder_tf.soft_get('name', ctc_greedy_decoder_tf.id)
|
||||
|
||||
# For normalizing input channel needs to transpose input data from [T, N, C] to [N, T, C]
|
||||
# which supported CTCGreedyDecoderSeqLen op.
|
||||
ctc_data_permute = create_op_with_const_inputs(graph, Transpose, {1: int64_array([1, 0, 2])},
|
||||
{'name': ctc_greedy_decoder_tf_name + '/ctc_data_permute'})
|
||||
|
||||
assert ctc_greedy_decoder_tf.has_valid('merge_repeated'), \
|
||||
'The CTCGreedyDecoderSeqLen node "{}" misses "merge_repeated" attribute'.format(ctc_greedy_decoder_tf_name)
|
||||
|
||||
ctc_greedy_decoder_tf.in_port(0).get_source().connect(ctc_data_permute.in_port(0))
|
||||
merge_repeated_tf = ctc_greedy_decoder_tf.merge_repeated
|
||||
ctc_greedy_decoder = CTCGreedyDecoderSeqLenOp(graph, {'name': sparse_to_dense_name,
|
||||
'merge_repeated': merge_repeated_tf}).create_node()
|
||||
rename_nodes(
|
||||
[(sparse_to_dense, sparse_to_dense_name + '/AbandonedName'), (ctc_greedy_decoder, sparse_to_dense_name)])
|
||||
ctc_greedy_decoder.in_port(0).connect(ctc_data_permute.out_port(0))
|
||||
ctc_greedy_decoder_tf.in_port(1).get_source().connect(ctc_greedy_decoder.in_port(1))
|
||||
|
||||
# Set output of the new sub-graph as a source for SparseToDense consumer
|
||||
sparse_to_dense.out_port(0).get_connection().set_source(ctc_greedy_decoder.out_port(0))
|
||||
|
||||
# Remove no longer needed nodes
|
||||
graph.remove_nodes_from([sparse_to_dense.id, cast.id, ctc_greedy_decoder_tf.id])
|
||||
|
||||
|
||||
class CTCGreedyDecoderReplacement(FrontReplacementSubgraph):
|
||||
"""
|
||||
TensorFlow CTCGreedyDecoder produces output in a sparse tensor that is not supported by Inference Engine, and
|
||||
Inference Engine's CTCGreedyDecoderSeqLen has a different output that is in a dense format. So this transformation
|
||||
intents to replace TF CTCGreedyDecoder+SparseToDense where SparseToDense third input get from input parameter
|
||||
to CTCGreedyDecoderSeqLen which compatible with IE.
|
||||
"""
|
||||
enabled = True
|
||||
|
||||
@staticmethod
|
||||
def pattern(**kwargs):
|
||||
return dict(
|
||||
nodes=[('decoder', dict(op='CTCGreedyDecoderSeqLen', output_sparse_format=True)),
|
||||
('cast', dict(op='Cast')),
|
||||
('sparse_to_dense', dict(op='SparseToDense'))
|
||||
],
|
||||
edges=[('decoder', 'sparse_to_dense', {'out': 0}),
|
||||
('decoder', 'cast', {'out': 1}),
|
||||
('cast', 'sparse_to_dense', {'out': 0})]
|
||||
)
|
||||
|
||||
def replace_sub_graph(self, graph: Graph, match: dict):
|
||||
replace_ctc_greedy_decoder(graph, match)
|
||||
|
||||
|
||||
class CTCGreedyDecoderWithSparseToDenseShapeReplacement(FrontReplacementSubgraph):
|
||||
"""
|
||||
TensorFlow CTCGreedyDecoder produces output in a sparse tensor that is not supported by Inference Engine, and
|
||||
Inference Engine's CTCGreedyDecoderSeqLen has a different output that is in a dense format. So this transformation
|
||||
intents to replace TF CTCGreedyDecoder+SparseToDense where SparseToDense third input get from CTCGreedyDecoder
|
||||
second output to CTCGreedyDecoderSeqLen which compatible with IE.
|
||||
"""
|
||||
enabled = True
|
||||
|
||||
@staticmethod
|
||||
def pattern(**kwargs):
|
||||
return dict(
|
||||
nodes=[('decoder', dict(op='CTCGreedyDecoderSeqLen', output_sparse_format=True)),
|
||||
('cast', dict(op='Cast')),
|
||||
('sparse_to_dense', dict(op='SparseToDense'))
|
||||
],
|
||||
edges=[('decoder', 'sparse_to_dense', {'out': 0}),
|
||||
('decoder', 'cast', {'out': 1}),
|
||||
('decoder', 'sparse_to_dense', {'out': 2}),
|
||||
('cast', 'sparse_to_dense', {'out': 0})]
|
||||
)
|
||||
|
||||
def replace_sub_graph(self, graph: Graph, match: dict):
|
||||
replace_ctc_greedy_decoder(graph, match)
|
||||
|
||||
|
||||
class CTCGreedyDecoderSingleReplacement(FrontReplacementPattern):
|
||||
"""
|
||||
TensorFlow CTCGreedyDecoder produces output in a sparse tensor that is not supported by Inference Engine, and
|
||||
Inference Engine's CTCGreedyDecoderSeqLen has a different output that is in a dense format. So this transformation
|
||||
handles a single TF CTCGreedyDecoder and warns the user about another format of the output
|
||||
"""
|
||||
enabled = True
|
||||
|
||||
def run_after(self):
|
||||
return [CTCGreedyDecoderReplacement, CTCGreedyDecoderWithSparseToDenseShapeReplacement]
|
||||
|
||||
def find_and_replace_pattern(self, graph: Graph):
|
||||
for ctc_greedy_decoder_tf in graph.get_op_nodes(op='CTCGreedyDecoderSeqLen', output_sparse_format=True):
|
||||
ctc_greedy_decoder_tf_name = ctc_greedy_decoder_tf.soft_get('name', ctc_greedy_decoder_tf.id)
|
||||
|
||||
# TF CTCGreedyDecoder have 4 output tensors. If any of them connected to not Result operation then
|
||||
# transformation in not applicable
|
||||
for port_num in ctc_greedy_decoder_tf.out_ports():
|
||||
if not ctc_greedy_decoder_tf.out_port(port_num).disconnected()\
|
||||
and ctc_greedy_decoder_tf.out_port(port_num).get_destination().node.soft_get('op') != 'Result':
|
||||
return
|
||||
|
||||
# If the first and second output are not connected to Result operations -
|
||||
# create Result operation and connect it to appropriate output
|
||||
if ctc_greedy_decoder_tf.out_port(0).disconnected():
|
||||
first_result = Result(graph,
|
||||
{'name': ctc_greedy_decoder_tf_name + '/decoded_classes'}
|
||||
).create_node()
|
||||
ctc_greedy_decoder_tf.out_port(0).connect(first_result.in_port(0))
|
||||
|
||||
if ctc_greedy_decoder_tf.out_port(1).disconnected():
|
||||
second_result = Result(graph,
|
||||
{'name': ctc_greedy_decoder_tf_name + '/seq_lengths_output'}
|
||||
).create_node()
|
||||
ctc_greedy_decoder_tf.out_port(1).connect(second_result.in_port(0))
|
||||
|
||||
|
||||
# For normalizing input channel needs to transpose input data from [T, N, C] to [N, T, C]
|
||||
# which supported CTCGreedyDecoderSeqLen op.
|
||||
log.warning('Found TF CTCGreedyDecoder operation at the end of network. '
|
||||
'PLEASE NOTE, appropriate network output operation CTCGreedyDecoderSeqLen {} '
|
||||
'will have dense format, not sparse format!'.format(ctc_greedy_decoder_tf_name))
|
||||
ctc_data_permute = create_op_with_const_inputs(graph, Transpose, {1: int64_array([1, 0, 2])},
|
||||
{'name': ctc_greedy_decoder_tf_name + '/ctc_data_permute'})
|
||||
|
||||
assert ctc_greedy_decoder_tf.has_valid('merge_repeated'), \
|
||||
'The CTCGreedyDecoderSeqLen node "{}" misses "merge_repeated" attribute'.format(
|
||||
ctc_greedy_decoder_tf_name)
|
||||
|
||||
ctc_greedy_decoder_tf.in_port(0).get_source().connect(ctc_data_permute.in_port(0))
|
||||
ctc_greedy_decoder_tf.in_port(0).disconnect()
|
||||
ctc_data_permute.out_port(0).connect(ctc_greedy_decoder_tf.in_port(0))
|
||||
|
||||
del ctc_greedy_decoder_tf['output_sparse_format']
|
||||
|
||||
for port_num in [2, 3]: # MO CTCGreedyDecoderSeqLen may have 2 outputs
|
||||
if port_num in ctc_greedy_decoder_tf.out_ports():
|
||||
if not ctc_greedy_decoder_tf.out_port(port_num).disconnected():
|
||||
ctc_greedy_decoder_tf.out_port(port_num).disconnect()
|
||||
@@ -13,6 +13,7 @@ class CTCCGreedyDecoderFrontExtractor(FrontExtractorOp):
|
||||
def extract(cls, node):
|
||||
attrs = {
|
||||
'merge_repeated': bool(node.pb.attr['merge_repeated'].b),
|
||||
'output_sparse_format': True, # Special argument for TF CTCGreedyDecoder replacement transformations
|
||||
}
|
||||
CTCGreedyDecoderSeqLenOp.update_node_stat(node, attrs)
|
||||
return cls.enabled
|
||||
+2
-2
@@ -20,14 +20,14 @@ class CTCLossReplacement(FrontReplacementSubgraph):
|
||||
enabled = True
|
||||
|
||||
def run_before(self):
|
||||
from extensions.front.CTCGreedyDecoderReplacement import CTCGreedyDecoderReplacement
|
||||
from extensions.front.tf.CTCGreedyDecoderReplacement import CTCGreedyDecoderReplacement
|
||||
return [CTCGreedyDecoderReplacement]
|
||||
|
||||
def pattern(self):
|
||||
return dict(
|
||||
nodes=[
|
||||
('transpose', dict(op='Transpose')),
|
||||
('ctc_greedy_decoder', dict(op='CTCGreedyDecoderSeqLen')),
|
||||
('ctc_greedy_decoder', dict(op='CTCGreedyDecoderSeqLen', output_sparse_format=True)),
|
||||
('cast', dict(op='Cast')),
|
||||
('sparse_to_dense', dict(op='SparseToDense')),
|
||||
('const', dict(op='Const')),
|
||||
+2
-2
@@ -21,8 +21,8 @@ class SparseToDenseReplacer(FrontReplacementOp):
|
||||
enabled = True
|
||||
|
||||
def run_after(self):
|
||||
from extensions.front.CTCGreedyDecoderReplacement import CTCGreedyDecoderReplacement
|
||||
from extensions.front.CTCLossReplacement import CTCLossReplacement
|
||||
from extensions.front.tf.CTCGreedyDecoderReplacement import CTCGreedyDecoderReplacement
|
||||
from extensions.front.tf.CTCLossReplacement import CTCLossReplacement
|
||||
return [CTCGreedyDecoderReplacement, CTCLossReplacement]
|
||||
|
||||
def replace_op(self, graph: Graph, node: Node):
|
||||
@@ -1,96 +0,0 @@
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import unittest
|
||||
|
||||
from extensions.front.CTCGreedyDecoderReplacement import CTCGreedyDecoderReplacement, CTCGreedyDecoderWithSparseToDenseShapeReplacement
|
||||
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, const
|
||||
|
||||
|
||||
class CTCGreedyDecoderReplacementTests(unittest.TestCase):
|
||||
def test1(self):
|
||||
nodes_attributes = {
|
||||
# nodes from original graph
|
||||
'logits': {'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'},
|
||||
'seq_len': {'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'},
|
||||
'order_arr': {'kind': 'op', 'op': 'Const'},
|
||||
'transpose': {'type': 'Transpose', 'kind': 'op', 'op': 'Transpose'},
|
||||
'decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'merge_repeated': True},
|
||||
'cast': {'kind': 'op', 'op': 'Cast'},
|
||||
'sparse_to_dense': {'kind': 'op', 'op': 'SparseToDense'},
|
||||
'last': {'type': None, 'value': None, 'kind': 'op', 'op': 'Result'},
|
||||
|
||||
# new nodes
|
||||
'new_decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'use_mask_format': True},
|
||||
**const('squeeze_axes', int64_array([2, 3])),
|
||||
'squeeze_dec_seq': {'kind': 'op', 'op': 'Squeeze'},
|
||||
'cast_to_int': {'kind': 'op', 'op': 'Cast'},
|
||||
}
|
||||
|
||||
graph = build_graph(nodes_attributes,
|
||||
[('logits', 'decoder', {'out': 0, 'in': 0}),
|
||||
('seq_len', 'decoder', {'out': 0, 'in': 1}),
|
||||
('decoder', 'sparse_to_dense', {'out': 0, 'in': 0}),
|
||||
('decoder', 'sparse_to_dense', {'out': 2, 'in': 1}),
|
||||
('decoder', 'cast', {'out': 1, 'in': 0}),
|
||||
('cast', 'sparse_to_dense', {'out': 0}),
|
||||
('sparse_to_dense', 'last', {'out': 0, 'in': 0}),
|
||||
], nodes_with_edges_only=True)
|
||||
graph.stage = 'front'
|
||||
CTCGreedyDecoderWithSparseToDenseShapeReplacement().find_and_replace_pattern(graph)
|
||||
|
||||
graph_ref = build_graph(nodes_attributes,
|
||||
[('logits', 'transpose', {'out': 0, 'in': 0}),
|
||||
('order_arr', 'transpose', {'out': 0, 'in': 1}),
|
||||
('transpose', 'decoder', {'out': 0, 'in': 0}),
|
||||
('seq_len', 'decoder', {'out': 0, 'in': 1}),
|
||||
('decoder', 'last', {'out': 0, 'in': 0}),
|
||||
],
|
||||
nodes_with_edges_only=True)
|
||||
|
||||
(flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
|
||||
def test2(self):
|
||||
nodes_attributes = {
|
||||
# nodes from original graph
|
||||
'logits': {'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'},
|
||||
'seq_len': {'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'},
|
||||
'order_arr': {'kind': 'op', 'op': 'Const'},
|
||||
'transpose': {'type': 'Transpose', 'kind': 'op', 'op': 'Transpose'},
|
||||
'decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'merge_repeated': True},
|
||||
'cast': {'kind': 'op', 'op': 'Cast'},
|
||||
'sparse_to_dense': {'kind': 'op', 'op': 'SparseToDense'},
|
||||
'last': {'type': None, 'value': None, 'kind': 'op', 'op': 'Result'},
|
||||
|
||||
# new nodes
|
||||
'new_decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'use_mask_format': True},
|
||||
**const('squeeze_axes', int64_array([2, 3])),
|
||||
'squeeze_dec_seq': {'kind': 'op', 'op': 'Squeeze'},
|
||||
'cast_to_int': {'kind': 'op', 'op': 'Cast'},
|
||||
}
|
||||
|
||||
graph = build_graph(nodes_attributes,
|
||||
[('logits', 'decoder', {'out': 0, 'in': 0}),
|
||||
('seq_len', 'decoder', {'out': 0, 'in': 1}),
|
||||
('decoder', 'sparse_to_dense', {'out': 0, 'in': 0}),
|
||||
('decoder', 'cast', {'out': 1, 'in': 0}),
|
||||
('cast', 'sparse_to_dense', {'out': 0}),
|
||||
('sparse_to_dense', 'last', {'out': 0, 'in': 0}),
|
||||
], nodes_with_edges_only=True)
|
||||
graph.stage = 'front'
|
||||
CTCGreedyDecoderReplacement().find_and_replace_pattern(graph)
|
||||
|
||||
graph_ref = build_graph(nodes_attributes,
|
||||
[('logits', 'transpose', {'out': 0, 'in': 0}),
|
||||
('order_arr', 'transpose', {'out': 0, 'in': 1}),
|
||||
('transpose', 'decoder', {'out': 0, 'in': 0}),
|
||||
('seq_len', 'decoder', {'out': 0, 'in': 1}),
|
||||
('decoder', 'last', {'out': 0, 'in': 0}),
|
||||
],
|
||||
nodes_with_edges_only=True)
|
||||
|
||||
(flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
@@ -1,115 +0,0 @@
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import numpy as np
|
||||
import unittest
|
||||
from argparse import Namespace
|
||||
|
||||
from extensions.front.CTCLossReplacement import CTCLossReplacement
|
||||
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, const
|
||||
|
||||
|
||||
class CTCLossFrontReplacementTest(unittest.TestCase):
|
||||
def test1(self):
|
||||
nodes_attributes = {
|
||||
'logits': {'shape': int64_array([2, 6, 100]), 'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'},
|
||||
'seq_mask': {'shape': int64_array([2]), 'data_type': np.int32, 'kind': 'op', 'op': 'Parameter'},
|
||||
'transpose': {'kind': 'op', 'op': 'Transpose'},
|
||||
'ctc_greedy_decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'merge_repeated': True},
|
||||
'cast': {'kind': 'op', 'op': 'Cast'},
|
||||
'sparse_to_dense': {'kind': 'op', 'op': 'SparseToDense'},
|
||||
'tf_ctc_loss': {'kind': 'op', 'op': 'CTCLoss', 'preprocess_collapse_repeated': False,
|
||||
'ctc_merge_repeated': True, 'unique': False, 'logits_time_major': True},
|
||||
'ctc_loss': {'kind': 'op', 'op': 'CTCLoss', 'preprocess_collapse_repeated': False,
|
||||
'ctc_merge_repeated': True, 'unique': False},
|
||||
**const('default_value', int64_array(-1)),
|
||||
'last': {'type': None, 'value': None, 'kind': 'op', 'op': 'Result'},
|
||||
'transpose2': {'kind': 'op', 'op': 'Transpose'},
|
||||
**const('transpose2_axis', int64_array([1, 0, 2])),
|
||||
}
|
||||
graph = build_graph(nodes_attributes, [('logits', 'transpose', {'out': 0, 'in': 0}),
|
||||
('transpose', 'ctc_greedy_decoder', {'out': 0, 'in': 0}),
|
||||
('seq_mask', 'ctc_greedy_decoder', {'out': 0, 'in': 1}),
|
||||
('transpose', 'tf_ctc_loss', {'out': 0, 'in': 0}),
|
||||
('seq_mask', 'tf_ctc_loss', {'out': 0, 'in': 3}),
|
||||
('ctc_greedy_decoder', 'sparse_to_dense', {'out': 0, 'in': 0}),
|
||||
('ctc_greedy_decoder', 'sparse_to_dense', {'out': 2, 'in': 1}),
|
||||
('ctc_greedy_decoder', 'sparse_to_dense', {'out': 1, 'in': 2}),
|
||||
('default_value', 'sparse_to_dense', {'out': 0, 'in': 3}),
|
||||
('ctc_greedy_decoder', 'cast', {'out': 1, 'in': 0}),
|
||||
('ctc_greedy_decoder', 'tf_ctc_loss', {'out': 0, 'in': 1}),
|
||||
('cast', 'tf_ctc_loss', {'out': 0, 'in': 2}),
|
||||
('tf_ctc_loss', 'last', {'out': 0, 'in': 0})],
|
||||
nodes_with_edges_only=True)
|
||||
graph.graph['cmd_params'] = Namespace(data_type='FP32')
|
||||
graph.stage = 'front'
|
||||
CTCLossReplacement().find_and_replace_pattern(graph)
|
||||
|
||||
graph_ref = build_graph(nodes_attributes,
|
||||
[('logits', 'transpose', {'out': 0, 'in': 0}),
|
||||
('transpose', 'transpose2', {'out': 0, 'in': 0}),
|
||||
('transpose2_axis', 'transpose2', {'out': 0, 'in': 1}),
|
||||
('transpose2', 'ctc_greedy_decoder', {'out': 0, 'in': 0}),
|
||||
('seq_mask', 'ctc_greedy_decoder', {'out': 0, 'in': 1}),
|
||||
('transpose2', 'ctc_loss', {'out': 0, 'in': 0}),
|
||||
('ctc_greedy_decoder', 'ctc_loss', {'out': 0, 'in': 2}),
|
||||
('ctc_greedy_decoder', 'ctc_loss', {'out': 1, 'in': 3}),
|
||||
('seq_mask', 'ctc_loss', {'out': 0, 'in': 1}),
|
||||
('ctc_loss', 'last', {'out': 0, 'in': 0})],
|
||||
nodes_with_edges_only=True)
|
||||
|
||||
(flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
|
||||
def test2(self):
|
||||
nodes_attributes = {
|
||||
'logits': {'shape': int64_array([2, 6, 100]), 'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'},
|
||||
'seq_mask': {'shape': int64_array([2]), 'data_type': np.int32, 'kind': 'op', 'op': 'Parameter'},
|
||||
'transpose': {'kind': 'op', 'op': 'Transpose'},
|
||||
'ctc_greedy_decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'merge_repeated': True},
|
||||
'cast': {'kind': 'op', 'op': 'Cast'},
|
||||
'sparse_to_dense': {'kind': 'op', 'op': 'SparseToDense'},
|
||||
'tf_ctc_loss': {'kind': 'op', 'op': 'CTCLoss', 'preprocess_collapse_repeated': False,
|
||||
'ctc_merge_repeated': True, 'unique': False, 'logits_time_major': False},
|
||||
'ctc_loss': {'kind': 'op', 'op': 'CTCLoss', 'preprocess_collapse_repeated': False,
|
||||
'ctc_merge_repeated': True, 'unique': False},
|
||||
**const('default_value', int64_array(-1)),
|
||||
'last': {'type': None, 'value': None, 'kind': 'op', 'op': 'Result'},
|
||||
'transpose2': {'kind': 'op', 'op': 'Transpose'},
|
||||
**const('transpose2_axis', int64_array([1, 0, 2])),
|
||||
}
|
||||
graph = build_graph(nodes_attributes, [('logits', 'transpose', {'out': 0, 'in': 0}),
|
||||
('transpose', 'ctc_greedy_decoder', {'out': 0, 'in': 0}),
|
||||
('seq_mask', 'ctc_greedy_decoder', {'out': 0, 'in': 1}),
|
||||
('transpose', 'tf_ctc_loss', {'out': 0, 'in': 0}),
|
||||
('seq_mask', 'tf_ctc_loss', {'out': 0, 'in': 3}),
|
||||
('ctc_greedy_decoder', 'sparse_to_dense', {'out': 0, 'in': 0}),
|
||||
('ctc_greedy_decoder', 'sparse_to_dense', {'out': 2, 'in': 1}),
|
||||
('ctc_greedy_decoder', 'sparse_to_dense', {'out': 1, 'in': 2}),
|
||||
('default_value', 'sparse_to_dense', {'out': 0, 'in': 3}),
|
||||
('ctc_greedy_decoder', 'cast', {'out': 1, 'in': 0}),
|
||||
('ctc_greedy_decoder', 'tf_ctc_loss', {'out': 0, 'in': 1}),
|
||||
('cast', 'tf_ctc_loss', {'out': 0, 'in': 2}),
|
||||
('tf_ctc_loss', 'last', {'out': 0, 'in': 0})],
|
||||
nodes_with_edges_only=True)
|
||||
graph.graph['cmd_params'] = Namespace(data_type='FP32')
|
||||
graph.stage = 'front'
|
||||
CTCLossReplacement().find_and_replace_pattern(graph)
|
||||
|
||||
graph_ref = build_graph(nodes_attributes,
|
||||
[('logits', 'transpose', {'out': 0, 'in': 0}),
|
||||
('transpose', 'transpose2', {'out': 0, 'in': 0}),
|
||||
('transpose2_axis', 'transpose2', {'out': 0, 'in': 1}),
|
||||
('transpose2', 'ctc_greedy_decoder', {'out': 0, 'in': 0}),
|
||||
('seq_mask', 'ctc_greedy_decoder', {'out': 0, 'in': 1}),
|
||||
('transpose', 'ctc_loss', {'out': 0, 'in': 0}),
|
||||
('ctc_greedy_decoder', 'ctc_loss', {'out': 0, 'in': 2}),
|
||||
('ctc_greedy_decoder', 'ctc_loss', {'out': 1, 'in': 3}),
|
||||
('seq_mask', 'ctc_loss', {'out': 0, 'in': 1}),
|
||||
('ctc_loss', 'last', {'out': 0, 'in': 0})],
|
||||
nodes_with_edges_only=True)
|
||||
|
||||
(flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
@@ -0,0 +1,149 @@
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import unittest
|
||||
|
||||
from extensions.front.tf.CTCGreedyDecoderReplacement import CTCGreedyDecoderReplacement, \
|
||||
CTCGreedyDecoderWithSparseToDenseShapeReplacement, CTCGreedyDecoderSingleReplacement
|
||||
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, const
|
||||
|
||||
|
||||
class CTCGreedyDecoderReplacementTests(unittest.TestCase):
|
||||
nodes_attributes = {
|
||||
# nodes from original graph
|
||||
'logits': {'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'},
|
||||
'seq_len': {'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'},
|
||||
'order_arr': {'kind': 'op', 'op': 'Const'},
|
||||
'transpose': {'type': 'Transpose', 'kind': 'op', 'op': 'Transpose'},
|
||||
'decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'merge_repeated': True, 'output_sparse_format': True},
|
||||
'cast': {'kind': 'op', 'op': 'Cast'},
|
||||
'sparse_to_dense': {'kind': 'op', 'op': 'SparseToDense'},
|
||||
'last': {'type': None, 'value': None, 'kind': 'op', 'op': 'Result'},
|
||||
'last_1': {'type': None, 'value': None, 'kind': 'op', 'op': 'Result'},
|
||||
|
||||
# new nodes
|
||||
'new_decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'merge_repeated': True},
|
||||
**const('squeeze_axes', int64_array([2, 3])),
|
||||
'squeeze_dec_seq': {'kind': 'op', 'op': 'Squeeze'},
|
||||
'cast_to_int': {'kind': 'op', 'op': 'Cast'},
|
||||
'out_seq_len': {'type': None, 'value': None, 'kind': 'op', 'op': 'Result'},
|
||||
}
|
||||
|
||||
def test_CTCGreedyDecoderWithSparseToDenseShape(self):
|
||||
graph = build_graph(self.nodes_attributes,
|
||||
[('logits', 'decoder', {'out': 0, 'in': 0}),
|
||||
('seq_len', 'decoder', {'out': 0, 'in': 1}),
|
||||
('decoder', 'sparse_to_dense', {'out': 0, 'in': 0}),
|
||||
('decoder', 'sparse_to_dense', {'out': 2, 'in': 1}),
|
||||
('decoder', 'cast', {'out': 1, 'in': 0}),
|
||||
('cast', 'sparse_to_dense', {'out': 0}),
|
||||
('sparse_to_dense', 'last', {'out': 0, 'in': 0}),
|
||||
], nodes_with_edges_only=True)
|
||||
graph.stage = 'front'
|
||||
CTCGreedyDecoderWithSparseToDenseShapeReplacement().find_and_replace_pattern(graph)
|
||||
|
||||
graph_ref = build_graph(self.nodes_attributes,
|
||||
[('logits', 'transpose', {'out': 0, 'in': 0}),
|
||||
('order_arr', 'transpose', {'out': 0, 'in': 1}),
|
||||
('transpose', 'new_decoder', {'out': 0, 'in': 0}),
|
||||
('seq_len', 'new_decoder', {'out': 0, 'in': 1}),
|
||||
('new_decoder', 'last', {'out': 0, 'in': 0}),
|
||||
],
|
||||
nodes_with_edges_only=True)
|
||||
|
||||
(flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
|
||||
def test_CTCGreedyDecoderReplacement(self):
|
||||
graph = build_graph(self.nodes_attributes,
|
||||
[('logits', 'decoder', {'out': 0, 'in': 0}),
|
||||
('seq_len', 'decoder', {'out': 0, 'in': 1}),
|
||||
('decoder', 'sparse_to_dense', {'out': 0, 'in': 0}),
|
||||
('decoder', 'cast', {'out': 1, 'in': 0}),
|
||||
('cast', 'sparse_to_dense', {'out': 0}),
|
||||
('sparse_to_dense', 'last', {'out': 0, 'in': 0}),
|
||||
], nodes_with_edges_only=True)
|
||||
graph.stage = 'front'
|
||||
CTCGreedyDecoderReplacement().find_and_replace_pattern(graph)
|
||||
|
||||
graph_ref = build_graph(self.nodes_attributes,
|
||||
[('logits', 'transpose', {'out': 0, 'in': 0}),
|
||||
('order_arr', 'transpose', {'out': 0, 'in': 1}),
|
||||
('transpose', 'new_decoder', {'out': 0, 'in': 0}),
|
||||
('seq_len', 'new_decoder', {'out': 0, 'in': 1}),
|
||||
('new_decoder', 'last', {'out': 0, 'in': 0}),
|
||||
],
|
||||
nodes_with_edges_only=True)
|
||||
|
||||
(flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
|
||||
def test_CTCGreedyDecoderSingle(self):
|
||||
graph = build_graph(self.nodes_attributes,
|
||||
[('logits', 'decoder', {'out': 0, 'in': 0}),
|
||||
('seq_len', 'decoder', {'out': 0, 'in': 1}),
|
||||
('decoder', 'last', {'out': 0, 'in': 0}),
|
||||
('decoder', 'last_1', {'out': 1, 'in': 0}),
|
||||
], nodes_with_edges_only=True)
|
||||
graph.stage = 'front'
|
||||
CTCGreedyDecoderSingleReplacement().find_and_replace_pattern(graph)
|
||||
|
||||
graph_ref = build_graph(self.nodes_attributes,
|
||||
[('logits', 'transpose', {'out': 0, 'in': 0}),
|
||||
('order_arr', 'transpose', {'out': 0, 'in': 1}),
|
||||
('transpose', 'new_decoder', {'out': 0, 'in': 0}),
|
||||
('seq_len', 'new_decoder', {'out': 0, 'in': 1}),
|
||||
('new_decoder', 'last', {'out': 0, 'in': 0}),
|
||||
('new_decoder', 'last_1', {'out': 1, 'in': 0}),
|
||||
],
|
||||
nodes_with_edges_only=True)
|
||||
|
||||
(flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
|
||||
def test_CTCGreedyDecoderSingle_negative(self):
|
||||
edges = [('logits', 'decoder', {'out': 0, 'in': 0}),
|
||||
('seq_len', 'decoder', {'out': 0, 'in': 1}),
|
||||
('decoder', 'sparse_to_dense', {'out': 0, 'in': 0}),
|
||||
('decoder', 'cast', {'out': 1, 'in': 0}),
|
||||
('cast', 'sparse_to_dense', {'out': 0}),
|
||||
('sparse_to_dense', 'last', {'out': 0, 'in': 0}),
|
||||
]
|
||||
graph = build_graph(self.nodes_attributes,
|
||||
edges, nodes_with_edges_only=True)
|
||||
graph.stage = 'front'
|
||||
CTCGreedyDecoderSingleReplacement().find_and_replace_pattern(graph)
|
||||
|
||||
graph_ref = build_graph(self.nodes_attributes,
|
||||
edges, nodes_with_edges_only=True)
|
||||
|
||||
(flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
|
||||
def test_CTCGreedyDecoder_no_consequent_transforms(self):
|
||||
graph = build_graph(self.nodes_attributes,
|
||||
[('logits', 'decoder', {'out': 0, 'in': 0}),
|
||||
('seq_len', 'decoder', {'out': 0, 'in': 1}),
|
||||
('decoder', 'sparse_to_dense', {'out': 0, 'in': 0}),
|
||||
('decoder', 'sparse_to_dense', {'out': 2, 'in': 1}),
|
||||
('decoder', 'cast', {'out': 1, 'in': 0}),
|
||||
('cast', 'sparse_to_dense', {'out': 0}),
|
||||
('sparse_to_dense', 'last', {'out': 0, 'in': 0}),
|
||||
], nodes_with_edges_only=True)
|
||||
graph.stage = 'front'
|
||||
CTCGreedyDecoderWithSparseToDenseShapeReplacement().find_and_replace_pattern(graph)
|
||||
CTCGreedyDecoderSingleReplacement().find_and_replace_pattern(graph)
|
||||
|
||||
graph_ref = build_graph(self.nodes_attributes,
|
||||
[('logits', 'transpose', {'out': 0, 'in': 0}),
|
||||
('order_arr', 'transpose', {'out': 0, 'in': 1}),
|
||||
('transpose', 'new_decoder', {'out': 0, 'in': 0}),
|
||||
('seq_len', 'new_decoder', {'out': 0, 'in': 1}),
|
||||
('new_decoder', 'last', {'out': 0, 'in': 0}),
|
||||
],
|
||||
nodes_with_edges_only=True)
|
||||
|
||||
(flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
@@ -0,0 +1,107 @@
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import numpy as np
|
||||
import unittest
|
||||
from argparse import Namespace
|
||||
|
||||
from extensions.front.tf.CTCLossReplacement import CTCLossReplacement
|
||||
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, const
|
||||
|
||||
|
||||
class CTCLossFrontReplacementTest(unittest.TestCase):
|
||||
nodes_attributes = {
|
||||
'logits': {'shape': int64_array([2, 6, 100]), 'type': 'Parameter', 'kind': 'op', 'op': 'Parameter'},
|
||||
'seq_mask': {'shape': int64_array([2]), 'data_type': np.int32, 'kind': 'op', 'op': 'Parameter'},
|
||||
'transpose': {'kind': 'op', 'op': 'Transpose'},
|
||||
'ctc_greedy_decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'merge_repeated': True,
|
||||
'output_sparse_format': True},
|
||||
'cast': {'kind': 'op', 'op': 'Cast'},
|
||||
'sparse_to_dense': {'kind': 'op', 'op': 'SparseToDense'},
|
||||
'tf_ctc_loss_true_logits': {'kind': 'op', 'op': 'CTCLoss', 'preprocess_collapse_repeated': False,
|
||||
'ctc_merge_repeated': True, 'unique': False, 'logits_time_major': True},
|
||||
'tf_ctc_loss_false_logits': {'kind': 'op', 'op': 'CTCLoss', 'preprocess_collapse_repeated': False,
|
||||
'ctc_merge_repeated': True, 'unique': False, 'logits_time_major': False},
|
||||
'ctc_loss': {'kind': 'op', 'op': 'CTCLoss', 'preprocess_collapse_repeated': False,
|
||||
'ctc_merge_repeated': True, 'unique': False},
|
||||
**const('default_value', int64_array(-1)),
|
||||
'last': {'type': None, 'value': None, 'kind': 'op', 'op': 'Result'},
|
||||
'transpose2': {'kind': 'op', 'op': 'Transpose'},
|
||||
**const('transpose2_axis', int64_array([1, 0, 2])),
|
||||
|
||||
'new_ctc_greedy_decoder': {'kind': 'op', 'op': 'CTCGreedyDecoderSeqLen', 'merge_repeated': True},
|
||||
}
|
||||
|
||||
def CTCLossReplacement_test_true_logits(self):
|
||||
graph = build_graph(self.nodes_attributes,
|
||||
[('logits', 'transpose', {'out': 0, 'in': 0}),
|
||||
('transpose', 'ctc_greedy_decoder', {'out': 0, 'in': 0}),
|
||||
('seq_mask', 'ctc_greedy_decoder', {'out': 0, 'in': 1}),
|
||||
('transpose', 'tf_ctc_loss_true_logits', {'out': 0, 'in': 0}),
|
||||
('seq_mask', 'tf_ctc_loss_true_logits', {'out': 0, 'in': 3}),
|
||||
('ctc_greedy_decoder', 'sparse_to_dense', {'out': 0, 'in': 0}),
|
||||
('ctc_greedy_decoder', 'sparse_to_dense', {'out': 2, 'in': 1}),
|
||||
('ctc_greedy_decoder', 'sparse_to_dense', {'out': 1, 'in': 2}),
|
||||
('default_value', 'sparse_to_dense', {'out': 0, 'in': 3}),
|
||||
('ctc_greedy_decoder', 'cast', {'out': 1, 'in': 0}),
|
||||
('ctc_greedy_decoder', 'tf_ctc_loss_true_logits', {'out': 0, 'in': 1}),
|
||||
('cast', 'tf_ctc_loss_true_logits', {'out': 0, 'in': 2}),
|
||||
('tf_ctc_loss_true_logits', 'last', {'out': 0, 'in': 0})],
|
||||
nodes_with_edges_only=True)
|
||||
graph.graph['cmd_params'] = Namespace(data_type='FP32')
|
||||
graph.stage = 'front'
|
||||
CTCLossReplacement().find_and_replace_pattern(graph)
|
||||
|
||||
graph_ref = build_graph(self.nodes_attributes,
|
||||
[('logits', 'transpose', {'out': 0, 'in': 0}),
|
||||
('transpose', 'transpose2', {'out': 0, 'in': 0}),
|
||||
('transpose2_axis', 'transpose2', {'out': 0, 'in': 1}),
|
||||
('transpose2', 'new_ctc_greedy_decoder', {'out': 0, 'in': 0}),
|
||||
('seq_mask', 'new_ctc_greedy_decoder', {'out': 0, 'in': 1}),
|
||||
('transpose2', 'ctc_loss', {'out': 0, 'in': 0}),
|
||||
('new_ctc_greedy_decoder', 'ctc_loss', {'out': 0, 'in': 2}),
|
||||
('new_ctc_greedy_decoder', 'ctc_loss', {'out': 1, 'in': 3}),
|
||||
('seq_mask', 'ctc_loss', {'out': 0, 'in': 1}),
|
||||
('ctc_loss', 'last', {'out': 0, 'in': 0})],
|
||||
nodes_with_edges_only=True)
|
||||
|
||||
(flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
|
||||
def CTCLossReplacement_test_false_logits(self):
|
||||
graph = build_graph(self.nodes_attributes,
|
||||
[('logits', 'transpose', {'out': 0, 'in': 0}),
|
||||
('transpose', 'ctc_greedy_decoder', {'out': 0, 'in': 0}),
|
||||
('seq_mask', 'ctc_greedy_decoder', {'out': 0, 'in': 1}),
|
||||
('transpose', 'tf_ctc_loss_false_logits', {'out': 0, 'in': 0}),
|
||||
('seq_mask', 'tf_ctc_loss_false_logits', {'out': 0, 'in': 3}),
|
||||
('ctc_greedy_decoder', 'sparse_to_dense', {'out': 0, 'in': 0}),
|
||||
('ctc_greedy_decoder', 'sparse_to_dense', {'out': 2, 'in': 1}),
|
||||
('ctc_greedy_decoder', 'sparse_to_dense', {'out': 1, 'in': 2}),
|
||||
('default_value', 'sparse_to_dense', {'out': 0, 'in': 3}),
|
||||
('ctc_greedy_decoder', 'cast', {'out': 1, 'in': 0}),
|
||||
('ctc_greedy_decoder', 'tf_ctc_loss_false_logits', {'out': 0, 'in': 1}),
|
||||
('cast', 'tf_ctc_loss_false_logits', {'out': 0, 'in': 2}),
|
||||
('tf_ctc_loss_false_logits', 'last', {'out': 0, 'in': 0})],
|
||||
nodes_with_edges_only=True)
|
||||
graph.graph['cmd_params'] = Namespace(data_type='FP32')
|
||||
graph.stage = 'front'
|
||||
CTCLossReplacement().find_and_replace_pattern(graph)
|
||||
|
||||
graph_ref = build_graph(self.nodes_attributes,
|
||||
[('logits', 'transpose', {'out': 0, 'in': 0}),
|
||||
('transpose', 'transpose2', {'out': 0, 'in': 0}),
|
||||
('transpose2_axis', 'transpose2', {'out': 0, 'in': 1}),
|
||||
('transpose2', 'new_ctc_greedy_decoder', {'out': 0, 'in': 0}),
|
||||
('seq_mask', 'new_ctc_greedy_decoder', {'out': 0, 'in': 1}),
|
||||
('transpose', 'ctc_loss', {'out': 0, 'in': 0}),
|
||||
('new_ctc_greedy_decoder', 'ctc_loss', {'out': 0, 'in': 2}),
|
||||
('new_ctc_greedy_decoder', 'ctc_loss', {'out': 1, 'in': 3}),
|
||||
('seq_mask', 'ctc_loss', {'out': 0, 'in': 1}),
|
||||
('ctc_loss', 'last', {'out': 0, 'in': 0})],
|
||||
nodes_with_edges_only=True)
|
||||
|
||||
(flag, resp) = compare_graphs(graph, graph_ref, 'last', check_op_attrs=True)
|
||||
self.assertTrue(flag, resp)
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
|
||||
import unittest
|
||||
|
||||
from extensions.front.sparse_to_dense_replacer import SparseToDenseReplacer
|
||||
from extensions.front.tf.sparse_to_dense_replacer import SparseToDenseReplacer
|
||||
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, const
|
||||
Reference in new issue
Block a user