Beispiel #1
0
    def test_mul_add_to_power_1(self):
        graph = self._create_graph_with_mul_add(np.array([3]), np.array([2]))

        graph_ref = build_graph(nodes_attributes, [
            ('placeholder_1', 'placeholder_1_data'),
            ('placeholder_1_data', 'power_1'),
            ('power_1', 'power_1_data'),
            ('power_1_data', 'op_output'),
        ], {
            'power_1': {
                'scale': 3,
                'shift': 2,
                'power': 1
            },
            'power_1_data': {}
        })

        convert_muladd_to_scaleshift_or_power(graph)
        graph_clean_up(graph)
        (flag, resp) = compare_graphs(graph,
                                      graph_ref,
                                      'add_1_data',
                                      'power_1_data',
                                      check_op_attrs=True)
        self.assertTrue(flag, resp)
    def test_mean_to_avg_1(self):
        graph = self._create_graph_with_mean(axis=np.array([1, 2]))

        graph_ref = build_graph(
            nodes_attributes, [
                ('placeholder_1', 'placeholder_1_data'),
                ('placeholder_1_data', 'pool_1'),
                ('pool_1', 'pool_1_data'),
                ('pool_1_data', 'op_output'),
            ], {
                'pool_1': {
                    'pool_method': 'avg',
                    'rounding_type': 'ceil',
                    'exclude_pad': 'true',
                    'op': 'AvgPool',
                    'shape': np.array([1, 227, 227, 3])
                },
                'pool_1_data': {
                    'shape': np.array([1, 227, 227, 3])
                }
            })

        MeanToAvgPool().find_and_replace_pattern(graph)
        graph_clean_up(graph)
        (flag, resp) = compare_graphs(graph,
                                      graph_ref,
                                      'mean_1_data',
                                      'pool_1_data',
                                      check_op_attrs=True)
        self.assertTrue(flag, resp)
def grouped_convolutions_fusing(graph: Graph):
    while True:
        is_fused = False
        graph_clean_up(graph, ['TFCustomSubgraphCall', 'ShapeOf', 'Shape'])
        for node in graph.pseudo_topological_sort():
            if node.kind == 'op' and len(node.out_nodes()) > 1:
                if node.soft_get('can_be_fused') == False:
                    continue

                is_valid_convolutions = True
                last_layer = None

                next_nodes = get_next_operation(node)
                # Check that all operation after this one are Convolutions
                # and all convolutions has same output
                if len(next_nodes) > 1 and all(_node.soft_get('type') in ['Convolution', 'Deconvolution'] for _node in next_nodes):
                    for conv in next_nodes:
                        conv_outputs = get_next_operation(conv)
                        if conv.soft_get('can_be_fused') == False:
                            is_valid_convolutions = False
                        if len(conv_outputs) != 1:
                            is_valid_convolutions = False
                        if last_layer is None:
                            last_layer = conv_outputs[0].id
                        elif conv_outputs[0].id != last_layer:
                            is_valid_convolutions = False

                    if is_valid_convolutions:
                        is_fused = concat_convolutions(graph, node, Node(graph, last_layer))
                        if is_fused:
                            break

        if not is_fused:
            break
Beispiel #4
0
    def test_mul_add_neg_5(self):
        graph = self._create_graph_with_mul_add(np.array([3]),
                                                np.array([3, 2, 1]))
        graph_ref = build_graph(
            nodes_attributes, [
                ('placeholder_1', 'placeholder_1_data'),
                ('placeholder_1_data', 'scaleshift_1'),
                ('scaleshift_1_w', 'scaleshift_1'),
                ('scaleshift_1_b', 'scaleshift_1'),
                ('scaleshift_1', 'add_1_data'),
            ], {
                'scaleshift_1_w': {
                    'shape': np.array([3]),
                    'value': np.array([3, 3, 3])
                },
                'scaleshift_1_b': {
                    'shape': np.array([3]),
                    'value': np.array([3, 2, 1])
                },
                'add_1_data': {
                    'is_output': True
                }
            })

        convert_muladd_to_scaleshift_or_power(graph)
        graph_clean_up(graph)
        (flag, resp) = compare_graphs(graph,
                                      graph_ref,
                                      'add_1_data',
                                      'add_1_data',
                                      check_op_attrs=True)
        self.assertTrue(flag, resp)
    def test_variadic_split_non_zero(self):
        graph = build_graph(nodes_attributes,
                            [('placeholder_1', 'placeholder_data'), ('placeholder_data', 'variadic_split'),
                             ('variadic_split', 'variadic_split_data_1'), ('variadic_split_data_1', 'last'),
                             ('last', 'last_data'), ('last_data', 'res'),

                             ('axis_const', 'axis_const_data'),
                             ('split_dim_const', 'split_dim_const_data'),
                             ('axis_const_data', 'variadic_split', {'in': 1}),
                             ('split_dim_const_data', 'variadic_split', {'in': 2}),
                             ], nodes_with_edges_only=True)
        node = Node(graph, 'variadic_split')

        # extractor should do it
        node['out_ports_count'] = 3
        for p in range(len(node.out_edges()), node.out_ports_count):
            node.add_output_port(p)

        replacer = AddFakeOutputsToVariadicSplit()
        replacer.find_and_replace_pattern(graph)

        for n in graph.get_op_nodes():
            n['need_shape_inference'] = False
        graph_clean_up(graph)

        self.assertTrue(len(node.out_edges()) == 3)
Beispiel #6
0
    def test_scaleshift2_axis1_to_mul(self):
        graph = build_graph(
            nodes_attributes, [
                ('placeholder_1', 'placeholder_1_data'),
                ('placeholder_2', 'placeholder_2_data'),
                ('placeholder_1_data', 'scaleshift_1'),
                ('placeholder_2_data', 'scaleshift_1'),
                ('scaleshift_1', 'scaleshift_1_data'),
            ], {
                'placeholder_1_data': {
                    'shape': np.array([1, 227, 227, 3])
                },
                'placeholder_2_data': {
                    'shape': np.array([227])
                },
                'scaleshift_1': {
                    'axis': 1
                },
                'scaleshift_1_data': {
                    'is_output': True
                }
            })

        graph_ref = build_graph(
            nodes_attributes, [
                ('placeholder_1', 'placeholder_1_data'),
                ('placeholder_2', 'placeholder_2_data'),
                ('placeholder_2_data', 'placeholder_2/Reshape_'),
                ('placeholder_2/Reshape_', 'placeholder_2/Reshape_data'),
                ('placeholder_1_data', 'mul_1'),
                ('placeholder_2/Reshape_data', 'mul_1'),
                ('mul_1', 'scaleshift_1_data'),
            ], {
                'placeholder_1_data': {
                    'shape': np.array([1, 227, 227, 3])
                },
                'placeholder_2_data': {
                    'shape': np.array([227])
                },
                'placeholder_2/Reshape_': {
                    'dim': np.array([1, 227, 1, 1])
                },
                'placeholder_2/Reshape_data': {
                    'shape': np.array([1, 227, 1, 1])
                },
                'mul_1': {
                    'can_be_fused': True
                },
                'scaleshift_1_data': {
                    'is_output': True
                }
            })

        graph.graph['layout'] = 'NHWC'
        convert_scale_shift_to_mul_add(graph)
        graph_clean_up(graph)
        (flag, resp) = compare_graphs(graph, graph_ref, 'scaleshift_1_data')
        self.assertTrue(flag, resp)
Beispiel #7
0
    def test_scaleshift_to_mul_2(self):
        graph = build_graph(
            nodes_attributes, [('placeholder_1', 'placeholder_1_data'),
                               ('placeholder_1_data', 'scaleshift_1'),
                               ('const_scaleshift_1_w', 'scaleshift_1_w'),
                               ('const_scaleshift_1_b', 'scaleshift_1_b'),
                               ('scaleshift_1_w', 'scaleshift_1'),
                               ('scaleshift_1_b', 'scaleshift_1'),
                               ('scaleshift_1', 'scaleshift_1_data'),
                               ('scaleshift_1_data', 'op_output')], {
                                   'placeholder_1_data': {
                                       'shape': np.array([1, 227, 227, 3])
                                   },
                                   'scaleshift_1_w': {
                                       'shape': np.array([3]),
                                       'value': np.array([1, 2, 3])
                                   },
                                   'scaleshift_1_b': {
                                       'shape': np.array([3]),
                                       'value': np.array([0, 0, 0])
                                   },
                                   'scaleshift_1_data': {}
                               })

        graph_ref = build_graph(
            nodes_attributes, [('placeholder_1', 'placeholder_1_data'),
                               ('placeholder_1_data', 'mul_1'),
                               ('const_mul_1_w', 'mul_1_w'),
                               ('mul_1_w', 'mul_1'),
                               ('mul_1', 'scaleshift_1_data'),
                               ('scaleshift_1_data', 'op_output')], {
                                   'placeholder_1_data': {
                                       'shape': np.array([1, 227, 227, 3])
                                   },
                                   'const_mul_1_w': {
                                       'shape': np.array([3]),
                                       'value': np.array([1, 2, 3])
                                   },
                                   'mul_1_w': {
                                       'shape': np.array([3]),
                                       'value': np.array([1, 2, 3])
                                   },
                                   'mul_1': {
                                       'can_be_fused': True
                                   },
                                   'scaleshift_1_data': {}
                               })

        graph.graph['layout'] = 'NHWC'
        convert_scale_shift_to_mul_add(graph)
        graph_clean_up(graph)
        (flag, resp) = compare_graphs(graph, graph_ref, 'placeholder_1')
        self.assertTrue(flag, resp)
Beispiel #8
0
    def test_mul_to_scaleshift_1(self):
        graph = AddToScaleShift._create_graph_with_mul(
            np.array([1, 2, 3], dtype=np.float32))
        graph.stage = 'middle'

        graph_ref = build_graph(nodes_attributes,
                                [('placeholder_1', 'placeholder_1_data'),
                                 ('placeholder_1_data', 'scaleshift_1'),
                                 ('const_scaleshift_1_w', 'scaleshift_1_w'),
                                 ('const_scaleshift_1_b', 'scaleshift_1_b'),
                                 ('scaleshift_1_w', 'scaleshift_1'),
                                 ('scaleshift_1_b', 'scaleshift_1'),
                                 ('scaleshift_1', 'scaleshift_1_data'),
                                 ('scaleshift_1_data', 'op_output')], {
                                     'placeholder_1_data': {
                                         'shape': np.array([1, 227, 227, 3])
                                     },
                                     'scaleshift_1_data': {
                                         'shape': np.array([1, 227, 227, 3])
                                     },
                                     'const_scaleshift_1_w': {
                                         'shape': np.array([3]),
                                         'value': np.array([1, 2, 3])
                                     },
                                     'scaleshift_1_w': {
                                         'shape': np.array([3]),
                                         'value': np.array([1, 2, 3])
                                     },
                                     'const_scaleshift_1_b': {
                                         'shape': np.array([3]),
                                         'value': np.array([0, 0, 0])
                                     },
                                     'scaleshift_1_b': {
                                         'shape': np.array([3]),
                                         'value': np.array([0, 0, 0])
                                     },
                                 },
                                nodes_with_edges_only=True)

        convert_add_or_mul_to_scaleshift(graph)
        graph_clean_up(graph)

        (flag, resp) = compare_graphs(graph, graph_ref, 'op_output')
        self.assertTrue(flag, resp)

        scsh_node = Node(graph, 'op_output').in_port(0).get_source().node

        self.assertTrue(
            graph.get_edge_data(scsh_node.in_node(1).id, scsh_node.id)[0]
            ['bin'] == 'weights')
        self.assertTrue(
            graph.get_edge_data(scsh_node.in_node(2).id, scsh_node.id)[0]
            ['bin'] == 'biases')
Beispiel #9
0
    def test_mul_add_neg_3(self):
        graph = self._create_graph_with_mul_add(None, None)
        graph_ref = self._create_graph_with_mul_add(None, None)

        convert_muladd_to_scaleshift_or_power(graph)
        graph_clean_up(graph)
        (flag, resp) = compare_graphs(graph,
                                      graph_ref,
                                      'add_1_data',
                                      'add_1_data',
                                      check_op_attrs=True)
        self.assertTrue(flag, resp)
Beispiel #10
0
def driver(argv, input_model, output_model_name, output_dir):
    meta_info = get_meta_info(argv)

    EltwiseChecker.enabled = False

    try:
        graph, input_shapes = load_kaldi_model(input_model)
    except Exception as e:
        raise Error('Model Optimizer is not able to read Kaldi model {}. '.format(input_model) +
                    refer_to_faq_msg(91)) from e
    graph.check_empty_graph('load_kaldi_nnet_model')
    graph.graph['cmd_params'] = argv
    graph.graph['fw'] = 'kaldi'
    graph.graph['ir_version'] = 2 if argv.generate_deprecated_IR_V2 else 5
    update_extractors_with_extensions(kaldi_type_extractors)
    extract_node_attrs(graph, lambda node: kaldi_extractor(node))

    # --------------------------------- LOAD END ------------------------------------------------------
    class_registration.apply_replacements(graph, class_registration.ClassType.FRONT_REPLACER)

    graph = partial_infer(graph)

    # The order is intentional, firstly eliminate repeated, then remove redundant
    FuseRepeatedReshapes().find_and_replace_pattern(graph)
    EliminateRedundantReshape().find_and_replace_pattern(graph)
    graph.check_empty_graph('partial_infer')
    if argv.counts:
        try:
            counts = read_counts_file(argv.counts)
        except Exception as e:
            raise Error('Model Optimizer is not able to read counts file {}'.format(argv.counts) +
                        refer_to_faq_msg(92)) from e

        apply_biases_to_last_layer(graph, counts)

    if argv.remove_output_softmax:
        RemoveLastSoftMaxPattern().find_and_replace_pattern(graph)
        graph_clean_up(graph)
        log.debug("After removing softmax")
        graph.print_graph_stat()

    # Intentionally after all transformations
    KaldiRemoveMemoryOutputBackReplacementPattern().find_and_replace_pattern(graph)

    remove_const_ops(graph)
    CreateConstNodesReplacement().find_and_replace_pattern(graph)

    remove_output_ops(graph)

    prepare_emit_ir(graph, argv.data_type, output_dir, output_model_name, meta_info=meta_info)
    return 0
Beispiel #11
0
    def test_mark_ops_producing_constant_values(self):
        """
        Checks case when operation produces only constant tensors so it could be removed. If the node produces several
        tensors and at least one of them is not constant then we should not mark this node.
        The graph contains data nodes.
        "data_node_2" and "data_node_5" are output.
        "node_3" produces constant tensor "data_node_3" and non-constant tensor "data_node_3_2".
        "node_6" produces constant tensor "data_node_6".
        "node_4" could be eliminated since it gets constant input.

                             node_6->data_node_6->
                                                  \
        placeholder_1->placeholder_1_data_node->node_1->data_node_1->node_2->data_node_2
                                                  /
        node_3->data_node_3->node_4->data_node_4->
           \
            ->data_node_3_2->node_5->data_node_5

        :return: None
        """
        graph = build_graph(nodes_attributes,
                            [('placeholder_1', 'placeholder_1_data_node'),
                             ('placeholder_1_data_node', 'node_1'),
                             ('node_1', 'data_node_1'),
                             ('data_node_1', 'node_2'),
                             ('node_2', 'data_node_2'),
                             ('node_3', 'data_node_3'),
                             ('node_3', 'data_node_3_2'),
                             ('node_6', 'data_node_6'),
                             ('data_node_6', 'node_1'),
                             ('data_node_3_2', 'node_5'),
                             ('node_5', 'data_node_5'),
                             ('data_node_3', 'node_4'),
                             ('data_node_4', 'node_1'),
                             ('data_node_2', 'op_output'),
                             ('data_node_5', 'op_output_1')
                             ],
                            {'data_node_2': {},
                             'data_node_5': {},
                             'data_node_3': {'value': np.array(1)},
                             'data_node_6': {'value': np.array(1)}},
                            nodes_with_edges_only=True)
        mark_const_producer_nodes(graph)
        self.assertTrue((graph.node['node_6']['is_const_producer']))
        self.assertListEqual(sorted(['node_1', 'node_2', 'node_3', 'node_5', 'placeholder_1']),
                             sorted(graph.get_nodes_with_attributes(is_const_producer=False, kind='op')))

        graph_clean_up(graph)
        self.assertTrue('node_3' in graph.nodes())
        self.assertTrue('node_4' not in graph.nodes())
        self.assertTrue('node_6' not in graph.nodes())
Beispiel #12
0
    def test_mul_add_neg_4(self):
        graph = self._create_graph_with_mul_add(np.array([1, 2, 3]),
                                                np.array([3]))
        graph_ref = self._create_graph_with_mul_add(np.array([1, 2, 3]),
                                                    np.array(3))

        convert_muladd_to_scaleshift_or_power(graph)
        graph_clean_up(graph)
        (flag, resp) = compare_graphs(graph,
                                      graph_ref,
                                      'add_1_data',
                                      'add_1_data',
                                      check_op_attrs=True)
        self.assertTrue(flag, resp)
Beispiel #13
0
 def test_output_port_cut(self, output):
     nodes = {'A': {'op': 'Placeholder', 'kind': 'op'},
              'B': {'op': 'Placeholder', 'kind': 'op'},
              'C': {'type': 'Identity', 'kind': 'op'},
              'D': {'type': 'Identity', 'kind': 'op'},
              'E': {'type': 'Identity', 'kind': 'op'},
              }
     edges = [
         ('A', 'C', {'in': 0, 'out': 0}),
         ('B', 'C', {'in': 1, 'out': 0}),
         ('C', 'D', {'in': 0, 'out': 0}),
         ('C', 'E', {'in': 0, 'out': 1})
     ]
     graph = build_graph_with_edge_attrs(nodes, edges)
     sinks = add_output_ops(graph, output)
     eliminate.graph_clean_up(graph)
     self.assertEqual(len(graph.nodes()), 2)
    def test_duplicate_shared_weights_1(self):
        graph = build_graph(nodes_attributes, [
            ('const', 'mul_1_w'), ('mul_1_w', 'mul_1'),
            ('mul_1', 'mul_1_data'), ('mul_1_w', 'mul_2'),
            ('mul_2', 'mul_2_data'), ('mul_1_w', 'mul_3'),
            ('mul_3', 'mul_3_data'), ('mul_1_data', 'concat_1'),
            ('mul_2_data', 'concat_1'), ('mul_3_data', 'concat_1'),
            ('concat_1', 'concat_1_data'), ('concat_1_data', 'op_output')
        ], {'mul_1_w': {
            'shape': np.array([3]),
            'value': np.array([1, 2, 3])
        }},
                            nodes_with_edges_only=True)

        graph_ref = build_graph(nodes_attributes,
                                [('mul_1_w', 'mul_1'), ('mul_1', 'mul_1_data'),
                                 ('mul_2_w', 'mul_2'), ('mul_2', 'mul_2_data'),
                                 ('mul_3_w', 'mul_3'), ('mul_3', 'mul_3_data'),
                                 ('mul_1_data', 'concat_1'),
                                 ('mul_2_data', 'concat_1'),
                                 ('mul_3_data', 'concat_1'),
                                 ('concat_1', 'concat_1_data'),
                                 ('concat_1_data', 'op_output')], {
                                     'mul_1_w': {
                                         'shape': np.array([3]),
                                         'value': np.array([1, 2, 3])
                                     },
                                     'mul_2_w': {
                                         'shape': np.array([3]),
                                         'value': np.array([1, 2, 3])
                                     },
                                     'mul_3_w': {
                                         'shape': np.array([3]),
                                         'value': np.array([1, 2, 3])
                                     },
                                 },
                                nodes_with_edges_only=True)

        SharedWeightsDuplication().find_and_replace_pattern(graph)
        graph_clean_up(graph)
        graph_clean_up(graph_ref)
        (flag, resp) = compare_graphs(graph, graph_ref, 'concat_1_data')
        self.assertTrue(flag, resp)
Beispiel #15
0
    def test_mean_to_avg_2(self):
        graph = self._create_graph_with_mean(axis=np.array([0]), keep_dims=False,
                                             mean_out_shape=np.array([227, 227, 3]))

        graph_ref = build_graph(nodes_attributes,
                                [('placeholder_1', 'placeholder_1_data'),
                                 ('placeholder_1_data', 'pool_1'),
                                 ('pool_1', 'pool_1_data'),
                                 ('pool_1_data', 'reshape_1'),
                                 ('reshape_1', 'reshape_1_data')
                                 ],
                                {'pool_1': {'pool_method': 'avg', 'rounding_type': 'ceil', 'exclude_pad': 'true',
                                            'op': 'AvgPool', 'shape': np.array([1, 227, 227, 3])},
                                 'pool_1_data': {'shape': np.array([1, 227, 227, 3])},
                                 'reshape_1_data': {'is_output': True, 'shape': np.array([227, 227, 3])},
                                 })

        mean_to_avgpool(graph)
        graph_clean_up(graph)
        (flag, resp) = compare_graphs(graph, graph_ref, 'mean_1_data', 'reshape_1_data', check_op_attrs=True)
        self.assertTrue(flag, resp)
Beispiel #16
0
    def test_scaleshift_to_nothing(self):
        graph = build_graph(nodes_attributes,
                            [('placeholder_1', 'placeholder_1_data'),
                             ('placeholder_1_data', 'scaleshift_1'),
                             ('const_scaleshift_1_w', 'scaleshift_1_w'),
                             ('const_scaleshift_1_b', 'scaleshift_1_b'),
                             ('scaleshift_1_w', 'scaleshift_1'),
                             ('scaleshift_1_b', 'scaleshift_1'),
                             ('scaleshift_1', 'scaleshift_1_data'),
                             ('scaleshift_1_data', 'op_output')], {
                                 'placeholder_1_data': {
                                     'shape': np.array([1, 227, 227, 3])
                                 },
                                 'scaleshift_1_w': {
                                     'shape': np.array([3]),
                                     'value': np.array([1, 1, 1])
                                 },
                                 'scaleshift_1_b': {
                                     'shape': np.array([3]),
                                     'value': np.array([0, 0, 0])
                                 },
                                 'scaleshift_1_data': {
                                     'shape': np.array([1, 227, 227, 3])
                                 }
                             },
                            nodes_with_edges_only=True)

        graph_ref = build_graph(
            nodes_attributes, [('placeholder_1', 'placeholder_1_data'),
                               ('placeholder_1_data', 'op_output')],
            {'placeholder_1_data': {
                'shape': np.array([1, 227, 227, 3])
            }},
            nodes_with_edges_only=True)

        graph.graph['layout'] = 'NHWC'
        convert_scale_shift_to_mul_add(graph)
        graph_clean_up(graph)
        (flag, resp) = compare_graphs(graph, graph_ref, 'placeholder_1')
        self.assertTrue(flag, resp)
Beispiel #17
0
def driver(argv: argparse.Namespace,
           proto_file_name: str,
           model_file_name: str,
           output_model_name: str,
           output_dir: str,
           caffe_proto_path: str,
           mean_file: str = "",
           mean_file_offsets: tuple = None,
           custom_layers_mapping_path: str = None):
    log_step(argv.steps, 'LOAD')
    meta_info = get_meta_info(argv)

    caffe_pb2 = loader.import_caffe_pb2(caffe_proto_path)

    proto, model = loader.load_caffe_proto_model(caffe_pb2, proto_file_name,
                                                 model_file_name)

    update_extractors_with_extensions(
        caffe_type_extractors, argv.disable_omitting_optional if hasattr(
            argv, 'disable_omitting_optional') else False,
        argv.disable_flattening_optional_params if hasattr(
            argv, 'disable_flattening_optional_params') else False)

    try:
        graph, original_shapes = loader.caffe_pb_to_nx(proto, model)
    except ValueError as e:
        raise Error(
            'Invalid prototxt file: value error {}. ' + refer_to_faq_msg(11),
            str(e)) from e

    log.debug("After caffe_pb_to_nx")
    graph.print_graph_stat()
    graph.check_empty_graph('load_caffe_proto_model')

    graph.__setattr__('proto_path', proto_file_name)
    graph.__setattr__('caffemodel_path', model_file_name)
    graph.__setattr__('name',
                      getattr(proto, 'name', None) or output_model_name)
    graph.graph['layout'] = 'NCHW'
    graph.graph['cmd_params'] = argv
    graph.graph['fw'] = 'caffe'
    if graph.graph['cmd_params'].generate_experimental_IR_V10:
        version = 10
    else:
        version = 6
    graph.graph[
        'ir_version'] = 2 if argv.generate_deprecated_IR_V2 else version

    custom_layers_map = custom_layers_mapping.load_layers_xml(
        custom_layers_mapping_path)
    custom_layers_mapping.update_extractors(
        caffe_type_extractors,
        custom_layers_map, argv.disable_omitting_optional if hasattr(
            argv, 'disable_omitting_optional') else False,
        argv.enable_flattening_nested_params if hasattr(
            argv, 'enable_flattening_nested_params') else False)
    extract_node_attrs(
        graph, lambda node: caffe_extractor(
            node, check_for_duplicates(caffe_type_extractors)))

    # --------------------------------- LOAD END ------------------------------------------------------
    log_step(argv.steps, 'FRONT')
    class_registration.apply_replacements(
        graph, class_registration.ClassType.FRONT_REPLACER)
    log_step(argv.steps, 'MIDDLE')
    class_registration.apply_replacements(
        graph, class_registration.ClassType.MIDDLE_REPLACER)

    # Mark nodes with attr 'can_be_fused': False to disable fusing for specified nodes
    mark_unfused_nodes(graph, argv.finegrain_fusing)

    # need this pass even without fusing to convert scale with 2 inputs
    convert_scale_shift_to_mul_add(graph)
    graph_clean_up(graph)

    if not argv.disable_fusing:
        convert_bn_to_mul_add(graph)
        graph_clean_up(graph)

        fuse_mul_add_sequence(graph)
        graph_clean_up(graph)

        fuse_linear_ops(graph)
        graph_clean_up(graph)

    if not argv.disable_resnet_optimization:
        stride_optimization(graph)

    convert_muladd_to_scaleshift(graph)
    convert_matmul_to_fully_connected(graph)
    batch_norm_fuse(graph)
    convert_add_or_mul_to_scaleshift(graph)  # scale = 1
    graph_clean_up(graph)

    log.debug("After graph_cleanup")
    graph.print_graph_stat()

    if argv.reverse_input_channels:
        reverse_input_channels(graph)

    if argv.move_to_preprocess:
        move_scaleshift_to_preprocess(graph)
        graph_clean_up(graph)

    FuseReshapesSequence().find_and_replace_pattern(graph)
    RemoveRedundantReshapes().find_and_replace_pattern(graph)

    input_names = find_inputs(graph)
    mf = []
    try:
        if mean_file and len(original_shapes) == 1:
            mf = loader.parse_mean(mean_file, original_shapes[input_names[0]],
                                   mean_file_offsets, caffe_pb2)
        elif mean_file:
            raise Error(
                'Mean file for topologies with multiple inputs is not supported. '
                + refer_to_faq_msg(9))
    except ValueError as e:
        raise Error(
            'Cannot load or process mean file: value error {}. ' +
            refer_to_faq_msg(10), str(e)) from e

    merge_nodes_permutations(graph)
    permute_data_nodes_attrs(graph)
    permute_op_nodes_attrs(graph)

    graph_clean_up(graph)
    log_step(argv.steps, 'BACK')
    class_registration.apply_replacements(
        graph, class_registration.ClassType.BACK_REPLACER)

    remove_const_ops(graph)
    CreateConstNodesReplacement().find_and_replace_pattern(graph)

    remove_output_ops(graph)
    log_step(argv.steps, 'EMIT')
    prepare_emit_ir(graph=graph,
                    data_type=argv.data_type,
                    output_dir=output_dir,
                    output_model_name=output_model_name,
                    mean_data=mf,
                    input_names=input_names,
                    meta_info=meta_info)
    return 0
Beispiel #18
0
    def test_bn_decomposition_1(self):
        graph = build_graph(
            nodes_attributes, [('placeholder_1', 'placeholder_1_data'),
                               ('placeholder_1_data', 'bn_op'),
                               ('bn_const', 'bn_op'), ('bn_beta', 'bn_op'),
                               ('bn_mean', 'bn_op'), ('bn_var', 'bn_op'),
                               ('bn_op', 'bn_data'), ('concat', 'concat_data'),
                               ('bn_data', 'concat')], {
                                   'placeholder_1_data': {
                                       'shape': np.array([1, 227, 227, 3])
                                   },
                                   'bn_op': {
                                       'eps': 1.2
                                   },
                                   'bn_const': {
                                       'shape': np.array([3]),
                                       'value': np.array([1, 2, 3])
                                   },
                                   'bn_beta': {
                                       'shape': np.array([3]),
                                       'value': np.array([1, 2, 3])
                                   },
                                   'bn_mean': {
                                       'shape': np.array([3]),
                                       'value': np.array([1, 2, 3])
                                   },
                                   'bn_var': {
                                       'shape': np.array([3]),
                                       'value': np.array([1, 2, 3])
                                   },
                                   'bn_data': {
                                       'shape': np.array([1, 227, 227, 3])
                                   },
                                   'concat_data': {
                                       'is_output': True
                                   }
                               })

        graph_ref = build_graph(
            nodes_attributes,
            [('placeholder_1', 'placeholder_1_data'),
             ('placeholder_1_data', 'mul_1'), ('mul_1_w', 'mul_1'),
             ('mul_1', 'mul_1_data'), ('mul_1_data', 'add_1'),
             ('add_1_w', 'add_1'), ('add_1', 'add_1_data'),
             ('add_1_data', 'mul_2'), ('mul_2_w', 'mul_2'),
             ('mul_2', 'mul_2_data'), ('mul_2_data', 'add_2'),
             ('add_2_w', 'add_2'), ('add_2', 'add_2_data'),
             ('concat', 'concat_data'), ('add_2_data', 'concat')], {
                 'placeholder_1_data': {
                     'shape': np.array([1, 227, 227, 3])
                 },
                 'mul_1_w': {
                     'shape': np.array([3]),
                     'value': np.array([0.67419986, 0.55901699, 0.48795004])
                 },
                 'mul_2_w': {
                     'shape': np.array([3]),
                     'value': np.array([1, 2, 3])
                 },
                 'add_1_w': {
                     'shape': np.array([3]),
                     'value': np.array([-0.67419986, -1.11803399, -1.46385011])
                 },
                 'add_2_w': {
                     'shape': np.array([3]),
                     'value': np.array([1, 2, 3])
                 },
                 'add_2_data': {
                     'shape': np.array([1, 227, 227, 3])
                 },
                 'mul_1': {
                     'can_be_fused': True
                 },
                 'mul_2': {
                     'can_be_fused': True
                 },
                 'add_1': {
                     'can_be_fused': True
                 },
                 'add_2': {
                     'can_be_fused': True
                 },
                 'concat_data': {
                     'is_output': True
                 }
             })

        graph.graph['layout'] = 'NHWC'
        convert_batch_norm(graph)
        graph_clean_up(graph)

        (flag, resp) = compare_graphs(graph, graph_ref, 'concat_data')
        self.assertTrue(flag, resp)
Beispiel #19
0
    def test_caffe_bn_decomposition_2(self):
        graph = build_graph(
            nodes_attributes, [('placeholder_1', 'placeholder_1_data'),
                               ('placeholder_1_data', 'bn_op'),
                               ('bn_mean', 'bn_op'), ('bn_var', 'bn_op'),
                               ('bn_op', 'bn_data'), ('concat', 'concat_data'),
                               ('bn_data', 'concat')], {
                                   'placeholder_1_data': {
                                       'shape': np.array([1, 227, 227, 3])
                                   },
                                   'bn_op': {
                                       'epsilon': 1.2,
                                       'op': 'BatchNormalization',
                                       'can_be_fused': False
                                   },
                                   'bn_mean': {
                                       'shape': np.array([3]),
                                       'value': np.array([1, 2, 3])
                                   },
                                   'bn_var': {
                                       'shape': np.array([3]),
                                       'value': np.array([1, 2, 3])
                                   },
                                   'bn_data': {
                                       'shape': np.array([1, 227, 227, 3])
                                   },
                                   'concat_data': {
                                       'is_output': True
                                   }
                               })

        del graph['placeholder_1']['placeholder_1_data'][0]['in']
        del graph['bn_op']['bn_data'][0]['in']

        graph_ref = build_graph(
            nodes_attributes, [('placeholder_1', 'placeholder_1_data'),
                               ('placeholder_1_data', 'mul_1'),
                               ('mul_1_w', 'mul_1'), ('mul_1', 'mul_1_data'),
                               ('mul_1_data', 'add_1'), ('add_1_w', 'add_1'),
                               ('add_1', 'add_1_data'),
                               ('concat', 'concat_data'),
                               ('add_1_data', 'concat')],
            {
                'placeholder_1_data': {
                    'shape': np.array([1, 227, 227, 3])
                },
                'mul_1_w': {
                    'shape': np.array([3]),
                    'value': np.array([0.67419986, 0.55901699, 0.48795004])
                },
                'add_1_w': {
                    'shape': np.array([3]),
                    'value': np.array([-0.67419986, -1.11803399, -1.46385011])
                },
                'add_1_data': {
                    'shape': np.array([1, 227, 227, 3])
                },
                'mul_1': {
                    'can_be_fused': False
                },
                'add_1': {
                    'can_be_fused': False
                },
                'concat_data': {
                    'is_output': True
                }
            })

        graph.graph['layout'] = 'NHWC'
        convert_bn_to_mul_add(graph)
        graph_clean_up(graph)

        (flag, resp) = compare_graphs(graph, graph_ref, 'concat_data')
        self.assertTrue(flag, resp)
Beispiel #20
0
    def test_scaleshift_can_be_fused(self):
        graph = build_graph(
            nodes_attributes, [
                ('placeholder_1', 'placeholder_1_data'),
                ('placeholder_1_data', 'scaleshift_1'),
                ('scaleshift_1_w', 'scaleshift_1'),
                ('scaleshift_1_b', 'scaleshift_1'),
                ('scaleshift_1', 'scaleshift_1_data'),
            ], {
                'placeholder_1_data': {
                    'shape': np.array([1, 227, 227, 3])
                },
                'scaleshift_1_w': {
                    'shape': np.array([3]),
                    'value': np.array([1, 1, 1])
                },
                'scaleshift_1_b': {
                    'shape': np.array([3]),
                    'value': np.array([0, 0, 0])
                },
                'scaleshift_1': {
                    'can_be_fused': False
                },
                'scaleshift_1_data': {
                    'shape': np.array([1, 227, 227, 3]),
                    'is_output': True
                }
            })

        graph_ref = build_graph(
            nodes_attributes, [
                ('placeholder_1', 'placeholder_1_data'),
                ('placeholder_1_data', 'scaleshift_1'),
                ('scaleshift_1_w', 'scaleshift_1'),
                ('scaleshift_1_b', 'scaleshift_1'),
                ('scaleshift_1', 'scaleshift_1_data'),
            ], {
                'placeholder_1_data': {
                    'shape': np.array([1, 227, 227, 3])
                },
                'scaleshift_1_w': {
                    'shape': np.array([3]),
                    'value': np.array([1, 1, 1])
                },
                'scaleshift_1_b': {
                    'shape': np.array([3]),
                    'value': np.array([0, 0, 0])
                },
                'scaleshift_1': {
                    'can_be_fused': False
                },
                'scaleshift_1_data': {
                    'shape': np.array([1, 227, 227, 3]),
                    'is_output': True
                }
            })

        convert_scale_shift_to_mul_add(graph)
        graph_clean_up(graph)

        (flag, resp) = compare_graphs(graph, graph_ref, 'scaleshift_1_data')
        self.assertTrue(flag, resp)
Beispiel #21
0
def driver(argv: argparse.Namespace, input_model: str, output_model_name: str,
           output_dir: str):
    meta_info = get_meta_info(argv)

    try:
        model_nodes, model_params, model_name, iteration_number = load_symbol_def(
            input_model, argv.input_symbol, argv.input, argv.nd_prefix_name,
            argv.pretrained_model_name, argv.legacy_mxnet_model)
    except (ValueError, mxnet.base.MXNetError) as e:
        raise FrameworkError(
            'The following error happened while loading mxnet model {}: {}. ' +
            refer_to_faq_msg(53), input_model, str(e)) from e

    if argv.nd_prefix_name and argv.pretrained_model_name and argv.save_params_from_nd:
        save_params_file(model_name, model_params._arg_params,
                         model_params._aux_params, iteration_number)

    update_extractors_with_extensions(mxnet_op_extractors)
    graph = symbol2nx(model_nodes, model_params, argv.input)
    graph.check_empty_graph(
        'symbol2nx. It may happen due to problems with loaded model')

    graph.__setattr__('name', output_model_name)
    graph.graph['layout'] = 'NCHW'
    graph.graph['cmd_params'] = argv
    graph.graph['fw'] = 'mxnet'
    graph.graph['feature_dim'] = 1 if graph.graph['layout'] == 'NCHW' else 3
    graph.graph['ir_version'] = 2 if argv.generate_deprecated_IR_V2 else 5
    extract_node_attrs(graph, mxnet_op_extractor)

    # --------------------------------- LOAD END ------------------------------------------------------
    class_registration.apply_replacements(
        graph, class_registration.ClassType.FRONT_REPLACER)
    class_registration.apply_replacements(
        graph, class_registration.ClassType.MIDDLE_REPLACER)

    fuse_pad(graph)

    # Mark nodes with attr 'can_be_fused': False to disable fusing for specified nodes
    mark_unfused_nodes(graph, argv.finegrain_fusing)

    # Converting FusedBatchNorm layer to Mul->Add->Mul->Add sequence
    convert_batch_norm(graph)
    graph_clean_up(graph)

    if not argv.disable_fusing:
        # Converting ScaleShift layer to Mul->Add
        convert_scale_shift_to_mul_add(graph)
        graph_clean_up(graph)

        # Fusing the sequences of Mul/Add operations
        fuse_mul_add_sequence(graph)
        graph_clean_up(graph)

        # Fusing linear operation to Convolution
        fuse_linear_ops(graph)
        graph_clean_up(graph)

    if not argv.disable_resnet_optimization:
        stride_optimization(graph)

    fuse_pad(graph)

    # Converting Mul->Add to ScaleShift node
    convert_muladd_to_scaleshift_or_power(graph)
    graph_clean_up(graph)

    convert_mul_add_to_power(graph)
    graph_clean_up(graph)
    convert_add_or_mul_to_scaleshift(graph)  # scale = 1
    graph_clean_up(graph)

    if argv.reverse_input_channels:
        reverse_input_channels(graph)

    if argv.move_to_preprocess:
        move_scaleshift_to_preprocess(graph)
        graph_clean_up(graph)

    pattern = EltwiseInputNormalize()
    pattern.find_and_replace_pattern(graph)

    class_registration.apply_replacements(
        graph, class_registration.ClassType.BACK_REPLACER)

    for_graph_and_each_sub_graph_recursively(graph, remove_const_ops)
    CreateConstNodesReplacement().find_and_replace_pattern(graph)

    for_graph_and_each_sub_graph_recursively(graph, remove_output_ops)

    prepare_emit_ir(graph=graph,
                    data_type=argv.data_type,
                    output_dir=output_dir,
                    output_model_name=output_model_name,
                    meta_info=meta_info)
    return 0
Beispiel #22
0
def driver(argv,
           input_model,
           output_model_name,
           outputs,
           output_dir,
           scale,
           placeholder_shapes=None,
           mean_scale_values=()):
    meta_info = get_meta_info(argv)

    EltwiseChecker.enabled = False

    try:
        graph, input_shapes = load_kaldi_model(input_model)
    except Exception as e:
        raise Error('Model Optimizer is not able to read Kaldi model {}. '.
                    format(input_model) + refer_to_faq_msg(91)) from e
    check_empty_graph(graph, 'load_kaldi_nnet_model')
    graph.graph['cmd_params'] = argv
    graph.graph['fw'] = 'kaldi'
    graph.graph['ir_version'] = 2 if argv.generate_deprecated_IR_V2 else 4

    update_extractors_with_extensions(kaldi_type_extractors)

    extract_node_attrs(graph, lambda node: kaldi_extractor(node))

    class_registration.apply_replacements(
        graph, class_registration.ClassType.FRONT_REPLACER)

    output_op_nodes = add_output_ops(
        graph, outputs)  # TODO pass real outputs instead of None
    log.debug("After adding specific nodes for outputs")
    print_graph_stat(graph)

    check_empty_graph(graph, 'add_output_ops')
    create_tensor_nodes(graph)

    graph_clean_up(graph)
    log.debug("After removing specific nodes for output")
    print_graph_stat(graph)

    override_placeholder_shapes(graph, placeholder_shapes)
    override_batch(graph, argv.batch)

    graph_clean_up(graph)
    log.debug("After setting input shapes")
    print_graph_stat(graph)
    graph_clean_up(graph)
    remove_output_ops(graph)
    log.debug("After removing specific nodes for output")
    print_graph_stat(graph)

    # You need to pass required network outputs here
    # but we don't have a way yet, so just passing all discovered sinks
    mark_outputs(graph)
    graph_clean_up(graph)
    log.debug("After graph_cleanup")
    print_graph_stat(graph)
    graph = partial_infer(graph)

    # The order is intentional, firstly eliminate repeated, then remove redundant
    FuseRepeatedReshapes().find_and_replace_pattern(graph)
    EliminateRedundantReshape().find_and_replace_pattern(graph)
    check_empty_graph(graph, 'partial_infer')
    if argv.counts:
        try:
            counts = read_counts_file(argv.counts)
        except Exception as e:
            raise Error('Model Optimizer is not able to read counts file {}'.
                        format(argv.counts) + refer_to_faq_msg(92)) from e

        apply_biases_to_last_layer(graph, counts)

    if argv.remove_output_softmax:
        RemoveLastSoftMaxPattern().find_and_replace_pattern(graph)
        graph_clean_up(graph)
        log.debug("After removing softmax")
        print_graph_stat(graph)

    # Intentionally after all transformations
    KaldiRemoveMemoryOutputBackReplacementPattern().find_and_replace_pattern(
        graph)
    prepare_emit_ir(graph,
                    argv.data_type,
                    output_dir,
                    output_model_name,
                    meta_info=meta_info)
    return 0
Beispiel #23
0
def driver(argv: argparse.Namespace,
           proto_file_name: str,
           model_file_name: str,
           output_model_name: str,
           outputs: list,
           output_dir: str,
           scale: float,
           user_shapes: [None, list, np.array] = None,
           mean_scale_values: [dict, list] = (),
           mean_file: str = "",
           mean_file_offsets: tuple = None,
           custom_layers_mapping_path: str = None):
    meta_info = get_meta_info(argv)

    FusePermutesSequence.enabled = False

    proto, model = loader.load_caffe_proto_model(proto_file_name,
                                                 model_file_name)

    update_extractors_with_extensions(
        caffe_type_extractors, argv.disable_omitting_optional if hasattr(
            argv, 'disable_omitting_optional') else False,
        argv.disable_flattening_optional_params if hasattr(
            argv, 'disable_flattening_optional_params') else False)

    try:
        graph, original_shapes = loader.caffe_pb_to_nx(proto, model)
    except ValueError as e:
        raise Error(
            'Invalid prototxt file: value error {}. ' + refer_to_faq_msg(11),
            str(e)) from e

    log.debug("After caffe_pb_to_nx")
    print_graph_stat(graph)
    check_empty_graph(graph, 'load_caffe_proto_model')

    graph.__setattr__('proto_path', proto_file_name)
    graph.__setattr__('caffemodel_path', model_file_name)
    graph.__setattr__('name',
                      getattr(proto, 'name', None) or output_model_name)
    graph.graph['layout'] = 'NCHW'
    graph.graph['cmd_params'] = argv
    graph.graph['fw'] = 'caffe'
    graph.graph['ir_version'] = 2 if argv.generate_deprecated_IR_V2 else 4

    extract_node_attrs(graph, lambda node: (True, common_caffe_fields(node)))

    log.debug("After adding specific nodes for outputs")
    print_graph_stat(graph)

    custom_layers_map = custom_layers_mapping.load_layers_xml(
        custom_layers_mapping_path)
    custom_layers_mapping.update_extractors(
        caffe_type_extractors,
        custom_layers_map, argv.disable_omitting_optional if hasattr(
            argv, 'disable_omitting_optional') else False,
        argv.enable_flattening_nested_params if hasattr(
            argv, 'enable_flattening_nested_params') else False)

    extract_node_attrs(
        graph, lambda node: caffe_extractor(
            node, check_for_duplicates(caffe_type_extractors)))

    log.debug("After extract_node_attr")
    print_graph_stat(graph)

    packed_user_shapes, packed_outputs, freeze_placeholder = user_data_repack(
        graph, user_shapes, outputs, argv.freeze_placeholder_with_value)
    if argv.freeze_placeholder_with_value is not None:
        FreezePlaceholderValue.enabled = True
        FreezePlaceholderValue.replacement_dict = freeze_placeholder
        class_registration.update_registration([FrontReplacementSubgraph])
    output_op_nodes = add_output_ops(graph, packed_outputs)
    input_op_nodes = add_input_ops(graph, packed_user_shapes, True)
    override_placeholder_shapes(graph, packed_user_shapes)
    override_batch(graph, argv.batch)
    graph_clean_up(graph)
    check_empty_graph(graph, 'add_output_ops and add_input_ops')
    class_registration.apply_replacements(
        graph, class_registration.ClassType.FRONT_REPLACER)

    graph = create_tensor_nodes(graph)

    log.debug("After create_tensor_nodes")
    print_graph_stat(graph)

    remove_op_nodes(graph, {'op': 'Identity'})
    remove_output_ops(graph)
    graph_clean_up(graph)

    log.debug("After removing specific nodes for output")
    print_graph_stat(graph)

    # you need to pass required network outputs here
    # but we don't have a way yet, so just passing all discovered sinks
    mark_outputs(graph)
    graph_clean_up(graph)
    log.debug("After graph_cleanup")
    print_graph_stat(graph)

    graph = partial_infer(graph)
    log.debug("After partial_infer")
    print_graph_stat(graph)
    check_empty_graph(graph, 'partial_infer')
    duplicate_shared_weights(graph)

    input_op_nodes = add_input_ops(graph, packed_user_shapes, False)
    graph_clean_up(graph)
    check_empty_graph(graph, 'add_input_ops')
    scale_input(graph, scale)

    add_mean_scale_values(graph, mean_scale_values)

    log.debug("Split multi input convolutions")
    convert_multi_input_conv(graph)

    graph_clean_up(graph)
    log.debug("After graph_cleanup")
    print_graph_stat(graph)

    remove_op_nodes(graph, {'op': 'Dropout'})
    remove_op_nodes(graph, {'phase': 0})
    graph_clean_up(graph)

    class_registration.apply_replacements(
        graph, class_registration.ClassType.MIDDLE_REPLACER)

    mean_to_avgpool(graph)

    # Mark nodes with attr 'can_be_fused': False to disable fusing for specified nodes
    mark_unfused_nodes(graph, argv.finegrain_fusing)

    #need this pass even without fusing to convert scale with 2 inputs
    convert_scale_shift_to_mul_add(graph)
    graph_clean_up(graph)

    if not argv.disable_fusing:
        convert_bn_to_mul_add(graph)
        graph_clean_up(graph)

        fuse_mul_add_sequence(graph)
        graph_clean_up(graph)

        fuse_linear_ops(graph)
        graph_clean_up(graph)

    if not argv.disable_resnet_optimization:
        stride_optimization(graph)

    convert_muladd_to_scaleshift_or_power(graph)
    convert_matmul_to_fully_connected(graph)
    batch_norm_fuse(graph)
    convert_mul_add_to_power(graph)
    convert_add_to_scaleshift(graph)  # scale = 1
    convert_mul_to_scaleshift(graph)  # biases = 0

    graph_clean_up(graph)
    log.debug("After graph_cleanup")
    print_graph_stat(graph)

    if argv.reverse_input_channels:
        reverse_input_channels(graph)

    if argv.move_to_preprocess:
        move_scaleshift_to_preprocess(graph)
        graph_clean_up(graph)

    fuse_sequence_of_reshapes(graph)

    input_names = find_inputs(graph)
    mf = []
    try:
        if mean_file and len(original_shapes) == 1:
            mf = loader.parse_mean(mean_file, original_shapes[input_names[0]],
                                   mean_file_offsets)
        elif mean_file:
            raise Error(
                'Mean file for topologies with multiple inputs is not supported. '
                + refer_to_faq_msg(9))
    except ValueError as e:
        raise Error(
            'Cannot load or process mean file: value error {}. ' +
            refer_to_faq_msg(10), str(e)) from e

    class_registration.apply_replacements(
        graph, class_registration.ClassType.BACK_REPLACER)

    prepare_emit_ir(graph=graph,
                    data_type=argv.data_type,
                    output_dir=output_dir,
                    output_model_name=output_model_name,
                    mean_data=mf,
                    input_names=input_names,
                    meta_info=meta_info)
    return 0
Beispiel #24
0
 def graph_clean_up_onnx(graph: Graph):
     graph_clean_up(graph, ['Shape'])
Beispiel #25
0
def driver(argv, input_model, output_model_name, output_dir):
    log_step(argv.steps, 'LOAD')
    meta_info = get_meta_info(argv)

    EltwiseChecker.enabled = False

    try:
        graph = load_kaldi_model(input_model)
    except Exception as e:
        raise Error('Model Optimizer is not able to parse Kaldi model {}. '.format(input_model) +
                    refer_to_faq_msg(91)) from e
    graph.check_empty_graph('load_kaldi_nnet_model')
    graph.graph['cmd_params'] = argv
    graph.graph['fw'] = 'kaldi'

    if graph.graph['cmd_params'].generate_experimental_IR_V10:
        version = 10
    else:
        version = 6
    graph.graph['ir_version'] = 2 if argv.generate_deprecated_IR_V2 else version

    update_extractors_with_extensions(kaldi_type_extractors)
    extract_node_attrs(graph, lambda node: kaldi_extractor(node))

    # --------------------------------- LOAD END ------------------------------------------------------
    log_step(argv.steps, 'FRONT')
    ReplaceLSTMNodePattern().find_and_replace_pattern(graph)
    class_registration.apply_replacements(graph, class_registration.ClassType.FRONT_REPLACER)
    log_step(argv.steps, 'MIDDLE')
    graph = partial_infer(graph)

    ReplacePNormNodePattern().find_and_replace_pattern(graph)
    ReplaceMemoryOffsetNodePattern().find_and_replace_pattern(graph)
    ReplaceMemoryOffsetWithMemoryNodePattern().find_and_replace_pattern(graph)
    RemoveMemoryDuplicationPattern().find_and_replace_pattern(graph)
    MergeNeighborSplicePattern().find_and_replace_pattern(graph)
    RemoveUselessCropsPattern().find_and_replace_pattern(graph)
    RemoveIdentity().find_and_replace_pattern(graph)
    graph_clean_up(graph)

    AddSelectBeforeMemoryNodePattern().find_and_replace_pattern(graph)

    ReplaceSpliceNodePattern().find_and_replace_pattern(graph)
    graph_clean_up(graph)

    # The order is intentional, firstly eliminate repeated, then remove redundant
    FuseRepeatedReshapes().find_and_replace_pattern(graph)
    EliminateRedundantReshape().find_and_replace_pattern(graph)
    graph_clean_up(graph)
    graph.check_empty_graph('partial_infer')
    if argv.counts:
        try:
            counts = read_counts_file(argv.counts)
        except Exception as e:
            raise Error('Model Optimizer is not able to read counts file {}'.format(argv.counts) +
                        refer_to_faq_msg(92)) from e

        apply_biases_to_last_layer(graph, counts)

    if argv.remove_output_softmax:
        RemoveLastSoftMaxPattern().find_and_replace_pattern(graph)
        graph_clean_up(graph)
        log.debug("After removing softmax")
        graph.print_graph_stat()

    log_step(argv.steps, 'BACK')
    LeakyReluToReluWithNegativeSlope().find_and_replace_pattern(graph)
    TransposeToPermute().find_and_replace_pattern(graph)
    DivideToEltwises().find_and_replace_pattern(graph)
    SubtractToEltwises().find_and_replace_pattern(graph)
    SimpleEltwiseToEltwiseOp().find_and_replace_pattern(graph)
    for_graph_and_each_sub_graph_recursively(graph, convert_matmul_to_fully_connected)

    # Intentionally after all transformations
    if argv.remove_memory:
        CutMemory().find_and_replace_pattern(graph)
        graph_clean_up(graph)
    ParameterToInput().find_and_replace_pattern(graph)

    KaldiRemoveMemoryOutputBackReplacementPattern().find_and_replace_pattern(graph)
    ForceStrictPrecision().find_and_replace_pattern(graph)
    remove_const_ops(graph)
    CreateConstNodesReplacement().find_and_replace_pattern(graph)

    remove_output_ops(graph)
    log_step(argv.steps, 'EMIT')
    prepare_emit_ir(graph, argv.data_type, output_dir, output_model_name, meta_info=meta_info)
    return 0
Beispiel #26
0
def driver(argv: argparse.Namespace, input_model: str, output_model_name: str, outputs: list, output_dir: str,
           scale: float,
           placeholder_shapes: [None, list, np.array] = None,
           mean_scale_values: [dict, list] = ()):
    meta_info = get_meta_info(argv)

    try:
        model_nodes, model_params, model_name, iteration_number = load_symbol_def(input_model, argv.input_symbol,
                                                                                  argv.input,
                                                                                  argv.nd_prefix_name,
                                                                                  argv.pretrained_model_name,
                                                                                  argv.legacy_mxnet_model)
    except (ValueError, mxnet.base.MXNetError) as e:
        raise FrameworkError(
            'The following error happened while loading mxnet model {}: {}. ' +
            refer_to_faq_msg(53),
            input_model,
            str(e)
        ) from e

    if argv.nd_prefix_name and argv.pretrained_model_name and argv.save_params_from_nd:
        save_params_file(model_name, model_params._arg_params, model_params._aux_params, iteration_number)

    update_extractors_with_extensions(mxnet_op_extractors)
    graph = symbol2nx(model_nodes, model_params, argv.input)
    check_empty_graph(graph, 'symbol2nx. It may happen due to problems with loaded model')

    graph.__setattr__('name', output_model_name)
    graph.graph['layout'] = 'NCHW'
    graph.graph['cmd_params'] = argv
    graph.graph['fw'] = 'mxnet'
    graph.graph['feature_dim'] = 1 if graph.graph['layout'] == 'NCHW' else 3
    graph.graph['ir_version'] = 2 if argv.generate_deprecated_IR_V2 else 4
    graph = extract_node_attrs(graph, mxnet_op_extractor)
    check_softmax_node_inputs(graph)

    user_shapes, packed_outputs, _ = user_data_repack(graph, placeholder_shapes, outputs, None)
    output_op_nodes = add_output_ops(graph, packed_outputs)
    input_op_nodes = add_input_ops(graph, user_shapes, True)

    try:
        override_placeholder_shapes(graph, user_shapes, argv.batch)
    except ValueError as err:
        raise Error(
            'The following error happened while processing input shapes: {}. ' +
            refer_to_faq_msg(54),
            str(err)
        ) from err
    check_empty_graph(graph, 'add_output_ops and add_input_ops')

    class_registration.apply_replacements(graph, class_registration.ClassType.FRONT_REPLACER)
    add_input_data_to_prior_boxes(graph, argv.input)

    graph = create_tensor_nodes(graph)

    graph_clean_up(graph)
    remove_output_ops(graph)
    mark_outputs(graph)
    remove_output_ops(graph)

    graph_clean_up(graph)

    log.debug("After removing specific nodes for output")

    print_graph_stat(graph)

    graph = partial_infer(graph)
    graph_clean_up(graph)
    check_empty_graph(graph, 'partial_infer')

    duplicate_shared_weights(graph)

    scale_input(graph, scale)
    add_mean_scale_values(graph, mean_scale_values)

    remove_op_nodes(graph, {'identity': True})

    graph_clean_up(graph)

    class_registration.apply_replacements(graph, class_registration.ClassType.MIDDLE_REPLACER)
    fuse_pad(graph)

    # Mark nodes with attr 'can_be_fused': False to disable fusing for specified nodes
    mark_unfused_nodes(graph, argv.finegrain_fusing)

    # Converting FusedBatchNorm layer to Mul->Add->Mul->Add sequence
    convert_batch_norm(graph)
    graph_clean_up(graph)

    if not argv.disable_fusing:
        # Converting ScaleShift layer to Mul->Add
        convert_scale_shift_to_mul_add(graph)
        graph_clean_up(graph)

        # Fusing the sequences of Mul/Add operations
        fuse_mul_add_sequence(graph)
        graph_clean_up(graph)

        # Fusing linear operation to Convolution
        fuse_linear_ops(graph)
        graph_clean_up(graph)

    if not argv.disable_resnet_optimization:
        stride_optimization(graph)

    fuse_pad(graph)

    # Converting Mul->Add to ScaleShift node
    convert_muladd_to_scaleshift_or_power(graph)
    graph_clean_up(graph)

    convert_mul_add_to_power(graph)
    convert_add_to_scaleshift(graph)  # scale = 1
    convert_mul_to_scaleshift(graph)  # biases = 0

    if argv.reverse_input_channels:
        reverse_input_channels(graph)

    if argv.move_to_preprocess:
        move_scaleshift_to_preprocess(graph)
        graph_clean_up(graph)

    pattern = EltwiseInputNormalize()
    pattern.find_and_replace_pattern(graph)

    class_registration.apply_replacements(graph, class_registration.ClassType.BACK_REPLACER)

    prepare_emit_ir(graph=graph, data_type=argv.data_type, output_dir=output_dir, output_model_name=output_model_name,
                    meta_info=meta_info)
    return 0
Beispiel #27
0
def driver_R5(onnx_modelproto_bytes,
              precision: str,
              output_model_name: str,
              outputs: list,
              output_dir: str,
              scale: float,
              user_shapes: [None, list, np.array] = None,
              mean_scale_values: [dict, list] = ()):

    try:
        model_proto = onnx.load_from_string(bytes(onnx_modelproto_bytes))
    except Exception as e:
        print("[python] onnx exception: ", str(e))

    model_graph = model_proto.graph  # pylint: disable=no-member
    log.debug("Number of nodes in graph_def: {}".format(len(model_graph.node)))
    log.debug(
        "Number of all input ports (not true inputs) in graph_def: {}".format(
            len(model_graph.input)))
    log.debug("Number of initializers in graph_def: {}".format(
        len(model_graph.initializer)))
    log.debug("Number of real inputs in graph_def: {}".format(
        len(model_graph.input) - len(model_graph.initializer)))
    update_extractors_with_extensions(onnx_op_extractors)

    try:
        graph = protobuf2nx(model_proto)
        log.debug("Number of nodes in NX graph: {}".format(
            graph.number_of_nodes()))
        graph.__setattr__(
            'name',
            output_model_name if output_model_name else model_proto.graph.name)  # pylint: disable=no-member
        graph.graph['layout'] = 'NCHW'
        graph.graph['fw'] = 'onnx'
        graph.graph[
            'feature_dim'] = 1 if graph.graph['layout'] == 'NCHW' else 3
        graph.graph['ir_version'] = 4
        extract_node_attrs(graph, lambda node:
                           (True, common_onnx_fields(node)))
    except Exception as e:
        raise Error(
            'Cannot pre-process ONNX graph after reading from model file "{}". '
            'File is corrupt or has unsupported format. Details: {}. ' +
            refer_to_faq_msg(44), model_file_name, str(e)) from e
    check_empty_graph(
        graph, 'protobuf2nx. It may happen due to problems with loaded model')
    packed_user_shapes, packed_outputs, _ = user_data_repack(
        graph, user_shapes, outputs, None)

    output_op_nodes = add_output_ops(graph, packed_outputs)
    input_op_nodes = add_input_ops(graph, packed_user_shapes, True)

    graph_clean_up(graph)
    check_empty_graph(graph, 'add_output_ops and add_input_ops')
    extract_node_attrs(
        graph, lambda node: onnx_op_extractor(
            node, check_for_duplicates(onnx_op_extractors)))

    class_registration.apply_replacements(
        graph, class_registration.ClassType.FRONT_REPLACER)

    create_tensor_nodes(graph)
    graph_clean_up(graph)

    override_placeholder_shapes(graph, packed_user_shapes)

    graph_clean_up(graph)
    remove_op_nodes(graph, {'op': 'Identity'})

    graph_clean_up(graph)

    remove_output_ops(graph)

    partial_infer(graph)
    graph_clean_up(graph)
    check_empty_graph(graph, 'partial_infer')

    input_op_nodes = add_input_ops(graph, packed_user_shapes, False)
    graph_clean_up(graph)
    check_empty_graph(graph, 'add_input_ops')

    scale_input(graph, scale)
    add_mean_scale_values(graph, mean_scale_values)

    convert_dilated_convolution(graph)
    graph_clean_up(graph)

    graph_clean_up(graph)

    remove_op_nodes(graph, {'op': 'Identity'})
    remove_useless_split(graph)

    class_registration.apply_replacements(
        graph, class_registration.ClassType.MIDDLE_REPLACER)

    convert_gemm_to_fully_connected(graph)
    NormalizeFullyConnected().find_and_replace_pattern(graph)

    fuse_pad(graph)
    graph_clean_up(graph)

    convert_batch_norm(graph)
    graph_clean_up(graph)

    convert_scale_shift_to_mul_add(graph)
    graph_clean_up(graph)

    fuse_mul_add_sequence(graph)
    graph_clean_up(graph)

    fuse_linear_ops(graph)
    graph_clean_up(graph)

    grouped_convolutions_fusing(graph)
    graph_clean_up(graph)

    fuse_linear_ops(graph)
    graph_clean_up(graph)

    convert_muladd_to_scaleshift_or_power(graph)
    graph_clean_up(graph)

    convert_mul_add_to_power(graph)
    graph_clean_up(graph)

    convert_reshape(graph)
    convert_add_to_scaleshift(graph)  # scale = 1
    convert_mul_to_scaleshift(graph)  # biases = 0

    fuse_pad(graph)
    graph_clean_up(graph)

    fuse_sequence_of_reshapes(graph)
    graph_clean_up(graph)

    pattern = EltwiseInputNormalize()
    pattern.find_and_replace_pattern(graph)

    merge_nodes_permutations(graph)
    permute_data_nodes_attrs(graph)
    permute_op_nodes_attrs(graph)

    class_registration.apply_replacements(
        graph, class_registration.ClassType.BACK_REPLACER)

    weights, xml_string = prepare_emit_ir(graph=graph,
                                          data_type=precision,
                                          output_dir=output_dir,
                                          output_model_name=output_model_name,
                                          meta_info={'unset': []})

    return weights, xml_string
Beispiel #28
0
def driver(argv: argparse.Namespace,
           model_file_name: str,
           output_model_name: str,
           outputs: list,
           output_dir: str,
           scale: float,
           user_shapes: [None, list, np.array] = None,
           mean_scale_values: [dict, list] = ()):

    meta_info = get_meta_info(argv)

    model_proto = load_onnx_model(model_file_name)
    model_graph = model_proto.graph  # pylint: disable=no-member
    #print(model_graph)
    #assert len(model_graph) == 1, "An ONNX model contains more than 1 graph: unsupported"
    log.debug("Number of nodes in graph_def: {}".format(len(model_graph.node)))
    log.debug(
        "Number of all input ports (not true inputs) in graph_def: {}".format(
            len(model_graph.input)))
    log.debug("Number of initializers in graph_def: {}".format(
        len(model_graph.initializer)))
    log.debug("Number of real inputs in graph_def: {}".format(
        len(model_graph.input) - len(model_graph.initializer)))
    update_extractors_with_extensions(onnx_op_extractors)

    try:
        graph = protobuf2nx(model_proto)
        log.debug("Number of nodes in NX graph: {}".format(
            graph.number_of_nodes()))
        graph.__setattr__(
            'name',
            output_model_name if output_model_name else model_proto.graph.name)  # pylint: disable=no-member
        graph.graph['layout'] = 'NCHW'
        graph.graph['cmd_params'] = argv
        graph.graph['fw'] = 'onnx'
        graph.graph[
            'feature_dim'] = 1 if graph.graph['layout'] == 'NCHW' else 3
        graph.graph['ir_version'] = 2 if argv.generate_deprecated_IR_V2 else 4
        # extract basic attributes earlier to enable some passes that relies on them before full attribute
        # extractor is called
        extract_node_attrs(graph, lambda node:
                           (True, common_onnx_fields(node)))
    except Exception as e:
        raise Error(
            'Cannot pre-process ONNX graph after reading from model file "{}". ' \
            'File is corrupt or has unsupported format. Details: {}. ' +
            refer_to_faq_msg(44),
            model_file_name,
            str(e)
        ) from e
    check_empty_graph(
        graph, 'protobuf2nx. It may happen due to problems with loaded model')
    packed_user_shapes, packed_outputs, _ = user_data_repack(
        graph, user_shapes, outputs, None)

    output_op_nodes = add_output_ops(graph, packed_outputs)
    input_op_nodes = add_input_ops(graph, packed_user_shapes, True)

    # this call of 'graph_clean_up' removes child nodes of outputs which is useful when custom output is specified
    graph_clean_up(graph)
    check_empty_graph(graph, 'add_output_ops and add_input_ops')
    extract_node_attrs(
        graph, lambda node: onnx_op_extractor(
            node, check_for_duplicates(onnx_op_extractors)))

    class_registration.apply_replacements(
        graph, class_registration.ClassType.FRONT_REPLACER)

    create_tensor_nodes(graph)
    graph_clean_up(graph)

    override_placeholder_shapes(graph, packed_user_shapes)
    override_batch(graph, argv.batch)

    graph_clean_up(graph)
    remove_op_nodes(graph, {'op': 'Identity'})

    graph_clean_up(graph)

    remove_output_ops(graph)

    partial_infer(graph)
    graph_clean_up(graph)
    check_empty_graph(graph, 'partial_infer')

    input_op_nodes = add_input_ops(graph, packed_user_shapes, False)
    graph_clean_up(graph)
    check_empty_graph(graph, 'add_input_ops')
    #change_placeholders_types_to_FP32(graph)

    scale_input(graph, scale)
    add_mean_scale_values(graph, mean_scale_values)

    convert_dilated_convolution(graph)
    graph_clean_up(graph)

    graph_clean_up(graph)

    remove_op_nodes(graph, {'op': 'Identity'})
    remove_useless_split(graph)

    class_registration.apply_replacements(
        graph, class_registration.ClassType.MIDDLE_REPLACER)

    convert_gemm_to_fully_connected(graph)
    NormalizeFullyConnected().find_and_replace_pattern(graph)

    fuse_pad(graph)
    graph_clean_up(graph)

    # Mark nodes with attr 'can_be_fused': False to disable fusing for specified nodes
    mark_unfused_nodes(graph, argv.finegrain_fusing)

    # Converting FusedBatchNorm layer to Mul->Add->Mul->Add sequence
    # IE doesn't support BN with 4 inputs, so we have to split it to two ScaleShift
    convert_batch_norm(graph)
    graph_clean_up(graph)

    if not argv.disable_fusing:
        # Converting ScaleShift layer to Mul->Add
        convert_scale_shift_to_mul_add(graph)
        graph_clean_up(graph)

        # Fusing the sequences of Mul/Add operations
        fuse_mul_add_sequence(graph)
        graph_clean_up(graph)

        # Fusing linear operation to Convolution
        fuse_linear_ops(graph)
        graph_clean_up(graph)

    if not argv.disable_gfusing:
        grouped_convolutions_fusing(graph)
        graph_clean_up(graph)
        if not argv.disable_fusing:
            fuse_linear_ops(graph)
            graph_clean_up(graph)

    convert_muladd_to_scaleshift_or_power(graph)
    graph_clean_up(graph)

    convert_mul_add_to_power(graph)
    graph_clean_up(graph)

    convert_reshape(graph)
    convert_add_to_scaleshift(graph)  # scale = 1
    convert_mul_to_scaleshift(graph)  # biases = 0

    fuse_pad(graph)
    graph_clean_up(graph)

    if argv.reverse_input_channels:
        reverse_input_channels(graph)

    if argv.move_to_preprocess:
        move_scaleshift_to_preprocess(graph)
        graph_clean_up(graph)

    fuse_sequence_of_reshapes(graph)
    graph_clean_up(graph)

    pattern = EltwiseInputNormalize()
    pattern.find_and_replace_pattern(graph)

    merge_nodes_permutations(graph)
    permute_data_nodes_attrs(graph)
    permute_op_nodes_attrs(graph)

    class_registration.apply_replacements(
        graph, class_registration.ClassType.BACK_REPLACER)

    prepare_emit_ir(graph=graph,
                    data_type=argv.data_type,
                    output_dir=output_dir,
                    output_model_name=output_model_name,
                    meta_info=meta_info)

    return 0