已合并
[西安交通大学][高校贡献][PyTorch离线推理][MAE]-初次提交 #583
AtomGit-Bot创建于 2022年5月30日
[西安交通大学][高校贡献][PyTorch离线推理][MAE]-初次提交 #583
已合并
AtomGit-Bot创建于 2022年5月30日
refs/pull/583/head合入到master
11 个文件变更+910-0
@@ -0,0 +1,201 @@
1+ Apache License
2+ Version 2.0, January 2004
3+ http://www.apache.org/licenses/
4+ 
5+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6+ 
7+ 1. Definitions.
8+ 
9+ "License" shall mean the terms and conditions for use, reproduction,
10+ and distribution as defined by Sections 1 through 9 of this document.
11+ 
12+ "Licensor" shall mean the copyright owner or entity authorized by
13+ the copyright owner that is granting the License.
14+ 
15+ "Legal Entity" shall mean the union of the acting entity and all
16+ other entities that control, are controlled by, or are under common
17+ control with that entity. For the purposes of this definition,
18+ "control" means (i) the power, direct or indirect, to cause the
19+ direction or management of such entity, whether by contract or
20+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21+ outstanding shares, or (iii) beneficial ownership of such entity.
22+ 
23+ "You" (or "Your") shall mean an individual or Legal Entity
24+ exercising permissions granted by this License.
25+ 
26+ "Source" form shall mean the preferred form for making modifications,
27+ including but not limited to software source code, documentation
28+ source, and configuration files.
29+ 
30+ "Object" form shall mean any form resulting from mechanical
31+ transformation or translation of a Source form, including but
32+ not limited to compiled object code, generated documentation,
33+ and conversions to other media types.
34+ 
35+ "Work" shall mean the work of authorship, whether in Source or
36+ Object form, made available under the License, as indicated by a
37+ copyright notice that is included in or attached to the work
38+ (an example is provided in the Appendix below).
39+ 
40+ "Derivative Works" shall mean any work, whether in Source or Object
41+ form, that is based on (or derived from) the Work and for which the
42+ editorial revisions, annotations, elaborations, or other modifications
43+ represent, as a whole, an original work of authorship. For the purposes
44+ of this License, Derivative Works shall not include works that remain
45+ separable from, or merely link (or bind by name) to the interfaces of,
46+ the Work and Derivative Works thereof.
47+ 
48+ "Contribution" shall mean any work of authorship, including
49+ the original version of the Work and any modifications or additions
50+ to that Work or Derivative Works thereof, that is intentionally
51+ submitted to Licensor for inclusion in the Work by the copyright owner
52+ or by an individual or Legal Entity authorized to submit on behalf of
53+ the copyright owner. For the purposes of this definition, "submitted"
54+ means any form of electronic, verbal, or written communication sent
55+ to the Licensor or its representatives, including but not limited to
56+ communication on electronic mailing lists, source code control systems,
57+ and issue tracking systems that are managed by, or on behalf of, the
58+ Licensor for the purpose of discussing and improving the Work, but
59+ excluding communication that is conspicuously marked or otherwise
60+ designated in writing by the copyright owner as "Not a Contribution."
61+ 
62+ "Contributor" shall mean Licensor and any individual or Legal Entity
63+ on behalf of whom a Contribution has been received by Licensor and
64+ subsequently incorporated within the Work.
65+ 
66+ 2. Grant of Copyright License. Subject to the terms and conditions of
67+ this License, each Contributor hereby grants to You a perpetual,
68+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69+ copyright license to reproduce, prepare Derivative Works of,
70+ publicly display, publicly perform, sublicense, and distribute the
71+ Work and such Derivative Works in Source or Object form.
72+ 
73+ 3. Grant of Patent License. Subject to the terms and conditions of
74+ this License, each Contributor hereby grants to You a perpetual,
75+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76+ (except as stated in this section) patent license to make, have made,
77+ use, offer to sell, sell, import, and otherwise transfer the Work,
78+ where such license applies only to those patent claims licensable
79+ by such Contributor that are necessarily infringed by their
80+ Contribution(s) alone or by combination of their Contribution(s)
81+ with the Work to which such Contribution(s) was submitted. If You
82+ institute patent litigation against any entity (including a
83+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84+ or a Contribution incorporated within the Work constitutes direct
85+ or contributory patent infringement, then any patent licenses
86+ granted to You under this License for that Work shall terminate
87+ as of the date such litigation is filed.
88+ 
89+ 4. Redistribution. You may reproduce and distribute copies of the
90+ Work or Derivative Works thereof in any medium, with or without
91+ modifications, and in Source or Object form, provided that You
92+ meet the following conditions:
93+ 
94+ (a) You must give any other recipients of the Work or
95+ Derivative Works a copy of this License; and
96+ 
97+ (b) You must cause any modified files to carry prominent notices
98+ stating that You changed the files; and
99+ 
100+ (c) You must retain, in the Source form of any Derivative Works
101+ that You distribute, all copyright, patent, trademark, and
102+ attribution notices from the Source form of the Work,
103+ excluding those notices that do not pertain to any part of
104+ the Derivative Works; and
105+ 
106+ (d) If the Work includes a "NOTICE" text file as part of its
107+ distribution, then any Derivative Works that You distribute must
108+ include a readable copy of the attribution notices contained
109+ within such NOTICE file, excluding those notices that do not
110+ pertain to any part of the Derivative Works, in at least one
111+ of the following places: within a NOTICE text file distributed
112+ as part of the Derivative Works; within the Source form or
113+ documentation, if provided along with the Derivative Works; or,
114+ within a display generated by the Derivative Works, if and
115+ wherever such third-party notices normally appear. The contents
116+ of the NOTICE file are for informational purposes only and
117+ do not modify the License. You may add Your own attribution
118+ notices within Derivative Works that You distribute, alongside
119+ or as an addendum to the NOTICE text from the Work, provided
120+ that such additional attribution notices cannot be construed
121+ as modifying the License.
122+ 
123+ You may add Your own copyright statement to Your modifications and
124+ may provide additional or different license terms and conditions
125+ for use, reproduction, or distribution of Your modifications, or
126+ for any such Derivative Works as a whole, provided Your use,
127+ reproduction, and distribution of the Work otherwise complies with
128+ the conditions stated in this License.
129+ 
130+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131+ any Contribution intentionally submitted for inclusion in the Work
132+ by You to the Licensor shall be under the terms and conditions of
133+ this License, without any additional terms or conditions.
134+ Notwithstanding the above, nothing herein shall supersede or modify
135+ the terms of any separate license agreement you may have executed
136+ with Licensor regarding such Contributions.
137+ 
138+ 6. Trademarks. This License does not grant permission to use the trade
139+ names, trademarks, service marks, or product names of the Licensor,
140+ except as required for reasonable and customary use in describing the
141+ origin of the Work and reproducing the content of the NOTICE file.
142+ 
143+ 7. Disclaimer of Warranty. Unless required by applicable law or
144+ agreed to in writing, Licensor provides the Work (and each
145+ Contributor provides its Contributions) on an "AS IS" BASIS,
146+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147+ implied, including, without limitation, any warranties or conditions
148+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149+ PARTICULAR PURPOSE. You are solely responsible for determining the
150+ appropriateness of using or redistributing the Work and assume any
151+ risks associated with Your exercise of permissions under this License.
152+ 
153+ 8. Limitation of Liability. In no event and under no legal theory,
154+ whether in tort (including negligence), contract, or otherwise,
155+ unless required by applicable law (such as deliberate and grossly
156+ negligent acts) or agreed to in writing, shall any Contributor be
157+ liable to You for damages, including any direct, indirect, special,
158+ incidental, or consequential damages of any character arising as a
159+ result of this License or out of the use or inability to use the
160+ Work (including but not limited to damages for loss of goodwill,
161+ work stoppage, computer failure or malfunction, or any and all
162+ other commercial damages or losses), even if such Contributor
163+ has been advised of the possibility of such damages.
164+ 
165+ 9. Accepting Warranty or Additional Liability. While redistributing
166+ the Work or Derivative Works thereof, You may choose to offer,
167+ and charge a fee for, acceptance of support, warranty, indemnity,
168+ or other liability obligations and/or rights consistent with this
169+ License. However, in accepting such obligations, You may act only
170+ on Your own behalf and on Your sole responsibility, not on behalf
171+ of any other Contributor, and only if You agree to indemnify,
172+ defend, and hold each Contributor harmless for any liability
173+ incurred by, or claims asserted against, such Contributor by reason
174+ of your accepting any such warranty or additional liability.
175+ 
176+ END OF TERMS AND CONDITIONS
177+ 
178+ APPENDIX: How to apply the Apache License to your work.
179+ 
180+ To apply the Apache License to your work, attach the following
181+ boilerplate notice, with the fields enclosed by brackets "[]"
182+ replaced with your own identifying information. (Don't include
183+ the brackets!) The text should be enclosed in the appropriate
184+ comment syntax for the file format. We also recommend that a
185+ file or class name and description of purpose be included on the
186+ same "printed page" as the copyright notice for easier
187+ identification within third-party archives.
188+ 
189+ Copyright [yyyy] [name of copyright owner]
190+ 
191+ Licensed under the Apache License, Version 2.0 (the "License");
192+ you may not use this file except in compliance with the License.
193+ You may obtain a copy of the License at
194+ 
195+ http://www.apache.org/licenses/LICENSE-2.0
196+ 
197+ Unless required by applicable law or agreed to in writing, software
198+ distributed under the License is distributed on an "AS IS" BASIS,
199+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200+ See the License for the specific language governing permissions and
201+ limitations under the License.
@@ -0,0 +1,175 @@
1+# Copyright 2021 Huawei Technologies Co., Ltd
2+#
3+# Licensed under the Apache License, Version 2.0 (the "License");
4+# you may not use this file except in compliance with the License.
5+# You may obtain a copy of the License at
6+#
7+# http://www.apache.org/licenses/LICENSE-2.0
8+#
9+# Unless required by applicable law or agreed to in writing, software
10+# distributed under the License is distributed on an "AS IS" BASIS,
11+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+# See the License for the specific language governing permissions and
13+# limitations under the License.
14+# ============================================================================
15+ 
16+import os
17+import sys
18+import json
19+import time
20+import argparse
21+import numpy as np
22+ 
23+ 
24+#============================================================================
25+# Variables
26+#============================================================================
27+np.set_printoptions(threshold=sys.maxsize)
28+ 
29+LABEL_FILE = "HiAI_label.json"
30+ 
31+ 
32+#============================================================================
33+# Functions
34+#============================================================================
35+def gen_file_name(img_name):
36+ full_name = img_name.split('/')[-1]
37+ index = full_name.rfind('.')
38+ return full_name[:index]
39+ 
40+ 
41+def cre_groundtruth_dict(gtfile_path):
42+ img_gt_dict = {}
43+ for gtfile in os.listdir(gtfile_path):
44+ if (gtfile != LABEL_FILE):
45+ with open(os.path.join(gtfile_path, gtfile), 'r') as f:
46+ gt = json.load(f)
47+ ret = gt["image"]["annotations"][0]["category_id"]
48+ img_gt_dict[gen_file_name(gtfile)] = ret
49+ return img_gt_dict
50+ 
51+ 
52+def cre_groundtruth_dict_fromtxt(gtfile_path):
53+ img_count = 0
54+ img_gt_dict = {}
55+ with open(gtfile_path, 'r')as f:
56+ for line in f.readlines():
57+ img_count += 1
58+ temp = line.strip().split(" ")
59+ imgName = temp[0].split(".")[0]
60+ imgLab = temp[1]
61+ img_gt_dict[imgName] = imgLab
62+ return img_gt_dict, img_count
63+ 
64+ 
65+def load_statistical_predict_result(filepath, index):
66+ """
67+ the prediction esult file data extraction
68+ """
69+ with open(filepath, 'r')as f:
70+ for i, index_data in enumerate(f):
71+ if i == index:
72+ data = index_data
73+ temp = data.strip().split(" ")
74+ n_label = len(temp)
75+ if data == '':
76+ n_label = 0
77+ data_vec = np.zeros((n_label), dtype=np.float32)
78+ in_type = ''
79+ color = ''
80+ if n_label == 0:
81+ in_type = f.readline()
82+ color = f.readline()
83+ else:
84+ for ind, prob in enumerate(temp):
85+ data_vec[ind] = np.float32(prob)
86+ return data_vec, n_label, in_type, color
87+ 
88+ 
89+def create_visualization_statistical_result(prediction_file_path,
90+ result_store_path, json_file_name,
91+ batch_size, img_gt_dict,
92+ img_num, topn=5):
93+ writer = open(os.path.join(result_store_path, json_file_name), 'w')
94+ table_dict = {}
95+ table_dict["title"] = "Overall statistical evaluation"
96+ table_dict["value"] = []
97+ 
98+ count = 0
99+ resCnt = 0
100+ n_labels = 0
101+ count_hit = np.zeros(topn)
102+ for tfile_name in os.listdir(prediction_file_path):
103+ for i in range(batch_size):
104+ count += 1
105+ temp = tfile_name.split('.')[0]
106+ index = temp.find('_') + 1
107+ img_index = temp[index: index+5]
108+ convert_index = int(img_index) * batch_size + i + 1
109+ if convert_index > img_num:
110+ break
111+ img_name = "ILSVRC2012_val_{:08d}".format(convert_index)
112+ filepath = os.path.join(prediction_file_path, tfile_name)
113+ ret = load_statistical_predict_result(filepath, i)
114+ prediction = ret[0]
115+ n_labels = ret[1]
116+ sort_index = np.argsort(-prediction)
117+ gt = img_gt_dict[img_name]
118+ if (n_labels == 1000):
119+ realLabel = int(gt)
120+ elif (n_labels == 1001):
121+ realLabel = int(gt) + 1
122+ else:
123+ realLabel = int(gt)
124+ 
125+ resCnt = min(len(sort_index), topn)
126+ for j in range(resCnt):
127+ if (str(realLabel) == str(sort_index[j])):
128+ count_hit[j] += 1
129+ break
130+ 
131+ if 'value' not in table_dict.keys():
132+ print("the item value does not exist!")
133+ else:
134+ table_dict["value"].extend(
135+ [{"key": "Number of images", "value": str(count)},
136+ {"key": "Number of classes", "value": str(n_labels)}])
137+ if count == 0:
138+ accuracy = 0
139+ else:
140+ accuracy = np.cumsum(count_hit) / count
141+ for i in range(resCnt):
142+ table_dict["value"].append({"key": "Top" + str(i + 1) + " accuracy",
143+ "value": str(round(accuracy[i] * 100, 2)) + '%'})
144+ json.dump(table_dict, writer)
145+ writer.close()
146+ 
147+ 
148+#============================================================================
149+# Main
150+#============================================================================
151+if __name__ == '__main__':
152+ start = time.time()
153+ 
154+ parser = argparse.ArgumentParser()
155+ parser.add_argument('--folder-davinci-target', type=str, default="./result/outputs_bs1_om/")
156+ parser.add_argument('--annotation-file-path', type=str, default="/opt/npu/imageNet/val_label.txt")
157+ parser.add_argument('--result-json-path', type=str, default="./result")
158+ parser.add_argument('--json-file-name', type=str, default="result_bs1.json")
159+ parser.add_argument('--batch-size', type=int, default=1)
160+ 
161+ opt = parser.parse_args()
162+ 
163+ sub_folder = os.listdir(opt.folder_davinci_target)
164+ opt.folder_davinci_target = os.path.join(opt.folder_davinci_target, sub_folder[0])
165+ 
166+ img_label_dict, img_num = cre_groundtruth_dict_fromtxt(opt.annotation_file_path)
167+ create_visualization_statistical_result(opt.folder_davinci_target,
168+ opt.result_json_path,
169+ opt.json_file_name,
170+ opt.batch_size,
171+ img_label_dict,
172+ img_num, topn=1)
173+ 
174+ elapsed = (time.time() - start)
175+ print("Time used:", elapsed)
@@ -0,0 +1,88 @@
1+# Copyright 2021 Huawei Technologies Co., Ltd
2+#
3+# Licensed under the Apache License, Version 2.0 (the "License");
4+# you may not use this file except in compliance with the License.
5+# You may obtain a copy of the License at
6+#
7+# http://www.apache.org/licenses/LICENSE-2.0
8+#
9+# Unless required by applicable law or agreed to in writing, software
10+# distributed under the License is distributed on an "AS IS" BASIS,
11+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+# See the License for the specific language governing permissions and
13+# limitations under the License.
14+# ============================================================================
15+ 
16+import os
17+import math
18+import torch
19+import argparse
20+import numpy as np
21+from tqdm import tqdm
22+ 
23+from PIL import Image
24+from torchvision import transforms
25+ 
26+ 
27+#============================================================================
28+# Functions
29+#============================================================================
30+def preprocess(img):
31+ input_transform = transforms.Compose([
32+ transforms.Resize(256, Image.BICUBIC),
33+ transforms.CenterCrop(224),
34+ transforms.ToTensor(),
35+ transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
36+ ])
37+ return input_transform(img)
38+ 
39+ 
40+def img_preprocess(args):
41+ global input_tensor
42+ save_path = os.path.realpath(args.prep_image)
43+ if not os.path.exists(save_path):
44+ os.makedirs(save_path)
45+ 
46+ in_files = os.listdir(args.image_path)
47+ file_list = []
48+ if not os.path.isfile(os.path.join(args.image_path, in_files[0])):
49+ for sub_dir in in_files:
50+ image_path = os.path.join(args.image_path, sub_dir)
51+ sub_file_list = os.listdir(image_path)
52+ for file in sub_file_list:
53+ file_list.append(os.path.join(image_path, file))
54+ else:
55+ for file in in_files:
56+ file_list.append(os.path.join(args.image_path, file))
57+ 
58+ suffix_len = -5
59+ file_list.sort(key=lambda x:int(x[suffix_len-8:suffix_len]))
60+ for i in tqdm(range(int(np.ceil(len(file_list) / args.batch_size)))):
61+ 
Liang Zhen
Liang ZhenLiang Zhen2022年6月22日

这里建议用tdqm库来代替print打印显示进度,可视化效果更好

likedislike
62+ for idx in range(args.batch_size):
63+ file_index = i * args.batch_size + idx
64+ if file_index < len(file_list):
65+ file = file_list[file_index]
66+ input_image = Image.open(file).convert('RGB')
67+ image_tensor = preprocess(input_image).unsqueeze(0)
68+ else:
69+ image_tensor = torch.zeros([1,3,224,224])
70+ 
71+ input_tensor = image_tensor if idx == 0 \
72+ else torch.cat([input_tensor, image_tensor], dim=0)
73+ 
74+ img = np.array(input_tensor).astype(np.float32)
75+ img.tofile(os.path.join(save_path, "input_{:05d}.bin".format(i)))
76+ 
77+ 
78+#============================================================================
79+# Main
80+#============================================================================
81+if __name__ == "__main__":
82+ parser = argparse.ArgumentParser()
83+ parser.add_argument('--image-path', type=str, default="/opt/npu/imageNet/val")
84+ parser.add_argument('--prep-image', type=str, default="./prep_image_bs1")
85+ parser.add_argument('--batch-size', type=int, default=1)
86+ opt = parser.parse_args()
87+ 
88+ img_preprocess(opt)
@@ -0,0 +1,46 @@
1+ 
2+# Copyright 2021 Huawei Technologies Co., Ltd
3+#
4+# Licensed under the Apache License, Version 2.0 (the "License");
5+# you may not use this file except in compliance with the License.
6+# You may obtain a copy of the License at
7+#
8+# http://www.apache.org/licenses/LICENSE-2.0
9+#
10+# Unless required by applicable law or agreed to in writing, software
11+# distributed under the License is distributed on an "AS IS" BASIS,
12+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+# See the License for the specific language governing permissions and
14+# limitations under the License.
15+# ============================================================================
16+ 
17+import torch
18+import argparse
19+import sys
20+from mae import models_vit
21+ 
22+def pth2onnx(pth_path,output_file):
23+ device = torch.device('cpu')
24+ model = models_vit.__dict__['vit_base_patch16'](
25+ num_classes=1000,
26+ drop_path_rate=0.1,
27+ global_pool=True,
28+ )
29+ model.to(device)
30+ checkpoint = torch.load(pth_path,map_location=torch.device("cpu"))
31+ model.load_state_dict(checkpoint['model'],False)
32+ model.eval()
33+ input_names = ["image"]
34+ output_names = ["output"]
Liang Zhen
Liang ZhenLiang Zhen2022年6月22日

我认为这里没有必要引入新变量 model_without_ddp,可以复用 model。同学再确认一下。

likedislike
35+ dynamic_axes = {'image': {0: '-1'}, 'class': {0: '-1'}}
36+ dummy_input = torch.randn(1, 3, 224, 224)
37+ torch.onnx.export(model, dummy_input, output_file, opset_version=11,
38+ input_names=input_names,dynamic_axes=dynamic_axes, output_names=output_names, verbose=False)
39+ 
Liang Zhen
Liang ZhenLiang Zhen2022年6月22日
  • 单行代码不建议超过80字符;
  • 上库release代码建议设置 verbose=Flase
likedislike
40+if __name__ == '__main__':
41+ 
42+ parser = argparse.ArgumentParser()
43+ parser.add_argument('--source', type=str, default="./mae_finetuned_vit_base.pth")
44+ parser.add_argument('--target', type=str, default="./mae_dynamicbs.onnx")
45+ args = parser.parse_args()
46+ pth2onnx(args.source,args.target)
@@ -0,0 +1,200 @@
1+# MAE ONNX模型端到端推理指导
2+- [1. 模型概述](#1)
3+ - [论文地址](#11)
4+ - [代码地址](#12)
5+- [2. 环境说明](#2)
6+ - [深度学习框架](#21)
7+ - [python第三方库](#22)
8+- [3. 模型转换](#3)
9+ - [pth转onnx模型](#31)
10+ - [onnx转om模型](#32)
11+- [4. 数据预处理](#4)
12+ - [数据处理](#41)
13+- [5. 离线推理](#5)
14+ - [msame工具概述](#51)
15+ - [离线推理](#52)
16+ - [精度和性能比较](#53)
17+ 
18+## <a name="1">1. 模型概述</a>
19+### <a name="11">1.1 论文地址</a>
20+[MAE论文]([https://arxiv.org/pdf/2111.06377.pdf])
21+ 
22+### <a name="12">1.2 代码地址</a>
23+[MAE代码](https://github.com/facebookresearch/mae)
Liang Zhen
Liang ZhenLiang Zhen2022年6月22日

这里需要指定代码仓分支名和 commit_id。防止开源代码仓更新后导致本模型代码出错或者不可用

likedislike
24+ 
25+branch=main
26+ 
27+commit_id= be47fef7a727943547afb0c670cf1b26034c3c89
28+ 
29+## <a name="2">2. 环境说明</a>
30+### <a name="21">2.1 深度学习框架与第三方库</a>
31+```
32+CANN 5.1.RC1
33+timm==0.5.4
34+torchvision==0.6.0
35+torch==1.8.1
36+onnx==1.11.0
37+Pillow==9.1.1
38+numpy==1.21.6
39+tqdm==4.64.0
40+```
41+ 
42+> **说明:**
43+> pytorch,torchvision和onnx:(X86架构)可以通过pip方式安装或官方下载whl包安装; (Arm架构)可以通过源码编译安装
44+> 其他第三方库: 可以通过 pip3 install -r requirements.txt 进行安装
45+ 
46+### <a name="21">2.2 权重文件</a>
47+ 
48+使用源仓提供的mae_finetuned_vit_base.pth
49+ 
Liang Zhen
Liang ZhenLiang Zhen2022年6月22日

不建议直接给出链接,可参考如下描述

使用开源仓提供的 mae_finetuned_vit_base.pth权重(提取码:1234)

likedislike
50+链接:https://pan.baidu.com/s/1FwIK2db5nojOT7YC6rI1Hg
51+提取码:1234
52+ 
53+## <a name="3">3. 模型转换</a>
54+一步式从pth权重文件转om模型的脚本,能够由pth权重文件生成动态Batch的onnx模型和bacth为{batch_size}的om模型,{chip_name}为Ascend版本,可通过`npu-smi info`指令查看:
55+```bash
56+bash ./test/pth2om.sh --batch_size={batch_size} --not_skip_onnx=true {chip_name}
57+```
58+运行后会生成如下文件:
59+```bash
60+├── mae_dynamicbs.onnx
61+├── mae_bs{batch_size}.om
62+```
63+ 
64+### <a name="31">3.1 pth转onnx模型</a>
65+1. 设置环境变量
66+```bash
67+source /usr/local/Ascend/ascend-toolkit/set_env.sh
68+```
Liang Zhen
Liang ZhenLiang Zhen2022年6月22日

内容不用重复,保留一处权重获取方式即可

likedislike
69+ 
70+2. 执行MAE_pth2onnx.py脚本,生成onnx模型文件
71+ 
72+```bash
73+python3 MAE_pth2onnx.py --source "./mae_finetuned_vit_base.pth" --target "./mae_dynamicbs.onnx"
74+```
75+其中"source"表示模型加载权重的地址和名称,"target"表示转换后生成的onnx模型的存储地址和名称
76+ 
77+### <a name="32">3.2 onnx转om模型</a>
78+1. 使用atc将onnx模型转换为om模型文件,工具使用方法可以参考[CANN V100R020C10 开发辅助工具指南 (推理) 01](https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/51RC2alpha002/infacldevg/atctool)
79+ 
80+ {batch_size}为batchsize,{chip_name}为Ascend版本,可通过`npu-smi info`指令查看
81+ 
Liang Zhen
Liang ZhenLiang Zhen2022年6月22日

关于 soc_version 的设置建议直接参考复用 PR805 的相关描述

likedislike
82+```bash
83+atc --framework=5 --model=mae_dynamicbs.onnx --output=mae_bs{batch_size} --input_format=NCHW --input_shape="image:{batch_size},3,224,224" --log=debug --soc_version={chip_name} --optypelist_for_implmode="Gelu" --op_select_implmode=high_performance --enable_small_channel=1
84+```
85+ 
86+## <a name="4">4. 数据预处理</a>
87+数据预处理过程包含在 test/eval_acc_perf.sh 的脚本中,可以直接运行,完成预处理+推理
88+### <a name="41">4.1 数据处理</a>
89+1. 设置环境变量
90+```bash
91+source /usr/local/Ascend/ascend-toolkit/set_env.sh
92+```
93+ 
94+2. MAE模型使用ImageNet2012中的5万张验证集数据进行测试,具体来说参考MAE的源码仓中的测试过程对验证集图像进行缩放,中心裁剪以及归一化,并将图像数据转换为二进制文件(.bin)
95+> **说明:**
96+> 本项目使用的推理工具为msame,需要针对不同的batch size生成不同的输入数据
97+ 
98+3. 执行输入数据的生成脚本,生成模型输入的bin文件,以batch_size=1为例:
99+```bash
100+python3 MAE_preprocess.py --image-path /opt/npu/imageNet/val --prep-image ./prep_dataset_bs1/ --batch-size 1
101+```
102+其中"image-path"表示处理前原数据集的地址,"prep-image"表示生成数据集的文件夹名称(将在文件夹名称后会自动标识对应batch size,"batch-size"表示生成数据集对应的batch size
103+运行后,将会得到如下形式的文件夹:
104+ 
105+```
106+├── prep_dataset_bs1
107+│ ├──input_00000.bin
108+│ ├──......
109+```
110+ 
111+## <a name="5">5. 离线推理</a>
112+执行一步式推理前,请先准备msame离线推理工具
113+一步式进行输入数据的准备,模型离线推理和NPU性能数据的获取:
114+ 
115+```bash
116+bash ./test/eval_acc_perf.sh --batch_size=1 --datasets_path=/opt/npu/imageNet
117+```
118+运行后会生成如下文件/文件夹:
119+```bash
120+├── prep_dataset_bs1 # 模型的标签输入(文件夹)
121+├── msame_bs1.txt # msame推理过程的输出
122+├── result
123+│ ├── outputs_bs1_om # 模型的输出(文件夹)
124+│ ├── result_bs1.json # 模型的精度输出
125+```
126+ 
127+### <a name="51">5.1 msame工具概述</a>
128+msame模型推理工具,其输入是om模型以及模型所需要的输入bin文件,其输出是模型根据相应输入产生的输出文件。获取工具及使用方法可以参考[msame模型推理工具指南](https://gitee.com/ascend/tools/tree/master/msame)
129+### <a name="52">5.2 离线推理</a>
130+1. 设置环境变量
131+```bash
132+source /usr/local/Ascend/ascend-toolkit/set_env.sh
133+```
134+ 
135+2. 执行离线推理
136+ 运行如下命令进行离线推理:
137+ 
138+ Batch_size=1
139+```bash
140+source /usr/local/Ascend/ascend-toolkit/set_env.sh
141+mkdir result
142+./msame --model ./mae_bs1.om --output ./result/outputs_bs1 --outfmt TXT --input ./prep_dataset_bs1
143+```
144+​ Batch_size=8
145+ 
146+```
147+source /usr/local/Ascend/ascend-toolkit/set_env.sh
148+mkdir result
149+./msame --model ./mae_bs8.om --output ./result/outputs_bs8 --outfmt TXT --input ./prep_dataset_bs8
150+```
151+ 
152+模型输出格式是txt,输出保存在"output"参数指定的文件夹中,同时会生成推理的日志文件msame_bs1.txt
153+ 
154+3.使用msame工具进行纯推理,可以根据不同的batchsize进行纯推理。
155+ 
156+```
157+source /usr/local/Ascend/ascend-toolkit/set_env.sh
158+mkdir result
159+./msame --model ./mae_bs{batch_size}.om --output ./result/outputs_bs{batch_size}_om --outfmt TXT --loop 20
160+```
161+ 
162+ 
163+ 
164+### <a name="53">5.3 精度和性能比较</a>
165+1. 性能数据的获取
166+通过给test/parser.py指定推理后的日志文件,可以得到离线推理的性能数据
167+```bash
168+python3 test/parse.py --result-file ./msame_bs1.txt --batch-size 1
169+```
170+其中"result-file"表示性能数据的地址和名称,"batch-size"表示性能测试时模型对应的batch size
171+ 
172+2. 精度数据的计算
173+精度计算利用MAE_postprocess.py脚本
174+```
175+python3 MAE_postprocess.py --folder-davinci-target ./result/outputs_bs1/ --annotation-file-path /opt/npu/imageNet/val_label.txt --result-json-path ./result --json-file-name result_bs1.json --batch-size 1
176+```
177+其中"folder-davinci-target"表示离线推理输出所在的文件夹,"annotation-file-path"表示ImageNet2012验证集标签的地址和名称,"result-json-path"输出精度数据所在的文件夹,"json-file-name"表示输出精度数据所在的文件名,"batch-size"表示精度测试时模型对应的batch size
178+ 
179+3. 精度数据的获取
180+通过给test/parser.py指定推理后的日志文件,可以得到离线推理的精度数据
181+```bash
182+python3 test/parse.py --result-file ./result/result_bs1.json
183+```
184+| 模型 | 参考精度 | 310P精度 | 性能基准 | 310P性能 |
185+| :------: | :------: | :------: | :------: | :------: |
186+| mae bs1 | top1:83.66% | top1:83.5% | 193.396fps | 247.525fps |
187+| mae bs8 | top1:83.66% | top1:83.5% | 272.124fps | 450.988fps |
188+ 
189+> **说明:**
190+> Top1表示预测结果中概率最大的类别与真实类别一致的概率,其值越大说明分类模型的效果越优
191+ 
192+| 模型 | 性能基准 | 310P性能 |
193+| :------: | :--------: | :--------: |
194+| mae bs1 | 193.396fps | 247.525fps |
195+| mae bs4 | 257.646fps | 283.168fps |
196+| mae bs8 | 272.124fps | 450.988fps |
197+| mae bs16 | 263.026fps | 320.32fps |
198+| mae bs32 | 269.874fps | 308.447fps |
199+| mae bs64 | 266.179fps | 296.744fps |
200+ 
@@ -0,0 +1,2 @@
1+ModelConvert:OK
2+QuantStatus:OK
@@ -0,0 +1,4 @@
1+timm==0.5.4
Liang Zhen
Liang ZhenLiang Zhen2022年6月22日

上面的 msame 二进制文件不用上传了

likedislike
2+Pillow==9.1.1
3+numpy==1.21.6
4+tqdm==4.64.0
@@ -0,0 +1,79 @@
1+#!/bin/bash
2+ 
3+source /usr/local/Ascend/ascend-toolkit/set_env.sh
4+ 
5+batch_size=1
6+datasets_path="/opt/npu/imageNet"
7+ 
8+for para in $*
9+do
10+ if [[ $para == --datasets_path* ]]; then
11+ datasets_path=`echo ${para#*=}`
12+ fi
13+ if [[ $para == --batch_size* ]]; then
14+ batch_size=`echo ${para#*=}`
15+ fi
16+done
17+ 
18+# ======================= generate prep_dataset ==============================
19+rm -rf ./prep_image_bs${batch_size}
20+python MAE_preprocess.py \
21+ --image-path ${datasets_path}/val \
22+ --prep-image ./prep_dataset_bs${batch_size} \
23+ --batch-size ${batch_size}
24+if [ $? != 0 ]; then
25+ echo "convmixer preprocess fail!"
26+ exit -1
27+fi
28+echo "==> 1. creating ./prep_image_bs${batch_size} successfully."
29+ 
30+# =============================== msame ======================================
31+ 
32+if [ ! -d ./result ]; then
33+ mkdir ./result
34+fi
35+rm -rf ./result/outputs_bs${batch_size}_om
36+source /usr/local/Ascend/ascend-toolkit/set_env.sh
37+echo "==> conducting. Please wait a moment!"
38+./msame --model ./mae_bs${batch_size}.om --output ./result/outputs_bs${batch_size}_om --outfmt TXT --input ./prep_dataset_bs${batch_size} > msame_bs${batch_size}.txt
39+if [ $? != 0 ]; then
40+ echo "msame bs${batch_size} fail!"
41+ exit -1
42+fi
43+echo "==> 2. conducting mae_bs${batch_size}.om successfully."
44+ 
45+ 
46+# ============================ evaluate ======================================
47+python3 MAE_postprocess.py \
48+ --folder-davinci-target ./result/outputs_bs${batch_size}_om/ \
49+ --annotation-file-path ${datasets_path}/val_label.txt \
50+ --result-json-path ./result \
51+ --json-file-name result_bs${batch_size}.json \
52+ --batch-size ${batch_size}
53+if [ $? != 0 ]; then
54+ echo "fail!"
55+ exit -1
56+fi
57+echo "==> 3. evaluating mae on bs${batch_size} successfully."
58+ 
59+ 
60+# =========================== print performance data =========================
61+echo "====performance data===="
62+python test/parse.py --result-file ./msame_bs${batch_size}.txt --batch-size ${batch_size}
63+if [ $? != 0 ]; then
64+ echo "parse bs${batch_size} performance fail!"
65+ exit -1
66+fi
67+ 
68+ 
69+# =========================== print accuracy data ============================
70+echo "====accuracy data===="
71+python test/parse.py --result-file ./result/result_bs${batch_size}.json
72+if [ $? != 0 ]; then
73+ echo "parse bs${batch_size} accuracy fail!"
74+ exit -1
75+fi
76+ 
77+ 
78+echo '==> 4. printing performance and accuracy data successfully.'
79+echo '==> 5. Done.'
@@ -0,0 +1,40 @@
1+# Copyright 2021 Huawei Technologies Co., Ltd
2+#
3+# Licensed under the Apache License, Version 2.0 (the "License");
4+# you may not use this file except in compliance with the License.
5+# You may obtain a copy of the License at
6+#
7+# http://www.apache.org/licenses/LICENSE-2.0
8+#
9+# Unless required by applicable law or agreed to in writing, software
10+# distributed under the License is distributed on an "AS IS" BASIS,
11+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+# See the License for the specific language governing permissions and
13+# limitations under the License.
14+# ============================================================================
15+ 
16+import re
17+import sys
18+import json
19+import argparse
20+ 
21+if __name__ == '__main__':
22+ parser = argparse.ArgumentParser()
23+ parser.add_argument('--result-file', type=str, default="./msame_bs1.txt")
24+ parser.add_argument('--batch-size', type=int, default=1)
25+ args = parser.parse_args()
26+ 
27+ if args.result_file.endswith('.json'):
28+ result_json = args.result_file
29+ with open(result_json, 'r') as f:
30+ content = f.read()
31+ tops = [i.get('value') for i in json.loads(content).get('value') if 'Top' in i.get('key')]
32+ print('om {} top1:{}'.format(result_json.split('_')[1].split('.')[0], tops[0]))
33+ elif args.result_file.endswith('.txt'):
34+ result_txt = args.result_file
35+ with open(result_txt, 'r') as f:
36+ content = f.read()
37+ txt_data_list = re.findall(r'Inference average time without first time:.*ms', content.replace('\n', ',') + ',')[-1]
38+ avg_time = txt_data_list.split(' ')[-2]
39+ fps = args.batch_size * 1000 / float(avg_time)
40+ print('310P bs{} fps:{:.3f}'.format(args.batch_size, fps))
@@ -0,0 +1,33 @@
1+#!/bin/bash
2+ 
3+ 
4+rm -rf perf_bs1.log
5+trtexec --onnx=./mae_dynamicbs.onnx --shapes=image:1x3x224x224 --fp16 --threads > perf_bs1.log
6+perf_str=`grep "GPU.* mean.*ms$" perf_bs1.log`
7+if [ -n "$perf_str" ]; then
8+ perf_num=`echo $perf_str | awk -F' ' '{print $16}'`
9+else
10+ perf_str=`grep "mean.*ms$" perf_bs1.log`
11+ perf_num=`echo $perf_str | awk -F' ' '{print $4}'`
12+fi
13+echo "==> mae bs=1."
14+awk 'BEGIN{printf "t4 bs1 fps:%.3f\n", 1000*1/('$perf_num'/1)}'
15+ 
16+ 
17+ 
18+rm -rf perf_bs8.log
19+trtexec --onnx=./mae_dynamicbs.onnx --shapes=image:8x3x224x224 --fp16 --threads > perf_bs8.log
20+perf_str=`grep "GPU.* mean.*ms$" perf_bs4.log`
21+if [ -n "$perf_str" ]; then
22+ perf_num=`echo $perf_str | awk -F' ' '{print $16}'`
23+else
24+ perf_str=`grep "mean.*ms$" perf_bs8.log`
25+ perf_num=`echo $perf_str | awk -F' ' '{print $4}'`
26+fi
27+echo "==> mae bs=8."
28+awk 'BEGIN{printf "t4 bs8 fps:%.3f\n", 1000*1/('$perf_num'/1)}'
29+ 
30+ 
31+ 
32+ 
33+ 
@@ -0,0 +1,42 @@
1+#!/bin/bash
2+ 
3+source /usr/local/Ascend/ascend-toolkit/set_env.sh
4+ 
5+batch_size=1
6+not_skip_onnx=true
7+chip_name==$3
8+ 
9+for para in $*
10+do
11+ if [[ $para == --batch_size* ]]; then
12+ batch_size=`echo ${para#*=}`
13+ fi
14+ if [[ $para == --not_skip_onnx* ]]; then
15+ not_skip_onnx=`echo ${para#*=}`
16+ fi
17+done
18+ 
19+# ======================= convert onnx =======================================
20+if [ $not_skip_onnx == true ]; then
21+ rm -rf mae_dynamicbs.onnx
22+ python MAE_pth2onnx.py \
23+ --source "./mae_finetuned_vit_base.pth" \
24+ --target "./mae_dynamicbs.onnx"
25+ if [ -f "./mae_dynamicbs.onnx" ]; then
26+ echo "==> 1. creating onnx model successfully."
27+ else
28+ echo "onnx export failed"
29+ exit -1
30+ fi
31+fi
32+ 
33+# ======================= convert om =========================================
34+rm -rf mae_bs${batch_size}.om
35+source /usr/local/Ascend/ascend-toolkit/set_env.sh
36+atc --framework=5 --model=mae_dynamicbs.onnx --output=mae_bs${batch_size} --input_format=NCHW --input_shape="image:${batch_size},3,224,224" --log=debug --soc_version=$3 --optypelist_for_implmode="Gelu" --op_select_implmode=high_performance --enable_small_channel=1
37+if [ -f "mae_bs${batch_size}.om" ] ; then
38+ echo "==> 2. creating om model successfully."
39+else
40+ echo "om export failed"
41+fi
42+echo "==> 3. Done."