def convert_quantize_layer(self, keras_op): op = self._mace_net_def.op.add() op.name = keras_op.name op.type = MaceOp.Identity.name op.input.append(get_input(keras_op).name) op.output.append(get_output(keras_op).name) output_shape = op.output_shape.add() output_shape.dims.extend(keras_shape2list(get_output(keras_op).shape)) ConverterUtil.add_data_type_arg(op, mace_pb2.DT_FLOAT) ConverterUtil.add_data_format_arg(op, DataFormat.NHWC) output_min = keras_op.weights[0].numpy() output_max = keras_op.weights[1].numpy() self.add_quantize_info(op, output_min, output_max) return op
def convert(model_file, output_dir, layers): mace_check(os.path.isdir(output_dir), "Output directory '" + output_dir + "' does not exist!") multi_net_def = init_multi_net_def(model_file) multi_net_info = MultiNetDefInfo(multi_net_def, layers) output_configs = {ModelKeys.subgraphs: []} while multi_net_info.index_valid(): # omit BatchToSpaceND and op before that due to changed graph cur_op = multi_net_info.get_current_op() next_op = multi_net_info.get_next_op() if cur_op.type == MaceOp.BatchToSpaceND.name or \ cur_op.type == HexagonOp.BatchToSpaceND_8.name or \ (cur_op.type == MaceOp.Quantize.name or cur_op.type == HexagonOp.QuantizeINPUT_f_to_8.name or cur_op.type == HexagonOp.INPUT.name) or \ (cur_op.type == HexagonOp.DequantizeOUTPUT_8tof.name or cur_op.type == HexagonOp.OUTPUT.name) or \ (next_op is not None and (next_op.type == MaceOp.BatchToSpaceND.name or next_op.type == HexagonOp.BatchToSpaceND_8.name)) or \ cur_op.name.startswith(MaceKeyword.mace_output_node_name): multi_net_info.StartIndexIncrement() continue multi_net = copy.deepcopy(multi_net_def) net_defs = multi_net.net_def # remove unused net_def net = None cur_net_idx = multi_net_info.get_current_net_idx() for net_def in net_defs[:]: if net_def.infer_order == cur_net_idx: net = net_def elif net_def.infer_order > cur_net_idx: net_defs.remove(net_def) del multi_net.output_tensor[:] data_format = net.output_info[0].data_format # remove unsued op cur_op_idx = multi_net_info.get_current_op_idx() is_hexagon = multi_net_info.is_hexagon(cur_net_idx) if is_hexagon: # reuse dequantize op and it's min/max tensor's node_id del net.op[(cur_op_idx + 1):-1] else: del net.op[(cur_op_idx + 1):] del net.output_info[:] op = net.op[cur_op_idx] multi_net_info.StartIndexIncrement() output_tensors = [] output_shapes = [] op_name = op.name if str(op.name).startswith(MaceKeyword.mace_output_node_name): continue is_quantize = multi_net_info.is_quantize(cur_net_idx) if is_quantize: op.name = MaceKeyword.mace_output_node_name + '_' + op.name if is_hexagon: if len(op.output) != 1: print("Skip %s(%s)" % (op.name, op.type)) continue for i in range(len(op.output)): output_tensors.append(str(op.output[i])) output_shapes.append(",".join( [str(dim) for dim in op.output_shape[i].dims])) # modify output info multi_net.output_tensor.append(op.output[i]) output_info = net.output_info.add() output_info.name = op.output[i] output_info.data_format = data_format output_info.dims.extend(op.output_shape[i].dims) output_info.data_type = mace_pb2.DT_FLOAT if is_quantize: output_info.scale = op.quantize_info[0].scale output_info.zero_point = op.quantize_info[0].zero_point # modify output op if is_quantize: output_name = op.output[i] new_output_name = \ MaceKeyword.mace_output_node_name + '_' + op.output[i] op.output[i] = new_output_name if not is_hexagon: dequantize_op = net.op.add() dequantize_op.name = normalize_op_name(output_name) dequantize_op.type = MaceOp.Dequantize.name dequantize_op.input.append(new_output_name) dequantize_op.output.append(output_name) output_shape = dequantize_op.output_shape.add() output_shape.dims.extend(op.output_shape[i].dims) dequantize_op.output_type.append(mace_pb2.DT_FLOAT) ConverterUtil.add_data_type_arg(dequantize_op, mace_pb2.DT_UINT8) else: dequantize_op = net.op[-1] dequantize_op.name = normalize_op_name(output_name) del dequantize_op.input[:] del dequantize_op.output[:] dequantize_op.input.append(new_output_name) dequantize_op.node_input[0].node_id = op.node_id dequantize_op.output.append(output_name) if dequantize_op.type == \ HexagonOp.DequantizeOUTPUT_8tof.name: input_min = new_output_name[:-1] + '1' input_max = new_output_name[:-1] + '2' dequantize_op.input.extend([input_min, input_max]) dequantize_op.node_input[1].node_id = op.node_id dequantize_op.node_input[2].node_id = op.node_id del dequantize_op.node_input[3:] else: del dequantize_op.node_input[1:] model_path = save_model_to_proto(multi_net, normalize_op_name(op_name), output_dir) output_config = { ModelKeys.model_file_path: str(model_path), ModelKeys.output_tensors: output_tensors, ModelKeys.output_shapes: output_shapes, "output_data_formats": [DataFormat.NHWC.name] * len(output_shapes) } output_configs[ModelKeys.subgraphs].append(output_config) output_configs_path = output_dir + "outputs.yml" with open(output_configs_path, "w") as f: yaml.dump(output_configs, f, default_flow_style=False)
def convert(model_file, output_dir, layers): mace_check(os.path.isfile(model_file), "Input graph file '" + model_file + "' does not exist!") mace_check(os.path.isdir(output_dir), "Output directory '" + output_dir + "' does not exist!") net_def = mace_pb2.NetDef() with open(model_file, "rb") as f: net_def.ParseFromString(f.read()) is_quantize = ConverterUtil.get_arg(net_def, MaceKeyword.mace_quantize_flag_arg_str) is_quantize = False if is_quantize is None else is_quantize.i == 1 is_hexagon = False index = 0 end_index = len(net_def.op) if is_quantize: while index < end_index: # omit op quantize if net_def.op[index].type == MaceOp.Quantize.name or \ net_def.op[index].type == \ HexagonOp.QuantizeINPUT_f_to_8.name or \ net_def.op[index].type == HexagonOp.INPUT.name: index += 1 # omit op dequantize elif net_def.op[end_index - 1].type == MaceOp.Dequantize.name or \ net_def.op[end_index - 1].type == \ HexagonOp.DequantizeOUTPUT_8tof.name or \ net_def.op[end_index - 1].type == HexagonOp.OUTPUT.name: end_index -= 1 else: break mace_check( 0 < index < end_index < len(net_def.op), "Wrong number of op quantize(%d) or dequantize(%d)." % (index, len(net_def.op) - end_index)) if net_def.op[-1].type == HexagonOp.DequantizeOUTPUT_8tof.name or \ net_def.op[-1].type == HexagonOp.OUTPUT.name: is_hexagon = True index, end_index = handle_index(index, end_index, layers) data_format = net_def.output_info[0].data_format output_configs = {"subgraphs": []} while index < end_index: # omit BatchToSpaceND and op before that due to changed graph if net_def.op[index].type == MaceOp.BatchToSpaceND.name or \ net_def.op[index].type == HexagonOp.BatchToSpaceND_8.name or \ (index + 1 < end_index and (net_def.op[index + 1].type == MaceOp.BatchToSpaceND.name or net_def.op[index + 1].type == HexagonOp.BatchToSpaceND_8.name)): # noqa index += 1 continue net = copy.deepcopy(net_def) if is_hexagon: # reuse dequantize op and it's min/max tensor's node_id del net.op[index + 1:-1] else: del net.op[index + 1:] del net.output_info[:] op = net.op[index] index += 1 output_tensors = [] output_shapes = [] op_name = op.name if str(op.name).startswith(MaceKeyword.mace_output_node_name): continue if is_quantize: op.name = MaceKeyword.mace_output_node_name + '_' + op.name if is_hexagon: if len(op.output) != 1: print("Skip %s(%s)" % (op.name, op.type)) continue for i in range(len(op.output)): output_tensors.append(str(op.output[i])) output_shapes.append(",".join( [str(dim) for dim in op.output_shape[i].dims])) # modify output info output_info = net.output_info.add() output_info.name = op.output[i] output_info.data_format = data_format output_info.dims.extend(op.output_shape[i].dims) output_info.data_type = mace_pb2.DT_FLOAT if is_quantize: output_info.scale = op.quantize_info[0].scale output_info.zero_point = op.quantize_info[0].zero_point # modify output op if is_quantize: output_name = op.output[i] new_output_name = \ MaceKeyword.mace_output_node_name + '_' + op.output[i] op.output[i] = new_output_name if not is_hexagon: dequantize_op = net.op.add() dequantize_op.name = normalize_op_name(output_name) dequantize_op.type = MaceOp.Dequantize.name dequantize_op.input.append(new_output_name) dequantize_op.output.append(output_name) output_shape = dequantize_op.output_shape.add() output_shape.dims.extend(op.output_shape[i].dims) dequantize_op.output_type.append(mace_pb2.DT_FLOAT) ConverterUtil.add_data_type_arg(dequantize_op, mace_pb2.DT_UINT8) else: dequantize_op = net.op[-1] dequantize_op.name = normalize_op_name(output_name) del dequantize_op.input[:] del dequantize_op.output[:] dequantize_op.input.append(new_output_name) dequantize_op.node_input[0].node_id = op.node_id dequantize_op.output.append(output_name) if dequantize_op.type == \ HexagonOp.DequantizeOUTPUT_8tof.name: input_min = new_output_name[:-1] + '1' input_max = new_output_name[:-1] + '2' dequantize_op.input.extend([input_min, input_max]) dequantize_op.node_input[1].node_id = op.node_id dequantize_op.node_input[2].node_id = op.node_id del dequantize_op.node_input[3:] else: del dequantize_op.node_input[1:] model_path = save_model_to_proto(net, normalize_op_name(op_name), output_dir) output_config = { "model_file_path": str(model_path), "output_tensors": output_tensors, "output_shapes": output_shapes, "output_data_formats": [DataFormat.NHWC.name] } output_configs["subgraphs"].append(output_config) output_configs_path = output_dir + "outputs.yml" with open(output_configs_path, "w") as f: yaml.dump(output_configs, f, default_flow_style=False)