netrans/src/export.py

218 lines
9.4 KiB
Python
Executable File

#!/usr/bin/env python3
from argparse import ArgumentParser
import os
import sys
import json
from quantize_types import QuantizerType
from measure import *
from utils import *
import importlib
try:
importlib.import_module("acuitylib")
except:
ACUITY_PATH = os.environ['ACUITY_PATH']
sys.path.append(ACUITY_PATH)
from acuitylib.vsi_nn import VSInn
post = None
def load_net(model_filename, quantized='asymu8', use_hybrid=False):
nn = VSInn()
net = nn.create_net()
if not use_hybrid:
model = model_filename + ".json"
else:
model = model_filename + "_" + quantized + "_hy.quantize.json"
data = model_filename + ".data"
inputmeta = model_filename + "_inputmeta.yml"
postprocess = model_filename + "_postprocess_file.yml"
if os.path.exists(model) is True:
nn.load_model(net, model)
else:
print("{} file does not exists.".format(model))
sys.exit(1)
if os.path.exists(data) is True:
nn.load_model_data(net, data)
else:
print("{} file does not exists.".format(data))
sys.exit(1)
if os.path.exists(inputmeta) is True:
nn.load_model_inputmeta(net, inputmeta)
else:
print("{} file does not exists.".format(inputmeta))
sys.exit(1)
if os.path.exists(postprocess) is True:
nn.load_model_outputmeta(net, postprocess)
global post
post = postprocess
if quantized != "float32":
if not use_hybrid:
model_quantize = model_filename + '_' + quantized + ".quantize"
else:
model_quantize = model_filename + '_' + quantized + "_hy.quantize"
if os.path.exists(model_quantize) is True:
nn.load_model_quantize(net, model_quantize)
else:
if quantized == "float16":
return net
print('{} does not exist'.format(model_quantize))
sys.exit(1)
return net
def export(net, model_filename, quantized='asymu8', force_remove_permute=False, use_hybrid=False):
nn = VSInn()
if not use_hybrid:
quantize_file = model_filename + '_' + quantized + ".quantize"
model = model_filename + ".json"
output_dir = 'wksp/{}_{}'.format(model_filename, quantized)
else:
# add hybrid quantize for print log
quantize_file = model_filename + '_' + quantized + "_hy.quantize"
model = model_filename + '_' + quantized + "_hy.quantize.json"
# add hybrid quantize output file name
output_dir = 'wksp/{}_{}'.format(model_filename, quantized + "_hy")
output_dir = os.path.join(output_dir, os.path.split(output_dir)[1])
if quantized != "float32":
print_params(nn.export_ovxlib, model=model, data=model_filename + ".data", quantize=quantize_file,
with_input_meta=model_filename + "_inputmeta.yml", postprocess_file=post, output_path=output_dir, save_fused_graph=True)
else:
print_params(nn.export_ovxlib, model=model, data=model_filename + ".data",
with_input_meta=model_filename + "_inputmeta.yml", postprocess_file=post, output_path=output_dir,
save_fused_graph=True)
nn.export_ovxlib(net, output_path=output_dir, dtype=quantized, save_fused_graph=True, force_remove_permute=force_remove_permute)
def generate_exe_script(net, model_filename, quantized='asymu8', iterations=1, use_hybrid=False):
if use_hybrid:
quantized = quantized + "_hy"
inputs = net.get_input_layers(ign_variable=True)
input_tensor_list = []
for l in inputs:
if l.is_op('input'):
url = l.get_output().url
input_tensor = url.replace('@', '').replace(':', '_').replace('/', '_')
shape = l.params.shape
dims = len(shape)
if dims > 0 and shape[0] == 0:
shape[0] = 1
shape = [str(i) for i in shape]
input_tensor = input_tensor + '_' + '_'.join(shape)
input_tensor = 'iter_{}_'.format(iterations - 1) + input_tensor + '.tensor'
input_tensor_list.append(input_tensor)
if len(input_tensor_list) < 1:
print("No input layer!")
return
else:
wksp_dir = 'wksp/{}_{}'.format(model_filename, quantized)
target_name = '{}_{}'.format(model_filename, quantized)
cmd_str = './{} {}.export.data'.format(
target_name.replace("_", "").replace("-", "").replace(".", "").replace(" ", "").lower(), target_name)
for i in range(len(input_tensor_list)):
cmd_str = cmd_str + ' ' + input_tensor_list[i]
os.system('echo {} > {}/cmd.sh'.format(cmd_str, wksp_dir))
os.system('chmod +x {}/cmd.sh'.format(wksp_dir))
print("The executable script cmd.sh is generated.")
def generate_criterion_json(net, model_filename, quantized='asymu8', iterations=1, use_hybrid=False):
if use_hybrid:
quantized = quantized + "_hy"
rule = dict()
rule['classification'] = False ## use normal jude
rule['rules'] = dict()
index = 0
outputs = net.get_output_layers()
net.compute_shape()
for l in outputs:
if l.is_op('output'):
url = l.get_output().url
output_tensor = url.replace('@', '').replace(':', '_').replace('/', '_')
shape = l.get_output().shape.dims
shape = [str(i) for i in shape]
output_tensor = output_tensor + '_' + '_'.join(shape)
output_tensor = 'iter_{}_'.format(iterations - 1) + output_tensor + '.tensor'
rule['rules'][index] = dict()
rule['rules'][index]['golden'] = output_tensor
# Modify 'tolerance' and 'threshold' based on actual condition
rule['rules'][index]['tolerance'] = 0.01
rule['rules'][index]['threshold'] = 0.95
index += 1
wksp_dir = 'wksp/{}_{}'.format(model_filename, quantized)
with open(os.path.join(wksp_dir, 'criterion.json'), 'w+') as f:
json.dump(rule, f, indent=4)
if os.path.exists(os.path.join(sys.path[0], "check_result.py")):
os.system("cp {}/check_result.py {}".format(sys.path[0], wksp_dir))
def main():
options = ArgumentParser()
options.add_argument("model", type=str, help="Model directory")
options.add_argument("quantized", type=str, help="Quantization type, including float32, " + ', '.join(list(QuantizerType.get_options()))
+ ", \'float32\' means not quantized.")
options.add_argument("--iterations", type=int, help="Running iterations.", default=1)
options.add_argument("--force_remove_permute", action="store_true",
help="Try to force remove permute of graph IO.\n"
"(Experimental use only) Force remove the head permute layers inserted after the input layer and "
"the tail permute layers inserted before the output layer from application. This argument is used "
"only for export of unify applications from models with NHWC layout data input/output, such as "
"TensorFlow, TensorFlow Lite, and Keras models. \n"
"For input layer, When this argument is not specified, permute layers are kept and the tensor"
"shape is in the NHWC layout. When this argument is specified, the tensor shape MAYBE in the NCHW "
"layout. Make sure that the feed data has the same layout as the first layer before "
"application deployed onto devices.\n"
" For example, for a TensorFlow model with input of (1,224,224,3) in the NHWC layout:\n"
"If this argument is not specified, the tensor with the shape (1,224,224,3) "
"NHWC layout is needed.\n"
"If this argument is specified, the tensor with the shape (1,3,224,224) "
"NCHW layout maybe needed.\n",
)
options.add_argument("--use_hybrid", action="store_true", help="if you use hybrid quantize,please set this --use_hybrid")
args = options.parse_args()
print(args)
if os.path.exists(args.model) and os.path.isdir(os.path.abspath(args.model)):
model_filename = get_modelfile_name(args.model)
if model_filename is None:
print("Please enter the path that includes the model.")
os.chdir(args.model)
else:
model_filename = args.model
quantized = args.quantized
iterations = args.iterations
force_remove_permute = args.force_remove_permute
use_hybrid = args.use_hybrid
quantized_format = QuantizerType.get_options()
if quantized not in quantized_format and quantized != 'float32':
print("Please enter the correct quantization format.")
quantized_format.insert(0, 'float32')
print(list(quantized_format))
sys.exit(1)
# load model
net = load_net(model_filename, quantized, use_hybrid)
# export
export(net, model_filename, quantized, force_remove_permute, use_hybrid)
# generate executable script
generate_exe_script(net, model_filename, quantized, iterations, use_hybrid)
# generate criterion.json
generate_criterion_json(net, model_filename, quantized, iterations, use_hybrid)
# measure
measure(net=net, model_filename=model_filename, quantized=quantized)
if __name__ == "__main__":
main()