已合并
【自研】【Pytorch离线推理】Resnet50推理工具适配ais-infer #1571
liuzhuheng创建于 2022年8月24日
【自研】【Pytorch离线推理】Resnet50推理工具适配ais-infer #1571
已合并
共 4 个文件变更+284-178
| @@ -0,0 +1,237 @@ | |||
| 1 | +# Resnet50-推理指导 | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +- [概述](#ZH-CN_TOPIC_0000001172161501) | ||
| 5 | + | ||
| 6 | +- [推理环境准备](#ZH-CN_TOPIC_0000001126281702) | ||
| 7 | + | ||
| 8 | +- [快速上手](#ZH-CN_TOPIC_0000001126281700) | ||
| 9 | + | ||
| 10 | + - [获取源码](#section4622531142816) | ||
| 11 | + - [准备数据集](#section183221994411) | ||
| 12 | + - [模型推理](#section741711594517) | ||
| 13 | + | ||
| 14 | +- [模型推理性能](#ZH-CN_TOPIC_0000001172201573) | ||
| 15 | + | ||
| 16 | +- [配套环境](#ZH-CN_TOPIC_0000001126121892) | ||
| 17 | + | ||
| 18 | + ****** | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +# 概述<a name="ZH-CN_TOPIC_0000001172161501"></a> | ||
| 23 | + | ||
| 24 | +Resnet是残差网络(Residual Network)的缩写,该系列网络广泛用于目标分类等领域以及作为计算机视觉任务主干经典神经网络的一部分,典型的网络有resnet50, resnet101等。Resnet网络的证明网络能够向更深(包含更多隐藏层)的方向发展。 | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +- 参考实现: | ||
| 28 | + | ||
| 29 | + ``` | ||
| 30 | + url=https://pytorch.org/vision/stable/_modules/torchvision/models/resnet.html | ||
| 31 | + ``` | ||
| 32 | + | ||
| 33 | + 通过Git获取对应commit\_id的代码方法如下: | ||
| 34 | + | ||
| 35 | + ``` | ||
| 36 | + git clone https://gitee.com/ascend/ModelZoo-PyTorch.git # 克隆仓库的代码 | ||
| 37 | + cd /ACL_PyTorch/built-in/cv/Resnet50_Pytorch_Infer # 切换到模型的代码仓目录 | ||
| 38 | + git checkout master # 切换到对应分支 | ||
| 39 | + ``` | ||
| 40 | + | ||
| 41 | + | ||
| 42 | +## 输入输出数据<a name="section540883920406"></a> | ||
| 43 | + | ||
| 44 | +- 输入数据 | ||
| 45 | + | ||
| 46 | + | 输入数据 | 数据类型 | 大小 | 数据排布格式 | | ||
| 47 | + | -------- | -------- | ------------------------- | ------------ | | ||
| 48 | + | input | RGB_FP32 | batchsize x 3 x 256 x 256 | NCHW | | ||
| 49 | + | ||
| 50 | + | ||
| 51 | +- 输出数据 | ||
| 52 | + | ||
| 53 | + | 输出数据 | 大小 | 数据类型 | 数据排布格式 | | ||
| 54 | + | -------- | -------- | -------- | ------------ | | ||
| 55 | + | output1 | 1 x 1000 | FLOAT32 | ND | | ||
| 56 | + | ||
| 57 | + | ||
| 58 | + | ||
| 59 | +# 推理环境准备<a name="ZH-CN_TOPIC_0000001126281702"></a> | ||
| 60 | + | ||
| 61 | +- 该模型需要以下插件与驱动 | ||
| 62 | + | ||
| 63 | + **表 1** 版本配套表 | ||
| 64 | + | ||
| 65 | +| 配套 | 版本 | 环境准备指导 | | ||
| 66 | +| ------------------------------------------------------------ | ------- | ------------------------------------------------------------ | | ||
| 67 | +| 固件与驱动 | 1.0.15 | [Pytorch框架推理环境准备](https://www.hiascend.com/document/detail/zh/ModelZoo/pytorchframework/pies) | | ||
| 68 | +| CANN | 5.1.RC2 | - | | ||
| 69 | +| Python | 3.7.5 | - | | ||
| 70 | +| PyTorch | >1.5.0 | - | | ||
| 71 | +| 说明:Atlas 300I Duo 推理卡请以CANN版本选择实际固件与驱动版本。 | \ | \ | | ||
| 72 | + | ||
| 73 | +# 快速上手<a name="ZH-CN_TOPIC_0000001126281700"></a> | ||
| 74 | + | ||
| 75 | + | ||
| 76 | + | ||
| 77 | +1. 安装依赖。 | ||
| 78 | + | ||
| 79 | + ``` | ||
| 80 | + pip3 install -r requirment.txt | ||
| 81 | + ``` | ||
| 82 | + | ||
| 83 | + | ||
| 84 | +## 准备数据集<a name="section183221994411"></a> | ||
| 85 | + | ||
| 86 | +1. 获取原始数据集。(解压命令参考tar –xvf \*.tar与 unzip \*.zip) | ||
| 87 | + | ||
| 88 | + 本模型使用ImageNet 50000张图片的验证集,请前往ImageNet官网下载数据集 | ||
| 89 | + | ||
| 90 | + ``` | ||
| 91 | + ├── ImageNet | ||
| 92 | + | ├── val | ||
| 93 | + | | ├── ILSVRC2012_val_00000001.JPEG | ||
| 94 | + │ | ├── ILSVRC2012_val_00000002.JPEG | ||
| 95 | + │ | ├── ...... | ||
| 96 | + | ├── val_label.txt | ||
| 97 | + ``` | ||
| 98 | + | ||
| 99 | +2. 数据预处理。\(请拆分sh脚本,将命令分开填写\) | ||
| 100 | + | ||
| 101 | + 数据预处理将原始数据集转换为模型输入的数据。 | ||
| 102 | + | ||
| 103 | + 执行imagenet_torch_preprocess.py脚本,完成预处理。 | ||
| 104 | + | ||
| 105 | + ``` | ||
| 106 | + python3 imagenet_torch_preprocess.py resnet ./ImageNet/val ./prep_dataset | ||
| 107 | + | ||
| 108 | + 每个图像对应生成一个二进制文件。运行成功后,在当前目录下生成prep_dataset二进制文件夹 | ||
| 109 | + ``` | ||
| 110 | + | ||
| 111 | + | ||
| 112 | +## 模型推理<a name="section741711594517"></a> | ||
| 113 | + | ||
| 114 | +1. 模型转换。 | ||
| 115 | + | ||
| 116 | + 使用PyTorch将模型权重文件.pth转换为.onnx文件,再使用ATC工具将.onnx文件转为离线推理模型文件.om文件。 | ||
| 117 | + | ||
| 118 | + 1. 获取权重文件。 | ||
| 119 | + | ||
| 120 | + 前往[Pytorch官方文档](https://pytorch.org/vision/stable/_modules/torchvision/models/resnet.html#resnet50)下载对应权重,参考下载权重如下: | ||
| 121 | + | ||
| 122 | +  | ||
| 123 | + | ||
| 124 | + 2. 导出onnx文件。 | ||
| 125 | + | ||
| 126 | + 1. 使用pth2onnx.py导出onnx文件。 | ||
| 127 | + | ||
| 128 | + 运行pth2onnx.py脚本。 | ||
| 129 | + | ||
| 130 | + ``` | ||
| 131 | + python3 pth2onnx.py ./resnet50-0676ba61.pth | ||
| 132 | + ``` | ||
| 133 | + | ||
| 134 | + 获得resnet50_official.onnx文件。 | ||
| 135 | + | ||
| 136 | + 3. 使用ATC工具将ONNX模型转OM模型。 | ||
| 137 | + | ||
| 138 | + 1. 配置环境变量。 | ||
| 139 | + | ||
| 140 | + ``` | ||
| 141 | + source /usr/local/Ascend/ascend-toolkit/set_env.sh | ||
| 142 | + ``` | ||
| 143 | + | ||
| 144 | + > **说明:** | ||
| 145 | + >该脚本中环境变量仅供参考,请以实际安装环境配置环境变量。详细介绍请参见《[CANN 开发辅助工具指南 \(推理\)](https://support.huawei.com/enterprise/zh/ascend-computing/cann-pid-251168373?category=developer-documents&subcategory=auxiliary-development-tools)》。 | ||
| 146 | + | ||
| 147 | + 2. 执行命令查看芯片名称($\{chip\_name\})。 | ||
| 148 | + | ||
| 149 | + ``` | ||
| 150 | + npu-smi info | ||
| 151 | + #该设备芯片名为Ascend310P3 (请根据实际芯片填入) | ||
| 152 | + 回显如下: | ||
| 153 | + +-------------------+-----------------+------------------------------------------------------+ | ||
| 154 | + | NPU Name | Health | Power(W) Temp(C) Hugepages-Usage(page) | | ||
| 155 | + | Chip Device | Bus-Id | AICore(%) Memory-Usage(MB) | | ||
| 156 | + +===================+=================+======================================================+ | ||
| 157 | + | 0 310P3 | OK | 15.8 42 0 / 0 | | ||
| 158 | + | 0 0 | 0000:82:00.0 | 0 1074 / 21534 | | ||
| 159 | + +===================+=================+======================================================+ | ||
| 160 | + | 1 310P3 | OK | 15.4 43 0 / 0 | | ||
| 161 | + | 0 1 | 0000:89:00.0 | 0 1070 / 21534 | | ||
| 162 | + +===================+=================+======================================================+ | ||
| 163 | + ``` | ||
| 164 | + | ||
| 165 | + 3. 执行ATC命令。 | ||
| 166 | + | ||
| 167 | + ``` | ||
| 168 | + atc --model=resnet50_official.onnx --framework=5 --output=resnet50_bs64 --input_format=NCHW --input_shape="actual_input_1:64,3,224,224" --enable_small_channel=1 --log=error --soc_version=Ascend${chip_name} --insert_op_conf=aipp_resnet50.aippconfig | ||
| 169 | + | ||
| 170 | + 备注:Ascend${chip_name}请根据实际查询结果填写 | ||
| 171 | + ``` | ||
| 172 | + | ||
| 173 | + - 参数说明: | ||
| 174 | + | ||
| 175 | + - --model:为ONNX模型文件。 | ||
| 176 | + - --framework:5代表ONNX模型。 | ||
| 177 | + - --output:输出的OM模型。 | ||
| 178 | + - --input\_format:输入数据的格式。 | ||
| 179 | + - --input\_shape:输入数据的shape。 | ||
| 180 | + - --log:日志级别。 | ||
| 181 | + - --soc\_version:处理器型号。 | ||
| 182 | + - --insert\_op\_conf: AIPP插入节点,通过config文件配置算子信息,功能包括图片色域转换、裁剪、归一化,主要用于处理原图输入数据,常与DVPP配合使用,详见下文数据预处理。 | ||
| 183 | + | ||
| 184 | + 运行成功后生成resnet50_bs64.om模型文件。 | ||
| 185 | + | ||
| 186 | + | ||
| 187 | + | ||
| 188 | +2.开始推理验证。 | ||
| 189 | + | ||
| 190 | +a. 使用ais-infer工具进行推理。 | ||
| 191 | + | ||
| 192 | +参考[ais-infer工具源码地址](https://gitee.com/ascend/tools/tree/master/ais-bench_workload/tool/ais_infer)安装将工具编译后的压缩包放置在当前目录;解压工具包,安装工具压缩包中的whl文件; | ||
| 193 | + | ||
| 194 | +``` | ||
| 195 | + pip3 install aclruntime-0.01-cp37-cp37m-linux_xxx.whl | ||
| 196 | +``` | ||
| 197 | + | ||
| 198 | +b. 执行推理。 | ||
| 199 | + | ||
| 200 | + source /usr/local/Ascend/ascend-toolkit/set_env.sh | ||
| 201 | + | ||
| 202 | + python3 ./ais_infer_x86_64/ais_infer.py --model ./resnet50_bs64.om --input ./prep_dataset/ --output ./result/ --outfmt TXT | ||
| 203 | + | ||
| 204 | + - 参数说明: | ||
| 205 | + --model:模型地址 | ||
| 206 | + --input:预处理完的数据集文件夹 | ||
| 207 | + --output:推理结果保存地址 | ||
| 208 | + --outfmt:推理结果保存格式 | ||
| 209 | + | ||
| 210 | + 运行成功后会在result/xxxx_xx_xx-xx-xx-xx(时间戳)下生成推理输出的txt文件。 | ||
| 211 | + | ||
| 212 | + **说明:** | ||
| 213 | + 执行ais-infer工具请选择与运行环境架构相同的命令。参数详情请参见 --help命令。 | ||
| 214 | + | ||
| 215 | +**因工具限制,需要把result/xxxx_xx_xx-xx-xx-xx/summary.json从结果目录中删除,或者迁移到其他目录;** | ||
| 216 | + | ||
| 217 | +c. 精度验证。 | ||
| 218 | + | ||
| 219 | +统计推理输出的Top 1-5 Accuracy | ||
| 220 | +调用脚本与数据集标签val\_label.txt比对,可以获得Accuracy数据,结果保存在result.json中。 | ||
| 221 | + | ||
| 222 | + python3 vision_metric_ImageNet.py result/xxxx_xx_xx-xx-xx-xx(时间戳) ./val_label.txt ./ result.json | ||
| 223 | + | ||
| 224 | + result/xxxx_xx_xx-xx-xx-xx(时间戳):为推理结果所在路径 | ||
| 225 | + | ||
| 226 | + val_label.txt:为标签数据 | ||
| 227 | + | ||
| 228 | + result.json:为生成结果文件 | ||
| 229 | + | ||
| 230 | +# 模型推理性能&精度<a name="ZH-CN_TOPIC_0000001172201573"></a> | ||
| 231 | + | ||
| 232 | +调用ACL接口推理计算,性能参考下列数据。 | ||
| 233 | + | ||
| 234 | +| 芯片型号 | Batch Size | 数据集 | 精度 | 性能 | | ||
| 235 | +| --------- | ---------------- | ---------- | ---------- | --------------- | | ||
| 236 | +| 310P3 | 64 | ImageNet | top-1: 76.14% ;top-5: 92.87% | 4250 | | ||
| 237 | + | ||
| @@ -1,94 +0,0 @@ | |||
| 1 | -# Resnet50模型PyTorch离线推理指导 | ||
| 2 | - | ||
| 3 | -## 1 准备数据集 | ||
| 4 | - | ||
| 5 | -1. 获取原始数据集 | ||
| 6 | - | ||
| 7 | - 本模型使用ImageNet 50000张图片的验证集,请前往ImageNet官网下载数据集 | ||
| 8 | - | ||
| 9 | - ``` | ||
| 10 | - ├── ImageNet | ||
| 11 | - | ├── val | ||
| 12 | - | | ├── ILSVRC2012_val_00000001.JPEG | ||
| 13 | - │ | ├── ILSVRC2012_val_00000002.JPEG | ||
| 14 | - │ | ├── ...... | ||
| 15 | - | ├── val_label.txt | ||
| 16 | - ``` | ||
| 17 | - | ||
| 18 | -2. 数据预处理 | ||
| 19 | - | ||
| 20 | - 1. 将原始数据集转换为模型输入的数据 | ||
| 21 | - | ||
| 22 | - ``` | ||
| 23 | - python3.7.5 imagenet_torch_preprocess.py resnet ./ImageNet/val ./prep_dataset | ||
| 24 | - ``` | ||
| 25 | - | ||
| 26 | - 每个图像对应生成一个二进制文件。运行成功后,在当前目录下生成prep_dataset二进制文件夹 | ||
| 27 | - | ||
| 28 | - 2. 获取benchmark推理工具所需的数据集info文件 | ||
| 29 | - | ||
| 30 | - ``` | ||
| 31 | - python3.7.5 gen_dataset_info.py bin ./prep_dataset ./resnet50_prep_bin.info 256 256 | ||
| 32 | - ``` | ||
| 33 | - | ||
| 34 | - 运行成功后,在当前目录下生成resnet50_prep_bin.info文件 | ||
| 35 | - | ||
| 36 | - | ||
| 37 | -## 3 模型生成 | ||
| 38 | - | ||
| 39 | -1. 生成onnx模型 | ||
| 40 | - | ||
| 41 | - 1. 获取权重文件 | ||
| 42 | - | ||
| 43 | - 前往[Pytorch官方文档](https://pytorch.org/vision/stable/_modules/torchvision/models/resnet.html#resnet50)下载 | ||
| 44 | - | ||
| 45 | - 2. 导出onnx文件 | ||
| 46 | - | ||
| 47 | - ``` | ||
| 48 | - python3.7.5 pth2onnx.py ./resnet50-0676ba61.pth | ||
| 49 | - ``` | ||
| 50 | - | ||
| 51 | -2. 将onnx转为om模型 | ||
| 52 | - | ||
| 53 | - 1. 配置环境变量 | ||
| 54 | - ``` | ||
| 55 | - source /usr/local/Ascend/ascend-toolkit/set_env.sh | ||
| 56 | - ``` | ||
| 57 | - | ||
| 58 | - 2. 使用ATC工具将onnx模型转om模型 | ||
| 59 | - | ||
| 60 | - ${chip_name}可通过`npu-smi info`指令查看 | ||
| 61 | - | ||
| 62 | -  | ||
| 63 | - | ||
| 64 | - ``` | ||
| 65 | - # Ascend310 or Ascend310P[1-4] | ||
| 66 | - atc --model=resnet50_official.onnx --framework=5 --output=resnet50_bs16 --input_format=NCHW --input_shape="actual_input_1:16,3,224,224" --enable_small_channel=1 --log=error --soc_version=Ascend${chip_name} --insert_op_conf=aipp_resnet50.aippconfig | ||
| 67 | - ``` | ||
| 68 | - | ||
| 69 | - 运行成功后生成resnet50_bs16.om模型文件 | ||
| 70 | - | ||
| 71 | -## 4 离线推理 | ||
| 72 | - | ||
| 73 | -1. 安装benchmark工具 | ||
| 74 | - | ||
| 75 | - 参考[benchmark工具源码地址](https://gitee.com/ascend/cann-benchmark/tree/master/infer)安装 | ||
| 76 | - | ||
| 77 | -2. 模型推理 | ||
| 78 | - | ||
| 79 | - ``` | ||
| 80 | - source /usr/local/Ascend/ascend-toolkit/set_env.sh | ||
| 81 | - ./benchmark.x86_64 -model_type=vision -batch_size=16 -device_id=0 -input_text_path=resnet50_prep_bin.info -input_width=256 -input_height=256 -om_path=./resnet50_bs16.om -useDvpp=False -output_binary=False | ||
| 82 | - ``` | ||
| 83 | - | ||
| 84 | - 运行成功后会在result/dumpOutput_device0下生成推理输出的txt文件 | ||
| 85 | - | ||
| 86 | -3. 精度验证 | ||
| 87 | - | ||
| 88 | - 统计推理输出的Top 1-5 Accuracy | ||
| 89 | - | ||
| 90 | - ``` | ||
| 91 | - python3.7.5 vision_metric_ImageNet.py result/dumpOutput_device0/ ./ImageNet/val_label.txt ./ result_prep.json | ||
| 92 | - ``` | ||
| 93 | - | ||
| 94 | - 运行成功后再当前目录下生成记录精度结果的result_prep.json | ||
| @@ -15,6 +15,7 @@ | |||
| 15 | import os | 15 | import os |
| 16 | import sys | 16 | import sys |
| 17 | from PIL import Image | 17 | from PIL import Image |
| 18 | +from tqdm import tqdm | ||
| 18 | import numpy as np | 19 | import numpy as np |
| 19 | import multiprocessing | 20 | import multiprocessing |
| 20 | 21 | ||
| @@ -68,12 +69,8 @@ def resize(img, size, interpolation=Image.BILINEAR): | |||
| 68 | return img.resize(size[::-1], interpolation) | 69 | return img.resize(size[::-1], interpolation) |
| 69 | 70 | ||
| 70 | 71 | ||
| 71 | -def gen_input_bin(mode_type, file_batches, batch): | 72 | +def gen_input_bin(mode_type, file_batches, batch, src_path, save_path): |
| 72 | - i = 0 | 73 | + for file in tqdm(file_batches[batch]): |
| 73 | - for file in file_batches[batch]: | ||
| 74 | - i = i + 1 | ||
| 75 | - print("batch", batch, file, "===", i) | ||
| 76 | - | ||
| 77 | # RGBA to RGB | 74 | # RGBA to RGB |
| 78 | image = Image.open(os.path.join(src_path, file)).convert('RGB') | 75 | image = Image.open(os.path.join(src_path, file)).convert('RGB') |
| 79 | image = resize(image, model_config[mode_type]['resize']) # Resize | 76 | image = resize(image, model_config[mode_type]['resize']) # Resize |
| @@ -81,29 +78,17 @@ def gen_input_bin(mode_type, file_batches, batch): | |||
| 81 | img = np.array(image, dtype=np.int8) | 78 | img = np.array(image, dtype=np.int8) |
| 82 | img.tofile(os.path.join(save_path, file.split('.')[0] + ".bin")) | 79 | img.tofile(os.path.join(save_path, file.split('.')[0] + ".bin")) |
| 83 | 80 | ||
| 84 | -def preprocess_s(mode_type, src_path, save_path): | ||
| 85 | - files = os.listdir(src_path) | ||
| 86 | - i = 0 | ||
| 87 | - for file in files: | ||
| 88 | - if not file.lower().endswith(".jpeg"): | ||
| 89 | - continue | ||
| 90 | - print("start to process image {}....".format(file)) | ||
| 91 | - i = i + 1 | ||
| 92 | - print("file", file, "===", i) | ||
| 93 | - path_image = os.path.join(src_path, file) | ||
| 94 | - # RGBA to RGB | ||
| 95 | - image = Image.open(path_image).convert('RGB') | ||
| 96 | - image = resize(image, model_config[mode_type]['resize']) # Resize | ||
| 97 | - image = center_crop(image, model_config[mode_type]['centercrop']) # CenterCrop | ||
| 98 | - img = np.array(image, dtype=np.int8) | ||
| 99 | - img.tofile(os.path.join(save_path, file.split('.')[0] + ".bin")) | ||
| 100 | 81 | ||
| 101 | def preprocess(mode_type, src_path, save_path): | 82 | def preprocess(mode_type, src_path, save_path): |
| 102 | files = os.listdir(src_path) | 83 | files = os.listdir(src_path) |
| 103 | - file_batches = [files[i:i + 500] for i in range(0, 50000, 500) if files[i:i + 500] != []] | 84 | + files.sort() |
| 85 | + if len(files) < 500: | ||
| 86 | + file_batches = [files[0 : len(files)]] | ||
| 87 | + else: | ||
| 88 | + file_batches = [files[i:i + 500] for i in range(0, len(files), 500) if files[i:i + 500] != []] | ||
| 104 | thread_pool = multiprocessing.Pool(len(file_batches)) | 89 | thread_pool = multiprocessing.Pool(len(file_batches)) |
| 105 | for batch in range(len(file_batches)): | 90 | for batch in range(len(file_batches)): |
| 106 | - thread_pool.apply_async(gen_input_bin, args=(mode_type, file_batches, batch)) | 91 | + thread_pool.apply_async(gen_input_bin, args=(mode_type, file_batches, batch, src_path, save_path)) |
| 107 | thread_pool.close() | 92 | thread_pool.close() |
| 108 | thread_pool.join() | 93 | thread_pool.join() |
| 109 | print("in thread, except will not report! please ensure bin files generated.") | 94 | print("in thread, except will not report! please ensure bin files generated.") |
| @@ -125,5 +110,5 @@ if __name__ == '__main__': | |||
| 125 | raise Exception(model_type_help) | 110 | raise Exception(model_type_help) |
| 126 | if not os.path.isdir(save_path): | 111 | if not os.path.isdir(save_path): |
| 127 | os.makedirs(os.path.realpath(save_path)) | 112 | os.makedirs(os.path.realpath(save_path)) |
| 128 | - preprocess_s(mode_type, src_path, save_path) | 113 | + preprocess(mode_type, src_path, save_path) |
| 129 | 114 | ||
| @@ -21,47 +21,28 @@ import time | |||
| 21 | 21 | ||
| 22 | np.set_printoptions(threshold=sys.maxsize) | 22 | np.set_printoptions(threshold=sys.maxsize) |
| 23 | 23 | ||
| 24 | -LABEL_FILE = "HiAI_label.json" | ||
| 25 | 24 | ||
| 26 | 25 | ||
| 27 | -def gen_file_name(img_name): | 26 | +def cre_groundtruth_dict_fromtxt(val_label_path): |
| 28 | - full_name = img_name.split('/')[-1] | ||
| 29 | - index = full_name.rfind('.') | ||
| 30 | - return full_name[:index] | ||
| 31 | - | ||
| 32 | - | ||
| 33 | -def cre_groundtruth_dict(gtfile_path): | ||
| 34 | """ | 27 | """ |
| 35 | - :param filename: file contains the imagename and label number | 28 | + 读取标签文件信息 |
| 36 | - :return: dictionary key imagename, value is label number | 29 | + :输入:标签文件地址 |
| 30 | + :输出: dict结构,key:图片名称,value:图片分类 | ||
| 37 | """ | 31 | """ |
| 38 | - img_gt_dict = {} | 32 | + img_label_dict = {} |
| 39 | - for gtfile in os.listdir(gtfile_path): | 33 | + with open(val_label_path, 'r')as f: |
| 40 | - if (gtfile != LABEL_FILE): | ||
| 41 | - with open(os.path.join(gtfile_path, gtfile), 'r') as f: | ||
| 42 | - gt = json.load(f) | ||
| 43 | - ret = gt["image"]["annotations"][0]["category_id"] | ||
| 44 | - img_gt_dict[gen_file_name(gtfile)] = ret | ||
| 45 | - return img_gt_dict | ||
| 46 | - | ||
| 47 | -def cre_groundtruth_dict_fromtxt(gtfile_path): | ||
| 48 | - """ | ||
| 49 | - :param filename: file contains the imagename and label number | ||
| 50 | - :return: dictionary key imagename, value is label number | ||
| 51 | - """ | ||
| 52 | - img_gt_dict = {} | ||
| 53 | - with open(gtfile_path, 'r')as f: | ||
| 54 | for line in f.readlines(): | 34 | for line in f.readlines(): |
| 55 | temp = line.strip().split(" ") | 35 | temp = line.strip().split(" ") |
| 56 | imgName = temp[0].split(".")[0] | 36 | imgName = temp[0].split(".")[0] |
| 57 | imgLab = temp[1] | 37 | imgLab = temp[1] |
| 58 | - img_gt_dict[imgName] = imgLab | 38 | + img_label_dict[imgName] = imgLab |
| 59 | - return img_gt_dict | 39 | + return img_label_dict |
| 40 | + | ||
| 60 | 41 | ||
| 61 | def load_statistical_predict_result(filepath): | 42 | def load_statistical_predict_result(filepath): |
| 62 | """ | 43 | """ |
| 63 | function: | 44 | function: |
| 64 | - the prediction esult file data extraction | 45 | + the prediction result file data extraction |
| 65 | input: | 46 | input: |
| 66 | result file:filepath | 47 | result file:filepath |
| 67 | output: | 48 | output: |
| @@ -86,23 +67,23 @@ def load_statistical_predict_result(filepath): | |||
| 86 | 67 | ||
| 87 | 68 | ||
| 88 | def create_visualization_statistical_result(prediction_file_path, | 69 | def create_visualization_statistical_result(prediction_file_path, |
| 89 | - result_store_path, json_file_name, | 70 | + result_json_path, json_file_name, |
| 90 | - img_gt_dict, topn=5): | 71 | + img_label_dict, topn=5): |
| 91 | """ | 72 | """ |
| 92 | - :param prediction_file_path: | 73 | + :param prediction_file_path: 推理结果路径 |
| 93 | - :param result_store_path: | 74 | + :param result_json_path: 后处理结果保存的json文件路径 |
| 94 | - :param json_file_name: | 75 | + :param json_file_name: 结果文件的名字 |
| 95 | - :param img_gt_dict: | 76 | + :param img_label_dict: 真实标签结果,dict形式,key为图片名称,value是标签 |
| 96 | - :param topn: | 77 | + :param topn: 1~5 |
| 97 | - :return: | 78 | + :return: NA |
| 98 | """ | 79 | """ |
| 99 | - writer = open(os.path.join(result_store_path, json_file_name), 'w') | 80 | + writer = open(os.path.join(result_json_path, json_file_name), 'w') |
| 100 | table_dict = {} | 81 | table_dict = {} |
| 101 | table_dict["title"] = "Overall statistical evaluation" | 82 | table_dict["title"] = "Overall statistical evaluation" |
| 102 | table_dict["value"] = [] | 83 | table_dict["value"] = [] |
| 103 | 84 | ||
| 104 | count = 0 | 85 | count = 0 |
| 105 | - resCnt = 0 | 86 | + res_count = 0 |
| 106 | n_labels = "" | 87 | n_labels = "" |
| 107 | count_hit = np.zeros(topn) | 88 | count_hit = np.zeros(topn) |
| 108 | for tfile_name in os.listdir(prediction_file_path): | 89 | for tfile_name in os.listdir(prediction_file_path): |
| @@ -111,30 +92,25 @@ def create_visualization_statistical_result(prediction_file_path, | |||
| 111 | index = temp.rfind('_') | 92 | index = temp.rfind('_') |
| 112 | img_name = temp[:index] | 93 | img_name = temp[:index] |
| 113 | filepath = os.path.join(prediction_file_path, tfile_name) | 94 | filepath = os.path.join(prediction_file_path, tfile_name) |
| 114 | - #print(filepath) | ||
| 115 | ret = load_statistical_predict_result(filepath) | 95 | ret = load_statistical_predict_result(filepath) |
| 116 | prediction = ret[0] | 96 | prediction = ret[0] |
| 117 | n_labels = ret[1] | 97 | n_labels = ret[1] |
| 118 | sort_index = np.argsort(-prediction) | 98 | sort_index = np.argsort(-prediction) |
| 119 | - #print(img_gt_dict) | 99 | + gt = img_label_dict[img_name] |
| 120 | - gt = img_gt_dict[img_name] | ||
| 121 | if (n_labels == 1000): | 100 | if (n_labels == 1000): |
| 122 | realLabel = int(gt) | 101 | realLabel = int(gt) |
| 123 | elif (n_labels == 1001): | 102 | elif (n_labels == 1001): |
| 124 | realLabel = int(gt) + 1 | 103 | realLabel = int(gt) + 1 |
| 125 | else: | 104 | else: |
| 126 | realLabel = int(gt) | 105 | realLabel = int(gt) |
| 127 | - # print(img_name) | ||
| 128 | - #print(n_labels) | ||
| 129 | - # print(gt) | ||
| 130 | 106 | ||
| 131 | - resCnt = min(len(sort_index), topn) | 107 | + |
| 132 | - # print(sort_index[:5]) | 108 | + res_count = min(len(sort_index), topn) |
| 133 | - for i in range(resCnt): | 109 | + for i in range(res_count): |
| 134 | if (str(realLabel) == str(sort_index[i])): | 110 | if (str(realLabel) == str(sort_index[i])): |
| 135 | count_hit[i] += 1 | 111 | count_hit[i] += 1 |
| 136 | break | 112 | break |
| 137 | - #print("***************") | 113 | + |
| 138 | if 'value' not in table_dict.keys(): | 114 | if 'value' not in table_dict.keys(): |
| 139 | print("the item value does not exist!") | 115 | print("the item value does not exist!") |
| 140 | else: | 116 | else: |
| @@ -145,11 +121,10 @@ def create_visualization_statistical_result(prediction_file_path, | |||
| 145 | accuracy = 0 | 121 | accuracy = 0 |
| 146 | else: | 122 | else: |
| 147 | accuracy = np.cumsum(count_hit) / count | 123 | accuracy = np.cumsum(count_hit) / count |
| 148 | - for i in range(resCnt): | 124 | + for i in range(res_count): |
| 149 | table_dict["value"].append({"key": "Top" + str(i + 1) + " accuracy", | 125 | table_dict["value"].append({"key": "Top" + str(i + 1) + " accuracy", |
| 150 | - "value": str( | 126 | + "value": str(round(accuracy[i] * 100, 2)) + '%'}) |
| 151 | - round(accuracy[i] * 100, 2)) + '%'}) | 127 | + |
| 152 | - #print("Top" + str(i + 1) + " accuracy" + ": " + str(round(accuracy[i] * 100, 2)) + '%') | ||
| 153 | json.dump(table_dict, writer) | 128 | json.dump(table_dict, writer) |
| 154 | writer.close() | 129 | writer.close() |
| 155 | 130 | ||
| @@ -157,20 +132,23 @@ def create_visualization_statistical_result(prediction_file_path, | |||
| 157 | if __name__ == '__main__': | 132 | if __name__ == '__main__': |
| 158 | start = time.time() | 133 | start = time.time() |
| 159 | try: | 134 | try: |
| 160 | - # txt file path | 135 | + # infer result file path |
| 161 | - folder_davinci_target = sys.argv[1] | 136 | + infer_result_path = sys.argv[1] |
| 137 | + | ||
| 162 | # annotation files path, "val_label.txt" | 138 | # annotation files path, "val_label.txt" |
| 163 | - annotation_file_path = sys.argv[2] | 139 | + annotation_file_path = sys.argv[2] |
| 140 | + | ||
| 164 | # the path to store the results json path | 141 | # the path to store the results json path |
| 165 | result_json_path = sys.argv[3] | 142 | result_json_path = sys.argv[3] |
| 143 | + | ||
| 166 | # result json file name | 144 | # result json file name |
| 167 | json_file_name = sys.argv[4] | 145 | json_file_name = sys.argv[4] |
| 168 | except IndexError: | 146 | except IndexError: |
| 169 | print("Stopped!") | 147 | print("Stopped!") |
| 170 | exit(1) | 148 | exit(1) |
| 171 | 149 | ||
| 172 | - if not (os.path.exists(folder_davinci_target)): | 150 | + if not (os.path.exists(infer_result_path)): |
| 173 | - print("target file folder does not exist.") | 151 | + print("infer result path does not exist.") |
| 174 | 152 | ||
| 175 | if not (os.path.exists(annotation_file_path)): | 153 | if not (os.path.exists(annotation_file_path)): |
| 176 | print("Ground truth file does not exist.") | 154 | print("Ground truth file does not exist.") |
| @@ -179,7 +157,7 @@ if __name__ == '__main__': | |||
| 179 | print("Result folder doesn't exist.") | 157 | print("Result folder doesn't exist.") |
| 180 | 158 | ||
| 181 | img_label_dict = cre_groundtruth_dict_fromtxt(annotation_file_path) | 159 | img_label_dict = cre_groundtruth_dict_fromtxt(annotation_file_path) |
| 182 | - create_visualization_statistical_result(folder_davinci_target, | 160 | + create_visualization_statistical_result(infer_result_path, |
| 183 | result_json_path, json_file_name, | 161 | result_json_path, json_file_name, |
| 184 | img_label_dict, topn=5) | 162 | img_label_dict, topn=5) |
| 185 | 163 | ||