def find_and_replace_pattern(self, graph: Graph): fw = graph.graph['fw'] argv = graph.graph['cmd_params'] layout = graph.graph['layout'] for_graph_and_each_sub_graph_recursively(graph, fuse_pad) for_graph_and_each_sub_graph_recursively(graph, lambda G: G.clean_up()) # Mark nodes with attr 'can_be_fused': False to disable fusing for specified nodes for_graph_and_each_sub_graph_recursively(graph, lambda graph: mark_unfused_nodes(graph, argv.finegrain_fusing)) # Converting FusedBatchNorm layer to Mul->Add->Mul->Add sequence # IE doesn't support batchNormInference with 4 inputs, so we have to split it to two ScaleShift for_graph_and_each_sub_graph_recursively(graph, convert_batch_norm) if fw == 'caffe': # Converting ScaleShift layer to Mul->Add for_graph_and_each_sub_graph_recursively(graph, convert_scale_shift_to_mul_add) for_graph_and_each_sub_graph_recursively(graph, Div().find_and_replace_pattern) for_graph_and_each_sub_graph_recursively(graph, Sub().find_and_replace_pattern) for_graph_and_each_sub_graph_recursively(graph, lambda G: G.clean_up()) if not argv.disable_fusing: if fw != 'caffe': # Converting ScaleShift layer to Mul->Add for_graph_and_each_sub_graph_recursively(graph, convert_scale_shift_to_mul_add) for_graph_and_each_sub_graph_recursively(graph, lambda G: G.clean_up()) # Fusing the sequences of Mul/Add operations for_graph_and_each_sub_graph_recursively(graph, fuse_mul_add_sequence) for_graph_and_each_sub_graph_recursively(graph, lambda G: G.clean_up()) normalize_eltwise_inputs(graph) for_graph_and_each_sub_graph_recursively(graph, lambda G: G.clean_up()) # Fusing linear operation to Convolution for_graph_and_each_sub_graph_recursively(graph, fuse_linear_ops) for_graph_and_each_sub_graph_recursively(graph, lambda G: G.clean_up()) if not argv.disable_gfusing: for_graph_and_each_sub_graph_recursively(graph, grouped_convolutions_fusing) for_graph_and_each_sub_graph_recursively(graph, lambda G: G.clean_up()) if not argv.disable_fusing: for_graph_and_each_sub_graph_recursively(graph, fuse_linear_ops) for_graph_and_each_sub_graph_recursively(graph, lambda G: G.clean_up()) for_graph_and_each_sub_graph_recursively(graph, normalize_eltwise_inputs) for_graph_and_each_sub_graph_recursively(graph, lambda G: G.clean_up()) MarkNodesToFuseUpToFakeQuantize().find_and_replace_pattern(graph) FakeQuantizeFuse().find_and_replace_pattern(graph) AddFakeQuantizeFuse().find_and_replace_pattern(graph) MulFakeQuantizeFuse().find_and_replace_pattern(graph) for_graph_and_each_sub_graph_recursively(graph, lambda G: G.clean_up()) for_graph_and_each_sub_graph_recursively(graph, fuse_pad) for_graph_and_each_sub_graph_recursively(graph, lambda G: G.clean_up()) if layout != 'NHWC' and not argv.disable_resnet_optimization: stride_optimization(graph)
def test_resnet_optimization_6(self): graph = build_graph(nodes_attributes, [ ('placeholder_1', 'placeholder_1_data'), ('placeholder_1_data', 'conv_1'), ('conv_1_w', 'conv_1'), ('conv_1_b', 'conv_1'), ('conv_1', 'conv_1_data'), ('conv_1_data', 'conv_2'), ('conv_2_w', 'conv_2'), ('conv_2_b', 'conv_2'), ('conv_2', 'conv_2_data'), ('conv_2_data', 'conv_3'), ('conv_3_w', 'conv_3'), ('conv_3_b', 'conv_3'), ('conv_3', 'conv_3_data'), ('conv_3_data', 'conv_4'), ('conv_4_w', 'conv_4'), ('conv_4_b', 'conv_4'), ('conv_4', 'conv_4_data'), ], { 'placeholder_1_data': { 'shape': np.array([1, 3, 224, 224]) }, 'conv_1_w': { 'value': np.zeros([3, 3, 1, 1]), 'shape': np.array([3, 3, 1, 1]) }, 'conv_1': { 'kernel_spatial': np.array([1, 1]), 'stride': np.array([1, 1, 1, 1]), 'output': np.array([3]), }, 'conv_1_data': { 'shape': np.array([1, 3, 224, 224]) }, 'conv_2_w': { 'value': np.zeros([3, 3, 1, 1]), 'shape': np.array([3, 3, 1, 1]) }, 'conv_2': { 'kernel_spatial': np.array([1, 1]), 'stride': np.array([1, 1, 2, 2]), 'output': np.array([3]), }, 'conv_2_data': { 'shape': np.array([1, 3, 112, 112]) }, 'conv_3_w': { 'value': np.zeros([3, 3, 3, 3]), 'shape': np.array([3, 3, 3, 3]) }, 'conv_3': { 'kernel_spatial': np.array([3, 3]), 'stride': np.array([1, 1, 1, 1]), 'output': np.array([3]), }, 'conv_3_data': { 'shape': np.array([1, 3, 110, 110]) }, 'conv_4_w': { 'value': np.zeros([3, 3, 1, 1]), 'shape': np.array([3, 3, 1, 1]) }, 'conv_4': { 'kernel_spatial': np.array([1, 1]), 'stride': np.array([1, 1, 2, 2]), 'output': np.array([3]), }, 'conv_4_data': { 'shape': np.array([1, 3, 55, 55]) }, }, nodes_with_edges_only=True) graph_ref = build_graph(nodes_attributes, [ ('placeholder_1', 'placeholder_1_data'), ('placeholder_1_data', 'conv_1'), ('conv_1_w', 'conv_1'), ('conv_1_b', 'conv_1'), ('conv_1', 'conv_1_data'), ('conv_1_data', 'conv_2'), ('conv_2_w', 'conv_2'), ('conv_2_b', 'conv_2'), ('conv_2', 'conv_2_data'), ('conv_2_data', 'conv_3'), ('conv_3_w', 'conv_3'), ('conv_3_b', 'conv_3'), ('conv_3', 'conv_3_data'), ('conv_3_data', 'conv_4'), ('conv_4_w', 'conv_4'), ('conv_4_b', 'conv_4'), ('conv_4', 'conv_4_data'), ], { 'placeholder_1_data': { 'shape': np.array([1, 3, 224, 224]) }, 'conv_1_w': { 'value': np.zeros([3, 3, 1, 1]), 'shape': np.array([3, 3, 1, 1]) }, 'conv_1': { 'kernel_spatial': np.array([1, 1]), 'stride': np.array([1, 1, 2, 2]), 'output': np.array([3]) }, 'conv_1_data': { 'shape': np.array([1, 3, 112, 112]) }, 'conv_2_w': { 'value': np.zeros([3, 3, 1, 1]), 'shape': np.array([3, 3, 1, 1]) }, 'conv_2': { 'kernel_spatial': np.array([1, 1]), 'stride': np.array([1, 1, 1, 1]), 'output': np.array([3]) }, 'conv_2_data': { 'shape': np.array([1, 3, 112, 112]) }, 'conv_3_w': { 'value': np.zeros([3, 3, 3, 3]), 'shape': np.array([3, 3, 3, 3]) }, 'conv_3': { 'kernel_spatial': np.array([3, 3]), 'stride': np.array([1, 1, 2, 2]), 'output': np.array([3]) }, 'conv_3_data': { 'shape': np.array([1, 3, 55, 55]) }, 'conv_4_w': { 'value': np.zeros([3, 3, 1, 1]), 'shape': np.array([3, 3, 1, 1]) }, 'conv_4': { 'kernel_spatial': np.array([1, 1]), 'stride': np.array([1, 1, 1, 1]), 'output': np.array([3]) }, 'conv_4_data': { 'shape': np.array([1, 3, 55, 55]) }, }, nodes_with_edges_only=True) graph.graph['layout'] = 'NCHW' graph_ref.graph['layout'] = 'NCHW' stride_optimization(graph) (flag, resp) = compare_graphs(graph, graph_ref, 'conv_4_data', check_op_attrs=True) self.assertTrue(flag, resp)
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
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
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
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