Ejemplo n.º 1
0
    def replace_pattern(self, graph: nx.MultiDiGraph, match: dict):
        node = match['slice']
        # Caffe case
        if not node.has_valid('start') or not node.has_valid('end'):
            return

        begin = node.start
        end = node.end

        input = node.in_node(0)
        output_data = node.out_node()

        # Check whether operation use only one axis or not
        dims = 0
        axes = np.zeros(begin.size)
        for i in range(begin.size):
            if begin[i] != 0 or end[i] != input.shape[i]:
                dims += 1
                axes[i] = 1
        axes = np.array(axes, dtype=bool)
        if dims == 0:
            return
        elif dims == 1:
            # If Slice use only one axis, than
            # convert Slice to StridedSlice

            node['op'] = 'StridedSlice'
            node['type'] = 'StridedSlice'
            node['new_axis_mask'] = np.zeros(len(output_data.shape),
                                             dtype=np.bool)
            node['shrink_axis_mask'] = np.zeros(len(output_data.shape),
                                                dtype=np.bool)

            convert_negative_indices(begin, input.shape)
            convert_negative_indices(end, input.shape)
        else:
            # If Slice use more than one axis use Crop layer
            crop = Crop(
                graph,
                dict(axis=np.arange(begin.size)[axes], offset=begin[axes]))
            # creating node with data
            crop.create_node_with_data(inputs=[input],
                                       data_nodes=[output_data])

            # Remove unnecessary edges from and to to Slice vertex
            graph.remove_edge(input.id, node.id)
            graph.remove_edge(node.id, output_data.id)
Ejemplo n.º 2
0
    def replace_pattern(self, graph: Graph, match: dict):
        """
        Converts specific for NasNet topology subgraph Pad->StridedSlice->AvgPool to Conv->Crop->AvgPool
        """
        input = match['input']

        pad_op = match['pad_op']

        sslice = match['sslice']
        sslice_out = match['sslice_out']
        begin = []
        end = []
        stride = []
        for s in sslice.slices:
            begin.append(s.start)
            end.append(s.stop)
            stride.append(s.step)

        if not np.array_equal(pad_op.pads,
                              np.array([[0, 0], [0, 1], [0, 1], [0, 0]])):
            log.error(" Pad values doesn't match!")
            return

        if not np.array_equal(begin, np.array([0, 1, 1, 0])):
            log.error("StridedSlice has wrong begin")
            return

        if not np.array_equal(sslice.end_mask, np.array(
            [0, 0, 0, 0])) or not np.array_equal(sslice.begin_mask,
                                                 np.array([0, 1, 1, 0])):
            log.error("StridedSlice has wrong masks")
            return

        # Cut Smth-x->Pad->StrudedSlice-x->AvgPool
        graph.remove_edge(input.id, pad_op.id)
        graph.remove_edge(sslice.id, sslice_out.id)

        # Pad -> Conv
        conv_node = graph.unique_id(pad_op.name + '/Conv_')
        conv_weights_node = graph.unique_id(pad_op.name + '/ConvW_')
        conv_weights = np.ones((input.shape[3], 1, 1, 1))
        conv_output = graph.unique_id(pad_op.name + '/ConvOut_')
        output_shape = np.array([
            input.shape[0], input.shape[1] + 1, input.shape[2] + 1,
            input.shape[3]
        ])

        graph.add_node(
            conv_node,
            **add_attrs_props(
                dict(kind='op',
                     type='Convolution',
                     name=conv_node,
                     op='Conv2D',
                     stride=np.array([1, 1, 1, 1]),
                     dilation=np.array([1, 1, 1, 1]),
                     group=input.shape[3],
                     bias_addable=True,
                     bias_term=False,
                     spatial_dims=np.array([1, 2]),
                     kernel_spatial=np.array([1, 1]),
                     pad=np.array([[0, 0], [0, 1], [0, 1], [0, 0]]),
                     output_shape=output_shape,
                     channel_dims=np.array([3]),
                     output=input.shape[3],
                     in_ports_count=3,
                     out_ports_count=1)))

        graph.add_node(
            conv_weights_node,
            **add_attrs_props(
                dict(kind='data',
                     name=conv_weights_node,
                     value=np.array(conv_weights),
                     shape=np.array(conv_weights.shape),
                     data_type=input.data_type,
                     infer=None,
                     spatial_dims=np.array([0, 1]),
                     input_channel_dim=2,
                     output_channel_dim=3,
                     dims_number=4,
                     can_be_bias=True)))
        graph.add_node(
            conv_output,
            **add_attrs_props(
                dict(kind='data',
                     name=conv_output,
                     value=None,
                     shape=output_shape,
                     data_type=input.data_type)))

        # StridedSlice -> Crop
        crop = Crop(
            graph,
            dict(name=sslice.name + '/Crop_',
                 axis=np.array([1, 2]),
                 dim=np.array([output_shape[1] - 1, output_shape[2] - 1]),
                 offset=np.array([1, 1])))
        crop.create_node_with_data([Node(graph, conv_output)],
                                   data_nodes=sslice_out)

        # Connect : Conv->Crop->AvgPool
        graph.add_edges_from([
            (input.id, conv_node, {
                'in': 0
            }),
            (conv_weights_node, conv_node, {
                'in': 1,
                'bin': 'weights'
            }),
            (conv_node, conv_output, {
                'out': 0
            }),
        ])
        update_ie_fields(graph.node[conv_node], graph.graph['ir_version'])
Ejemplo n.º 3
0
    def replace_pattern(self, graph: Graph, match: dict):
        node = match['slice']
        # Caffe case
        if not node.has_valid('start') or not node.has_valid('end'):
            return

        begin = node.start
        end = node.end
        axis = node.axis if node.has_valid('axis') else range(begin.size)

        input = node.in_node(0)
        output_data = node.out_node()

        # Check whether operation use only one axis or not
        axes_begin = np.zeros(len(input.shape), dtype=np.int32)
        axes_end = np.zeros(len(input.shape), dtype=np.int32)
        begin_ext = np.zeros(len(input.shape), dtype=np.int32)
        end_ext = np.zeros(len(input.shape), dtype=np.int32)
        dims = 0
        axes = np.zeros(begin.size)
        for i in range(len(axis)):
            if begin[i] != 0 or end[i] < input.shape[i]:
                dims += 1
                axes[i] = 1
                if begin[i] != 0:
                    axes_begin[axis[i]] = 1
                    begin_ext[axis[i]] = begin[i]
                if end[i] < input.shape[i]:
                    axes_end[axis[i]] = 1
                    end_ext[axis[i]] = end[i]
        axes = np.array(axes, dtype=bool)

        if dims == 1 or dims == 0:
            # If Slice use only one axis or no axis, than
            # convert Slice to StridedSlice
            ss = StridedSlice(
                graph,
                dict(new_axis_mask=np.zeros(len(output_data.shape),
                                            dtype=np.int32),
                     shrink_axis_mask=np.zeros(len(output_data.shape),
                                               dtype=np.int32),
                     ellipsis_mask=np.zeros(len(output_data.shape),
                                            dtype=np.int32),
                     begin_mask=axes_begin,
                     end_mask=axes_end))

            convert_negative_indices(begin_ext, input.shape)
            convert_negative_indices(end_ext, input.shape)

            begin_node = Const(graph, {
                'name': 'begin',
                'value': begin_ext,
                'force_precision': 'I32'
            }).create_node_with_data()
            end_node = Const(graph, {
                'name': 'end',
                'value': end_ext,
                'force_precision': 'I32'
            }).create_node_with_data()

            ss.create_node_with_data(inputs=[input, begin_node, end_node],
                                     data_nodes=[output_data])
            # Remove unnecessary edges from and to to Slice vertex
            graph.remove_edge(input.id, node.id)
            graph.remove_edge(node.id, output_data.id)
        else:
            # If Slice use more than one axis use Crop layer
            crop = Crop(
                graph,
                dict(axis=np.arange(begin.size)[axes], offset=begin[axes]))
            # creating node with data
            crop.create_node_with_data(inputs=[input],
                                       data_nodes=[output_data])

            # Remove unnecessary edges from and to to Slice vertex
            graph.remove_edge(input.id, node.id)
            graph.remove_edge(node.id, output_data.id)