def insert_reduce(self, model_graph, insert_op, node, granularity, type_stat, node_name, axis=1): axis_const = self.find_axis(node, granularity, axis) if isinstance(axis_const, str): return (True, node.name) out_port = self.get_out_port(node_name) if out_port is not None: node_name = f'{node_name[0]}.{out_port}' reduce_op = create_op_node_with_second_input( node.graph, insert_op, int64_array(axis_const), dict(name=f'{type_stat}_{node_name}')) reduce_op['fullname'] = reset_node_fullname(node.fullname, reduce_op.name) if node.graph != model_graph: Op.create_data_node(reduce_op.graph, reduce_op, {'shape': [1]}) node.out_port(out_port if out_port else 0).connect( reduce_op.in_port(0)) return self.insert_result(model_graph, node, reduce_op, type_stat, out_port)
def _create_data_if_necessary(self): if self.node.graph.stage == 'front': raise Error("_create_data_if_necessary method is not applicable for front Graph phase!") if self.type == 'in': raise Error("_create_data_if_necessary method is not applicable for 'in' Port type!") if self.idx not in self.node.out_nodes(control_flow=self.control_flow): from openvino.tools.mo.ops.op import Op Op.create_data_node(self.node.graph, self.node, out_port=self.idx) self.node['need_shape_inference'] = True return self.node.out_node(self.idx, control_flow=self.control_flow)
def insert_abs_max(self, model_graph, node, type_stat, node_name, **kwargs): axis_const = self.find_axis(node, kwargs.get('granularity')) if isinstance(axis_const, str): return (True, node.name) abs_node = Abs(node.graph, { "name": f'abs_{node_name}' }).create_node_with_data([node.out_node(0)]).in_node(0) max_op = create_op_node_with_second_input( node.graph, ReduceMax, int64_array(axis_const), dict(name=f'{type_stat}_{node_name}')) if node.graph != model_graph: Op.create_data_node(max_op.graph, max_op, {'shape': [1]}) max_op['fullname'] = reset_node_fullname(node.fullname, max_op.name) abs_node.out_port(0).connect(max_op.in_port(0)) return self.insert_result(model_graph, node, max_op, type_stat)
def find_and_replace_pattern(self, graph: Graph): for node in list(graph.nodes()): node = Node(graph, node) node_name = node.soft_get('name', node.id) # Check that node layout mismatch with graph layout # For example: NHWC and NCHW or NCDHW and NDHWC if node.kind == 'op' and node.has_valid( 'layout') and node.layout != indices_mapping[len( node.layout)][graph.graph['layout']]: input = node.in_node() output = node.out_node() # Calculate permutation for further Transpose operations if graph.graph['layout'] == 'NCHW': # if Node has NCHW and graph has NHWC layout permutation = PermuteAttrs.get_nhwc_to_nchw_permutation( len(node.layout)) else: # if Node has NHWC and graph has NCHW layout permutation = PermuteAttrs.get_nchw_to_nhwc_permutation( len(node.layout)) # Schematic representation of transformation below # # \ NCHW NCHW # NHWC -- \ | permutation permutation | # data-->Convolution(example)-->data -- / | | NCHW | | # / data->Transpose->data->Convolution->data->Transpose->data # 1. Insert input Transpose # This Transpose will permute input from original input layout to operation layout edge_attrs = graph.get_edge_data(input.id, node.id)[0] graph.remove_edge(input.id, node.id) input_permute_name = node_name + '/input_transpose' input_order_const = Const( graph, { 'name': input_permute_name + '/order', 'value': permutation.perm }).create_node_with_data() input_permute_op = Transpose(graph, {'name': input_permute_name}) input_permute_data_node = input_permute_op.create_node_with_data( [input, input_order_const]) graph.add_edge(input_permute_data_node.id, node.id, **edge_attrs) # 2. Insert output Transpose # This Transpose will permute output from operation layout to original input layout edge_attrs = graph.get_edge_data(node.id, output.id)[0] graph.remove_edge(node.id, output.id) input_data_node = Op.create_data_node( graph, node, {'shape': output.shape[permutation.perm]}, edge_attrs) output_permute_name = node_name + '/output_transpose' output_order_const = Const( graph, { 'name': output_permute_name + '/order', 'value': permutation.inv }).create_node_with_data() output_permute_op = Transpose(graph, { 'name': output_permute_name }).create_node_with_data([input_data_node, output_order_const], data_nodes=output) # 3. Add permutations for Node # Here we use permutation mechanism where data nodes takes permutation attribute. # And then we call permute_attrs method that permutes node attributes according to permutations on # data nodes. node.in_node()['permutation'] = permutation node.out_node()['permutation'] = permutation node.permute_attrs.permute_attrs(node) node.in_node()['permutation'] = None node.out_node()['permutation'] = None