From 1ec0709aa42fbb580e58b69c1c4f6d5c9fff4d7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=98=B1=E5=BF=83?= Date: Fri, 18 Nov 2022 09:03:11 +0000 Subject: [PATCH 1/3] =?UTF-8?q?=E9=A6=96=E6=AC=A1=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 王昱心 --- .../contrib/cv/Evo_levit_ACL/README.md | 211 ++++++++++++ .../contrib/cv/Evo_levit_ACL/ais_infer.py | 299 ++++++++++++++++++ .../contrib/cv/Evo_levit_ACL/evo_levit_fix.py | 30 ++ .../cv/Evo_levit_ACL/evo_levit_postprocess.py | 160 ++++++++++ .../cv/Evo_levit_ACL/evo_levit_pth2onnx.py | 39 +++ .../imagenet_torch_preprocess.py | 72 +++++ .../contrib/cv/Evo_levit_ACL/requirements.txt | 7 + 7 files changed, 818 insertions(+) create mode 100644 ACL_TensorFlow/contrib/cv/Evo_levit_ACL/README.md create mode 100644 ACL_TensorFlow/contrib/cv/Evo_levit_ACL/ais_infer.py create mode 100644 ACL_TensorFlow/contrib/cv/Evo_levit_ACL/evo_levit_fix.py create mode 100644 ACL_TensorFlow/contrib/cv/Evo_levit_ACL/evo_levit_postprocess.py create mode 100644 ACL_TensorFlow/contrib/cv/Evo_levit_ACL/evo_levit_pth2onnx.py create mode 100644 ACL_TensorFlow/contrib/cv/Evo_levit_ACL/imagenet_torch_preprocess.py create mode 100644 ACL_TensorFlow/contrib/cv/Evo_levit_ACL/requirements.txt diff --git a/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/README.md b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/README.md new file mode 100644 index 000000000..ec109bc76 --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/README.md @@ -0,0 +1,211 @@ +# 模型PyTorch离线推理指导 + +- [1 模型概述](#1-模型概述) + - [1.1 论文地址](#11-论文地址) + - [1.2 代码地址](#12-代码地址) +- [2 环境说明](#2-环境说明) + - [2.1 深度学习框架](#21-深度学习框架) + - [2.2 python第三方库](#22-python第三方库) +- [3 模型转换](#3-模型转换) + - [3.1 pth转onnx模型](#31-pth转onnx模型) + - [3.2 onnx转om模型](#32-onnx转om模型) +- [4 数据集预处理](#4-数据集预处理) + - [4.1 数据集获取](#41-数据集获取) + - [4.2 数据集预处理](#42-数据集预处理) + - [4.3 生成数据集信息文件](#43-生成数据集信息文件) +- [5 离线推理](#5-离线推理) + - [5.1 获取ais_infer推理工具](#51-获取ais_infer推理工具) + - [5.2 离线推理](#52-离线推理) +- [6 精度对比](#6-精度对比) + - [6.1 离线推理mAP精度统计](#61-离线推理mAP精度统计) + - [6.2 开源mAP精度](#62-开源mAP精度) + - [6.3 精度对比](#63-精度对比) +- [7 性能对比](#7-性能对比) + - [7.1 npu性能数据](#71-npu性能数据) + + + +## 1 模型概述 + +- **[论文地址](#11-论文地址)** + +- **[代码地址](#12-代码地址)** + +### 1.1 论文地址 +[论文](https://arxiv.org/abs/2202.07800) + +### 1.2 代码地址 +[代码](https://github.com/YifanXu74/Evo-ViT) +branch:master + +## 2 环境说明 + +- **[深度学习框架](#21-深度学习框架)** + +- **[python第三方库](#22-python第三方库)** + +### 2.1 深度学习框架 +``` +CANN 5.1.RC1 +torch==1.7.0 +torchvision==0.8.0 +onnx==1.8.0 +onnxruntime==1.9.0 +``` + +### 2.2 python第三方库 + +``` +numpy==1.20.0 +opencv-python==4.4.0.46 +``` + +**说明:** +> X86架构:pytorch,torchvision和onnx可以通过官方下载whl包安装,其它可以通过pip3.7 install 包名 安装 +> +> Arm架构:pytorch,torchvision和onnx可以通过源码编译安装,其它可以通过pip3.7 install 包名 安装 + +## 3 模型转换 + +- **[pth转onnx模型](#31-pth转onnx模型)** + +- **[onnx转om模型](#32-onnx转om模型)** + +### 3.1 pth转onnx模型 + +1.准备pth权重文件 +使用训练好的pth权重文件 + +2.使用开源仓,获取开源命令 + +``` +git clone https://github.com/YifanXu74/Evo-ViT.git +``` + +3.调用pth2onnx脚本导出ONNX模型。 +以batchsize为16为例,下同 +``` +python3 evo_levit_pth2onnx.py ../evo-levit-256.pth ../evo_levit_bs16.onnx 16 +``` +4.简化模型(依赖onnx-simplifier库) + +``` +python3 -m onnxsim evo_levit_bs16.onnx evo_levit_bs16_sim.onnx +``` + +5.改图 + +``` +# 安装依赖 +git clone https://gitee.com/Ronnie_zheng/MagicONNX.git MagicONNX +cd MagicONNX && git checkout 99a713801fe70db702e3903744d2a6372a975fea +pip3 install . && cd .. + +# 运行改图脚本 +python3 evo_levit_fix.py evo_levit_bs16_sim.onnx evo_levit_bs16_fix.onnx +``` + + **说明:** +>注意目前ATC支持的onnx算子版本为11 + + +### 3.2 onnx转om模型 + +1.设置环境变量 +``` +source /usr/local/Ascend/ascend-toolkit/set_env.sh +``` + +2.使用atc将onnx模型转换为om模型文件,工具使用方法可以参考CANN 5.0.1 开发辅助工具指南 (推理) +${chip_name}可通过npu-smi info指令查看,例:310P3 + +![Image](https://gitee.com/ascend/ModelZoo-PyTorch/raw/master/ACL_PyTorch/images/310P3.png) + +``` +atc --framework=5 --model=./evo_levit_bs16_fix.onnx --output=evo_levit_bs16.om --input_format=NCHW --input_shape="input:16,3,224,224" --log=debug --soc_version=Ascend310``` +运行成功后生成“evo_levit_bs16.om”模型文件。 +## 4 数据集预处理 + +- **[数据集获取](#41-数据集获取)** + +- **[数据集预处理](#42-数据集预处理)** + +- **[生成数据集信息文件](#43-生成数据集信息文件)** + +### 4.1 数据集获取 +自行获取LSVRC2012验证集和标签文本 + + +### 4.2 数据集预处理 + +执行“imagenet_torch_preprocess.py”脚本。 +``` +python3 imagenet_torch_preprocess.py /root/datasets/imagenet/val ./pre_dataset +``` + +## 5 离线推理 + +- **[获取ais_infer推理工具](#51-获取ais_infer推理工具)** + +- **[离线推理](#52-离线推理)** + +### 5.1 获取ais_infer推理工具 + +https://gitee.com/ascend/tools/tree/master/ais-bench_workload/tool/ais_infer + +将工具编译后的压缩包放置在当前目录;解压工具包,安装工具压缩包中的whl文件; pip3 install aclruntime-0.01-cp37-cp37m-linux_xxx.whl + +### 5.2 离线推理 +昇腾芯片上执行,执行时使npu-smi info查看设备状态,确保device空闲 + +1.设置环境变量 +``` +source /usr/local/Ascend/ascend-toolkit/set_env.sh +``` +2.执行离线推理 + +执行推理 +``` +python3 ais_infer.py --model ../evo_levit_bs16.om --input ../pre_dataset --output ../result/ +``` +参数说明: + +--model:模型地址 + +--input:预处理完的数据集文件夹 + +--output:推理结果保存地址 + + +## 6 精度对比 + +- **[离线推理mAP精度](#61-离线推理mAP精度)** +- **[开源mAP精度](#62-开源mAP精度)** +- **[精度对比](#63-精度对比)** + +### 6.1 离线推理mAP精度统计 + +### 6.2 开源mAP精度 + +### 6.3 精度对比 + +## 7 性能对比 + +- **[npu性能数据](#71-npu性能数据)** + +### 7.1 npu性能数据 +1.ais_infer工具在整个数据集上推理获得性能数据 +ais_infer工具在整个数据集上推理后生成result/sumary.json: +``` +[INFO] -----------------Performance Summary------------------ +[INFO] H2D_latency (ms): min = 1.7910003662109375, max = 1.7910003662109375, mean = 1.7910003662109375, median = 1.7910003662109375, percentile(99%) = 1.7910003662109375 +[INFO] NPU_compute_time (ms): min = 28.81999969482422, max = 29.11400032043457, mean = 28.912600135803224, median = 28.851500511169434, percentile(99%) = 29.11112035751343 +[INFO] D2H_latency (ms): min = 0.11444091796875, max = 0.11444091796875, mean = 0.11444091796875, median = 0.11444091796875, percentile(99%) = 0.11444091796875 +[INFO] throughput 1000*batchsize(16)/NPU_compute_time.mean(28.912600135803224): 553.3919441643985 + +``` +Interface throughputRate:1000 * batchsize/npu_compute_time.mean=553.39既是batch1 310P单卡吞吐率 + +**性能优化:** + +>没有遇到性能不达标的问题,故不需要进行性能优化 diff --git a/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/ais_infer.py b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/ais_infer.py new file mode 100644 index 000000000..f53ab628a --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/ais_infer.py @@ -0,0 +1,299 @@ +import argparse +import asyncio +import json +import logging +import os +import sys +import time + +import aclruntime +from tqdm import tqdm + +from frontend.io_oprations import (create_infileslist_from_inputs_list, + create_intensors_from_infileslist, + create_intensors_zerodata, + get_tensor_from_files_list, + outtensors_to_host, pure_infer_fake_file, + save_tensors_to_file) +from frontend.summary import summary +from frontend.utils import logger + + +def set_session_options(session, args): + # 增加校验 + if args.dymBatch != 0: + session.set_dynamic_batchsize(args.dymBatch) + elif args.dymHW !=None: + hwstr = args.dymHW.split(",") + session.set_dynamic_hw((int)(hwstr[0]), (int)(hwstr[1])) + elif args.dymDims !=None: + session.set_dynamic_dims(args.dymDims) + elif args.dymShape !=None: + session.set_dynamic_shape(args.dymShape) + else: + session.set_staticbatch() + + # 设置custom out tensors size + if args.outputSize != None: + customsizes = [int(n) for n in args.outputSize.split(',')] + logger.debug("set customsize:{}".format(customsizes)) + session.set_custom_outsize(customsizes) + + +def get_acl_json_path(args): + """ + get acl json path. when args.profiler is true or args.dump is True, create relative acl.json , default current folder + """ + if args.acl_json_path is not None: + return args.acl_json_path + if not args.profiler and not args.dump: + return None + + output_json_dict = {} + if args.profiler: + output_json_dict = {"profiler": {"switch": "on", "aicpu": "on", "output": "", "aic_metrics": ""}} + out_profiler_path = os.path.join(args.output, "profiler") + + if not os.path.exists(out_profiler_path): + os.mkdir(out_profiler_path) + output_json_dict["profiler"]["output"] = out_profiler_path + elif args.dump: + output_json_dict = {"dump": {"dump_path": "", "dump_mode": "output", "dump_list": [{"model_name": ""}]}} + out_dump_path = os.path.join(args.output, "dump") + + if not os.path.exists(out_dump_path): + os.mkdir(out_dump_path) + + model_name = args.model.split("/")[-1] + output_json_dict["dump"]["dump_path"] = out_dump_path + output_json_dict["dump"]["dump_list"][0]["model_name"] = model_name.split('.')[0] + + out_json_file_path = os.path.join(args.output, "acl.json") + with open(out_json_file_path, "w") as f: + json.dump(output_json_dict, f, indent=4, separators=(", ", ": "), sort_keys=True) + return out_json_file_path + +def init_inference_session(args): + options = aclruntime.session_options() + acl_json_path = get_acl_json_path(args) + if acl_json_path is not None: + options.acl_json_path = acl_json_path + if args.debug == True: + logger.setLevel(logging.DEBUG) + options.log_level = 1 + options.loop = args.loop + session = aclruntime.InferenceSession(args.model, args.device, options) + + set_session_options(session, args) + logger.debug("session info:{}".format(session)) + return session + +def run_inference_step(session, inputs, outputs_names, loop=1): + session.run_setinputs(inputs) + starttime = time.time() + session.run_execute(loop) + endtime = time.time() + summary.npu_compute_time_list.append(float(endtime - starttime) * 1000.0/loop) # millisecond + outputs = session.run_getoutputs(outputs_names) + return outputs + +def set_dymshape_shape(session, inputs): + l = [] + intensors_desc = session.get_inputs() + for i, input in enumerate(inputs): + if -1 in intensors_desc[i].shape: + str_shape = [ str(shape) for shape in input.shape ] + dyshape = "{}:{}".format(intensors_desc[i].name, ",".join(str_shape)) + l.append(dyshape) + dyshapes = ';'.join(l) + logger.debug("set dymshape shape:{}".format(dyshapes)) + session.set_dynamic_shape(dyshapes) + +def run_inference(session, inputs, outputs_names): + if args.auto_set_dymshape_mode == True: + set_dymshape_shape(session, inputs) + outputs = session.run(outputs_names, inputs) + return outputs + +def warmup(session, args, intensors_desc, outputs_names): + n_loop = 1 + inputs = create_intensors_zerodata(intensors_desc, args.device, args.pure_data_type) + run_inference_step(session, inputs, outputs_names, n_loop) + summary.reset() + session.reset_sumaryinfo() + logger.info("warm up {} times done".format(n_loop)) + +# Rotation training operation reference +def infer_loop_run(session, args, intensors_desc, infileslist, outputs_names, output_prefix): + for i, infiles in enumerate(tqdm(infileslist, file=sys.stdout, desc='Inference Processing')): + intensors = [] + for j, files in enumerate(infiles): + tensor = get_tensor_from_files_list(files, args.device, intensors_desc[j].realsize, args.pure_data_type, args.auto_set_dymshape_mode) + intensors.append(tensor) + outputs = run_inference(session, intensors, outputs_names) + outtensors_to_host(outputs) + if output_prefix != None: + save_tensors_to_file(outputs, output_prefix, infiles, args.outfmt, i, args.output_batchsize_axis) + +# First prepare the data, then execute the reference, and then write the file uniformly +def infer_fulltensors_run(session, args, intensors_desc, infileslist, outputs_names, output_prefix): + outtensors = [] + intensorslist = create_intensors_from_infileslist(infileslist, intensors_desc, args.device, args.pure_data_type, args.auto_set_dymshape_mode) + + #for inputs in intensorslist: + for inputs in tqdm(intensorslist, file=sys.stdout, desc='Inference Processing full'): + outputs = run_inference(session, inputs, outputs_names) + outtensors.append(outputs) + + for i, outputs in enumerate(outtensors): + outtensors_to_host(outputs) + if output_prefix != None: + save_tensors_to_file(outputs, output_prefix, infileslist[i], args.outfmt, i, args.output_batchsize_axis) + +async def in_task(inque, args, intensors_desc, infileslist): + logger.debug("in_task begin") + for i, infiles in enumerate(tqdm(infileslist, file=sys.stdout, desc='Inference Processing task')): + intensors = [] + for j, files in enumerate(infiles): + tensor = get_tensor_from_files_list(files, args.device, intensors_desc[j].realsize, args.pure_data_type, args.auto_set_dymshape_mode) + intensors.append(tensor) + await inque.put([intensors, infiles, i]) + await inque.put([None, None, None]) + logger.debug("in_task exit") + +async def infer_task(inque, session, outputs_names, args, outque): + logger.debug("infer_task begin") + while True: + intensors, infiles, i = await inque.get() + if intensors == None: + await outque.put([None, None, None]) + logger.debug("infer_task exit") + break + outputs = run_inference(session, intensors, outputs_names) + await outque.put([outputs, infiles, i]) + +async def out_task(outque, output_prefix, args): + logger.debug("out_task begin") + while True: + outputs, infiles, i = await outque.get() + if outputs == None: + logger.debug("out_task exit") + break + + outtensors_to_host(outputs) + if output_prefix != None: + save_tensors_to_file(outputs, output_prefix, infiles, args.outfmt, i, args.output_batchsize_axis) + +async def infer_pipeline_process_run(session, args, intensors_desc, infileslist, outputs_names, output_prefix): + inque = asyncio.Queue(maxsize=args.infer_queue_count) + outque = asyncio.Queue(maxsize=args.infer_queue_count) + + await asyncio.gather( + in_task(inque, args, intensors_desc, infileslist), + infer_task(inque, session, outputs_names, args, outque), + out_task(outque, output_prefix, args), + ) + +def str2bool(v): + if isinstance(v, bool): + return v + if v.lower() in ('yes', 'true', 't', 'y', '1'): + return True + elif v.lower() in ('no', 'false', 'f', 'n', '0'): + return False + else: + raise argparse.ArgumentTypeError('Boolean value expected true, 1, false, 0 with case insensitive.') + + +def check_positive_integer(value): + ivalue = int(value) + if ivalue <= 0: + raise argparse.ArgumentTypeError("%s is an invalid positive int value" % value) + return ivalue + + +def check_nonnegative_integer(value): + ivalue = int(value) + if ivalue < 0: + raise argparse.ArgumentTypeError("%s is an invalid nonnegative int value" % value) + return ivalue + + +def get_args(): + parser = argparse.ArgumentParser() + parser.add_argument("--model", "--om", required=True, help="the path of the om model") + parser.add_argument("--input", "-i", default=None, help="input file or dir") + parser.add_argument("--output", "-o", default=None, help="Inference data output path. The inference results are output to the subdirectory named current date under given output path") + parser.add_argument("--output_dirname", type=str, default=None, help="actual output directory name. Used with parameter output, cannot be used alone. The inference result is output to subdirectory named by output_dirname under output path. such as --output_dirname 'tmp', the final inference results are output to the folder of {$output}/tmp") + parser.add_argument("--outfmt", default="BIN", choices=["NPY", "BIN", "TXT"], help="Output file format (NPY or BIN or TXT)") + parser.add_argument("--loop", "-r", type=check_positive_integer, default=1, help="the round of the PrueInfer.") + parser.add_argument("--debug", type=str2bool, default=False, help="Debug switch,print model information") + parser.add_argument("--device", "--device", type=int, default=0, choices=range(0, 255), help="the NPU device ID to use") + parser.add_argument("--dymBatch", type=int, default=0, help="dynamic batch size param,such as --dymBatch 2") + parser.add_argument("--dymHW", type=str, default=None, help="dynamic image size param, such as --dymHW \"300,500\"") + parser.add_argument("--dymDims", type=str, default=None, help="dynamic dims param, such as --dymDims \"data:1,600;img_info:1,600\"") + parser.add_argument("--dymShape", type=str, help="dynamic shape param, such as --dymShape \"data:1,600;img_info:1,600\"") + parser.add_argument("--outputSize", type=str, default=None, help="output size for dynamic shape mode") + parser.add_argument("--auto_set_dymshape_mode", type=str2bool, default=False, help="auto_set_dymshape_mode") + parser.add_argument("--batchsize", type=int, default=1, help="batch size of input tensor") + parser.add_argument("--pure_data_type", type=str, default="zero", choices=["zero", "random"], help="null data type for pure inference(zero or random)") + parser.add_argument("--profiler", action="store_true", default=False, help="profiler switch") + parser.add_argument("--dump", action="store_true", default=False, help="dump switch") + parser.add_argument("--acl_json_path", type=str, default=None, help="acl json path for profiling or dump") + parser.add_argument("--infer_queue_count", type=check_positive_integer, default=20, help="Maximum number of data in inference queue, such as --maxqueue 15") + parser.add_argument("--output_batchsize_axis", type=check_nonnegative_integer, default=0, help="splitting axis number when outputing tensor results, such as --output_batchsize_axis 12") + + args = parser.parse_args() + + if args.profiler is True and args.dump is True: + logger.error("parameter --profiler cannot be true at the same time as parameter --dump, please check them!\n") + raise RuntimeError('error bad parameters --profiler and --dump') + + if (args.profiler is True or args.dump is True) and (args.output is None): + logger.error("when dump or profiler, miss output path, please check them!") + raise RuntimeError('miss output parameter!') + + return args + +if __name__ == "__main__": + args = get_args() + + session = init_inference_session(args) + + intensors_desc = session.get_inputs() + outtensors_desc = session.get_outputs() + + if args.output != None: + if args.output_dirname is None: + timestr = time.strftime("%Y_%m_%d-%H_%M_%S") + output_prefix = os.path.join(args.output, timestr) + else: + output_prefix = os.path.join(args.output, args.output_dirname) + if not os.path.exists(output_prefix): + os.mkdir(output_prefix, 0o755) + logger.info("output path:{}".format(output_prefix)) + else: + output_prefix = None + + outputs_names = [desc.name for desc in outtensors_desc] + + if args.auto_set_dymshape_mode == False: + warmup(session, args, intensors_desc, outputs_names) + + inputs_list = [] if args.input == None else args.input.split(',') + + # create infiles list accord inputs list + if len(inputs_list) == 0: + # Pure reference scenario. Create input zero data + infileslist = [[ [ pure_infer_fake_file ] for index in intensors_desc ]] + else: + infileslist = create_infileslist_from_inputs_list(inputs_list, intensors_desc, args.auto_set_dymshape_mode) + + #infer_fulltensors_run(session, args, intensors_desc, infileslist, outputs_names, output_prefix) + infer_loop_run(session, args, intensors_desc, infileslist, outputs_names, output_prefix) + #asyncio.run(infer_pipeline_process_run(session, args, intensors_desc, infileslist, outputs_names, output_prefix)) + + summary.add_args(sys.argv) + s = session.sumary() + summary.npu_compute_time_list = s.exec_time_list + summary.report(args.batchsize, output_prefix) diff --git a/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/evo_levit_fix.py b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/evo_levit_fix.py new file mode 100644 index 000000000..7dae656d0 --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/evo_levit_fix.py @@ -0,0 +1,30 @@ +import sys +import numpy as np +from magiconnx import OnnxGraph +from magiconnx.optimize.optimizer_manager import OptimizerManager + +def main(input_file, output_file): + # Int64ToInt32 + graph = OnnxGraph(input_file) + optimize_manager_cus = OptimizerManager(graph, optimizers=['Int64ToInt32Optimizer']) + optimized_graph = optimize_manager_cus.apply() + + # fix concat dtype + # weight = np.array(optimized_graph['onnx::Concat_330'].value, dtype='float32') + # optimized_graph['onnx::Concat_330'].value = weight + + concat_nodes = optimized_graph.get_nodes('Concat') + for concat_node in concat_nodes: + if len(concat_node.inputs) == 3: + for input_name in concat_node.inputs: + if optimized_graph[input_name].op_type == 'Initializer': + ini_name = input_name + weight = np.array(optimized_graph[ini_name].value, dtype='float32') + optimized_graph[ini_name].value = weight + + optimized_graph.save(output_file) + +if __name__=="__main__": + input_file = sys.argv[1] + output_file = sys.argv[2] + main(input_file, output_file) diff --git a/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/evo_levit_postprocess.py b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/evo_levit_postprocess.py new file mode 100644 index 000000000..9210eed13 --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/evo_levit_postprocess.py @@ -0,0 +1,160 @@ +import os +import sys +import json +import numpy as np +import argparse + +np.set_printoptions(threshold=sys.maxsize) + +LABEL_FILE = "HiAI_label.json" + + +def gen_file_name(img_name): + full_name = img_name.split('/')[-1] + index = full_name.rfind('.') + return full_name[:index] + + +def cre_groundtruth_dict(gtfile_path): + """ + :param filename: file contains the imagename and label number + :return: dictionary key imagename, value is label number + """ + img_gt_dict = {} + for gtfile in os.listdir(gtfile_path): + if (gtfile != LABEL_FILE): + with open(os.path.join(gtfile_path, gtfile), 'r') as f: + gt = json.load(f) + ret = gt["image"]["annotations"][0]["category_id"] + img_gt_dict[gen_file_name(gtfile)] = ret + return img_gt_dict + + +def cre_groundtruth_dict_fromtxt(gtfile_path): + """ + :param filename: file contains the imagename and label number + :return: dictionary key imagename, value is label number + """ + img_gt_dict = {} + with open(gtfile_path, 'r')as f: + for line in f.readlines(): + temp = line.strip().split(" ") + imgName = temp[0].split(".")[0] + imgLab = temp[1] + img_gt_dict[imgName] = imgLab + return img_gt_dict + + +def load_statistical_predict_result(filepath): + """ + function: + the prediction esult file data extraction + input: + result file:filepath + output: + n_label:numble of label + data_vec: the probabilitie of prediction in the 1000 + :return: probabilities, numble of label, in_type, color + """ + with open(filepath, 'r')as f: + data = f.readline() + temp = data.strip().split(" ") + n_label = len(temp) + if data == '': + n_label = 0 + data_vec = np.zeros((n_label), dtype=np.float32) + in_type = '' + color = '' + if n_label == 0: + in_type = f.readline() + color = f.readline() + else: + for ind, prob in enumerate(temp): + data_vec[ind] = np.float32(prob) + return data_vec, n_label, in_type, color + + +def create_visualization_statistical_result(prediction_file_path, + result_file, img_gt_dict, + topn=5): + """ + :param prediction_file_path: + :param result_file: + :param img_gt_dict: + :param topn: + :return: + """ + writer = open(result_file, 'w') + table_dict = {} + table_dict["title"] = "Overall statistical evaluation" + table_dict["value"] = [] + + count = 0 + resCnt = 0 + count_hit = np.zeros(topn) + for tfile_name in os.listdir(prediction_file_path): + count += 1 + temp = tfile_name.split('.')[0] + print(temp) + index1 = temp.rfind('_') + a = temp[:index1] + index2 = a.rfind('_') + img_name = temp[:index2] + filepath = os.path.join(prediction_file_path, tfile_name) + ret = load_statistical_predict_result(filepath) + prediction = ret[0] + n_labels = ret[1] + sort_index = np.argsort(-prediction) + print(img_name) + gt = img_gt_dict[img_name] + if (n_labels == 1000): + realLabel = int(gt) + elif (n_labels == 1001): + realLabel = int(gt) + 1 + else: + realLabel = int(gt) + + resCnt = min(len(sort_index), topn) + for i in range(resCnt): + if (str(realLabel) == str(sort_index[i])): + count_hit[i] += 1 + break + + if 'value' not in table_dict.keys(): + print("the item value does not exist!") + else: + table_dict["value"].extend( + [{"key": "Number of images", "value": str(count)}, + {"key": "Number of classes", "value": str(n_labels)}]) + accuracy = np.cumsum(count_hit) / count + for i in range(resCnt): + table_dict["value"].append({"key": "Top" + str(i + 1) + " accuracy", + "value": str( + round(accuracy[i] * 100, 2)) + '%'}) + json.dump(table_dict, writer) + writer.close() + + +def check_args(args): + if not (os.path.exists(args.anno_file)): + print("annotation file:{} does not exist.".format(args.anno_file)) + exit() + if not (os.path.exists(args.benchmark_out)): + print("benchmark output:{} does not exist.".format(args.benchmark_out)) + exit() + return args + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Precision statistics of Vision model') + parser.add_argument("--anno_file", default="./HiAI_label.json", help='annotation file') + parser.add_argument("--benchmark_out", default="result/dumpOutput_device0", help='Benchmark output directory') + parser.add_argument("--result_file", default="./result.json", help='Output json file') + args = parser.parse_args() + args = check_args(args) + if args.anno_file.endswith('txt'): + img_label_dict = cre_groundtruth_dict_fromtxt(args.anno_file) + + else: + img_label_dict = cre_groundtruth_dict(args.anno_file) + create_visualization_statistical_result(args.benchmark_out, args.result_file, img_label_dict, topn=5) \ No newline at end of file diff --git a/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/evo_levit_pth2onnx.py b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/evo_levit_pth2onnx.py new file mode 100644 index 000000000..5435356c2 --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/evo_levit_pth2onnx.py @@ -0,0 +1,39 @@ +import sys +import torch +import torchvision +from levit import evo_levit +from timm import create_model + +import pdb + + + +def pth2onnx(input_file, output_file, batch_size): + + model = create_model( + 'EvoLeViT_256', + num_classes=1000, + distillation=(False), + pretrained=False, + fuse=True, + ) + + checkpoint = torch.load(input_file, map_location='cpu') + checkpoint = checkpoint['model'] + model.load_state_dict(checkpoint, strict=False) + + model.eval() + dummy_input = torch.randn(int(batch_size), 3, 224, 224) + input_names = ["input"] + output_names = ["output"] + torch.onnx.export(model, dummy_input, output_file, verbose=True, input_names=input_names, + opset_version=11, + output_names=output_names) + +if __name__=="__main__": + input_file = sys.argv[1] + output_file = sys.argv[2] + batch_size = sys.argv[3] + pth2onnx(input_file, output_file, batch_size) + + diff --git a/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/imagenet_torch_preprocess.py b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/imagenet_torch_preprocess.py new file mode 100644 index 000000000..6b598ece2 --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/imagenet_torch_preprocess.py @@ -0,0 +1,72 @@ +import os +import sys +from PIL import Image +import numpy as np +import multiprocessing + + +def center_crop(img, output_size): + if isinstance(output_size, int): + output_size = (int(output_size), int(output_size)) + image_width, image_height = img.size + crop_height, crop_width = output_size + crop_top = int(round((image_height - crop_height) / 2.)) + crop_left = int(round((image_width - crop_width) / 2.)) + return img.crop((crop_left, crop_top, crop_left + crop_width, crop_top + crop_height)) + + +def resize(img, size, interpolation=Image.BILINEAR): + if isinstance(size, int): + w, h = img.size + if (w <= h and w == size) or (h <= w and h == size): + return img + if w < h: + ow = size + oh = int(size * h / w) + return img.resize((ow, oh), interpolation) + else: + oh = size + ow = int(size * w / h) + return img.resize((ow, oh), interpolation) + else: + return img.resize(size[::-1], interpolation) + + +def gen_input_bin(file_batches, batch): + i = 0 + for file in file_batches[batch]: + i =i + 1 + print("batch", batch, file, "===", i) + + # RGBA to RGB + image = Image.open(os.path.join(src_path, file)).convert('RGB') + image = resize(image, 256) # Resize + image = center_crop(image, 224) # CenterCrop + img = np.array(image, dtype=np.float32) + img = img.transpose(2, 0, 1) # ToTensor: HWC -> CHW + img = img / 255. # ToTensor: div 255 + img -= np.array([0.485, 0.456, 0.406], dtype=np.float32)[:, None, None] # Normalize: mean + img /= np.array([0.229, 0.224, 0.225], dtype=np.float32)[:, None, None] # Normalize: std + img.tofile(os.path.join(save_path, file.split('.')[0] + ".bin")) + + +def preprocess(src_path): + files = os.listdir(src_path) + file_batches = [files[i:i + 500] for i in range(0, 50000, 500) if files[i:i + 500] != []] + thread_pool = multiprocessing.Pool(len(file_batches)) + for batch in range(len(file_batches)): + thread_pool.apply_async(gen_input_bin, args=(file_batches, batch)) + thread_pool.close() + thread_pool.join() + + +if __name__ == '__main__': + if len(sys.argv) < 3: + raise Exception("usage: python3 xxx.py[src_path] [save_path]") + src_path = sys.argv[1] + save_path = sys.argv[2] + src_path = os.path.realpath(src_path) + save_path = os.path.realpath(save_path) + if not os.path.isdir(save_path): + os.makedirs(os.path.realpath(save_path)) + preprocess(src_path) diff --git a/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/requirements.txt b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/requirements.txt new file mode 100644 index 000000000..1d4e4eb71 --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/requirements.txt @@ -0,0 +1,7 @@ +python3.7.5 +onnx=1.7.0 +torch=1.5.0 +torchvision=0.6.0 +numpy=1.18.5 +opencv-python=3.3.1 +pillow=7.2.0 \ No newline at end of file -- Gitee From 53f18e66c227b6a32ed0ede497f56323aed82065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=98=B1=E5=BF=83?= Date: Fri, 18 Nov 2022 09:09:36 +0000 Subject: [PATCH 2/3] update ACL_TensorFlow/contrib/cv/Evo_levit_ACL/README.md. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 王昱心 --- ACL_TensorFlow/contrib/cv/Evo_levit_ACL/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/README.md b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/README.md index ec109bc76..c7522821f 100644 --- a/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/README.md +++ b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/README.md @@ -122,7 +122,8 @@ ${chip_name}可通过npu-smi info指令查看,例:310P3 ![Image](https://gitee.com/ascend/ModelZoo-PyTorch/raw/master/ACL_PyTorch/images/310P3.png) ``` -atc --framework=5 --model=./evo_levit_bs16_fix.onnx --output=evo_levit_bs16.om --input_format=NCHW --input_shape="input:16,3,224,224" --log=debug --soc_version=Ascend310``` +atc --framework=5 --model=./evo_levit_bs16_fix.onnx --output=evo_levit_bs16.om --input_format=NCHW --input_shape="input:16,3,224,224" --log=debug --soc_version=Ascend310 +``` 运行成功后生成“evo_levit_bs16.om”模型文件。 ## 4 数据集预处理 -- Gitee From 2943b1f5e893b6fcec426cfb0bfd7b3f6cf84dc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=98=B1=E5=BF=83?= Date: Fri, 18 Nov 2022 09:17:25 +0000 Subject: [PATCH 3/3] =?UTF-8?q?=E6=8F=90=E4=BA=A4license?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 王昱心 --- .../contrib/cv/Evo_levit_ACL/LICENSE | 203 ++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 ACL_TensorFlow/contrib/cv/Evo_levit_ACL/LICENSE diff --git a/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/LICENSE b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/LICENSE new file mode 100644 index 000000000..7cc7b9344 --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/Evo_levit_ACL/LICENSE @@ -0,0 +1,203 @@ +Copyright 2019 The TensorFlow Authors. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file -- Gitee