* [MO] Implement EmbeddingBag_3 * Transform dynamic sub-graph of Wide and Deep into EmbeddingSegmentsSum - Expressed SparseWeightedSum sub-graph through EmbeddingSegmentsSum - Removed experimental SparseWeightedSum layer - Implemented tests for the transformation Signed-off-by: Roman Kazantsev <roman.kazantsev@intel.com> * Fix EmbeddingBag shape infer * Fix EmbeddingSegmentsSum transformation for Wide and Deep Signed-off-by: Roman Kazantsev <roman.kazantsev@intel.com> * Fix EmbeddingSegmentSum replacer after ports swap Signed-off-by: Roman Kazantsev <roman.kazantsev@intel.com> * Update package_BOM.txt Signed-off-by: Roman Kazantsev <roman.kazantsev@intel.com> * Add unit tests for EmbeddingXXX shape infer * Fix ATen resolver * Remove deleted files from BOM * Add opset version to embedding_bag * Use base class for EmbeddingBag * Fix per_sample_weights case * Fix EmbeddingSegmentsSum transformation Signed-off-by: Roman Kazantsev <roman.kazantsev@intel.com> * Fix EmbeddingBag checks * Fix ATen front transformation and merge conflicts * Fix BOM * Work around limitation for I64 input of W&D model Signed-off-by: Roman Kazantsev <roman.kazantsev@intel.com> * Cleanup where operation to fix affect of WhereDecomposition transform Signed-off-by: Roman Kazantsev <roman.kazantsev@intel.com> * Fix BOM * Correct EmbeddingSegmentSum transform for Wide and Deep Add casting segment ids to i32 and remove ConstToResult sub-graph. Signed-off-by: Roman Kazantsev <roman.kazantsev@intel.com> * Update BOM with RemoveConstToResult transform Signed-off-by: Roman Kazantsev <roman.kazantsev@intel.com> * Add more comments for RemoveConstToResult transformation Signed-off-by: Roman Kazantsev <roman.kazantsev@intel.com> * Remove useless logging in EmbeddingSegmentsSum transformation Signed-off-by: Roman Kazantsev <roman.kazantsev@intel.com> * Small fixes * Move EmbeddingBag resolving back to front phase * Improve error messages * Fix typo in unittests * Reimplement sparse_reshape middle transform Avoid deprecated API. Signed-off-by: Roman Kazantsev <roman.kazantsev@intel.com> * Clean-up graph after sparse_reshape and ConstToResult transformation Signed-off-by: Roman Kazantsev <roman.kazantsev@intel.com> * Fix clean-up for transformations Signed-off-by: Roman Kazantsev <roman.kazantsev@intel.com> * Fix clean-up for transformation #2 Signed-off-by: Roman Kazantsev <roman.kazantsev@intel.com> Co-authored-by: Roman Kazantsev <roman.kazantsev@intel.com>
80 lines
3.2 KiB
Python
80 lines
3.2 KiB
Python
"""
|
|
Copyright (C) 2018-2020 Intel Corporation
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
"""
|
|
|
|
import numpy as np
|
|
|
|
from mo.graph.graph import Graph
|
|
from mo.middle.passes.eliminate import merge_data_nodes
|
|
from mo.middle.replacement import MiddleReplacementPattern
|
|
from mo.utils.error import Error
|
|
|
|
|
|
class SparseReshapeMiddleReplacer(MiddleReplacementPattern):
|
|
"""
|
|
Removes SparseReshape operation if the old shape and the output shape are the same.
|
|
"""
|
|
enabled = True
|
|
|
|
def run_before(self):
|
|
from extensions.middle.pass_separator import MiddleFinish
|
|
return [MiddleFinish]
|
|
|
|
def pattern(self):
|
|
return dict(
|
|
nodes=[
|
|
('sparse_reshape', dict(op='SparseReshape')),
|
|
],
|
|
edges=[
|
|
])
|
|
|
|
def replace_pattern(self, graph: Graph, match: dict):
|
|
sparse_reshape = match['sparse_reshape']
|
|
|
|
input_shape_value = sparse_reshape.in_port(1).data.get_value()
|
|
output_shape_value = sparse_reshape.out_port(1).data.get_value()
|
|
|
|
# establish output shape if value of new shape is given as input
|
|
new_shape_value = sparse_reshape.in_port(2).data.get_value()
|
|
if output_shape_value is None and new_shape_value is not None:
|
|
output_shape_value = new_shape_value
|
|
if np.count_nonzero(output_shape_value == -1) == 1:
|
|
elem = np.prod(input_shape_value) // np.prod(new_shape_value[new_shape_value != -1])
|
|
output_shape_value[output_shape_value == -1] = elem
|
|
|
|
if input_shape_value is None or output_shape_value is None:
|
|
raise Error("Input shape and output shape values must be defined for node {}".format(sparse_reshape.id))
|
|
if not np.array_equal(input_shape_value, output_shape_value):
|
|
raise Error("Input shape and output shape values must be equal for node {}".format(sparse_reshape.id))
|
|
|
|
nodes_to_remove = [sparse_reshape.id]
|
|
if sparse_reshape.is_out_port_connected(0):
|
|
sparse_reshape.out_port(0).get_connection().set_source(sparse_reshape.in_port(0).get_source())
|
|
output_data_node = sparse_reshape.out_node(0)
|
|
nodes_to_remove.append(output_data_node.id)
|
|
else:
|
|
input_data_node = sparse_reshape.in_node(0)
|
|
nodes_to_remove.append(input_data_node.id)
|
|
|
|
if sparse_reshape.is_out_port_connected(1):
|
|
sparse_reshape.out_port(1).get_connection().set_source(sparse_reshape.in_port(1).get_source())
|
|
output_data_node = sparse_reshape.out_node(1)
|
|
nodes_to_remove.append(output_data_node.id)
|
|
else:
|
|
input_data_node = sparse_reshape.in_node(1)
|
|
nodes_to_remove.append(input_data_node.id)
|
|
|
|
graph.remove_nodes_from(nodes_to_remove)
|