diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/.DS_Store b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c9b9b7889599850787aa37ed0e89aa4ce5087003 Binary files /dev/null and b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/.DS_Store differ diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/.keep b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/.keep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/README.md b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/README.md new file mode 100644 index 0000000000000000000000000000000000000000..5a72184198531df5e367f93ff8bf24f45a06e700 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/README.md @@ -0,0 +1,247 @@ +## 基本信息 + +**发布者(Publisher):Huawei** + +**应用领域(Application Domain):** Classification + +**版本(Version):1.1** + +**修改时间(Modified) :2022.05.15** + +**大小(Size):** + +**框架(Framework):TensorFlow 1.15.0** + +**模型格式(Model Format):** + +**精度(Precision):** + +**处理器(Processor):昇腾910** + +**应用级别(Categories):Research** + +**描述(Description):基于TensorFlow框架的VisionTransformer图像分类网络训练代码** + +## 概述 + +当前Transformer模型被大量应用在NLP自然语言处理当中,而在计算机视觉领域,Transformer的注意力机制attention也被广泛应用,比如Se模块,CBAM模块等等注意力模块,这些注意力模块能够帮助提升网络性能。而VisionTransformer展示了不需要依赖CNN的结构,也可以在图像分类任务上达到很好的效果,并且也十分适合用于迁移学习。 + + +- 参考论文: + + Dosovitskiy, A., Beyer, L., Kolesnikov, A., Weissenborn, D., Zhai, X., Unterthiner, T., Dehghani, M., Minderer, M., Heigold, G., Gelly, S., Uszkoreit, J., & Houlsby, N. (2021). An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale. ArXiv, abs/2010.11929. + + + - arXiv:2010.11929(http://xxx.itp.ac.cn/pdf/2010.11929.pdf) + +- 参考实现: + + https://github.com/faustomorales/vit-keras + +- 适配昇腾 AI 处理器的实现: + + + https://gitee.com/ascend/ModelZoo-TensorFlow/tree/master/TensorFlow/contrib/cv/BicycleGAN_ID1287_for_TensorFlow + + + +- 通过Git获取对应commit\_id的代码方法如下: + + ``` + git clone {repository_url} # 克隆仓库的代码 + cd {repository_name} # 切换到模型的代码仓目录 + git checkout {branch} # 切换到对应分支 + git reset --hard {commit_id} # 代码设置到对应的commit_id + cd {code_path} # 切换到模型代码所在路径,若仓库下只有该模型,则无需切换 + ``` + +- 精度 + +| | GPU | NPU | +|-------|-------|-------| +| LPIPS | 0.8709 | 0.871 | + +- 性能 + +| batchsize | image_size | GPU (v100) | NPU | +|-----------|------------|---|---| +| 1 | 384*384 | | | + + +## 默认配置 + +- 训练数据集预处理(以原论文的maps训练集为例,仅作为用户参考示例): + + - 图像的输入尺寸为384*384 + - 图像输入格式:从cifar压缩文件中读取数据 +```python + def _preprocess(image, label): + image = tf.image.resize(image, (image_size, image_size)) + image = (image - 127.5) / 127.5 + return image, label +``` + +- 测试数据集预处理(以原论文的maps验证集为例,仅作为用户参考示例) + + - 图像的输入尺寸为384*384 + - 图像输入格式:从cifar压缩文件中读取数据 +```python + def _preprocess(image, label): + image = tf.image.resize(image, (image_size, image_size)) + image = (image - 127.5) / 127.5 + return image, label +``` + +- 训练超参 + + - Batch size: 4 + - Learning rate(LR): 0.001 + - Optimizer: Adam + - Train epoch: 1 + +## 支持特性 + +| 特性列表 | 是否支持 | +|-------|------| +| 分布式训练 | 否 | +| 混合精度 | 是 | +| 并行数据 | 否 | + + + +

训练环境准备

+ +1. 硬件环境准备请参见各硬件产品文档"[驱动和固件安装升级指南]( https://support.huawei.com/enterprise/zh/category/ai-computing-platform-pid-1557196528909)"。需要在硬件设备上安装与CANN版本配套的固件与驱动。 +2. 宿主机上需要安装Docker并登录[Ascend Hub中心](https://ascendhub.huawei.com/#/detail?name=ascend-tensorflow-arm)获取镜像。 + + 当前模型支持的镜像列表如[表1](#zh-cn_topic_0000001074498056_table1519011227314)所示。 + + **表 1** 镜像列表 + + + + + + + + + + + + +

镜像名称

+

镜像版本

+

配套CANN版本

+
+

20.2.0

+

20.2

+
+ + +## 注意事项 +1. 本项目是在104机器裸机上完成的,线上modelart的总是报算子错。 +2. vision transformer 需要加载预训练才能达到好的效果,这是是加载了gpu训练的模型。 + +

快速上手

+ +- 数据集准备 +1. 104机器上位置为 `/home/HwHiAiUser/wubo/vit/vit-ckpt/datasets` 另外obs也有 + +2. 获得数据集后,放入模型目录下,在训练脚本中指定数据集路径,可正常使用。 + + +## 模型训练 + +- 单击“立即下载”,并选择合适的下载方式下载源码包。 + +- 启动训练之前,首先要配置程序运行相关环境变量。 + + 环境变量配置信息参见: + + [Ascend 910训练平台环境变量设置](https://gitee.com/ascend/modelzoo/wikis/Ascend%20910%E8%AE%AD%E7%BB%83%E5%B9%B3%E5%8F%B0%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E8%AE%BE%E7%BD%AE?sort_id=3148819) + +- 单卡训练 + + 1. 配置训练参数。 + + 首先在脚本test/train_full_1p.sh中,配置训练数据集路径,请用户根据实际路径配置,数据集参数如下所示: + + ``` + --data_path ./dataset + ``` + + 2. 启动训练。 + + 启动单卡训练 (脚本为modelarts_entry_acc.py) + + ``` + python3 modelarts_entry_acc.py + ``` + + + +

迁移学习指导

+ +- 数据集准备。 + + 数据集要求如下: + + 1. 获取数据。 + + 如果要使用自己的数据集, obs://cann-id1217/ 需要将数据集放到脚本参数data_path对应目录下。参考代码中的数据集存放路径如下: + + - 训练集: ./dataset/train + - 测试集: ./dataset/val + + 数据集也可以放在其它目录,则修改对应的脚本入参data_path即可。 + + +- 模型训练。 + + 参考“模型训练”中训练步骤。 + +- 模型评估。 + + 参考“模型训练”中验证步骤。 + +

高级参考

+ +## 脚本和示例代码 + +``` +VisionTransformer +└─ + ├─README.md + ├─dataset用于存放训练数据集和预训练文件 + |-model/ + ├─train + └─val + ├─precision_tool 用来去掉某一些算子融合策略 + └─... + ├─test 用于测试 + ├─output 用于存放测试结果和日志 + └─test_1p.sh +``` + +## 脚本参数 + +``` +--learning_rate 学习率,默认是0.001 +--batch_size 训练的batch大小,默认是4 +--data_path 训练集文件路径 +--output_path 日志,模型文件等存放的路径 +``` + + +## 训练过程 + +1. 通过“模型训练”中的训练指令启动单卡训练。 + +2. 参考脚本的模型存储路径为./output。 + + + +## 推理/验证过程 + + + diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/fusion_result.json b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/fusion_result.json new file mode 100644 index 0000000000000000000000000000000000000000..d8a4da7ff4977c0f09e51ef56036e312962dafd9 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/fusion_result.json @@ -0,0 +1,383 @@ +{ + "graph_fusion": { + "MulAddFusionPass": { + "effect_times": "0", + "match_times": "148" + }, + "MulSquareFusionPass": { + "effect_times": "0", + "match_times": "75" + } + }, + "session_and_graph_id": "0_1", + "ub_fusion": { + "AutomaticUbFusion": { + "effect_times": "74", + "match_times": "74" + } + } +}{ + "graph_fusion": { + "AABiasaddConvFusion": { + "effect_times": "1", + "match_times": "1" + }, + "AAMatMulNzToNdFusionPass": { + "effect_times": "0", + "match_times": "402" + }, + "AReduceAllFusionPass": { + "effect_times": "0", + "match_times": "1" + }, + "AReduceMeanFusionPass": { + "effect_times": "0", + "match_times": "50" + }, + "AReduceSumFusionPass": { + "effect_times": "0", + "match_times": "115" + }, + "ASoftmaxFusionPass": { + "effect_times": "0", + "match_times": "12" + }, + "AddNFusionPass": { + "effect_times": "0", + "match_times": "87" + }, + "ApplyAddOutputPass": { + "effect_times": "200", + "match_times": "200" + }, + "BatchMatMulFusionPass": { + "effect_times": "0", + "match_times": "291" + }, + "BatchMatMulV2ReduceFusionPass": { + "effect_times": "0", + "match_times": "72" + }, + "BatchMatMulV2ReshapeFusionPass": { + "effect_times": "0", + "match_times": "72" + }, + "CastRemoveFusionPass": { + "effect_times": "0", + "match_times": "36" + }, + "ConstToAttrPass": { + "effect_times": "351", + "match_times": "351" + }, + "ConstToAttrReduceSumFusion": { + "effect_times": "115", + "match_times": "115" + }, + "ConstToAttrStridedSliceFusion": { + "effect_times": "1", + "match_times": "1" + }, + "Conv2DbpFilterMulFusionPass": { + "effect_times": "0", + "match_times": "1" + }, + "ConvConcatFusionPass": { + "effect_times": "0", + "match_times": "1" + }, + "ConvToFullyConnectionFusionPass": { + "effect_times": "0", + "match_times": "1" + }, + "ConvWeightCompressFusionPass": { + "effect_times": "0", + "match_times": "220" + }, + "FIXPIPEAPREQUANTFUSIONPASS": { + "effect_times": "0", + "match_times": "293" + }, + "FIXPIPEFUSIONPASS": { + "effect_times": "0", + "match_times": "293" + }, + "ForceFp16CastFusionPass": { + "effect_times": "0", + "match_times": "36" + }, + "LayerNormTrainingFusionPass": { + "effect_times": "25", + "match_times": "25" + }, + "MatMulBiasAddFusionPass": { + "effect_times": "1", + "match_times": "1" + }, + "MatMulReshapeBiasAddFusionPass": { + "effect_times": "72", + "match_times": "72" + }, + "MatMulV2FusionPass": { + "effect_times": "0", + "match_times": "72" + }, + "MulAddNL2LossFusionPass": { + "effect_times": "0", + "match_times": "40" + }, + "MulAddNPass": { + "effect_times": "0", + "match_times": "40" + }, + "MulGradFusionPass": { + "effect_times": "0", + "match_times": "87" + }, + "MulSquareFusionPass": { + "effect_times": "0", + "match_times": "703" + }, + "RefreshInt64ToInt32FusionPass": { + "effect_times": "1", + "match_times": "1" + }, + "ReshapeTransposeFusionPass": { + "effect_times": "0", + "match_times": "48" + }, + "SoftmaxFusionPass": { + "effect_times": "0", + "match_times": "12" + }, + "SoftmaxGradExtFusion": { + "effect_times": "12", + "match_times": "12" + }, + "SparseSoftMaxFusionPass": { + "effect_times": "1", + "match_times": "1" + }, + "SplitConvConcatFusionPass": { + "effect_times": "0", + "match_times": "1" + }, + "StridedSliceGradFusionPass": { + "effect_times": "0", + "match_times": "1" + }, + "StridedSliceRemovePass": { + "effect_times": "0", + "match_times": "1" + }, + "SubFusionPass": { + "effect_times": "0", + "match_times": "25" + }, + "TileConstToAttrFusion": { + "effect_times": "50", + "match_times": "50" + }, + "TransdataCastFusionPass": { + "effect_times": "0", + "match_times": "857" + }, + "TransposeReshapeFusionPass": { + "effect_times": "0", + "match_times": "84" + }, + "TransposedUpdateFusionPass": { + "effect_times": "96", + "match_times": "96" + }, + "ZConcatExt2FusionPass": { + "effect_times": "1", + "match_times": "1" + }, + "ZConcatv2dFusionPass": { + "effect_times": "0", + "match_times": "1" + }, + "softmaxTransFusionPass": { + "effect_times": "0", + "match_times": "12" + } + }, + "session_and_graph_id": "0_21", + "ub_fusion": { + "AutomaticUbFusion": { + "effect_times": "25", + "match_times": "25" + }, + "TbeEltwiseFusionPass": { + "effect_times": "12", + "match_times": "12" + }, + "TbeFullyconnectionElemwiseDequantFusionPass": { + "effect_times": "85", + "match_times": "85" + }, + "TbeMultiOutputFusionPass": { + "effect_times": "37", + "match_times": "37" + } + } +}{ + "graph_fusion": { + "RefreshInt64ToInt32FusionPass": { + "effect_times": "1", + "match_times": "1" + }, + "TransdataCastFusionPass": { + "effect_times": "0", + "match_times": "2" + } + }, + "session_and_graph_id": "0_31" +}{ + "graph_fusion": { + "AABiasaddConvFusion": { + "effect_times": "1", + "match_times": "1" + }, + "AAMatMulNzToNdFusionPass": { + "effect_times": "0", + "match_times": "146" + }, + "AReduceMeanFusionPass": { + "effect_times": "0", + "match_times": "50" + }, + "ASoftmaxFusionPass": { + "effect_times": "0", + "match_times": "12" + }, + "BatchMatMulFusionPass": { + "effect_times": "0", + "match_times": "97" + }, + "BatchMatMulV2ReduceFusionPass": { + "effect_times": "0", + "match_times": "24" + }, + "BatchMatMulV2ReshapeFusionPass": { + "effect_times": "0", + "match_times": "24" + }, + "CastRemoveFusionPass": { + "effect_times": "0", + "match_times": "36" + }, + "ConstToAttrPass": { + "effect_times": "99", + "match_times": "99" + }, + "ConstToAttrStridedSliceFusion": { + "effect_times": "1", + "match_times": "1" + }, + "ConvConcatFusionPass": { + "effect_times": "0", + "match_times": "1" + }, + "ConvToFullyConnectionFusionPass": { + "effect_times": "0", + "match_times": "1" + }, + "ConvWeightCompressFusionPass": { + "effect_times": "0", + "match_times": "74" + }, + "FIXPIPEAPREQUANTFUSIONPASS": { + "effect_times": "0", + "match_times": "98" + }, + "FIXPIPEFUSIONPASS": { + "effect_times": "0", + "match_times": "98" + }, + "ForceFp16CastFusionPass": { + "effect_times": "0", + "match_times": "36" + }, + "LayerNormTrainingFusionPass": { + "effect_times": "25", + "match_times": "25" + }, + "MatMulBiasAddFusionPass": { + "effect_times": "1", + "match_times": "1" + }, + "MatMulReshapeBiasAddFusionPass": { + "effect_times": "72", + "match_times": "72" + }, + "MatMulV2FusionPass": { + "effect_times": "0", + "match_times": "72" + }, + "MulSquareFusionPass": { + "effect_times": "0", + "match_times": "108" + }, + "RefreshInt64ToInt32FusionPass": { + "effect_times": "1", + "match_times": "1" + }, + "ReshapeTransposeFusionPass": { + "effect_times": "0", + "match_times": "36" + }, + "SoftmaxFusionPass": { + "effect_times": "0", + "match_times": "12" + }, + "SplitConvConcatFusionPass": { + "effect_times": "0", + "match_times": "1" + }, + "StridedSliceRemovePass": { + "effect_times": "0", + "match_times": "1" + }, + "TransdataCastFusionPass": { + "effect_times": "0", + "match_times": "271" + }, + "TransposeReshapeFusionPass": { + "effect_times": "0", + "match_times": "12" + }, + "TransposedUpdateFusionPass": { + "effect_times": "48", + "match_times": "48" + }, + "ZConcatExt2FusionPass": { + "effect_times": "1", + "match_times": "1" + }, + "ZConcatv2dFusionPass": { + "effect_times": "0", + "match_times": "1" + }, + "softmaxTransFusionPass": { + "effect_times": "0", + "match_times": "12" + } + }, + "session_and_graph_id": "0_41", + "ub_fusion": { + "AutomaticUbFusion": { + "effect_times": "36", + "match_times": "36" + }, + "TbeEltwiseFusionPass": { + "effect_times": "12", + "match_times": "12" + }, + "TbeFullyconnectionElemwiseDequantFusionPass": { + "effect_times": "12", + "match_times": "12" + } + } +} \ No newline at end of file diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/modelarts_entry_acc.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/modelarts_entry_acc.py new file mode 100644 index 0000000000000000000000000000000000000000..13077b10e660de32d6f7861257a50e1a01ede9ba --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/modelarts_entry_acc.py @@ -0,0 +1,63 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# 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. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# 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. + +import os +import argparse +import sys + +# 解析输入参数data_url +parser = argparse.ArgumentParser() +parser.add_argument("--data_url", type=str, default="/home/ma-user/modelarts/inputs/data_url_0") +parser.add_argument("--train_url", type=str, default="/home/ma-user/modelarts/outputs/train_url_0/") +config = parser.parse_args() + +print("[CANN-Modelzoo] code_dir path is [%s]" % (sys.path[0])) +code_dir = sys.path[0] +os.chdir(code_dir) +print("[CANN-Modelzoo] work_dir path is [%s]" % (os.getcwd())) + +print("[CANN-Modelzoo] before train - list my run files:") +os.system("ls -al /usr/local/Ascend/ascend-toolkit/") + +print("[CANN-Modelzoo] before train - list my dataset files:") +os.system("ls -al %s" % config.data_url) + +print("[CANN-Modelzoo] start run train shell") +# 设置sh文件格式为linux可执行 +os.system("dos2unix ./test/*") + +# 执行train_full_1p.sh或者train_performance_1p.sh,需要用户自己指定 +# full和performance的差异,performance只需要执行很少的step,控制在15分钟以内,主要关注性能FPS +os.system("bash ./test/train_full_1p.sh --data_path=%s --output_path=%s " % (config.data_url, config.train_url)) + +print("[CANN-Modelzoo] finish run train shell") + +# 将当前执行目录所有文件拷贝到obs的output进行备份 +print("[CANN-Modelzoo] after train - list my output files:") +os.system("cp -r %s %s " % (code_dir, config.train_url)) +os.system("ls -al %s" % config.train_url) diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/modelarts_entry_perf.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/modelarts_entry_perf.py new file mode 100644 index 0000000000000000000000000000000000000000..14384e227a0fa90a514254590aef5078c62ff700 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/modelarts_entry_perf.py @@ -0,0 +1,63 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# 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. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# 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. + +import os +import argparse +import sys + +# 解析输入参数data_url +parser = argparse.ArgumentParser() +parser.add_argument("--data_url", type=str, default="/home/ma-user/modelarts/inputs/data_url_0") +parser.add_argument("--train_url", type=str, default="/home/ma-user/modelarts/outputs/train_url_0/") +config = parser.parse_args() + +print("[CANN-Modelzoo] code_dir path is [%s]" % (sys.path[0])) +code_dir = sys.path[0] +os.chdir(code_dir) +print("[CANN-Modelzoo] work_dir path is [%s]" % (os.getcwd())) + +print("[CANN-Modelzoo] before train - list my run files:") +os.system("ls -al /usr/local/Ascend/ascend-toolkit/") + +print("[CANN-Modelzoo] before train - list my dataset files:") +os.system("ls -al %s" % config.data_url) + +print("[CANN-Modelzoo] start run train shell") +# 设置sh文件格式为linux可执行 +os.system("dos2unix ./test/*") + +# 执行train_full_1p.sh或者train_performance_1p.sh,需要用户自己指定 +# full和performance的差异,performance只需要执行很少的step,控制在15分钟以内,主要关注性能FPS +os.system("bash ./test/train_performance_1p.sh --data_path=%s --output_path=%s " % (config.data_url, config.train_url)) + +print("[CANN-Modelzoo] finish run train shell") + +# 将当前执行目录所有文件拷贝到obs的output进行备份 +print("[CANN-Modelzoo] after train - list my output files:") +os.system("cp -r %s %s " % (code_dir, config.train_url)) +os.system("ls -al %s" % config.train_url) diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/msprof.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/msprof.py new file mode 100755 index 0000000000000000000000000000000000000000..550663f8b02211027a2ef5eef4b16d6cc99100b2 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/msprof.py @@ -0,0 +1,48 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# 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. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# 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. + +#!/usr/bin/python3 +# coding=utf-8 +""" +Function: +This class mainly involves the main function. +Copyright Information: +Huawei Technologies Co., Ltd. All Rights Reserved © 2020 +""" +import importlib +import os +import sys + +if __name__ == '__main__': + sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))) + _model_path = "ms_interface.msprof_entrance" + MSPROF_ENTRANCE_CLASS = "MsprofEntrance" + os.umask(0o027) + msprof_entrance_module = importlib.import_module(_model_path) + if hasattr(msprof_entrance_module, MSPROF_ENTRANCE_CLASS): + getattr(msprof_entrance_module, MSPROF_ENTRANCE_CLASS)().main() diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/.DS_Store b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ca63ff7dc12e7690e5692279ae870da9520b7de1 Binary files /dev/null and b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/.DS_Store differ diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/README.md b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/README.md new file mode 100644 index 0000000000000000000000000000000000000000..39c36d6f2f99665a7bbe1ebfe23f735f4ca965f6 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/README.md @@ -0,0 +1,490 @@ +# 精度问题分析工具 + +## 功能介绍 +### 简介 +该工具包提供了精度比对常用的功能,当前该工具主要适配Tensorflow训练场景 + +对于常用功能基本可以做到一键操作,同时提供Dump数据/图信息的交互式查询和操作入口 + +推理场景可直接使用[推理一键式全流程精度比对](https://gitee.com/ascend/tools/tree/master/msquickcmp) 工具 +### 主要功能 +#### 已完成功能 +1. 简化脚本修改【手动/半自动】 +2. TF标杆数据生成【自动/半自动】 +3. 算子溢出检测分析【自动】 +4. 开启GE图Dump和图解析【自动】 +5. 开启数据Dump并进行全网比对【自动】 +6. 查询算子列表/节点信息【手动】 +7. 查询/解析Dump数据信息【手动】 +8. 数据比对【手动】 +### 工具获取 +1. 下载压缩包的方式获取 + 将https://gitee.com/ascend/tools 以压缩包形式下载 +2. 使用git命令方式获取 +3. 移动 tools/precision_tool 子目录至训练工作目录 +### 安装python3三方依赖 +```shell +pip3 install rich gnureadline pexpect graphviz +# ubuntu/Debian +sudo apt-get install graphviz +# fedora/Centos +sudo yum install graphviz +``` +### 工具执行依赖 +* 一般直接在NPU训练环境上部署该脚本,环境上能够正常执行CPU和NPU训练脚本 +* 如果需要进行数据Dump比对,则需要先检查并去除训练脚本内部使用到的随机处理,避免由于输入数据不一致导致数据比对结果不可用 + ```python + # 对于使用tf.random / np.random / (python) random的可以通过固定随机种子的方式固定输入 + # import tf_config.py 默认会设置上述三种random的seed,但由于import位置关系,可能不一定能作用到所有的关联代码,建议在代码确认合适位置手动嵌入 + random.seed(cfg.DUMP_SEED) + tf.random.set_random_seed(cfg.DUMP_SEED) + np.random.seed(cfg.DUMP_SEED) + + # 此处给出一些典型示例,需要根据自己的脚本进行排查 + + # 1. 参数初始化中的随机操作 + # 加载checkpoint的方式能够固定大多数初始参数 + saver.restore(sess, saver_dir) + + # 2. 输入数据的随机操作(例如对输入数据做shuffle操作) + dataset = tf.data.TFRecordDataset(tf_data) + dataset = dataset.shuffle(batch_size*10) # 直接注释掉该行 + + # 3. 模型中的随机操作(例如使用dropout) + net = slim.dropout(net, keep_prob=dropout_keep_prob, scope='Dropout_1b') # 建议注释该行 + + # 4. 图像预处理使用的随机操作(根据实际情况固定随机种子,或者替换成其他固定的预处理操作) + # 4.1 Random rotate + random_angle = tf.random_uniform([], - self.degree * 3.141592 / 180, self.degree * 3.141592 / 180) + image = tf.contrib.image.rotate(image, random_angle, interpolation='BILINEAR') + depth_gt = tf.contrib.image.rotate(depth_gt, random_angle, interpolation='NEAREST') + + # 4.2 Random flipping + do_flip = tf.random_uniform([], 0, 1) + image = tf.cond(do_flip > 0.5, lambda: tf.image.flip_left_right(image), lambda: image) + depth_gt = tf.cond(do_flip > 0.5, lambda: tf.image.flip_left_right(depth_gt), lambda: depth_gt) + + # 4.3 Random crop + mage_depth = tf.concat([image, depth_gt], 2) + image_depth_cropped = tf.random_crop(image_depth, [self.params.height, self.params.width, 4]) + + # 5. RunConfig/NPURunConfig中设置tf_random_seed固定网络随机因子 + run_config = tf.estimator.RunConfig(tf_random_seed=1, ...) + run_config = NPURunConfig(tf_random_seed=1, ...) + + # 其他...... + ``` +* 该工具基于**NPU的计算图**,**NPU的DUMP数据**,**NPU的溢出检测数据**,**TF的计算图meta文件**,**TF的DUMP数据**进行数据解析和分析。 +这几类依赖数据可以通过以下方式获取(只使用部分工具功能并不需要提前获取所有依赖数据): +#### 1. NPU的计算图获取 + ``` + 注意:NPU的Dump数据和计算图存在一定的对应关系,需要同时获取 + 避免在自定义的训练脚本中unset DUMP GRAPH相关的环境变量 + ``` +* 【推荐】方法一:配置2、3依赖中的NPU数据Dump或者overflow检测功能,将自动配置上Dump GE图的环境变量 + +* 【不推荐】方法二:参考迁移指导中的修改配置,执行NPU脚本,并将获取到的图转存至precision_data图目录 + ```shell + export DUMP_GE_GRAPH=2 + export DUMP_GRAPH_LEVEL=3 + export DUMP_GRAPH_PATH=./precision_data/npu/debug_0/graph + # 未配置DUMP_GRAPH_PATH时,图文件将保存在脚本执行目录,可以直接转存至precision_data目录 + mkdir -p ./precision_data/npu/debug_0/graph && mv ge_proto_*.txt ./precision_data/npu/debug_0/graph + ``` +#### 2. NPU的DUMP数据获取 +* 【推荐】方法一:在训练脚本中**import precision_tool.tf_config**,并使用precision_tool中提供的辅助命令行执行训练脚本 + ``` python + # NPU的DUMP获取和溢出检测数据的获取,均可按如下方式修改代码 + # 注意:参数action可以设置为'dump'或'overflow' + # 引用 precision_tool/tf_config.py + import precision_tool.tf_config as npu_tf_config + + # 如果使用的是Estimator的NPURunConfig配置使能NPU,则可以参考以下修改 + dump_config = npu_tf_config.estimator_dump_config(action='dump') # 新增行 + npu_config = NPURunConfig(dump_config=dump_config) + + # 如果使用的是session.run或者使用tf.ConfigProto创建session_config传入tf.estimator.RunConfig的方式使能npu + # 可以参考如下修改 + session_config = npu_tf_config.session_dump_config(session_config, action='dump') # 新增行 + # tf.estimator + run_config = tf.estimator.RunConfig(session_config=session_config,...) + # tf.keras + npu_keras_sess = set_keras_session_npu_config(config=session_config) + # session run + with tf.Session(config=npu_config_proto(session_config)): + ...... + + # 如果使用的是custom_op方式,则可以参考以下修改 + config = tf.ConfigProto() + custom_op = config.graph_options.rewrite_options.custom_optimizers.add() + custom_op.name = "NpuOptimizer" + custom_op.parameter_map["use_off_line"].b = True + custom_op = npu_tf_config.update_custom_op(custom_op, action='dump') # 新增行 + ``` + +* 【不推荐】方法二:参考[精度比对工具使用指南](https://www.hiascend.com/document?tag=community-developer) 修改训练脚本。 + 执行训练脚本,并将dump的数据拷贝到【precision_data/dump/npu/】目录 +#### 3. NPU的溢出检测数据的获取(缺少该数据将无法展示溢出检测结果) +* 【推荐】方法一:在训练脚本中**import precision_tool.tf_config**,并按【2. NPU的DUMP数据获取】中修改训练代码,使用precision_tool中提供的辅助命令行执行训练脚本 + ```python + # 需要将action设置成'overflow' + # 引用 precision_tool/tf_config.py + import precision_tool.tf_config as npu_tf_config + dump_config = npu_tf_config.estimator_dump_config(action='overflow') # 新增行 + ``` +* 【不推荐】方法二:参考[使用溢出检测工具分析算子溢出](https://www.hiascend.com/document?tag=community-developer) 修改训练脚本, + 并将溢出数据拷贝至【precision_tool/dump/overflow/】目录 + +#### 4. TF的DUMP数据获取(缺少该数据无法使用数据比对功能) +* 【推荐】方法一:在CPU/GPU训练脚本中添加tf_debug代码,并使用precision_tool中提供的辅助命令行工具生成标杆DUMP数据 + ```python + import precision_tool.tf_config as npu_tf_config + + # 如果使用的是Estimator,EstimatorSpec加入training_hooks + estim_specs = tf.estimator.EstimatorSpec(training_hooks=[npu_tf_config.estimator_dump()]) + + # 如果使用的session.run,以下代码在为sess加上了tf_debug的wrapper + sess = npu_tf_config.sess_dump(sess=sess) + ``` + ```shell + # 1. 执行脚本 + # 2. 解析tf debug dump文件,生成算子输出tensor文件 + # 注意:TF dump数据的原理是使用tf_debug的print_tensor(pt)命令实现的,由于训练代码提供了非常灵活的run()接口, + # 脚本无法感知用户需要dump的tensor在哪个run阶段,因此需要用户修改训练代码,在执行完正确的run后,立即退出。 + # 例如,修改代码只执行一个step的训练,根据代码中run的次数,会获取到1~N个离线tf_debug的dump目录 + # precision_tool脚本会自动提取最后一个run阶段中出现的所有tensor作为标杆数据。 + python3.7.5 precision_tool/cli.py tf_dump + + # 在precision_data/tf/dump/ 目录会存放提取的tensor + # 如果获取tensor不符合预期,可以检查下precision_data/dump/cpu_debug/目录, 只保留预期run阶段的tf_debug离线数据 + # 执行以下命令重新生成 + rm -rf precision_data/tf/dump/* && python3.7.5 precision_tool/cli.py tf_dump + ``` +* 【不推荐】方法二:参考[准备基于GPU/CPU运行生成的npy数据](https://www.hiascend.com/document?tag=community-developer) + 获取CPU/GPU的TF数据,并拷贝至【precision/dump/cpu/】目录 +#### 5. TF计算图Meta文件的获取(可选) +* 通过saver保存ckpt获取 + ```python + # 修改CPU/NPU脚本 + with tf.Session() as sess: + # do session.run() + saver = tf.train.Saver() + # 保存ckpt + saver.save(sess, saver_dir) + ``` +#### 6. 关闭NPU的融合功能(根据情况启用) +* NPU会对计算图中的算子进行融合,以提高网络性能,由于大多数融合是自动识别的,可能存在未考虑到的场景,导致精度问题, + 因此,可以尝试关闭融合定界网络问题是否是由于融合导致。 + ```python + # 关闭融合可以和溢出检测/数据Dump同时进行,启用方法也类似 + # 引用 precision_tool/tf_config.py + import precision_tool.tf_config as npu_tf_config + + # 如果使用的是Estimator的NPURunConfig配置使能NPU,则可以参考以下修改 + npu_config = NPURunConfig(fusion_switch_file=npu_tf_config.FUSION_OFF_FILE) # 修改行 + # 如果需要关闭指定的融合规则,则可以修改precision_tool/fusion_switch.cfg, 并参考如下修改 + npu_config = NPURunConfig(fusion_switch_file=npu_tf_config.FUSION_SWITCH_FILE) # 关闭特定融合修改行 + + # 如果使用的是session.run或者使用tf.ConfigProto创建session_config传入tf.estimator.RunConfig的方式使能npu + # 可以参考如下修改(数据Dump和关闭融合同时使能) + session_config = npu_tf_config.session_dump_config(session_config, action='dump|fusion_off') # 新增行 + session_config = npu_tf_config.session_dump_config(session_config, action='dump|fusion_switch') # 关闭特定融合新增行 + # tf.estimator + run_config = tf.estimator.RunConfig(session_config=session_config,...) + # tf.keras + npu_keras_sess = set_keras_session_npu_config(config=session_config) + # session run + with tf.Session(config=npu_config_proto(session_config)): + ...... + ``` +## 使用说明 +1. 配置文件precision_tool/config.py(正常默认即可) + ```python + # 如果需要dump特定曾的数据,则可以修改以下配置项 + # 一般对比分析dump首层即可 + # Dump config '0|5|10' + TF_DUMP_STEP = '0' + + # 融合开关配置,可以再该配置文件中配置融合开关的开启和关闭,使用方法参考以下文档: + # https://support.huaweicloud.com/tensorflowdevg-cann330alphaXtraining/atlastfadapi_07_0005.html + FUSION_SWITCH_FILE = './precision_tool/fusion_switch.cfg' + + # 依赖run包中的atc和msaccucmp.pyc工具,一般在run包安装目录,配置到父目录即可 + # 默认run包安装在/usr/local/Ascend,可以不用修改。指定目录安装则需要修改 + # parent dir path of msaccucmp.pyc and atc, usually run package dir + CMD_ROOT_PATH = '/usr/local/' + + # ASCEND Log Path + ASCEND_LOG_PATH = '/root/ascend/log/plog/' + + # 日志级别及数据分析目录设置 + # TOOL CONFIG + LOG_LEVEL = "NOTSET" + # ModelArts场景下,可以根据情况将数据跟目录修改成自定义目录,并在完成后完整下载该目录 + ROOT_DIR = './' + ``` +2. 启动脚本(交互命令行) + ```shell + python3 ./precision_tool/cli.py + ``` + +### 交互模式命令 +1. ac -l [limit_num] -c + ```shell + # auto check. 自动化检测命令 + # 列出Fusion信息;解析算子溢出信息; + # -c 可选,进行全网比对 + # -l 可选,限制输出结果的条数(overflow解析的条数等) + PrecisionTool > ac -c + ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ [TransData][327] trans_TransData_1170 │ + │ - [AI Core][Status:32][TaskId:327] ['浮点计算有溢出'] │ + │ - First overflow file timestamp [1619347786532995] - │ + │ |- TransData.trans_TransData_1170.327.1619347786532995.input.0.npy │ + │ |- [Shape: (32, 8, 8, 320)] [Dtype: bool] [Max: True] [Min: False] [Mean: 0.11950836181640626] │ + │ |- TransData.trans_TransData_1170.327.1619347786532995.output.0.npy │ + │ |- [Shape: (32, 20, 8, 8, 16)] [Dtype: bool] [Max: True] [Min: False] [Mean: 0.07781982421875] │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ + ``` +2. run [command] + ```shell + # 不退出交互命令环境执行shell命令,与内置命令不冲突的可以直接执行,否则需要加run前缀 + PrecisionTool > run vim cli.py + PrecisionTool > vim cli.py + ``` + +3. ls -n [op_name] -t [op_type] + ```shell + # 通过[算子名]/[算子类型]查询网络里的算子,模糊匹配 + PrecisionTool > ls -t Mul -n mul_3 -f TbeMulti + [Mul][TbeMultiOutputFusionPass] InceptionV3/InceptionV3/Mixed_5b/Branch_1/mul_3 + [Mul][TbeMultiOutputFusionPass] InceptionV3/InceptionV3/Mixed_5c/Branch_1/mul_3 + [Mul][TbeMultiOutputFusionPass] InceptionV3/InceptionV3/Mixed_5d/Branch_1/mul_3 + [Mul][TbeMultiOutputFusionPass] InceptionV3/InceptionV3/Mixed_6b/Branch_1/mul_3 + ``` + +4. ni (-n) [op_name] -d -s [save sub graph deep] + ```shell + # 通过[算子名]查询算子节点信息 + # -d 显示相应的dump数据信息 + # -s 保存一个以当前算子节点为根,深度为参数值的子图 + PrecisionTool > ni gradients/InceptionV3/InceptionV3/Mixed_7a/Branch_0/Maximum_1_grad/GreaterEqual -d -s 3 + ╭─────────────────── [GreaterEqual]gradients/InceptionV3/InceptionV3/Mixed_7a/Branch_0/Maximum_1_grad/GreaterEqual ────────────────────╮ + │ [GreaterEqual] gradients/InceptionV3/InceptionV3/Mixed_7a/Branch_0/Maximum_1_grad/GreaterEqual │ + │ Input: │ + │ -[0][DT_FLOAT][NHWC][32, 8, 8, 320] InceptionV3/InceptionV3/Mixed_7a/Branch_0/add_3:0 │ + │ -[1][DT_FLOAT][NHWC][1, 8, 1, 1] InceptionV3/Mixed_7a/Branch_0/Conv2d_1a_3x3tau:0 │ + │ -[2][][[]][] atomic_addr_clean0_21:-1 │ + │ Output: │ + │ -[0][DT_BOOL][NHWC][32, 8, 8, 320] ['trans_TransData_1170'] │ + │ NpuDumpInput: │ + │ -[0] GreaterEqual.gradients_InceptionV3_InceptionV3_Mixed_7a_Branch_0_Maximum_1_grad_GreaterEqual.325.1619494134722860.input.0.npy │ + │ |- [Shape: (32, 8, 8, 320)] [Dtype: float32] [Max: 5.846897] [Min: -8.368301] [Mean: -0.72565556] │ + │ -[1] GreaterEqual.gradients_InceptionV3_InceptionV3_Mixed_7a_Branch_0_Maximum_1_grad_GreaterEqual.325.1619494134722860.input.1.npy │ + │ |- [Shape: (1, 8, 1, 1)] [Dtype: float32] [Max: 0.0] [Min: 0.0] [Mean: 0.0] │ + │ NpuDumpOutput: │ + │ -[0] GreaterEqual.gradients_InceptionV3_InceptionV3_Mixed_7a_Branch_0_Maximum_1_grad_GreaterEqual.325.1619494134722860.output.0.npy │ + │ |- [Shape: (32, 8, 8, 320)] [Dtype: bool] [Max: True] [Min: False] [Mean: 0.1176300048828125] │ + │ CpuDumpOutput: │ + │ -[0] gradients_InceptionV3_InceptionV3_Mixed_7a_Branch_0_Maximum_1_grad_GreaterEqual.0.1619492699305998.npy │ + │ |- [Shape: (32, 8, 8, 320)] [Dtype: bool] [Max: True] [Min: False] [Mean: 0.11764373779296874] │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + 2021-04-27 14:39:55 (15178) -[DEBUG]write 14953 bytes to './precision_data/dump/temp/op_graph/GreaterEqual.gradients_InceptionV3_InceptionV3_Mixed_7a_Branch_0_Maximum_1_grad_GreaterEqual.3.gv' + 2021-04-27 14:39:55 (15178) -[INFO]Sub graph saved to /root/sym/inception/precision_data/dump/temp/op_graph + ``` + +5. pt (-n) [*.npy] (-c) + ```shell + # 查看某个dump数据块的数据信息 + # -c : save data to txt + PrecisionTool > pt TransData.trans_TransData_1170.327.1619347786532995.input.0.npy -c + ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Shape: (32, 8, 8, 320) │ + │ Dtype: bool │ + │ Max: True │ + │ Min: False │ + │ Mean: 0.11950836181640626 │ + │ Path: ./precision_data/dump/temp/overflow_decode/TransData.trans_TransData_1170.327.1619347786532995.input.0.npy │ + │ TxtFile: ./precision_data/dump/temp/overflow_decode/TransData.trans_TransData_1170.327.1619347786532995.input.0.npy.txt │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ``` + +6. cp (-n) [left *.npy] [right *.npy] -p [print num] -al [atol] -rl [rtol] + ```shell + # 对比两个tensor的数据 + # -p 指定输出的错误数据的个数及前多少个数据 + # -al/rl 指定相对误差的参数,在两个场景中用到 + # 1. np.allclose(left, right, atol=al, rtol=rl) + # 2. err_cnt += 1 if abs(data_left[i] - data_right[i]) > (al + rl * abs(data_right[i])) + PrecisionTool > cp Add.InceptionV3_InceptionV3_Mixed_7a_Branch_0_add_3.323.1619494134703053.output.0.npy InceptionV3_InceptionV3_Mixed_7a_Branch_0_add_3.0.1619492699305998.npy -p 10 -s -al 0.002 -rl 0.005 + Error Item Table Top Item Table + ┏━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓ ┏━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Index ┃ Left ┃ Right ┃ Diff ┃ ┃ Index ┃ Left ┃ Right ┃ Diff ┃ + ┡━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━┩ ┡━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ 155 │ 0.024600908 │ 0.022271132 │ 0.002329776 │ │ 0 │ -0.9206961 │ -0.9222216 │ 0.0015255213 │ + │ 247 │ 0.015752593 │ 0.017937578 │ 0.0021849852 │ │ 1 │ -0.6416973 │ -0.64051837 │ 0.0011789203 │ + │ 282 │ -0.0101207765 │ -0.007852031 │ 0.0022687456 │ │ 2 │ -0.35383835 │ -0.35433492 │ 0.0004965663 │ + │ 292 │ 0.019581757 │ 0.02240482 │ 0.0028230622 │ │ 3 │ -0.18851271 │ -0.18883198 │ 0.00031927228 │ + │ 640 │ -0.06593232 │ -0.06874806 │ 0.0028157383 │ │ 4 │ -0.43508735 │ -0.43534422 │ 0.00025686622 │ + │ 1420 │ 0.09293677 │ 0.09586689 │ 0.0029301196 │ │ 5 │ 1.4447614 │ 1.4466647 │ 0.0019032955 │ + │ 1462 │ -0.085207745 │ -0.088047795 │ 0.0028400496 │ │ 6 │ -0.3455438 │ -0.3444429 │ 0.0011008978 │ + │ 1891 │ -0.03433288 │ -0.036525503 │ 0.002192624 │ │ 7 │ -0.6560242 │ -0.6564579 │ 0.0004336834 │ + │ 2033 │ 0.06828873 │ 0.07139922 │ 0.0031104907 │ │ 8 │ -2.6964858 │ -2.6975214 │ 0.0010356903 │ + │ 2246 │ -0.06376442 │ -0.06121233 │ 0.002552092 │ │ 9 │ -0.73746175 │ -0.73650354 │ 0.00095820427 │ + └───────┴───────────────┴──────────────┴──────────────┘ └───────┴─────────────┴─────────────┴───────────────┘ + ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Left: │ + │ |- NpyFile: ./precision_data/dump/temp/decode/Add.InceptionV3_InceptionV3_Mixed_7a_Branch_0_add_3.323.1619494134703053.output.0.npy │ + │ |- TxtFile: ./precision_data/dump/temp/decode/Add.InceptionV3_InceptionV3_Mixed_7a_Branch_0_add_3.323.1619494134703053.output.0.npy.txt │ + │ |- NpySpec: [Shape: (32, 8, 8, 320)] [Dtype: float32] [Max: 5.846897] [Min: -8.368301] [Mean: -0.72565556] │ + │ DstFile: │ + │ |- NpyFile: ./precision_data/dump/cpu/InceptionV3_InceptionV3_Mixed_7a_Branch_0_add_3.0.1619492699305998.npy │ + │ |- TxtFile: ./precision_data/dump/cpu/InceptionV3_InceptionV3_Mixed_7a_Branch_0_add_3.0.1619492699305998.npy.txt │ + │ |- NpySpec: [Shape: (32, 8, 8, 320)] [Dtype: float32] [Max: 5.8425903] [Min: -8.374472] [Mean: -0.7256237] │ + │ NumCnt: 655360 │ + │ AllClose: False │ + │ CosSim: 0.99999493 │ + │ ErrorPer: 0.023504638671875 (rl= 0.005, al= 0.002) │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ``` + +7. vc -lt [left_path] -rt [right_path] -g [graph] + ```python + # 用于手动指定两个目录进行整网对比 + # -lt 必选,其中一个文件目录 + # -rt 必选,另一个目录,一般是标杆目录 + # -g 可选,指定-g将尝试解析graph内的映射关系比对(一般用于NPU和TF之间的数据比对, NPU与NPU之间比对不需要,直接按照算子name对比) + ``` +8. vcs -f [file_name] -c [cos_sim_threshold] -l [limit] + ```python + # 查看精度比对结果的概要信息,可以更加预先相似的阈值过滤出低于阈值的算子/信息 + # -f (--file) 可选,指定csv文件,不设置则默认遍历precision_data/temp/vector_compare/目录下最近产生的对比目录内的所有csv + # -c (--cos_sim) 可选,指定筛选所使用的预先相似度阈值,默认0.98 + # -l (--limit) 可选,指定输出前多少个结果,默认值3 + PrecisionTool > vcs -c 0.98 -l 2 + 2021-05-31 14:48:56 (2344298) -[INFO]Sub path num:[1]. Dirs[['20210529145750']], choose[20210529145750] + 2021-05-31 14:48:56 (2344298) -[DEBUG]Find ['result_20210529145751.csv', 'result_20210529145836.csv', 'result_20210529145837.csv', 'result_20210529145849.csv', 'result_20210529150404.csv', 'result_20210529151102.csv'] result files in dir precision_data/temp/vector_compare/20210529145750 + 2021-05-31 14:48:56 (2344298) -[INFO]Find 0 ops less then 0.98 in precision_data/temp/vector_compare/20210529145750/result_20210529145751.csv + 2021-05-31 14:48:56 (2344298) -[INFO]Find 0 ops less then 0.98 in precision_data/temp/vector_compare/20210529145750/result_20210529145836.csv + 2021-05-31 14:48:56 (2344298) -[INFO]Find 1 ops less then 0.98 in precision_data/temp/vector_compare/20210529145750/result_20210529145837.csv + 2021-05-31 14:48:56 (2344298) -[INFO]Find 2 ops less then 0.98 in precision_data/temp/vector_compare/20210529145750/result_20210529145849.csv + 2021-05-31 14:48:56 (2344298) -[INFO]Find 2 ops less then 0.98 in precision_data/temp/vector_compare/20210529145750/result_20210529150404.csv + 2021-05-31 14:48:56 (2344298) -[INFO]Find 0 ops less then 0.98 in precision_data/temp/vector_compare/20210529145750/result_20210529151102.csv + ╭── [578] pixel_cls_loss/cond_1/TopKV2 ───╮ + │ Left: ['pixel_cls_loss/cond_1/TopKV2'] │ + │ Right: ['pixel_cls_loss/cond_1/TopKV2'] │ + │ Input: │ + │ - [0]1.0 - [1]nan │ + │ Output: │ + │ - [0]0.999999 - [1]0.978459 │ + ╰─────────────────────────────────────────╯ + ╭── [490] gradients/AddN_5 ───╮ + │ Left: ['gradients/AddN_5'] │ + │ Right: ['gradients/AddN_5'] │ + │ Input: │ + │ - [0]nan - [1]1.0 │ + │ Output: │ + │ - [0]0.05469 │ + ╰─────────────────────────────╯ + ``` +### Precision_data目录结构 +``` +precision_data/ +├── npu +│ ├── debug_0 +| | ├── dump +| | └── 20210510101133 +| │ └── graph +| | └── ge_proto_00000179_PreRunAfterBuild.txt +│ └── debug_1 +├── tf +| ├── tf_debug +| └── dump +├── overflow +├── fusion +└── temp + ├── op_graph + ├── decode + | ├── dump_decode + | ├── overflow_decode + | └── dump_convert + └── vector_compare + ├── 20210510101133 + | ├── result_123456.csv + | └── result_123455.csv + └── 20210510101134 + └── result_123458.csv +``` +### 配合msquickcmp一键式推理精度比对工具使用 +- msquickcmp会将中间dump数据和图自动保存在一个时间戳命名的目录内, 可以使用precision_tool工具直接对该目录进行分析 +```python +output-path/timestamp +├── dump_data +├── input +├── model +├── result_2021211214657.csv +└── tmp +``` +- 修改配置 +```python +# file precision_tool/config.py +# [train/infer] if adapt from msquickcmp result, set net type to infer +NET_TYPE = 'infer' +``` +- 执行以下命令 +```shell +# 前提条件: +# 当前目录没有precision_data目录(导入过程会新创建一个precision_data,用于保存导入数据) +# 只有第一次需要使用infer子命令导入,后续直接python3 precision_tool/cli.py +python3 precision_tool/cli.py infer output-path/timestamp +``` + + + + +### TF脚本修改参考 + +```python +# 打印动态Scale的Loss值 +loss_scale_manager = ExponentialUpdateLossScaleManager() +scale_v = sess.run([loss_scale_manager.get_loss_scale()]) +print(">>> Current Loss Scale >>> ", scale_v) + + +with tf.Session() as sess: + # do session.run() + saver = tf.train.Saver() + # 保存ckpt + saver.save(sess, saver_dir) + # ... + # 从ckpt恢复 + saver.restore(sess, saver_dir) + # ... + # 保存Tensorboard + summary_writer = tf.summary.FileWriter(logdir=log_dir, graph=sess.graph) + +``` + +### F&Q +1. 安装gnureadline报错找不到lncurses + ```shell + /usr/bin/ld: cannot find -lncurses + collect2: error: ld returned 1 exit status + error: command 'gcc' failed with exit status 1 + ``` + ```shell + # 先尝试在本地查找libncurses.so* + find / -name libncurses.so* + # 如果能找到以下文件,直接创建一个libncurses.so指向libncurses.so.5即可,否则需要用包管理工具安装ncurses + /usr/lib64/libncurses.so.5 + /usr/lib64/libncurses.so.5.9 + /usr/lib64/libncursesw.so.5 + # 创建软连接 + ln -s /usr/lib64/libncurses.so.5.9 /usr/lib64/libncurses.so + ``` +#### 参与贡献 + +1. Fork 本仓库 +2. 新建 Feat_xxx 分支 +3. 提交代码 +4. 新建 Pull Request \ No newline at end of file diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/__pycache__/config.cpython-37.pyc b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/__pycache__/config.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fb0778ee827c60a67d5f426c23f42ff6aa72081c Binary files /dev/null and b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/__pycache__/config.cpython-37.pyc differ diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/__pycache__/tf_config.cpython-37.pyc b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/__pycache__/tf_config.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..68c8c82fb527c7618c2fd8b27e0f37af3ec4cf25 Binary files /dev/null and b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/__pycache__/tf_config.cpython-37.pyc differ diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/caffe_dump.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/caffe_dump.py new file mode 100644 index 0000000000000000000000000000000000000000..89f8adcb950198c579136b6379eea0ef8242cd6b --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/caffe_dump.py @@ -0,0 +1,160 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# 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. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# 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. + +# coding=utf-8 +""" +Source code: + https://bbs.huaweicloud.com/blogs/181056 +Example: + python3.7 caffe_dump.py -m resnet50.prototxt -w resnet50.caffemodel -i test.bin -n 'data:0' -o ./output_dir + +Guide for setting up Caffe/Tensorflow precision golden data generation environments: + https://bbs.huaweicloud.com/blogs/181059 +""" +import caffe +import sys +import argparse +import os +import caffe.proto.caffe_pb2 as caffe_pb2 +import google.protobuf.text_format +import json +import numpy as np +import time + +TIME_LENGTH = 1000 +FILE_PERMISSION_FLAG = 0o600 + + +class CaffeProcess: + def __init__(self): + parse = argparse.ArgumentParser() + parse.add_argument("-w", dest="weight_file_path", + help=" the caffe weight file path", + required=True) + parse.add_argument("-m", dest="model_file_path", + help=" the caffe model file path", + required=True) + parse.add_argument("-o", dest="output_path", help=" the output path", + required=True) + parse.add_argument("-i", "--input_bins", dest="input_bins", help="input_bins bins. e.g. './a.bin;./c.bin'", + required=True) + parse.add_argument("-n", "--input_names", dest="input_names", + help="input nodes name. e.g. 'graph_input_0:0;graph_input_0:1'", + required=True) + args, _ = parse.parse_known_args(sys.argv[1:]) + self.weight_file_path = os.path.realpath(args.weight_file_path) + self.model_file_path = os.path.realpath(args.model_file_path) + self.input_bins = args.input_bins.split(";") + self.input_names = args.input_names.split(";") + self.output_path = os.path.realpath(args.output_path) + self.net_param = None + self.cur_layer_idx = -1 + + @staticmethod + def _check_file_valid(path, is_file): + if not os.path.exists(path): + print('Error: The path "' + path + '" does not exist.') + exit(-1) + if is_file: + if not os.path.isfile(path): + print('Error: The path "' + path + '" is not a file.') + exit(-1) + else: + if not os.path.isdir(path): + print('Error: The path "' + path + '" is not a directory.') + exit(-1) + + def _check_arguments_valid(self): + self._check_file_valid(self.model_file_path, True) + self._check_file_valid(self.weight_file_path, True) + self._check_file_valid(self.output_path, False) + for input_file in self.input_bins: + self._check_file_valid(input_file, True) + + @staticmethod + def calDataSize(shape): + dataSize = 1 + for dim in shape: + dataSize *= dim + return dataSize + + def _load_inputs(self, net): + inputs_map = {} + for layer_name, blob in net.blobs.items(): + if layer_name in self.input_names: + input_bin = np.fromfile( + self.input_bins[self.input_names.index(layer_name)], np.float32) + input_bin_shape = blob.data.shape + if self.calDataSize(input_bin_shape) == self.calDataSize(input_bin.shape): + input_bin = input_bin.reshape(input_bin_shape) + else: + print("Error: input node data size %d not match with input bin data size %d.", self.calDataSize( + input_bin_shape), self.calDataSize(input_bin.shape)) + exit(-1) + inputs_map[layer_name] = input_bin + return inputs_map + + def process(self): + """ + Function Description: + process the caffe net, save result as dump data + """ + # check path valid + self._check_arguments_valid() + + # load model and weight file + net = caffe.Net(self.model_file_path, self.weight_file_path, + caffe.TEST) + inputs_map = self._load_inputs(net) + for key, value in inputs_map.items(): + net.blobs[key].data[...] = value + # process + net.forward() + + # read prototxt file + net_param = caffe_pb2.NetParameter() + with open(self.model_file_path, 'rb') as model_file: + google.protobuf.text_format.Parse(model_file.read(), net_param) + for layer in net_param.layer: + name = layer.name.replace("/", "_").replace(".", "_") + index = 0 + for top in layer.top: + data = net.blobs[top].data[...] + file_name = name + "." + str(index) + "." + str( + round(time.time() * 1000000)) + ".npy" + output_dump_path = os.path.join(self.output_path, file_name) + np.save(output_dump_path, data) + os.chmod(output_dump_path, FILE_PERMISSION_FLAG) + print('The dump data of "' + layer.name + + '" has been saved to "' + output_dump_path + '".') + index += 1 + + +if __name__ == "__main__": + caffe_process = CaffeProcess() + caffe_process.process() \ No newline at end of file diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/cli.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/cli.py new file mode 100644 index 0000000000000000000000000000000000000000..9c68ba3b48c6bd02b22ce1b24656e43db425421d --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/cli.py @@ -0,0 +1,143 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# 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. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# 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. +# coding=utf-8 +""" +cli +""" +import os +import sys +import argparse +import time + +from termcolor import colored +from lib.precision_tool import PrecisionTool +from lib.interactive_cli import InteractiveCli +from lib.precision_tool_exception import PrecisionToolException +from lib.util import util +from lib.tf_dump import TfDump +from lib.msquickcmp_adapter import MsQuickCmpAdapter +import config as cfg + + +INTRODUCE_DOC = \ + "===============================\n" \ + "Usage:\n" \ + " Single mode:\n" \ + " Exp:\n" \ + " Dump TF data:\n" \ + " > python3.7.5 precision_tool/cli.py tf_dump \"sh cpu_train.sh param1 param2\" \n" \ + " Dump NPU data:\n" \ + " > python3.7.5 precision_tool/cli.py npu_dump \"sh npu_train.sh param1 param2\" \n" \ + " Check NPU overflow:\n" \ + " > python3.7.5 precision_tool/cli.py npu_overflow \"sh npu_train.sh param1 param2\" \n" \ + " Interactive mode:\n" \ + " Exp:\n" \ + " Start command line:\n" \ + " > python3.7.5 precision_tool/cli.py\n" + + +def _run_tf_dbg_dump(cmdline): + tf_dump = TfDump() + tf_dump.run_tf_dbg_dump(cmdline) + + +def _unset_flags(): + if cfg.PRECISION_TOOL_OVERFLOW_FLAG in os.environ: + del os.environ[cfg.PRECISION_TOOL_OVERFLOW_FLAG] + if cfg.PRECISION_TOOL_DUMP_FLAG in os.environ: + del os.environ[cfg.PRECISION_TOOL_DUMP_FLAG] + + +def _run_npu_dump(cmd): + _unset_flags() + log = util.get_log() + os.environ[cfg.PRECISION_TOOL_DUMP_FLAG] = 'True' + log.info("Start run NPU script with dump data.") + ret = util.execute_command(cmd) + log.info("Finish run NPU script with dump data. ret [%s]", ret) + _unset_flags() + + +def _run_npu_overflow(cmd): + _unset_flags() + log = util.get_log() + os.environ[cfg.PRECISION_TOOL_OVERFLOW_FLAG] = 'True' + log.info("Start run NPU script with overflow check process....") + ret = util.execute_command(cmd) + log.info("Finish run NPU script with overflow check process. ret [%s]", ret) + precision_tool = PrecisionTool() + precision_tool.prepare() + precision_tool.do_check_overflow() + _unset_flags() + + +def _run_infer_adapter(output_path): + """ Run precision_tool with msquickcmp output data + :param output_path: msquickcmp output path + :return: None + """ + adapter = MsQuickCmpAdapter(output_path) + adapter.run() + _run_interactive_cli() + + +def _run_interactive_cli(cli=None): + util.get_log().info("Interactive command mode.") + if cli is None: + cli = InteractiveCli() + try: + cli.cmdloop(intro="Enjoy!") + except KeyboardInterrupt: + util.get_log().info("Bye.......") + + +function_list = { + 'tf_dump': _run_tf_dbg_dump, + 'npu_dump': _run_npu_dump, + 'npu_overflow': _run_npu_overflow, + 'infer': _run_infer_adapter +} + + +def main(): + while len(sys.argv) > 1: + util.get_log().info("Single command mode.") + function_key = sys.argv[1] + cmd_line = sys.argv[2] if len(sys.argv) > 2 else None + if function_key in function_list: + return function_list[function_key](cmd_line) + precision_tool = PrecisionTool() + return precision_tool.single_cmd(sys.argv) + _run_interactive_cli() + + +if __name__ == '__main__': + try: + main() + except PrecisionToolException as pte: + util.get_log().error(pte.error_info) diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/config.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/config.py new file mode 100644 index 0000000000000000000000000000000000000000..12bb53a04b2d3412897f6f921d0644db6e225ff5 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/config.py @@ -0,0 +1,131 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# 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. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# 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. +# coding=utf-8 +import os + +# Dump config '0|5|10' +TF_DUMP_STEP = '0' + +# path to run package operator cmp compare +# default may be /usr/local/Ascend/ +CMD_ROOT_PATH = '/usr/local/Ascend/' + +# ASCEND Log Path +ASCEND_LOG_PATH = '/root/ascend/log/plog/' + +# TOOL CONFIG +LOG_LEVEL = "NOTSET" +ROOT_DIR = '' + +# [train/infer] if adapt from msquickcmp result, set net type to infer +NET_TYPE = 'train' + +''' +precision_data/ +├── npu +│ ├── debug_0 +| | ├── dump +| | | └── 20210510101133 +| │ └── graph +| | └── ge_proto_00000179_PreRunAfterBuild.txt +│ └── debug_1 +├── tf +| ├── tf_debug +| └── dump +├── overflow +├── fusion +└── temp + ├── op_graph + ├── decode + | ├── dump_decode + | ├── overflow_decode + | └── dump_convert + └── vector_compare + ├── 20210510101133 + | ├── result_123456.csv + | └── result_123455.csv + └── 20210510101134 + └── result_123458.csv +''' + +# Static dirs, do not change +DATA_ROOT_DIR = os.path.join(ROOT_DIR, 'precision_data') + +# fusion +FUSION_DIR = os.path.join(DATA_ROOT_DIR, 'fusion') + +# npu dump/graph parent dir +NPU_DIR = os.path.join(DATA_ROOT_DIR, 'npu') +DEFAULT_NPU_DIR = os.path.join(NPU_DIR, 'debug_0') +DEFAULT_NPU_DUMP_DIR = os.path.join(DEFAULT_NPU_DIR, 'dump') +DEFAULT_NPU_GRAPH_DIR = os.path.join(DEFAULT_NPU_DIR, 'graph') +DEFAULT_OP_DEBUG_DIR = DEFAULT_NPU_DIR + +# npu overflow dir +OVERFLOW_DIR = os.path.join(DATA_ROOT_DIR, 'overflow') +NPU_OVERFLOW_DUMP_DIR = os.path.join(OVERFLOW_DIR, 'dump') + +# tf dirs +TF_DIR = os.path.join(DATA_ROOT_DIR, 'tf') +TF_DEBUG_DUMP_DIR = os.path.join(TF_DIR, 'tf_debug') +TF_DUMP_DIR = os.path.join(TF_DIR, 'dump') +TF_GRAPH_DIR = os.path.join(TF_DIR, 'graph') + +# pytroch dirs +PT_DIR = os.path.join(DATA_ROOT_DIR, 'pt') +PT_DUMP_DIR = os.path.join(PT_DIR, 'dump') + +# tmp dirs +TMP_DIR = os.path.join(DATA_ROOT_DIR, 'temp') +OP_GRAPH_DIR = os.path.join(TMP_DIR, 'op_graph') + +DECODE_DIR = os.path.join(TMP_DIR, 'decode') +OVERFLOW_DECODE_DIR = os.path.join(DECODE_DIR, 'overflow_decode') +DUMP_DECODE_DIR = os.path.join(DECODE_DIR, 'dump_decode') +DUMP_CONVERT_DIR = os.path.join(DECODE_DIR, 'dump_convert') + +VECTOR_COMPARE_PATH = os.path.join(TMP_DIR, 'vector_compare') +TF_TENSOR_NAMES = os.path.join(TMP_DIR, 'tf_tensor_names.txt') +TF_TENSOR_DUMP_CMD = os.path.join(TMP_DIR, 'tf_tensor_cmd.txt') + +# FLAG +PRECISION_TOOL_OVERFLOW_FLAG = 'PRECISION_TOOL_OVERFLOW' +PRECISION_TOOL_DUMP_FLAG = 'PRECISION_TOOL_DUMP' + +# DUMP CONFIG +OP_DEBUG_LEVEL = 0 +DUMP_GE_GRAPH_VALUE = 2 +DUMP_GRAPH_LEVEL_VALUE = 3 +DUMP_SEED = 0 + +# TF_DEBUG +TF_DEBUG_TIMEOUT = 360 + +# MSACCUCMP +MS_ACCU_CMP = r'msaccucmp.py[c]?' +BUILD_JSON_GRAPH_NAME = 'Build' diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/fusion_off.cfg b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/fusion_off.cfg new file mode 100644 index 0000000000000000000000000000000000000000..16999744a97314fe09ac1ae61595de9624ce053c --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/fusion_off.cfg @@ -0,0 +1,10 @@ +{ + "Switch": { + "GraphFusion": { + "ScopeLayerNormFusionPass": "off" + }, + "UBFusion": { + "ALL": "on" + } + } +} diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/fusion_switch.cfg b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/fusion_switch.cfg new file mode 100644 index 0000000000000000000000000000000000000000..572ad427170fddff27404666b8676f75c74a3164 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/fusion_switch.cfg @@ -0,0 +1,6 @@ +{ +"Switch": { + "GraphFusion": {}, + "UBFusion": {} +} +} \ No newline at end of file diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/compare.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/compare.py new file mode 100644 index 0000000000000000000000000000000000000000..972e7667c736e1c0a7c1cde593fd27844bfec01e --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/compare.py @@ -0,0 +1,209 @@ +# coding=utf-8 +""" +Compare +""" +import json +import os +import numpy as np +from lib.tool_object import ToolObject +from lib.util import util +from lib.compare_result import CompareResult +from lib.constant import Constant +import config as cfg +from lib.precision_tool_exception import PrecisionToolException +from lib.precision_tool_exception import catch_tool_exception + + +class Compare(object): + def __init__(self): + """Init""" + super(Compare, self).__init__() + self.log = util.get_log() + self.vector_compare_results = {} + + @catch_tool_exception + def prepare(self): + util.create_dir(cfg.VECTOR_COMPARE_PATH) + + def npu_tf_vector_compare(self, graphs, npu_root_dir, tf_root_dir, result_dir): + """Compare npu dump data with tf dump data + :param graphs: npu ge graph json file list + :param npu_root_dir: + :param tf_root_dir: + :param result_dir: result dir + :return: + """ + for graph_file in graphs: + self.log.info("Compare npu tf with graph %s", graph_file) + sub_graphs = self._get_sub_graphs(graph_file) + if sub_graphs is None: + continue + for sub_graph in sub_graphs: + npu_dir = self._get_sub_dir_by_sub_graph_name(sub_graph, npu_root_dir) + if npu_dir is None: + continue + self.vector_compare(npu_dir, tf_root_dir, result_dir, graph_file) + + @catch_tool_exception + def _get_sub_dir_by_sub_graph_name(self, sub_graph, npu_root_dir): + sub_graph_dirs = [] + for dir_path, dir_names, file_names in os.walk(npu_root_dir, followlinks=True): + if sub_graph in dir_names: + # walk sub graph dir + for sub_dir_path, sub_dir_names, sub_file_names in os.walk(os.path.join(dir_path, sub_graph), + followlinks=True): + if len(sub_dir_names) == 0: + sub_graph_dirs.append(sub_dir_path) + if len(sub_graph_dirs) == 0: + return None + self.log.warning("Find [%d] dirs in sub graph dir [%s], %s, compare first.", len(sub_graph_dirs), sub_graph, + sub_graph_dirs) + return sub_graph_dirs[0] + + @catch_tool_exception + def _get_sub_graphs(self, graph_file): + with open(graph_file, 'r') as f: + graph_json = json.load(f) + if 'graph' not in graph_json: + raise PrecisionToolException("No graph in file: %s" % graph_file) + sub_graphs = [] + for graph in graph_json['graph']: + sub_graphs.append(graph['name']) + return sub_graphs + + ''' + @staticmethod + def _get_ge_default_dirs(self, root_dir): + for dir_path, dir_names, file_names in os.walk(root_dir, followlinks=True): + for dir_name in dir_names: + ''' + + def npu_vector_compare(self, debug_0_root_dir, debug_1_root_dir): + """Compare two npu dump data + :param debug_0_root_dir: + :param debug_1_root_dir: + :return: + """ + # debug_0_sub_dirs = self._get_ge_default_dirs(debug_0_root_dir) + # debug_1_sub_dirs = self._get_ge_default_dirs(debug_1_root_dir) + + def vector_compare(self, lh_path, rh_path, result_dir, graph_json=None): + """Compare all ops""" + if lh_path is None or util.empty_dir(lh_path): + raise PrecisionToolException("No valid dump file in %s" % lh_path) + if rh_path is None or util.empty_dir(rh_path): + raise PrecisionToolException("No valid dump file in %s" % rh_path) + self.log.info("Start vector compare process...") + util.compare_vector(lh_path, rh_path, graph_json, result_dir) + self.log.info("Vector compare process finish.") + + def _get_compare_result_by_file_name(self, file_name): + results = [] + if file_name is None: + sub_dir = util.get_newest_dir(cfg.VECTOR_COMPARE_PATH) + if sub_dir == '': + raise PrecisionToolException("Empty vector compare path:%s" % cfg.VECTOR_COMPARE_PATH) + file_name = os.path.join(cfg.VECTOR_COMPARE_PATH, sub_dir) + if os.path.isfile(file_name): + results.append(CompareResult(file_name)) + if os.path.isdir(file_name): + vector_compare_result_files = util.list_vector_compare_result_files(file_name) + if vector_compare_result_files is None or len(vector_compare_result_files) == 0: + raise PrecisionToolException("Can not find any vector compare result in dir:%s" % file_name) + file_list = sorted(vector_compare_result_files.values(), key=lambda x: x.timestamp) + file_names = [x.file_name for x in file_list] + self.log.debug("Find %s result files in dir %s", file_names, file_name) + for file in file_list: + results.append(CompareResult(file.path)) + return results + + @catch_tool_exception + def vector_summary(self, file_name=None, cos_sim_threshold=0.98, limit=1): + """Print not NaN result in vector compare result""" + compare_results = self._get_compare_result_by_file_name(file_name) + error_ops = [] + for compare_result in compare_results: + err_ops = compare_result.get_op_by_cosine_sim_threshold(cos_sim_threshold, limit) + self.log.info("Find %d ops less then %s in %s", len(err_ops), cos_sim_threshold, compare_result.file_path) + error_ops.extend(err_ops) + if len(error_ops) == 0: + self.log.info("Can not find any compare result over threshold: %s" % cos_sim_threshold) + else: + for i, error_op in enumerate(error_ops): + if i < limit: + error_op.summary(cos_sim_threshold) + return error_ops + + def compare_data(self, left, right, save_txt=False, rl=0.001, al=0.001, diff_count=20): + """Compare data""" + left = self._detect_file(left) + right = self._detect_file(right) + if left is None or right is None: + raise PrecisionToolException("invalid input or output") + # save to txt + if save_txt: + util.save_npy_to_txt(left) + util.save_npy_to_txt(right) + # compare data + total_cnt, all_close, cos_sim, err_percent = self._do_compare_data(left, right, rl, al, diff_count) + content = ['Left:', ' ├─ NpyFile: %s' % left] + if save_txt: + content.append(' ├─ TxtFile: [green]%s.txt[/green]' % left) + content.append(' └─ NpySpec: [yellow]%s[/yellow]' % util.gen_npy_info_txt(left)) + content.append('Right:') + content.append(' ├─ NpyFile: %s' % right) + if save_txt: + content.append(' ├─ TxtFile: [green]%s.txt[/green]' % right) + content.append(' └─ NpySpec: [yellow]%s[/yellow]' % util.gen_npy_info_txt(right)) + content.append('NumCnt: %s' % total_cnt) + content.append('AllClose: %s' % all_close) + content.append('CosSim: %s' % cos_sim) + content.append('ErrorPer: %s (rl= %s, al= %s)' % (err_percent, rl, al)) + util.print_panel(Constant.NEW_LINE.join(content)) + + def _do_compare_data(self, left, right, rl=0.001, al=0.001, diff_count=20): + data_left = np.load(left).astype(np.float32) + data_right = np.load(right).astype(np.float32) + shape_left = data_left.shape + shape_right = data_right.shape + if shape_left != shape_right: + self.log.warning("Data shape not equal: %s vs %s", data_left.shape, data_right.shape) + data_left = data_left.reshape(-1) + data_right = data_right.reshape(-1) + if data_left.shape[0] != data_right.shape[0]: + self.log.warning("Data size not equal: %s vs %s", data_left.shape, data_right.shape) + if data_left.shape[0] < data_right.shape[0]: + data_left = np.pad(data_left, (0, data_right.shape[0] - data_left.shape[0]), 'constant') + else: + data_right = np.pad(data_right,(0, data_left.shape[0] - data_right.shape[0]), 'constant') + all_close = np.allclose(data_left, data_right, atol=al, rtol=rl) + # cos_sim = 1 - spatial.distance.cosine(data_left, data_right) + cos_sim = np.dot(data_left, data_right) / ( + np.sqrt(np.dot(data_left, data_left)) * np.sqrt(np.dot(data_right, data_right))) + err_cnt = 0 + total_cnt = data_left.shape[0] + diff_table_columns = ['Index', 'Left', 'Right', 'Diff'] + err_table = util.create_table("Error Item Table", diff_table_columns) + top_table = util.create_table("Top Item Table", diff_table_columns) + for i in range(total_cnt): + abs_diff = abs(data_left[i] - data_right[i]) + if i < diff_count: + top_table.add_row(str(i), str(data_left[i]), str(data_right[i]), str(abs_diff)) + if abs_diff > (al + rl * abs(data_right[i])): + if err_cnt < diff_count: + err_table.add_row(str(i), str(data_left[i]), str(data_right[i]), str(abs_diff)) + err_cnt += 1 + err_percent = float(err_cnt / total_cnt) + util.print(util.create_columns([err_table, top_table])) + return total_cnt, all_close, cos_sim, err_percent + + def _detect_file(self, file_name): + """Find files in npu/overflow/cpu dump dir""" + if os.path.isfile(file_name): + return file_name + for parent_dir in [cfg.TMP_DIR, cfg.TF_DUMP_DIR]: + file_infos = util.list_numpy_files(parent_dir, file_name) + if len(file_infos) > 0: + self.log.info("Find %s, choose first one.", list(file_infos.keys())) + return list(file_infos.values())[0].path + return None diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/compare_result.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/compare_result.py new file mode 100644 index 0000000000000000000000000000000000000000..06341ad8cca081a4925644c4ff02d650ec045c58 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/compare_result.py @@ -0,0 +1,143 @@ +import collections +import os +import numpy as np +from lib.util import util +from lib.constant import Constant +from lib.precision_tool_exception import PrecisionToolException +from lib.precision_tool_exception import catch_tool_exception + + +class RowMap(object): + """ + 'Index': 0, + 'LeftOp': 1, + 'RightOp': 2, + 'TensorIdx': 3, # TensorIndex + 'CosSim': 4, # CosineSimilarity + 'MaxAbs': 5, # MaxAbsoluteError + 'ARE': 6, # AccumulatedRelativeError + 'RED': 7, # RelativeEuclideanDistance + 'KLD': 8, # KullbackLeiblerDivergence + 'StandardDeviation': 9 # StandardDeviation + """ + def __init__(self, item=None): + self.index = 0 + self.left = 1 + self.right = 2 + self.tensor_index = 3 + self.cosine_similarity = 4 + self.max_abs = 5 + if item is not None: + self.update(item) + + def update(self, item): + for i, value in enumerate(item): + self.left = i if value == 'LeftOp' else self.left + self.right = i if value == 'RightOp' else self.right + self.tensor_index = i if value == 'TensorIndex' else self.tensor_index + self.cosine_similarity = i if value == 'CosineSimilarity' else self.cosine_similarity + self.max_abs = i if value == 'MaxAbsoluteError' else self.max_abs + + +class CompareItem(object): + def __init__(self, op_name, item, row_map): + self.row_map = row_map + self.index = int(item[self.row_map.index]) + self.op_name = op_name + self.left = item[self.row_map.left].split(" ") + self.right = item[self.row_map.right].split(" ") + self.input = [] + self.output = [] + + def update(self, item): + tensor_index = item[self.row_map.tensor_index] + if tensor_index not in ['NaN', '*']: + item_detail = tensor_index.split(':') + if len(item_detail) != 3: + raise PrecisionToolException("item:%d tensor index invalid. [%s]" % ( + item[self.row_map.index], tensor_index)) + if item_detail[1] == 'input': + self.input.insert(int(item_detail[2]), item) + else: + self.output.insert(int(item_detail[2]), item) + + def is_cosine_sim_over_threshold(self, threshold): + for item in self.output: + if item[self.row_map.cosine_similarity] == 'NaN': + continue + if float(item[self.row_map.cosine_similarity]) <= threshold: + return True + return False + + @staticmethod + def _color_data(data, threshold): + try: + data = float(data) + if np.isnan(data): + raise ValueError + elif data <= threshold: + return "[red]%s[/red]" % data + else: + return "[green]%s[/green]" % data + except ValueError: + return "[yellow]%s[/yellow]" % data + + def summary(self, threshold): + content = ["Left: %s" % self.left, "Right: %s" % self.right, "Input: "] + input_txt = [] + for i, item in enumerate(self.input): + input_txt.append(" - [%d]%s" % (i, self._color_data(item[self.row_map.cosine_similarity], threshold))) + content.extend([Constant.TAB_LINE.join(input_txt), "Output:"]) + output_txt = [] + for i, item in enumerate(self.output): + output_txt.append(" - [%d]%s" % (i, self._color_data(item[self.row_map.cosine_similarity], threshold))) + content.append(Constant.TAB_LINE.join(output_txt)) + title = "[%d] %s" % (self.index, self.op_name) + util.print_panel(Constant.NEW_LINE.join(content), title=title) + + +class CompareResult(object): + def __init__(self, file_path): + self.file_path = file_path + self.ops = None + self.prepare() + + @catch_tool_exception + def prepare(self): + if not str(self.file_path).endswith(Constant.Suffix.CSV): + raise PrecisionToolException("Compare result file %s not a csv file." % self.file_path) + if not os.path.isfile(self.file_path): + raise PrecisionToolException("Compare result file %s not exist." % self.file_path) + items = util.read_csv(self.file_path) + self.ops = collections.OrderedDict() + row_map = RowMap() + for item in items: + if item[row_map.index] == 'Index': + row_map.update(item) + continue + if item[row_map.tensor_index] in ['NaN', '*']: + continue + tensor_index = item[row_map.tensor_index] + op_name = tensor_index.split(":")[0] + if op_name not in self.ops: + self.ops[op_name] = CompareItem(op_name, item, row_map) + op = self.ops[op_name] + op.update(item) + + def get_compare_item_by_op(self, op_name): + if self.ops is None: + self.prepare() + if self.ops is None: + raise PrecisionToolException("Invalid compare result file: %s" % self.file_path) + if op_name in self.ops: + return self.ops[op_name] + return None + + def get_op_by_cosine_sim_threshold(self, threshold, limit=-1): + result = [] + for compare_item in self.ops.values(): + if compare_item.is_cosine_sim_over_threshold(threshold): + result.append(compare_item) + if len(result) == limit: + break + return result diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/constant.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/constant.py new file mode 100644 index 0000000000000000000000000000000000000000..01c69b18ede388f8dcde0fb9f05843f40e304462 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/constant.py @@ -0,0 +1,19 @@ +# coding=utf-8 + + +class Constant(object): + NEW_LINE = "\n" + TAB_LINE = "\t" + DEFAULT_DEBUG_ID = "debug_0" + NPU_DEBUG_ID_1 = "debug_1" + GRAPH = "graph" + DUMP = "dump" + + class Suffix(object): + JSON = '.json' + CSV = '.csv' + H5 = '.h5' + + class Pattern(object): + GE_PROTO_GRAPH_PATTERN = r'^ge_proto_([0-9]+)_([A-Za-z0-9_-]+)\.txt$' + diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/cpu_tvm.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/cpu_tvm.py new file mode 100644 index 0000000000000000000000000000000000000000..a0906071e33bfcbc2c8a51e3a3fe18381bcfc79d --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/cpu_tvm.py @@ -0,0 +1,51 @@ +import numpy as np +from tbe import tvm + + +class CpuTvm(): + def __init__(self, json_file, dump_input_files, dump_output_files): + self.json_file = json_file + self.dump_input_files = dump_input_files + self.dump_output_files = dump_output_files + self.input_list = [] + self.output_list = [] + + def _load_schedule(self): + with open(self.json_file, 'r') as jsonfile: + tvm_node = tvm.load_json(jsonfile.read()) + self.output_list = tvm_node.op.attrs['output_list'] + self.input_list = tvm_node.op.attrs['input_list'] + schedule = tvm.create_schedule([res.op for res in self.output_list]) + return schedule + + def _build_tvm(self, schedule): + tensor_list = [ele for ele in self.input_list if ele is not None] + for ele in self.output_list: + if ele is not None: + tensor_list.append(ele) + fusion_op = tvm.build(schedule, tensor_list, "c", "llvm") + return fusion_op + + def _load_data(self, dump_files): + ctx = tvm.cpu(0) + data_tvm = [] + for dump_file in dump_files: + data_temp_numpy = np.load(dump_file) + data_temp_tvm = tvm.nd.array(data_temp_numpy, ctx) + data_tvm.append(data_temp_tvm) + return data_tvm + + def run_cpu_tvm(self): + # load schedule and build tvm + schedule = self._load_schedule() + fusion_op = self._build_tvm(schedule) + + #load data and run cpu tvm + data_tvm_in = self._load_data(self.dump_input_files) + data_tvm_out = self._load_data(self.dump_output_files) + data_tvm_in.extend(data_tvm_out) + fusion_op(*data_tvm_in) + + #tvm format to numpy format + data_np_out = [data.asnumpy() for data in data_tvm_out] + return data_np_out diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/desc.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/desc.py new file mode 100644 index 0000000000000000000000000000000000000000..bac7ea75e9cf939ff3f7be3dfffcc23454714e72 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/desc.py @@ -0,0 +1,150 @@ +# coding=utf-8 +from lib.util import util + +ATTR = 'attr' +ATTR_KEY = 'key' +ATTR_VALUE = 'value' +DATA_DUMP_ORIGIN_OUTPUT_INDEX = '_datadump_origin_output_index' +FUSION_ORIGIN_OUTPUT_INDEX = '_fusion_origin_output_index' +DATA_DUMP_ORIGIN_NAME = '_datadump_origin_name' +ORIGIN_FORMAT = 'origin_format' +ORIGIN_SHAPE = 'origin_shape' +VALUE_RANGE = 'value_range' +SHAPE_RANGE = 'shape_range' +DT_STRING = 's' +DT_INT = 'i' +DT_LIST_LIST_INT = 'list_list_int' +DT_LIST_LIST_I = 'list_list_i' +DT_LIST = 'list' +DT_LIST_INT = 'list_i' +DATA_TYPE_DEFAULT_VALUE = { + 'i': 0, + 's': '' +} + + +class Desc(object): + """ Op desc + shape: data shape + dtype: data type + format: data format + npu_file: npu file name/path + cpu_file: cpu file name/path + idx: input idx + """ + def __init__(self, desc_json, index): + self.desc_json = desc_json + self.index = index + self.log = util.get_log() + + def idx(self): + return self.index + + def shape(self): + return self.desc_json['shape']['dim'] if 'shape' in self.desc_json else [] + + def dtype(self): + return self.desc_json['dtype'] if 'dtype' in self.desc_json else '' + + def format(self): + return self.desc_json['layout'] if 'layout' in self.desc_json else [] + + def origin_shape(self): + return self._get_attr_list(ORIGIN_SHAPE, DT_INT) + + def origin_format(self): + return self._get_attr(ORIGIN_FORMAT, DT_STRING) + + def value_range(self): + return self._get_attr_list_list(VALUE_RANGE, DT_LIST_INT) + + def shape_range(self): + return self._get_attr_list_list(SHAPE_RANGE, DT_LIST_INT) + + def _get_attr_list_list(self, key, data_type): + val = self._get_attr_base(key, DT_LIST_LIST_INT) + if val is None or DT_LIST_LIST_I not in val: + return [] + res = [] + for item in val[DT_LIST_LIST_I]: + if data_type in item: + res.append(item[data_type]) + return res + + def _get_attr_list(self, key, data_type): + val = self._get_attr_base(key, DT_LIST) + return val[data_type] if val is not None else [] + + def _get_attr(self, key, data_type): + val = self._get_attr_base(key, data_type) + return val if val is not None else DATA_TYPE_DEFAULT_VALUE[data_type] + + def _get_attr_base(self, key, data_type): + if ATTR in self.desc_json: + for attr in self.desc_json[ATTR]: + if attr[ATTR_KEY] == key: + if data_type in attr[ATTR_KEY]: + return attr[ATTR_VALUE][data_type] + return None + + def compare(self, right_desc): + if self.dtype() == right_desc.dtype() and self.format() == right_desc.format(): + return "[green][%d] [%s][%s] %s[/green]" % (self.idx(), self.dtype(), self.format(), self.shape()), True + else: + return "[yellow][%d] [%s][%s] %s | [%s][%s] %s[/yellow]" % ( + self.idx(), self.dtype(), self.format(), self.shape(), + right_desc.dtype(), right_desc.format(), right_desc.shape()), False + + +class InputDesc(Desc): + def __init__(self, name, desc_json, index): + super(InputDesc, self).__init__(desc_json, index) + if name == '': + self.log.warning('invalid input name.') + name_info = name.split(':') + self.op_name = name + self.peer_index = -2 + if len(name_info) == 2: + self.op_name = name_info[0] + self.peer_index = int(name_info[1]) + + def name(self): + return self.op_name + + def peer_idx(self): + return self.peer_index + + def is_control(self): + return self.peer_index == -1 + + def summary(self, origin_txt=False): + """idx | dtype | format | shape | [blue]value_range | shape_range[/blue] | op_name | peer_idx""" + if origin_txt: + return "[%d][%s][%s]%s %s:%d" % (self.idx(), self.dtype(), self.format(), + self.shape(), self.name(), self.peer_idx()) + return "[green][%d][/green][yellow][%s][%s]%s[/yellow][blue] %s %s [/blue] %s:%d" % ( + self.idx(), self.dtype(), self.format(), self.shape(), + self.value_range(), self.shape_range(), self.name(), self.peer_idx()) + + +class OutputDesc(Desc): + def __init__(self, name, desc_json, index): + super(OutputDesc, self).__init__(desc_json, index) + if name == '': + self.log.warning('invalid output name.') + self.op_names = name.split(':') + + def names(self): + return self.op_names + + def summary(self, origin_txt=False): + if origin_txt: + return "[%d][%s][%s]%s %s" % (self.idx(), self.dtype(), self.format(), self.shape(), self.names()) + return "[green][%d][/green][yellow][%s][%s]%s[/yellow] %s" % ( + self.idx(), self.dtype(), self.format(), self.shape(), self.names()) + + def data_dump_origin_name(self): + return self._get_attr(DATA_DUMP_ORIGIN_NAME, DT_STRING) + + def data_dump_origin_output_index(self): + return self._get_attr(DATA_DUMP_ORIGIN_OUTPUT_INDEX, DT_INT) diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/dump_manager.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/dump_manager.py new file mode 100644 index 0000000000000000000000000000000000000000..7eecc7c6e3d7483d1b187f0a9c981c6cee627e98 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/dump_manager.py @@ -0,0 +1,78 @@ +# coding=utf-8 +import os +import re +import collections +from lib.util import util +from lib.constant import Constant +from lib.npu_dump import NpuDump +from lib.tf_dump import TfDump +import config as cfg +from lib.precision_tool_exception import catch_tool_exception +from lib.precision_tool_exception import PrecisionToolException + + +class DumpManager(object): + def __init__(self): + self.npu_dumps = collections.OrderedDict() + self.tf_dump = TfDump(cfg.TF_DUMP_DIR) + self._init_dirs() + + def prepare(self): + # prepare npu + sub_dirs = os.listdir(cfg.NPU_DIR) + if len(sub_dirs) == 0: + # create default + sub_dirs = [Constant.DEFAULT_DEBUG_ID] + sorted(sub_dirs) + for sub_dir in sub_dirs: + npu_dump = NpuDump(sub_dir) + npu_dump.prepare() + self.npu_dumps[sub_dir] = npu_dump + # prepare tf + self.tf_dump.prepare() + + def get_dump_root_dir(self, debug_id): + if debug_id in self.npu_dumps: + return self.npu_dumps[debug_id].dump_root + return None + + def op_dump_summary(self, ops): + npu_result = collections.OrderedDict() + for debug_id, op in ops.items(): + if debug_id in self.npu_dumps: + npu_result[debug_id] = collections.OrderedDict() + for op_detail in op: + npu_result[debug_id][op_detail.graph_name] = self.npu_dumps[debug_id].op_dump_summary(op_detail) + tf_result = None + if self.tf_dump is not None and len(ops[Constant.DEFAULT_DEBUG_ID]) != 0: + tf_result = self.tf_dump.op_dump_summary(ops[Constant.DEFAULT_DEBUG_ID][0]) + return npu_result, tf_result + + def print_tensor(self, file_name, is_convert): + """Print numpy data file""" + if os.path.isfile(file_name): + return util.print_npy_summary(os.path.dirname(file_name), os.path.basename(file_name), is_convert) + # file_name = file_name.replace('/', '_') + # npu decode file + npu_convert_files = self.npu_dumps[Constant.DEFAULT_DEBUG_ID].get_npu_dump_decode_files_by_name(file_name) + # util.list_npu_dump_convert_files(cfg.DECODE_DIR, file_name) + # tf decode file + tf_decode_files = self.tf_dump.get_dump_files_by_name(file_name, True) + # pt decode file + # pt_decode_files = self.pt_dump.get_dump_files_by_name(file_name) + self._print_tensors(npu_convert_files, is_convert) + self._print_tensors(tf_decode_files, is_convert) + + @staticmethod + def _print_tensors(file_infos, is_convert): + if file_infos is not None: + for file_info in file_infos.values(): + util.print_npy_summary(file_info.dir_path, file_info.file_name, is_convert) + + @staticmethod + def _init_dirs(): + """Create dump file dirs""" + util.create_dir(cfg.DUMP_DECODE_DIR) + util.create_dir(cfg.NPU_OVERFLOW_DUMP_DIR) + util.create_dir(cfg.OVERFLOW_DECODE_DIR) + util.create_dir(cfg.TF_DUMP_DIR) diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/file_desc.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/file_desc.py new file mode 100644 index 0000000000000000000000000000000000000000..563a4dc1c2fb400af4238e225c24a430e743ae1f --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/file_desc.py @@ -0,0 +1,36 @@ +# coding=utf-8 +import os + + +class FileDesc(object): + def __init__(self, file_name, dir_path, timestamp=-1): + self.file_name = file_name + self.dir_path = dir_path + self.path = os.path.join(dir_path, file_name) + self.timestamp = timestamp + if self.timestamp == -1: + self.timestamp = os.path.getmtime(self.path) + + +class BuildGraphFileDesc(FileDesc): + def __init__(self, file_name, dir_path, timestamp, graph_id, graph_name): + super(BuildGraphFileDesc, self).__init__(file_name, dir_path, timestamp) + self.graph_id = graph_id + self.graph_name = graph_name + + +class NpuDumpFileDesc(FileDesc): + def __init__(self, file_name, dir_path, timestamp, op_name, op_type, task_id, stream_id=0): + super(NpuDumpFileDesc, self).__init__(file_name, dir_path, timestamp) + self.op_name = op_name + self.op_type = op_type + self.task_id = task_id + stream_id = 0 if stream_id is None else int(stream_id) + self.stream_id = stream_id + + +class DumpDecodeFileDesc(NpuDumpFileDesc): + def __init__(self, file_name, dir_path, timestamp, op_name, op_type, task_id, anchor_type, anchor_idx): + super(DumpDecodeFileDesc, self).__init__(file_name, dir_path, timestamp, op_name, op_type, task_id) + self.type = anchor_type + self.idx = anchor_idx diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/fusion.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/fusion.py new file mode 100644 index 0000000000000000000000000000000000000000..3883bbce7092415ce4a5f7468b677e5eac5655d7 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/fusion.py @@ -0,0 +1,109 @@ +# coding=utf-8 +import json +import os +import shutil + +from lib.tool_object import ToolObject +from lib.util import util +import config as cfg + +FUSION_RESULT_FILE_NAME = 'fusion_result.json' +EFFECT_TIMES_KEY = 'effect_times' +GRAPH_FUSION_KEY = 'graph_fusion' +UB_FUSION_KEY = 'ub_fusion' +GRAPH_ID_KEYS = ['graphId', 'session_and_graph_id'] + + +class FusionResult(object): + def __init__(self, fusion_json): + self.fusion_json = fusion_json + + def get_effect_graph_fusion(self): + """Get effect graph fusion rule""" + if GRAPH_FUSION_KEY in self.fusion_json: + return self._get_effect_fusion(self.fusion_json[GRAPH_FUSION_KEY]) + return {} + + def get_effect_ub_fusion(self): + """Get effect UB fusion rule""" + if UB_FUSION_KEY in self.fusion_json: + return self._get_effect_fusion(self.fusion_json[UB_FUSION_KEY]) + return {} + + def graph_id(self): + """Get graph id""" + for key in GRAPH_ID_KEYS: + if key in self.fusion_json: + return self.fusion_json[key] + return "NONE" + + @staticmethod + def _get_effect_fusion(fusion): + res = {} + for fusion_name in fusion: + effect_times = int(fusion[fusion_name][EFFECT_TIMES_KEY]) + if effect_times > 0: + res[fusion_name] = effect_times + return res + + +class Fusion(ToolObject): + def __init__(self): + super(Fusion, self).__init__() + self.fusion_result = [] + self.log = util.get_log() + + def prepare(self, json_path='./'): + """Prepare fusion rule manager + :param json_path: path to fusion_result.json + :return: None + """ + util.create_dir(cfg.FUSION_DIR) + file_path = os.path.join(json_path, FUSION_RESULT_FILE_NAME) + file_path_local = os.path.join(cfg.FUSION_DIR, FUSION_RESULT_FILE_NAME) + if not os.path.isfile(file_path): + if not os.path.isfile(file_path_local): + self.log.warning("Can not find fusion result json.") + return + else: + shutil.copy(file_path, cfg.FUSION_DIR) + fe_jsons = self._get_result_jsons(file_path_local) + for fe_json in fe_jsons: + self.fusion_result.append(FusionResult(fe_json)) + + def check(self): + """Check fusion rules + :return: None + """ + self.log.info("Check effect fusion rule list.") + for fusion in self.fusion_result: + graph_fusion_table = self._build_table('Graph Fusion [GraphID: %s]' % fusion.graph_id(), + fusion.get_effect_graph_fusion()) + ub_fusion_table = self._build_table('UB Fusion [GraphID: %s]' % fusion.graph_id(), + fusion.get_effect_ub_fusion()) + util.print_panel(util.create_columns([graph_fusion_table, ub_fusion_table]), + title='GraphID:' + fusion.graph_id(), fit=True) + + @staticmethod + def _get_result_jsons(file_name): + result_jsons = [] + with open(file_name, 'r') as f: + txt = f.read() + sk = [] + start = -1 + for i in range(len(txt)): + if txt[i] == '{': + sk.append('{') + if txt[i] == '}': + sk.pop() + if len(sk) == 0: + result_jsons.append(json.loads(txt[start+1: i+1])) + start = i + return result_jsons + + @staticmethod + def _build_table(title, fusion): + table = util.create_table(title, ['Fusion Name', 'Effect times']) + for f in fusion: + table.add_row(f, str(fusion[f])) + return table diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/graph_manager.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/graph_manager.py new file mode 100644 index 0000000000000000000000000000000000000000..42e34295fb1a0efb786e478d5fd872175680c5e2 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/graph_manager.py @@ -0,0 +1,115 @@ +# coding=utf-8 +""" +Graph Manager +""" +import json +import os +import collections +import time +import config as cfg +from lib.tf_graph import TfGraph +from lib.op import Op +from lib.constant import Constant +from lib.npu_graph import NpuGraph +from lib.tf_graph import TfGraph +from lib.util import util +from lib.precision_tool_exception import catch_tool_exception +from lib.precision_tool_exception import PrecisionToolException + + +class GraphManager(object): + def __init__(self): + self.log = util.get_log() + self.npu_graphs = collections.OrderedDict() + self.tf_graph = None + + def prepare(self): + # prepare npu graphs + if not os.path.exists(cfg.NPU_DIR): + util.create_dir(cfg.NPU_DIR) + sub_dirs = os.listdir(cfg.NPU_DIR) + if len(sub_dirs) == 0: + # create default dir + sub_dirs = [Constant.DEFAULT_DEBUG_ID] + for sub_dir in sub_dirs: + npu_graph = NpuGraph(sub_dir) + npu_graph.prepare() + self.npu_graphs[sub_dir] = npu_graph + # prepare cpu graph + self.tf_graph = TfGraph(cfg.TF_GRAPH_DIR) + + def check_cast(self): + for graph in self.npu_graphs.values(): + graph.check_cast() + + def check_dtype(self): + for graph in self.npu_graphs.values(): + graph.check_dtype() + + def check_similarity(self): + self._check_npu_graph_similarity() + + def _check_npu_graph_similarity(self): + """Check npu graph similarity""" + if len(self.npu_graphs) < 2: + self.log.debug("Only one npu debug, no need to check npu graph similarity.") + return + left_graphs = self.npu_graphs[Constant.DEFAULT_DEBUG_ID].sub_graphs + right_graphs = self.npu_graphs[Constant.NPU_DEBUG_ID_1].sub_graphs + for left_graph in left_graphs.values(): + for right_graph in right_graphs.values(): + if left_graph.graph_id != right_graph.graph_id: + continue + left_graph.compare(right_graph) + + def get_graphs(self, debug_id): + if debug_id not in self.npu_graphs: + raise PrecisionToolException("Get graphs failed with no debug_id:%s" % debug_id) + return self.npu_graphs[debug_id].build_json_files + + def get_ops(self, op_name, graph_name=None): + """ Get npu/tf ops by op_name + :param op_name: op name + :param graph_name: graph name + :return: npu op dict: debug_id->Op, tf op + """ + npu_ops = collections.OrderedDict() + for debug_id, npu_graph in self.npu_graphs.items(): + npu_ops[debug_id] = npu_graph.get_op(op_name, graph_name) + # tf graph op + return npu_ops, None + + def print_op_list(self, op_type='', op_name='', pass_name='', kernel_name=''): + if op_type == '' and op_name == '' and pass_name == '' and kernel_name == '': + table_list = [] + for debug_id, graph in self.npu_graphs.items(): + table = util.create_table(debug_id, ["OpType", "Count"]) + op_type_counter = collections.Counter() + for op in graph.ops_list: + op_type_counter[op.type()] += 1 + for op_types, count in op_type_counter.items(): + table.add_row(op_types, str(count)) + table_list.append(table) + util.print(util.create_columns(table_list)) + + else: + for debug_id, graph in self.npu_graphs.items(): + ops = graph.list_ops(op_type, op_name, pass_name, kernel_name) + ops_txt = ['[green][%s][/green][yellow][%s][/yellow] %s' % ( + op.type(), op.pass_name(), op.name()) for op in ops] + util.print_panel(Constant.NEW_LINE.join(ops_txt), debug_id) + + @staticmethod + def op_graph_summary(ops): + npu_summary = collections.OrderedDict() + for debug_id, op in ops.items(): + npu_summary[debug_id] = collections.OrderedDict() + for op_detail in op: + npu_summary[debug_id][op_detail.graph_name] = op_detail.summary() + return npu_summary, None + + def save_sub_graph(self, ops, deep): + for debug_id, op in ops.items(): + if debug_id in self.npu_graphs: + for op_detail in op: + self.npu_graphs[debug_id].save_sub_graph(op_detail, deep) diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/h5_util.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/h5_util.py new file mode 100644 index 0000000000000000000000000000000000000000..4a9ab1480bf2fe39b392b8f2629abe837b796194 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/h5_util.py @@ -0,0 +1,47 @@ +import h5py +import os +import numpy as np + +from lib.util import util +from lib.constant import Constant +import config as cfg + + +class H5Util(object): + def __init__(self, file_name): + self.log = util.get_log() + self.file_name = file_name + self.h5 = None + self._prepare() + + def __del__(self): + if self.h5 is not None: + self.h5.close() + + def _prepare(self): + if not os.path.isfile(self.file_name) or not str(self.file_name).endswith(Constant.Suffix.H5): + self.log.error("File [%s] not exist or not a h5 file" % self.file_name) + self.h5 = h5py.File(self.file_name, 'r') + + def get_tensor_by_name(self, tensor_name): + if self.h5 is None: + self.log.warning("h5 file is None.") + return None + return np.array(self.h5[tensor_name]) + + def print_tensor(self, tensor_name): + tensor = self.get_tensor_by_name(tensor_name) + if tensor is None: + self.log.warning("Tensor:%s not exist." % tensor_name) + return + file_path = self._dump_numpy(tensor_name, tensor) + util.print_npy_summary(os.path.dirname(file_path), os.path.basename(file_path)) + + def _dump_numpy(self, tensor_name, tensor): + if not os.path.exists(cfg.DUMP_DECODE_DIR): + util.create_dir(cfg.DUMP_DECODE_DIR) + file_name = tensor_name.replace('/', '_').strip('_') + '.npy' + file_path = os.path.join(cfg.DUMP_DECODE_DIR, file_name) + self.log("Dump file: %s" % file_path) + np.save(file_path, tensor) + return file_path diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/interactive_cli.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/interactive_cli.py new file mode 100644 index 0000000000000000000000000000000000000000..c15eb50d845bc97ffe692bf95ca340625a0fba39 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/interactive_cli.py @@ -0,0 +1,89 @@ +# coding=utf-8 +import cmd +from .util import util +from .precision_tool import PrecisionTool + +HEADER = r""" ____ _ _ ______ __ + / __ \________ _____(_)____(_)___ ____/_ __/___ ____ / / + / /_/ / ___/ _ \/ ___/ / ___/ / __ \/ __ \/ / / __ \/ __ \/ / + / ____/ / / __/ /__/ (__ ) / /_/ / / / / / / /_/ / /_/ / / +/_/ /_/ \___/\___/_/____/_/\____/_/ /_/_/ \____/\____/_/""" + +HELP_AC = "Run auto check function, use [-c] to start vector compare process.\n" \ + " usage: ac (-c) \n" +HELP_RUN = "Run any shell command.\n" \ + " usage: (run) vim tensor_name.txt \n" +HELP_PT = "Print npy tensor, use [-c] to convert and save to txt file.\n" \ + " usage: pt (-c) [tensor_name.npy] \n" + + +class InteractiveCli(cmd.Cmd): + def __init__(self): + cmd.Cmd.__init__(self) + self.prompt = "PrecisionTool > " + self.precision_tool = None + util.print_panel(HEADER) + self._prepare() + + def default(self, line=''): + util.execute_command(line) + return False + + def _prepare(self): + self.precision_tool = PrecisionTool() + self.precision_tool.prepare() + + def do_ac(self, line=''): + """Auto check.""" + argv = line.split(' ') if line != '' else [] + self.precision_tool.do_auto_check(argv) + + def do_run(self, line=''): + """Run any shell command""" + util.execute_command(line) + + def do_ls(self, line=''): + """List ops: \n usage: ls (op(default)/dump) -n [op_name] -t [op_type]""" + argv = line.split(' ') if line != '' else [] + if len(argv) > 0 and argv[0] == 'dump': + return self.precision_tool.do_list_dump(argv[1:]) + self.precision_tool.do_list_nodes(argv) + + def do_ni(self, line=''): + """Print node info:\n usage: ni (-n) [op_name]""" + argv = line.split(' ') if line != '' else [] + if '-n' not in argv and '-h' not in argv: + argv.insert(0, '-n') + self.precision_tool.do_node_info(argv) + + def do_dc(self, line=''): + """Convert npu dump by op names:\n usage: dc (-n) [npu dump file] -f [target format]""" + argv = line.split(' ') if line != '' else [] + # if len(argv) == 0: + # return self.precision_tool.do_convert_all_npu_dump() + if '-n' not in argv: + argv.insert(0, '-n') + self.precision_tool.do_convert_npu_dump(argv) + + def do_vc(self, line=''): + """Do vector compare: \n usage: vc """ + argv = line.split(' ') if line != '' else [] + self.precision_tool.do_vector_compare(argv) + + def do_vcs(self, line=''): + """Do vector compare summary""" + argv = line.split(' ') if line != '' else [] + self.precision_tool.do_vector_compare_summary(argv) + + def do_pt(self, line=''): + """Print data info:\n usage: pt (-n) [*.npy] (-c)\n -c: convert and save to txt file""" + argv = line.split(' ') if line != '' else [] + if len(argv) > 0 and argv[0] != '-n' and argv[0] != '-c': + argv.insert(0, '-n') + self.precision_tool.do_print_data(argv) + + def do_cp(self, line=''): + """Compare two data file """ + argv = line.split(' ') if line != '' else [] + argv.insert(0, '-n') + self.precision_tool.do_compare_data(argv) diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/msquickcmp_adapter.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/msquickcmp_adapter.py new file mode 100644 index 0000000000000000000000000000000000000000..885be1f8a1a832dd6b463f05f21dd84844f63a3e --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/msquickcmp_adapter.py @@ -0,0 +1,88 @@ +# coding=utf-8 +import os +import time +import pathlib +import shutil +from lib.util import util +from lib.constant import Constant +import config as cfg +from lib.precision_tool_exception import catch_tool_exception +from lib.precision_tool_exception import PrecisionToolException + + +class MsQuickCmpAdapter(object): + def __init__(self, output_path): + self.output_path = output_path + self.log = util.get_log() + + def run(self): + if self.output_path is None or not os.path.isdir(self.output_path): + raise PrecisionToolException("Invalid output path.") + if os.path.exists(cfg.DATA_ROOT_DIR): + raise PrecisionToolException("Precision data dir exist, can not adapt msquickcmp result.") + + for dir_path, dir_names, file_names in os.walk(self.output_path, followlinks=True): + if 'model' in dir_names: + self._adapt_model(os.path.join(dir_path, 'model')) + if 'dump_data' in dir_names: + self._adapt_dump(os.path.join(dir_path, 'dump_data')) + for file_name in file_names: + if str(file_name).endswith(Constant.Suffix.CSV): + self._adapt_vector_compare_result(os.path.join(dir_path, file_name)) + + def _adapt_model(self, path): + file_names = os.listdir(path) + graph_id = 0 + for file_name in file_names: + if str(file_name).endswith(Constant.Suffix.JSON): + self.log.info("Find msquickcmp model json: %s", file_name) + util.create_dir(cfg.DEFAULT_NPU_GRAPH_DIR) + graph_file_name = 'ge_proto_%d_%s.txt' % (graph_id, cfg.BUILD_JSON_GRAPH_NAME) + graph_json_file_name = graph_file_name + Constant.Suffix.JSON + pathlib.Path(os.path.join(cfg.DEFAULT_NPU_GRAPH_DIR, graph_file_name)).touch() + src_path = os.path.join(path, file_name) + dst_path = os.path.join(cfg.DEFAULT_NPU_GRAPH_DIR, graph_json_file_name) + self.log.info("Copy graph file: %s->%s", src_path, dst_path) + shutil.copy(src_path, dst_path) + time.sleep(3) + pathlib.Path(dst_path).touch() + if not util.empty_dir(cfg.DEFAULT_NPU_GRAPH_DIR): + self.log.info("Adapt model success.") + + def _adapt_dump(self, path): + dir_names = os.listdir(path) + if 'tf' in dir_names: + self._adapt_tf_dump(os.path.join(path, 'tf')) + if 'onnx' in dir_names: + self._adapt_tf_dump(os.path.join(path, 'onnx')) + if 'npu' in dir_names: + self._adapt_npu_dump(os.path.join(path, 'npu')) + + def _adapt_tf_dump(self, path): + if util.empty_dir(path): + return + src_path = os.path.abspath(path) + util.create_dir(cfg.TF_DIR) + dst_path = cfg.TF_DUMP_DIR + self.log.info("Create symbol link file: %s->%s", src_path, dst_path) + os.symlink(src_path, dst_path) + self.log.info("Adapt tf dump success.") + + def _adapt_npu_dump(self, path): + sub_dirs = os.listdir(path) + self.log.info("Find npu dump dir:%s", sub_dirs) + sub_dirs = filter(lambda x: str(x).isdigit(), sub_dirs) + for sub_dir in sub_dirs: + util.create_dir(cfg.DEFAULT_NPU_DUMP_DIR) + src_path = os.path.abspath(os.path.join(path, sub_dir)) + dst_path = os.path.join(cfg.DEFAULT_NPU_DUMP_DIR, sub_dir) + self.log.info("Create symbol link file: %s->%s", src_path, dst_path) + os.symlink(src_path, dst_path) + self.log.info("Adapt npu dump success.") + + def _adapt_vector_compare_result(self, path): + target_path = os.path.join(cfg.VECTOR_COMPARE_PATH, '0') + util.create_dir(target_path) + dst_path = os.path.join(target_path, os.path.basename(path)) + shutil.copy(path, dst_path) + self.log.info("Adapt vector compare result.") diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/npu_dump.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/npu_dump.py new file mode 100644 index 0000000000000000000000000000000000000000..2da705c158e956883fc6e1fc1938e9127c43df99 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/npu_dump.py @@ -0,0 +1,184 @@ +# coding=utf-8 +import os +import re +from lib.util import util +from lib.constant import Constant +import config as cfg +from lib.precision_tool_exception import catch_tool_exception +from lib.precision_tool_exception import PrecisionToolException + + +class NpuDumpDecodeFile(object): + def __init__(self): + self.log = util.get_log() + self.input_files = {} + self.output_files = {} + self.timestamp = -1 + self.op_name = '' + self.op_type = '' + self.task_id = -1 + # self.stream_id = -1 + + def update(self, file_info): + """Prepare op npu decode file map.""" + if not self._check(file_info): + self.log.warning('Invalid NpuDumpDecodeFile: %s', file_info) + return + if file_info.type == 'input': + self.input_files[file_info.idx] = file_info + else: + self.output_files[file_info.idx] = file_info + + def summary(self): + txt = ['[yellow][%s][TaskID: %d][/yellow][green][%s][/green] %s' % ( + self.timestamp, self.task_id, self.op_type, self.op_name)] + if len(self.input_files) > 0: + info = self.input_files[0] + shape, dtype, max_data, min_data, mean = util.npy_info(info.path) + txt.append(' - Input: [green][0][/green][yellow][%s][%s][Max:%d][Min:%d][Mean:%d][/yellow] %s' % ( + shape, dtype, max_data, min_data, mean, info.file_name)) + for idx in range(1, len(self.input_files)): + info = self.input_files[idx] + shape, dtype, max_data, min_data, mean = util.npy_info(info.path) + txt.append(' [green][%d][/green][yellow][%s][%s][Max:%d][Min:%d][Mean:%d][/yellow] %s' % ( + idx, shape, dtype, max_data, min_data, mean, info.file_name)) + if len(self.output_files) > 0: + info = self.output_files[0] + shape, dtype, max_data, min_data, mean = util.npy_info(info.path) + txt.append(' - Output: [green][0][/green][yellow][%s][%s][Max:%d][Min:%d][Mean:%d][/yellow] %s' % ( + shape, dtype, max_data, min_data, mean, info.file_name)) + for idx in range(1, len(self.output_files)): + info = self.output_files[idx] + shape, dtype, max_data, min_data, mean = util.npy_info(info.path) + txt.append(' [green][%d][/green][yellow][%s][%s][Max:%d][Min:%d][Mean:%d][/yellow] %s' % ( + idx, shape, dtype, max_data, min_data, mean, info.file_name)) + return Constant.NEW_LINE.join(txt) + + def _check(self, file_info): + if self.timestamp == -1: + self.timestamp = file_info.timestamp + self.op_name = file_info.op_name + self.op_type = file_info.op_type + self.task_id = file_info.task_id + # self.stream_id = file_info['stream'] + return True + return self.timestamp == file_info['timestamp'] + + +class NpuDump(object): + def __init__(self, debug_id=Constant.DEFAULT_DEBUG_ID): + """Init""" + self.log = util.get_log() + self.debug_id = debug_id + npu_root = os.path.join(cfg.NPU_DIR, debug_id) + self.dump_root = os.path.join(npu_root, Constant.DUMP) + self.decode_dir = os.path.join(cfg.DUMP_DECODE_DIR, debug_id) + self.dump_files = None + self._init_dirs() + + def prepare(self): + """Prepare npu/cpu dump files""" + self._parse_dump_files() + + def get_dump_files_by_op(self, op): + """Get npu dump files by Op""" + npu_files = {} + op_name = op.name().replace('/', '_').replace('.', '_') + match_name = op.type() + '.' + op_name + '\\.' + for f in self.dump_files: + # match op name and graph name, infer dump directory may not has graph + if re.match(match_name, f) and (op.graph_name in self.dump_files[f].path or cfg.NET_TYPE == 'infer'): + npu_files[f] = self.dump_files[f] + return npu_files + + @catch_tool_exception + def op_dump_summary(self, op): + """ print op dump info""" + if op is None: + raise PrecisionToolException("Get None operator") + # search npu dump file by op name + npu_dump_files = self.get_npu_dump_decode_files_by_op(op) + npu_dump_files = sorted(npu_dump_files.values(), key=lambda x: (x.idx, x.timestamp)) + input_txt = ['NpuDumpInput:'] + output_txt = ['NpuDumpOutput:'] + for npu_dump_file in npu_dump_files: + if npu_dump_file.type == 'input': + input_txt.append(' -[green][%s][/green] %s' % (npu_dump_file.idx, npu_dump_file.file_name)) + input_txt.append(' └─ [yellow]%s[/yellow]' % util.gen_npy_info_txt(npu_dump_file.path)) + else: + output_txt.append(' -[green][%s][/green] %s' % (npu_dump_file.idx, npu_dump_file.file_name)) + output_txt.append(' └─ [yellow]%s[/yellow]' % util.gen_npy_info_txt(npu_dump_file.path)) + input_txt.extend(output_txt) + return Constant.NEW_LINE.join(input_txt) + + def _init_dirs(self): + util.create_dir(self.dump_root) + util.create_dir(self.decode_dir) + + @catch_tool_exception + def _parse_dump_files(self): + """prepare npu dump, support soft link""" + sub_dir = util.get_newest_dir(self.dump_root) + sub_dir = os.path.join(self.dump_root, sub_dir) if sub_dir != '' else self.dump_root + self.dump_files = util.list_npu_dump_files(sub_dir) + + def list_dump(self, dir_path, file_name): + """""" + + @staticmethod + def get_npu_dump_decode_files_by_name(file_name): + file_name = file_name.replace('/', '_') + return util.list_npu_dump_convert_files(cfg.DECODE_DIR, file_name) + + def get_npu_dump_decode_files_by_op(self, op): + """Get npu dump decode files by op""" + dump_files = self.get_dump_files_by_op(op) + result = {} + for dump_file in dump_files.values(): + dump_decode_files = util.list_npu_dump_decode_files(self.decode_dir, dump_file.file_name) + if len(dump_decode_files) == 0: + util.convert_dump_to_npy(dump_file.path, self.decode_dir) + dump_decode_files = util.list_npu_dump_decode_files(self.decode_dir, dump_file.file_name) + result.update(dump_decode_files) + return result + + def convert_npu_dump(self, name, data_format=None, dst_path=None): + """Convert npu dump to npy of data_format""" + if os.path.isfile(name): + # absolute path to file + self.log.info("Decode file: %s", name) + file_name = os.path.basename(name) + file_path = name + elif os.path.isdir(name): + # decode all files in path + self.log.info("Decode all files in path: %s", name) + file_name = '' + file_path = name + elif self.dump_files is not None and name in self.dump_files: + self.log.info("Decode npu dump file: %s in default dump path", name) + file_info = self.dump_files[name] + file_name = file_info.file_name + file_path = file_info.path + else: + # maybe op name + file_info = self._get_file_by_op_name(name) + if file_info is None: + raise PrecisionToolException("Can not find any op/dump file named %s" % name) + file_name = file_info.file_name + file_path = file_info.path + dst_path = cfg.DUMP_CONVERT_DIR if dst_path is None else dst_path + util.convert_dump_to_npy(file_path, dst_path, data_format) + dump_convert_files = util.list_npu_dump_convert_files(dst_path, file_name) + # print result info + + summary_txt = ['SrcFile: %s' % name] + for convert_file in dump_convert_files.values(): + summary_txt.append(' - %s' % convert_file.file_name) + util.print_panel(Constant.NEW_LINE.join(summary_txt)) + + def _get_file_by_op_name(self, op_name): + """Get dump file info by op name""" + for file_info in self.dump_files.values(): + if file_info.op_name == op_name: + return file_info + return None diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/npu_graph.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/npu_graph.py new file mode 100644 index 0000000000000000000000000000000000000000..48625bd631014d68df6f39af244b20f1c73b356c --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/npu_graph.py @@ -0,0 +1,296 @@ +# coding=utf-8 +""" +Graph Manager +""" +import json +import os +import collections +import time + +import config as cfg +from lib.op import Op +from lib.util import util +from lib.constant import Constant +from lib.precision_tool_exception import catch_tool_exception +from lib.precision_tool_exception import PrecisionToolException + +DANGEROUS_CAST = { + 'DT_FLOAT': ['DT_INT32'] +} + +NO_DIG_OPS = ['AtomicAddrClean', 'NetOutput'] +CKPT_META_SHUFFIX='.meta' + +OP_CAST = 'Cast' + + +class NpuSubGraph(object): + def __init__(self, graph_json, build_file): + self.log = util.get_log() + self.graph_name = graph_json['name'] + self.graph = graph_json + self.build_file = build_file + self.ops_list = collections.OrderedDict() + self.ops_type_list = {} + self._prepare() + self.graph_id = self._get_graph_id() + + def _prepare(self): + self.log.debug("Graph %s operator count: %d" % (self.graph_name, len(self.graph['op']))) + for op_json in self.graph['op']: + op_name = op_json['name'] + op_type = op_json['type'] + if op_name not in self.ops_list: + self.ops_list[op_name] = [] + op = Op(op_json, self.ops_list, self.graph['name']) + if op_type not in self.ops_type_list: + self.ops_type_list[op_type] = {} + self.ops_list[op_name] = op + self.ops_type_list[op_type][op_name] = op + + def _get_graph_id(self): + if 'attr' in self.graph: + for item in self.graph['attr']: + if item['key'] == '_session_graph_id': + return item['value']['s'] + self.log.warning("Unknown sub graph id.") + return "UNKNOWN" + + def compare(self, sub_graph): + """compare with another sub graph""" + if not isinstance(sub_graph, NpuSubGraph): + raise PrecisionToolException("Should compare with another subgraph.") + right_ops_list = sub_graph.ops_list + ignore_ops = ["TransData", "Cast", "Recv", "Send", "Variable", "NetOutput", "NoOp", "Assign", "Constant", + "StreamActive"] + similar_count = 0 + for op_name in self.ops_list: + if self.ops_list[op_name].type() in ignore_ops: + continue + if op_name not in right_ops_list: + self.log.warning("Can not Find [%s] %s in right subgraph.", self.ops_list[op_name].type(), op_name) + continue + result, similar = self.ops_list[op_name].compare(right_ops_list[op_name]) + if not similar: + util.print_panel(result, title=op_name) + else: + similar_count += 1 + for op_name in right_ops_list: + if right_ops_list[op_name].type() in ignore_ops: + continue + if op_name not in self.ops_list: + self.log.warning("Can not Find [%s] %s in left subgraph.", right_ops_list[op_name].type(), op_name) + self.log.info("Compare [%s] [%s], similarity is [%s / %s]", + self.graph_name, sub_graph.graph_name, similar_count, len(self.ops_list)) + + def get_op(self, name): + if name in self.ops_list: + return [self.ops_list[name]] + guess_op_list = [] + for op_detail in self.ops_list.values(): + if name in op_detail.name(): + guess_op_list.append(op_detail) + return guess_op_list + + def check_cast(self): + cast_list = {} + danger_cast_list = {} + if OP_CAST in self.ops_type_list: + cast_ops = self.ops_type_list[OP_CAST] + for op in cast_ops.values(): + input_type = '' + output_type = '' + for input_desc in op.inputs(): + input_type = input_desc.dtype() if input_desc.dtype() != '' else input_type + for output_desc in op.outputs(): + output_type = output_desc.dtype() if output_desc.dtype() != '' else output_type + cast_type = "%s -> %s" % (input_type, output_type) + if cast_type not in cast_list: + cast_list[cast_type] = [] + cast_list[cast_type].append(op.name()) + for cast_type in cast_list: + if self._is_dangerous_cast(cast_type): + summary_txt = "[green][Cast][/green][red][%s][/red] %s" % (cast_type, cast_list[cast_type]) + util.print(summary_txt) + + @staticmethod + def _is_dangerous_cast(cast_type): + """Check if cast """ + cast_info = cast_type.split(" -> ") + input_dtype = cast_info[0] + output_dtype = cast_info[1] + if input_dtype in DANGEROUS_CAST: + if output_dtype in DANGEROUS_CAST[input_dtype]: + return True + return False + + +class NpuGraph(object): + def __init__(self, debug_id=Constant.DEFAULT_DEBUG_ID): + self.log = util.get_log() + self.build_files = None + self.build_json_files = [] + self.debug_id = debug_id + self.npu_root = os.path.join(cfg.NPU_DIR, debug_id) + self.graph_root = os.path.join(self.npu_root, Constant.GRAPH) + self.sub_graphs = collections.OrderedDict() + self.ops_list = [] + util.create_dir(self.graph_root) + + @catch_tool_exception + def prepare(self): + """prepare""" + self._prepare_npu_graphs() + if self.build_files is not None: + for build_file in self.build_files: + self._parse_ops(build_file) + + def check_cast(self): + """Check cast op type""" + for sub_graph in self.sub_graphs.values(): + sub_graph.check_cast() + + def check_dtype(self): + """Check op input/output dtype""" + for op in self.ops_list: + input_dtype = '' + for input_desc in op.inputs(): + input_dtype += ' ' + input_desc.dtype() + output_dtype = '' + for output_desc in op.outputs(): + output_dtype += ' ' + output_desc.dtype() + util.print('[green][%s][/green] %s\n - Input: %s\n - Output: %s' % ( + op.type(), op.name(), input_dtype, output_dtype)) + + def check_similarity(self): + """Check graph similarity.""" + + @catch_tool_exception + def save_sub_graph(self, op, deep=0, dump_manager=None, compare_manager=None): + """Save sub graph""" + if op is None: + raise PrecisionToolException("Save sub graph failed as root operator is None.") + try: + from graphviz import Digraph + file_name_list = [self.debug_id, op.graph_name, op.type(), op.name().replace('/', '_').replace('.', '_'), + str(deep), 'gv'] + file_name = '.'.join(file_name_list) + path = os.path.join(cfg.OP_GRAPH_DIR, file_name) + dot = Digraph(file_name, filename=path, node_attr={'shape': 'Mrecord'}, format='svg') + dot_list = [] + edge_list = [] + self._gen_sub_graph(dot, op, deep, dot_list, edge_list, 'red', direction='all', + dump_manager=dump_manager, compare_manager=compare_manager) + dot.format = 'svg' + dot.save(path) + self.log.info("Sub graph saved to %s" % os.path.abspath(cfg.OP_GRAPH_DIR)) + try: + dot.view(path) + time.sleep(1) + except Exception as err: + raise PrecisionToolException( + "graphviz not install, use [yum/apt-get] install graphviz xdg-utils. %s" % err) + except ImportError as err: + raise PrecisionToolException("Save sub graph failed as import graphviz module failed. %s" % err) + + def _gen_sub_graph(self, dot, op, deep, dot_list, edge_list, color='black', direction='all', + dump_manager=None, compare_manager=None): + """Gen sub graph""" + if deep == 0 or op.type() in NO_DIG_OPS: + return + if op.name() not in dot_list: + dot.node(op.name(), self._gen_sub_graph_label(op), color=color, tooltip=op.summary(True)) + dot_list.append(op.name()) + # add input and output + for desc in op.inputs(): + sub_op = self.get_op(desc.name(), op.graph_name) + if len(sub_op) != 0: + sub_op = sub_op[0] + if direction in ['all', 'input']: + self._gen_sub_graph(dot, sub_op, deep - 1, dot_list, edge_list, direction='input') + if sub_op.name() in dot_list: + src_edge = '%s:o%d' % (sub_op.name(), desc.peer_idx()) + else: + dot.node(sub_op.name(), self._gen_sub_graph_label(sub_op), color=color, tooltip=op.summary(True)) + src_edge = '%s:o%d' % (sub_op.name(), desc.peer_idx()) + dst_edge = '%s:i%d' % (op.name(), desc.idx()) + if src_edge + dst_edge not in edge_list: + dot.edge(src_edge, dst_edge) + edge_list.append(src_edge + dst_edge) + # add output + for desc in op.outputs(): + for out_node_name in desc.names(): + sub_op = self.get_op(out_node_name, op.graph_name) + if len(sub_op) != 0 and direction in ['all', 'output']: + sub_op = sub_op[0] + self._gen_sub_graph(dot, sub_op, deep - 1, dot_list, edge_list, direction='output') + + def _gen_sub_graph_label(self, op): + input_labels = [] + for desc in op.inputs(): + input_labels.append(self._gen_sub_graph_desc(desc, 'i')) + output_labels = [] + for desc in op.outputs(): + output_labels.append(self._gen_sub_graph_desc(desc, 'o')) + str_cell = '|' + return '{{ %s } | [%s] %s | { %s }}' % (str_cell.join(input_labels), op.type(), op.name(), + str_cell.join(output_labels)) + + @staticmethod + def _gen_sub_graph_desc(desc, id_prefix): + desc_str = r'<%s%d> [%d]' % (id_prefix, desc.idx(), desc.idx()) + desc_str = r'%s [%s]' % (desc_str, desc.dtype()) if desc.dtype() != '' else desc_str + desc_str = r'%s\n%s' % (desc_str, desc.shape()) if len(desc.shape()) != 0 else desc_str + return desc_str + + def list_ops(self, op_type='', op_name='', pass_name='', kernel_name=''): + """list ops in graph""" + return filter(lambda op: op_type in op.type() and op_name in op.name() and pass_name in op.pass_name() + and kernel_name in op.kernel_name(), self.ops_list) + + def get_op(self, name, graph_name=None): + """get op by name""" + # get op in specific sub graph + if graph_name is not None and graph_name in self.sub_graphs: + return self.sub_graphs[graph_name].get_op(name) + ops = [] + for sub_graph in self.sub_graphs.values(): + ops.extend(sub_graph.get_op(name)) + # check if there is an exact match operation + match_ops = list(filter(lambda x: x.name() == name, ops)) + if len(match_ops) != 0: + return match_ops + # return guess operations by name + self.log.info("Can not find Operator named %s. You may mean the operator bellow.", name) + guess_op_name_list = ['[green][%s][/green] %s' % (x.type(), x.name()) for x in ops] + util.print_panel(Constant.NEW_LINE.join(guess_op_name_list), title='Possible Operators') + return ops + + def _prepare_npu_graphs(self): + """prepare ge graphs """ + # move graphs to precision data dir + graph_files = util.list_ge_graph_files(self.graph_root) + self.build_files = sorted(filter(lambda x: x.graph_name == cfg.BUILD_JSON_GRAPH_NAME, graph_files.values()), + key=lambda x: x.graph_id) + if len(self.build_files) == 0: + self.log.warning("Can not find any build files in dir: %s", self.graph_root) + self.log.info("Find [%d] GE build files.", len(self.build_files)) + + @catch_tool_exception + def _parse_ops(self, build_file): + """Parse *_Build.txt.json to op objects.""" + build_file_json = build_file.path + '.json' + build_file_json = util.convert_proto_to_json(build_file.path, build_file_json) + if build_file_json is not None: + self.build_json_files.append(build_file_json) + with open(build_file_json, 'r') as f: + graph_json = json.load(f) + if 'graph' not in graph_json: + raise PrecisionToolException("No graph in file: %s" % build_file.file_name) + if len(graph_json['graph']) != 1: + self.log.warning("There are more then one graph in ge build file, find %d" % len(graph_json['graph'])) + # sub_graphs = [] + for graph in graph_json['graph']: + npu_sub_graph = NpuSubGraph(graph, build_file) + self.sub_graphs[graph['name']] = npu_sub_graph + self.ops_list.extend(npu_sub_graph.ops_list.values()) diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/op.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/op.py new file mode 100644 index 0000000000000000000000000000000000000000..491f5590041b92f4768c1ccb702656d96086d5e4 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/op.py @@ -0,0 +1,184 @@ +# coding=utf-8 +import json +import re +from typing import List +from lib.desc import InputDesc +from lib.desc import OutputDesc +from lib.util import util +from lib.constant import Constant +from lib.precision_tool_exception import PrecisionToolException + +NO_INPUT_NODES = ['Data', 'AtomicAddrClean', 'Recv', 'Constant'] +NO_OUTPUT_NODES = ['Send', 'Recv', 'NetOutput'] + +JSON_KEY_NAME = 'name' +JSON_KEY_TYPE = 'type' +JSON_KEY_ATTR = 'attr' +JSON_KEY = 'key' +JSON_VALUE = 'value' +JSON_KEY_LIST = 'list' +JSON_KEY_STR = 's' +JSON_KEY_PASS_NAME = 'pass_name' +JSON_KEY_DATA_DUMP_ORIGINAL_OP_NAMES = '_datadump_original_op_names' +JSON_KEY_GE_ATTR_OP_KERNEL_LIB_NAME = "_ge_attr_op_kernel_lib_name" + +KERNEL_NAME_SHUFFIX = '_kernelname' + + +class Op(object): + """ Op class. + name: op name + type: op type + inputs: list of input descs + outputs: list of output descs + """ + def __init__(self, op_json, op_list, graph_name): + """Init""" + self.op_json = op_json + self.op_list = op_list + self.graph_name = graph_name + self.input_list = None + self.output_list = None + self.log = util.get_log() + + def name(self): + """Get op name""" + return self.op_json[JSON_KEY_NAME] + + def json(self): + return json.dumps(self.op_json, indent=2) + + def type(self): + """Get op type""" + return self.op_json[JSON_KEY_TYPE] + + def inputs(self): + """Get the input list""" + if self.input_list is None: + self._parse_inputs() + return self.input_list + + def outputs(self): + """Get output list""" + if self.output_list is None: + self._parse_outputs() + return self.output_list + + def pass_name(self): + return self._attr(JSON_KEY_PASS_NAME) + + def kernel_name(self): + return self._attr(self.name() + KERNEL_NAME_SHUFFIX) + + def ge_attr_op_kernel_lib_name(self): + return self._attr(JSON_KEY_GE_ATTR_OP_KERNEL_LIB_NAME) + + def data_dump_original_op_names(self): + return self._attr(JSON_KEY_DATA_DUMP_ORIGINAL_OP_NAMES) + + def _attr(self, key): + if JSON_KEY_ATTR in self.op_json: + for attr in self.op_json[JSON_KEY_ATTR]: + if key == attr[JSON_KEY]: + if JSON_KEY_STR in attr[JSON_VALUE]: + return attr[JSON_VALUE][JSON_KEY_STR] + elif JSON_KEY_LIST in attr[JSON_VALUE]: + if JSON_KEY_STR in attr[JSON_VALUE][JSON_KEY_LIST]: + return attr[JSON_VALUE][JSON_KEY_LIST][JSON_KEY_STR] + else: + self.log.warning("Unknown attr format: %s", attr[JSON_VALUE]) + return '' + + def compare(self, right_op): + """Compare with another op""" + if not isinstance(right_op, Op): + raise PrecisionToolException("Should compare with another op.") + res_str = ['LeftOp(Type/Name) : [green][%s][/green] %s' % (self.type(), self.name()), + 'RightOp(Type/Name): [green][%s][/green] %s' % (right_op.type(), right_op.name())] + similar = True + if len(self.inputs()) != len(right_op.inputs()): + res_str.append("Input: [yellow]Input num mismatch.[/yellow]") + else: + res_str.append("Input:") + for left_input in self.inputs(): + for right_input in right_op.inputs(): + if left_input.idx() != right_input.idx(): + continue + txt, input_similar = left_input.compare(right_input) + res_str.append(' - ' + txt) + similar = similar and input_similar + if len(self.outputs()) != len(right_op.outputs()): + res_str.append("Output: [yellow]Output num mismatch.[/yellow]") + else: + res_str.append("Output:") + for left_output in self.outputs(): + for right_output in right_op.outputs(): + if left_output.idx() != right_output.idx(): + continue + txt, output_similar = left_output.compare(right_output) + res_str.append(' - ' + txt) + similar = similar and output_similar + return Constant.NEW_LINE.join(res_str), similar + + def summary(self, origin_txt=False): + """Summary of current op""" + res_str = ['Op(Type/Name): [green][%s][/green] %s' % (self.type(), self.name()), + 'KernelName: [yellow]%s[/yellow]' % self.kernel_name(), + 'KernelLibName: [yellow]%s[/yellow]' % self.ge_attr_op_kernel_lib_name(), + 'GraphName: [yellow]%s[/yellow]' % self.graph_name] + pass_name = self.pass_name() + if pass_name != '': + res_str.append('PassName: [yellow]%s[/yellow]' % pass_name) + origin_op = self.data_dump_original_op_names() + if origin_op != '': + res_str.append('OriginalOp: %s' % origin_op) + res_str.append('Input:%s' % InputDesc.summary.__doc__) + for i in self.inputs(): + res_str.append(' -' + i.summary(origin_txt)) + res_str.append('Output:') + for i in self.outputs(): + res_str.append(' -' + i.summary(origin_txt)) + return Constant.NEW_LINE.join(res_str) + + def _parse_inputs(self): + """ parse input desc in graph """ + self.input_list = [] + if 'input' not in self.op_json: + if self.type() not in NO_INPUT_NODES: + self.log.warning('Parse Op[%s][%s] inputs error.' % (self.type(), self.name())) + return self.input_list + desc_index = 0 + for i in range(len(self.op_json['input'])): + name = self.op_json['input'][i] + if name == '': + # if self.type() not in NO_INPUT_NODES: + # self.log.warning('invalid input name.') + continue + name_info = name.split(':') + if len(name_info) == 2 and int(name_info[1]) == -1: + # control edge + self.input_list.append(InputDesc(name, [], i)) + else: + self.input_list.append(InputDesc(name, self.op_json['input_desc'][desc_index], i)) + desc_index += 1 + self.input_list.sort(key=lambda x: x.index) + return self.input_list + + def _parse_outputs(self): + """ parse output desc in graph """ + self.output_list = [] + if 'dst_index' not in self.op_json: + if self.type() not in NO_OUTPUT_NODES: + self.log.warning('Parse Op[%s][%s] outputs error.' % (self.type(), self.name())) + return self.output_list + desc_index = 0 + for i in range(len(self.op_json['dst_index'])): + dst_name = self.op_json['dst_name'][i] + if self.op_json['dst_index'][i] == -1: + # control edge + self.output_list.append(OutputDesc(dst_name, [], -1)) + else: + self.output_list.append(OutputDesc(dst_name, self.op_json['output_desc'][desc_index], desc_index)) + desc_index += 1 + self.output_list.sort(key=lambda x: x.index) + return self.output_list diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/overflow.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/overflow.py new file mode 100644 index 0000000000000000000000000000000000000000..b3c783e5c0b019b690bba122aea71b8230263b48 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/overflow.py @@ -0,0 +1,180 @@ +# coding=utf-8 +import json +import os + +from lib.util import util +import config as cfg +from lib.precision_tool_exception import PrecisionToolException +from lib.precision_tool_exception import catch_tool_exception +from lib.constant import Constant + +AI_CORE_OVERFLOW_STATUS = { + '0x8': '符号证书最小附属NEG符号位取反溢出', + '0x10': '整数加法、减法、乘法或乘加操作计算有溢出', + '0x20': '浮点计算有溢出', + '0x80': '浮点数转无符号数的输入是负数', + '0x100': 'FP32转FP16或32符号整数转FP16中出现溢出', + '0x400': 'CUBE累加出现溢出' +} +DHA_ATOMIC_ADD_STATUS = { + '0x9': '[atomic overflow] 向上溢出', + '0xA': '[atomic underflow] 向下溢出', + '0xB': '[atomic src nan] 源操作数非法', + '0xC': '[atomic dst nan] 目的操作数非法', + '0xD': '[atomic both nan] 源操作数和目的操作数均非法' +} +L2_ATOMIC_ADD_STATUS = { + '000': '[atomic no error] 无异常', + '001': '[atomic overflow] 向上溢出', + '010': '[atomic underflow] 向下溢出', + '011': '[atomic src nan] 源操作数非法', + '100': '[atomic dst nan] 目的操作数非法', + '101': '[atomic both nan] 源操作数和目的操作数均非法' +} + + +class Overflow(object): + def __init__(self): + """Init""" + self.log = util.get_log() + self.debug_files = None + + @catch_tool_exception + def prepare(self): + """Prepare""" + # find right path in DUMP_FILES_NPU_ALL + util.create_dir(cfg.NPU_OVERFLOW_DUMP_DIR) + sub_dir = util.get_newest_dir(cfg.NPU_OVERFLOW_DUMP_DIR) + overflow_dump_files = util.list_npu_dump_files(os.path.join(cfg.NPU_OVERFLOW_DUMP_DIR, sub_dir)) + self.debug_files = [item for item in overflow_dump_files.values() if item.op_type == 'Opdebug'] + # sort by timestamp + self.debug_files = sorted(self.debug_files, key=lambda x: x.timestamp) + self.log.info("Find [%d] debug files in overflow dir.", len(self.debug_files)) + + def check(self, max_num=3): + """Check overflow info""" + if len(self.debug_files) == 0: + self.log.info("[Overflow] Checked success. find [0] overflow node!") + return + self.log.info("[Overflow] Find [%s] overflow debug file. Will show top %s ops.", len(self.debug_files), max_num) + for i, debug_file in enumerate(self.debug_files): + debug_decode_files = self._decode_file(debug_file, True) + with open(debug_decode_files[0].path, 'r') as f: + overflow_json = json.load(f) + util.print_panel(self._json_summary(overflow_json, debug_file)) + if i >= max_num: + break + + def _json_summary(self, json_txt, debug_file): + res = [] + detail = {'task_id': -1} + if 'AI Core' in json_txt and json_txt['AI Core']['status'] > 0: + detail = json_txt['AI Core'] + res.append(' - [AI Core][Status:%s][TaskId:%s] %s' % ( + detail['status'], detail['task_id'], self._decode_ai_core_status(detail['status']))) + if 'DHA Atomic Add' in json_txt and json_txt['DHA Atomic Add']['status'] > 0: + detail = json_txt['DHA Atomic Add'] + res.append(' - [DHA Atomic Add][Status:%s][TaskId:%s] %s' % ( + detail['status'], detail['task_id'], self._decode_dha_atomic_add_status(detail['status']))) + if 'L2 Atomic Add' in json_txt and json_txt['L2 Atomic Add']['status'] > 0: + detail = json_txt['L2 Atomic Add'] + res.append(' - [L2 Atomic Add][Status:%s][TaskId:%s] %s' % ( + detail['status'], detail['task_id'], self._decode_l2_atomic_add_status(detail['status']))) + dump_file_info = self._find_dump_files_by_task_id(detail['task_id'], debug_file.dir_path) + res.append(' - First overflow file timestamp [%s] -' % debug_file.timestamp) + if dump_file_info is None: + self.log.warning("Can not find any dump file for debug file: %s, op task id: %s", debug_file.file_name, + detail['task_id']) + else: + dump_decode_files = self._decode_file(dump_file_info) + # sort input/output & index + sorted(dump_decode_files, key=lambda x: x.idx) + for anchor_type in ['input', 'output']: + for dump_decode_file in dump_decode_files: + if dump_decode_file.type != anchor_type: + continue + res.append(' ├─ %s' % dump_decode_file.file_name) + res.append(' └─ [yellow]%s[/yellow]' % util.gen_npy_info_txt(dump_decode_file.path)) + res.insert(0, '[green][%s][%s][/green] %s' % (dump_file_info.op_type, dump_file_info.task_id, + dump_file_info.op_name)) + return Constant.NEW_LINE.join(res) + + @staticmethod + def _decode_file(file_info, debug=False): + file_name = file_info.file_name + if debug: + decode_files = util.list_debug_decode_files(cfg.OVERFLOW_DECODE_DIR, file_name) + else: + decode_files = util.list_npu_dump_decode_files(cfg.OVERFLOW_DECODE_DIR, file_name) + if len(decode_files) == 0: + # decode info file + util.convert_dump_to_npy(file_info.path, cfg.OVERFLOW_DECODE_DIR) + if debug: + decode_files = util.list_debug_decode_files(cfg.OVERFLOW_DECODE_DIR, file_name) + else: + decode_files = util.list_npu_dump_decode_files(cfg.OVERFLOW_DECODE_DIR, file_name) + if len(decode_files) == 0: + raise PrecisionToolException("Decode overflow debug file: %s failed." % file_name) + decode_files = sorted(decode_files.values(), key=lambda x: x.timestamp) + return decode_files + + @staticmethod + def _find_dump_files_by_task_id(task_id, search_dir): + dump_files = util.list_npu_dump_files(search_dir) + dump_file_list = [item for item in dump_files.values() if item.op_type != 'Opdebug'] + dump_file_list = sorted(dump_file_list, key=lambda x: x.timestamp) + for dump_file in dump_file_list: + if dump_file.task_id == int(task_id): + return dump_file + return None + + def _decode_ai_core_status(self, status): + error_code = [] + if type(status) is not int: + return error_code + bin_status = ''.join(reversed(bin(status))) + prefix = '' + self.log.debug('Decode AI Core Overflow status:[%s]', hex(status)) + for i in range(len(bin_status)): + if bin_status[i] == '1': + error_code.append(AI_CORE_OVERFLOW_STATUS[hex(int('1' + prefix, 2))]) + prefix += '0' + return error_code + + def _decode_l2_atomic_add_status(self, status): + if type(status) is not int: + return 'status is not int.' + code, _ = self._sub_bin_code(status, 16, 18) + if code in L2_ATOMIC_ADD_STATUS: + return L2_ATOMIC_ADD_STATUS[code] + return 'Status invalid' + + def _decode_dha_atomic_add_status(self, status): + if type(status) is not int: + return 'status is not int.' + _, code = self._sub_bin_code(status, 8, 15) + if code in DHA_ATOMIC_ADD_STATUS: + return DHA_ATOMIC_ADD_STATUS[status] + return 'Status invalid' + + @staticmethod + def _sub_bin_code(status, start, end): + """ Get specific bit code from status in bin format + :param status: status num + :param start: start bit + :param end: end bit + :return: result in bin format and hex format + """ + bin_code = bin(status).replace('0b', '') + append_num = end + 1 - len(bin_code) + if append_num > 0: + bin_list = ['0'] * append_num + bin_list.append(bin_code) + bin_code = ''.join(bin_list) + bin_start = len(bin_code) - end - 1 + bin_end = len(bin_code) - start + bin_start = max(0, bin_start) + bin_code = bin_code[bin_start: bin_end] + return bin_code, hex(int(bin_code, 2)) + + diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/precision_tool.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/precision_tool.py new file mode 100644 index 0000000000000000000000000000000000000000..d301ffbc051a8b4cf7ca4130618475770d32195d --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/precision_tool.py @@ -0,0 +1,212 @@ +import argparse +import os +import time + +from lib.overflow import Overflow +from lib.dump_manager import DumpManager +from lib.graph_manager import GraphManager +from lib.compare import Compare +from lib.fusion import Fusion +from lib.util import util +from lib.constant import Constant +import config as cfg +from lib.precision_tool_exception import PrecisionToolException +from lib.precision_tool_exception import catch_tool_exception + + +class PrecisionTool(object): + def __init__(self): + """init""" + self.graph_manager = GraphManager() + self.overflow = Overflow() + self.dump_manager = DumpManager() + self.compare = Compare() + self.fusion = Fusion() + self.log = util.get_log() + + @catch_tool_exception + def prepare(self): + """prepare""" + util.create_dir(cfg.DATA_ROOT_DIR) + self.graph_manager.prepare() + self.dump_manager.prepare() + self.overflow.prepare() + self.fusion.prepare() + self.compare.prepare() + + @catch_tool_exception + def do_auto_check(self, argv): + """Auto check""" + parser = argparse.ArgumentParser() + parser.add_argument('-c', '--vector_compare', dest='vector_compare', help='Run vector compare process', + action='store_true') + parser.add_argument('-l', '--limit', dest='limit', type=int, help='limit', default=3) + args = parser.parse_args(argv) + # vector compare + if args.vector_compare: + self.do_vector_compare() + self.do_vector_compare_summary() + self.do_check_fusion() + self.do_check_overflow(args.limit) + self.do_check_cast() + self.do_check_graph_similarity() + + @catch_tool_exception + def do_check_overflow(self, limit=3): + """check overflow""" + self.overflow.check(limit) + + @catch_tool_exception + def do_check_cast(self): + self.graph_manager.check_cast() + + @catch_tool_exception + def do_check_dtype(self): + """Check input/output dtype""" + self.graph_manager.check_dtype() + + @catch_tool_exception + def do_check_fusion(self): + """print fusion info summary""" + self.fusion.check() + + @catch_tool_exception + def do_check_graph_similarity(self): + self.graph_manager.check_similarity() + + @catch_tool_exception + def do_vector_compare(self, argv=None): + """do vector compare""" + parser = argparse.ArgumentParser() + parser.add_argument('-lt', '--left', dest='lt', default=None, help='left path(npu dump path)') + parser.add_argument('-rt', '--right', dest='rt', default=None, help='right path(cpu/npu dump path)') + parser.add_argument('-g', '--graph', dest='graph', required=False, default=None, help='graph json file') + args = parser.parse_args() if argv is None else parser.parse_args(argv) + # 1. compare npu_debug0 - tf dump data (auto) + # 2. compare npu_debug0 - npu_debug1 dump data + # 3. compare dir - dir dump data + result_dir = os.path.join(cfg.VECTOR_COMPARE_PATH, time.strftime("%Y%m%d%H%M%S", time.localtime())) + if args.lt is None: + debug_0_dump_root = self.dump_manager.get_dump_root_dir(Constant.DEFAULT_DEBUG_ID) + if util.empty_dir(debug_0_dump_root): + raise PrecisionToolException("NPU debug_0 dump dir is empty, no files to compare.") + if not util.empty_dir(cfg.TF_DUMP_DIR): + self.log.info("Tf dump dir is not empty, will compare npu dump data with tf dump data.") + self.compare.npu_tf_vector_compare(self.graph_manager.get_graphs(Constant.DEFAULT_DEBUG_ID), + debug_0_dump_root, cfg.TF_DUMP_DIR, result_dir) + else: + self.log.warning("Tf dump dir is empty, maybe run [python3 precision_tool/cli.py tf_dump] to decode" + " tf debug data.") + debug_1_dump_root = self.dump_manager.get_dump_root_dir(Constant.NPU_DEBUG_ID_1) + if debug_1_dump_root is not None and not util.empty_dir(debug_1_dump_root): + self.log.info("NPU debug_1 dump dir is not empty, will compare two npu dump data.") + self.compare.npu_vector_compare(debug_0_dump_root, debug_1_dump_root) + else: + lh_path = args.lt + rh_path = args.rt + graph_json = args.graph + self.compare.vector_compare(lh_path, rh_path, result_dir, graph_json) + self.compare.vector_summary(result_dir) + + @catch_tool_exception + def do_vector_compare_summary(self, argv=None): + parser = argparse.ArgumentParser(description="show vector compare result summary.") + parser.add_argument('-f', '--file', dest='file', default=None, required=False, help='compare_result file/path') + parser.add_argument('-c', '--cos_sim', dest='cos_sim', type=float, help='cos_sim_threshold', default=0.98) + parser.add_argument('-l', '--limit', dest='limit', type=int, help='limit', default=3) + args = parser.parse_args() if argv is None else parser.parse_args(argv) + error_ops = self.compare.vector_summary(args.file, args.cos_sim, args.limit) + # parse error_ops + + @catch_tool_exception + def do_print_data(self, argv=None): + """print tensor data""" + parser = argparse.ArgumentParser() + parser.add_argument('-n', '--name', dest='name', default='', help='list by op name') + args = parser.parse_args() if argv is None else parser.parse_args(argv) + self.dump_manager.print_tensor(args.name, True) + + @catch_tool_exception + def do_list_nodes(self, argv): + """list op nodes in graph""" + parser = argparse.ArgumentParser() + parser.add_argument('-t', '--type', dest='type', default='', help='list by op type') + parser.add_argument('-n', '--name', dest='name', default='', help='list by op name') + parser.add_argument('-f', '--fusion', dest='fusion', default='', help='list by op fusion pass') + parser.add_argument('-k', '--kernel_name', dest='kernel_name', default='', help='list by op kernel_name') + args = parser.parse_args(argv) + self.graph_manager.print_op_list(args.type, args.name, args.fusion, args.kernel_name) + + @catch_tool_exception + def do_node_info(self, argv): + """Print op node info""" + parser = argparse.ArgumentParser() + parser.add_argument('-n', '--name', dest='name', default='', help='op name') + parser.add_argument('-g', '--graph', dest='graph', help='graph name') + parser.add_argument('-s', '--save', dest='save', type=int, default=0, + help='save subgraph, param gives the deep of subgraph') + args = parser.parse_args(argv) + # print graph op info + npu_ops, _ = self.graph_manager.get_ops(args.name, args.graph) + npu_op_summary, tf_op_summary = self.graph_manager.op_graph_summary(npu_ops) + npu_dump_summary, tf_dump_summary = self.dump_manager.op_dump_summary(npu_ops) + # merge graph/dump/compare info + for debug_id, graph_summary in npu_op_summary.items(): + for graph_name, summary_detail in graph_summary.items(): + summary_txt = [summary_detail] + if debug_id in npu_dump_summary and graph_name in npu_dump_summary[debug_id]: + summary_txt.append(npu_dump_summary[debug_id][graph_name]) + if tf_dump_summary is not None: + summary_txt.append(tf_dump_summary) + title = "[green](%s)[/green] %s" % (debug_id, graph_name) + util.print_panel(Constant.NEW_LINE.join(summary_txt), title) + if args.save != 0: + self.graph_manager.save_sub_graph(npu_ops, args.save) + + @catch_tool_exception + def do_compare_data(self, argv): + """compare two tensor""" + parser = argparse.ArgumentParser() + parser.add_argument('-n', '--name', dest='names', type=str, default=[], help='op name', nargs='+') + parser.add_argument('-p', '--print', dest='count', default=20, type=int, help='print err data num') + parser.add_argument('-s', '--save', dest='save', action='store_true', help='save data in txt format') + parser.add_argument('-al', '--atol', dest='atol', default=0.001, type=float, help='set rtol') + parser.add_argument('-rl', '--rtol', dest='rtol', default=0.001, type=float, help='set atol') + args = parser.parse_args(argv) + if len(args.names) != 2: + self.log.error("compare files should be 2.") + else: + self.compare.compare_data(args.names[0], args.names[1], args.save, args.rtol, args.atol, args.count) + + @catch_tool_exception + def do_list_dump(self, argv): + """List dump files""" + parser = argparse.ArgumentParser() + parser.add_argument('-t', '--type', dest='type', help='') + parser.add_argument('-n', '--name', dest='name') + self.dump_manager.list_dump(argv.dir, argv.name) + + @catch_tool_exception + def do_convert_npu_dump(self, argv): + parser = argparse.ArgumentParser() + parser.add_argument('-n', '--name', dest='name', help='op name') + parser.add_argument('-f', '--format', dest='format', default=None, required=False, help='target format') + parser.add_argument('-o', '--output', dest='output', required=False, default=None, help='output path') + args = parser.parse_args(argv) + self.dump_manager.convert_npu_dump(args.name, args.format, args.output) + + @catch_tool_exception + def do_convert_all_npu_dump(self): + self.dump_manager.decode_all_npu_dump() + + @catch_tool_exception + def check_graph_similarity(self): + """ Check graph similarity """ + + def single_cmd(self, argv): + cmd_func_map = {'compare': self.do_compare_data, + 'vector_compare': self.do_vector_compare} + if argv[1] in cmd_func_map: + func = cmd_func_map[argv[1]] + return func(argv[2:]) + raise PrecisionToolException("cmd %s is not supported or cmd should be run in interactive mode." % argv[1]) diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/precision_tool_exception.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/precision_tool_exception.py new file mode 100644 index 0000000000000000000000000000000000000000..02084770f2c8f391710f1835e9a422ddf25a624f --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/precision_tool_exception.py @@ -0,0 +1,24 @@ +# coding=utf-8 +import logging + + +class PrecisionToolException(Exception): + """ + Class for PrecisionTool Exception + """ + def __init__(self, error_info): + super(PrecisionToolException, self).__init__() + self.error_info = error_info + + +def catch_tool_exception(fuc): + def handle(*args, **kwargs): + log = logging.getLogger() + try: + return fuc(*args, **kwargs) + except PrecisionToolException as pte: + log.warning(pte.error_info) + except SystemExit: + # do not exit + log.debug("Exit") + return handle diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/pt_dump.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/pt_dump.py new file mode 100644 index 0000000000000000000000000000000000000000..155bd8c516519a714a4df3690457ba38c94b0d71 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/pt_dump.py @@ -0,0 +1,19 @@ +# coding=utf-8 +import os +import re +import time +import sys +from lib.util import util +from lib.constant import Constant +import config as cfg +from lib.precision_tool_exception import catch_tool_exception +from lib.precision_tool_exception import PrecisionToolException + + +class PTDump(object): + def __init__(self): + self.log = util.get_log() + # self.h5_util = + + def prepare(self): + print("test") \ No newline at end of file diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/tf_dump.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/tf_dump.py new file mode 100644 index 0000000000000000000000000000000000000000..487c25b946e05a9b473af23cd2e8ae35fa914788 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/tf_dump.py @@ -0,0 +1,122 @@ +# coding=utf-8 +import os +import re +import time +import sys +from lib.util import util +from lib.constant import Constant +import config as cfg +from lib.precision_tool_exception import catch_tool_exception +from lib.precision_tool_exception import PrecisionToolException + + +class TfDump(object): + def __init__(self, dump_root=cfg.TF_DUMP_DIR): + self.log = util.get_log() + self.dump_root = dump_root + self.dump_files = None + + def prepare(self): + if not os.path.exists(self.dump_root): + util.create_dir(self.dump_root) + self._parse_dump_files() + + def get_dump_files_by_op(self, op): + """Get cpu dump files by op""" + tf_files = {} + for output in op.outputs(): + if output.data_dump_origin_name() != '': + tf_files.update(self.get_dump_files_by_name(output.data_dump_origin_name())) + if len(tf_files) == 0: + tf_files.update(self.get_dump_files_by_name(op.name())) + return tf_files + + def get_dump_files_by_name(self, name, likely=False): + match_name = name.replace('/', '_') + if not likely: + match_name = match_name.replace('.', '_') + '\\.' + tf_files = {} + for f in self.dump_files: + if re.match(match_name, f): + tf_files[f] = self.dump_files[f] + return tf_files + + @catch_tool_exception + def op_dump_summary(self, op): + # cpu dump info + if op is None: + return '' + cpu_dump_txt = ['TfDumpOutput:'] + cpu_dump_files = self.get_dump_files_by_op(op) + for cpu_dump_file in cpu_dump_files.values(): + cpu_dump_txt.append(' -[green][%s][/green] %s' % (cpu_dump_file.idx, cpu_dump_file.file_name)) + cpu_dump_txt.append(' └─ [yellow]%s[/yellow]' % util.gen_npy_info_txt(cpu_dump_file.path)) + return Constant.NEW_LINE.join(cpu_dump_txt) + + def _parse_dump_files(self): + self.dump_files = util.list_cpu_dump_decode_files(self.dump_root) + + def run_tf_dbg_dump(self, cmd_line): + """Run tf train script to get dump data.""" + if os.path.exists(cfg.TF_DEBUG_DUMP_DIR) and len(os.listdir(cfg.TF_DEBUG_DUMP_DIR)) != 0: + self.log.info("TF offline debug path [%s] is not empty, will analyze it directly." % cfg.TF_DEBUG_DUMP_DIR) + elif cmd_line is not None: + self.log.info("Run command: %s" % cmd_line) + util.execute_command(cmd_line) + self.log.info("Run finish, start analyze TF dump.") + if not os.path.exists(cfg.TF_DEBUG_DUMP_DIR) or len(os.listdir(cfg.TF_DEBUG_DUMP_DIR)) == 0: + raise PrecisionToolException("Empty tf debug dir. %s" % cfg.TF_DEBUG_DUMP_DIR) + run_dirs = os.listdir(cfg.TF_DEBUG_DUMP_DIR) + run_dirs.sort() + # create dirs + util.create_dir(cfg.TF_DUMP_DIR) + util.create_dir(cfg.TMP_DIR) + # extra the last run dir + for run_dir in run_dirs: + time.sleep(1) + command = "%s -m tensorflow.python.debug.cli.offline_analyzer --ui_type readline --dump_dir %s" % ( + util.python, os.path.join(cfg.TF_DEBUG_DUMP_DIR, run_dir)) + self._do_run_tf_dbg_dump(command, 0) + + def _do_run_tf_dbg_dump(self, cmd_line, run_times=2): + """Run tf debug with pexpect, should set tf debug ui_type='readline'""" + try: + import pexpect + import readline + except ImportError as import_err: + self.log.error("Import failed with err:%s. You can run " + "'pip3 install pexpect gnureadline pyreadline' to fix it.", + import_err) + raise PrecisionToolException("Import module error.") + self.log.info("======< Auto run tf train process to dump data >======") + self.log.info("Send run times: %d", run_times) + tf_dbg = pexpect.spawn(cmd_line) + # tf_dbg.logfile = open(cfg.DUMP_FILES_CPU_LOG, 'wb') + tf_dbg.logfile = sys.stdout.buffer + for i in range(run_times): + tf_dbg.expect('tfdbg>', timeout=cfg.TF_DEBUG_TIMEOUT) + self.log.info("Process %d tf_debug.run", i + 1) + tf_dbg.sendline('run') + self.log.info("Generate tensor name file.") + tf_dbg.expect('tfdbg>', timeout=cfg.TF_DEBUG_TIMEOUT) + tf_dbg.sendline('lt > %s' % cfg.TF_TENSOR_NAMES) + tf_dbg.expect('tfdbg>', timeout=cfg.TF_DEBUG_TIMEOUT) + if not os.path.exists(cfg.TF_TENSOR_NAMES): + self.log.error("Failed to get tensor name in tf_debug.") + raise PrecisionToolException("Get tensor name in tf_debug failed.") + self.log.info("Save tensor name success. Generate tf dump commands from file: %s", cfg.TF_TENSOR_NAMES) + convert_cmd = "timestamp=" + str(int(time.time())) + "; cat " + cfg.TF_TENSOR_NAMES + \ + " | awk '{print \"pt\",$4,$4}'| awk '{gsub(\"/\", \"_\", $3); gsub(\":\", \".\", $3);" \ + "print($1,$2,\"-n 0 -w " + cfg.TF_DUMP_DIR + "/" + \ + "\"$3\".\"\"'$timestamp'\"\".npy\")}' > " + cfg.TF_TENSOR_DUMP_CMD + util.execute_command(convert_cmd) + if not os.path.exists(cfg.TF_TENSOR_DUMP_CMD): + self.log.error("Save tf dump cmd failed") + raise PrecisionToolException("Failed to generate tf dump command.") + self.log.info("Generate tf dump commands. Start run commands in file: %s", cfg.TF_TENSOR_DUMP_CMD) + for cmd in open(cfg.TF_TENSOR_DUMP_CMD): + self.log.debug(cmd.strip()) + tf_dbg.sendline(cmd.strip()) + tf_dbg.expect('tfdbg>', timeout=cfg.TF_DEBUG_TIMEOUT) + tf_dbg.sendline('exit') + self.log.info('Finish dump tf data') diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/tf_graph.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/tf_graph.py new file mode 100644 index 0000000000000000000000000000000000000000..b898c59ccf4f2c11d3c89a9630748520c0e8780b --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/tf_graph.py @@ -0,0 +1,45 @@ +# coding=utf-8 +import collections +import logging +import os +import config as cfg +from lib.util import util +from lib.precision_tool_exception import catch_tool_exception +from lib.precision_tool_exception import PrecisionToolException + +CKPT_META_SHUFFIX='.meta' + + +class TfGraph(object): + def __init__(self, graph_root=cfg.TF_GRAPH_DIR): + """""" + self.graph_root = graph_root + self.log = util.get_log() + self.op_list = collections.OrderedDict() + + @catch_tool_exception + def get_op_list(self, ckpt_path=None): + if self.op_list is None: + self._convert_ckpt_to_graph(ckpt_path) + return self.op_list + + def _convert_ckpt_to_graph(self, ckpt_path): + log_level = self.log.level + try: + self.log.setLevel('ERROR') + import tensorflow as tf + self.log.setLevel(log_level) + except ImportError as err: + self.log.setLevel(log_level) + raise PrecisionToolException("Import tensorflow failed.") + meta_files = util.list_cpu_graph_files(ckpt_path) + if len(meta_files) == 0: + raise PrecisionToolException("Can not find any ckpt meta files.") + file_list = sorted(meta_files.values(), key=lambda x: x['timestamp']) + ckpt_file = file_list[-1] + self.log.info("Find %d tf ckpt meta files, choose [%s]" % (len(meta_files), ckpt_file['file_name'])) + self.op_list = collections.OrderedDict() + saver = tf.train.import_meta_graph(ckpt_file['path'], clear_devices=True) + graph = tf.get_default_graph() + for op in graph.get_operations(): + self.op_list[op.name] = op diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/tool_object.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/tool_object.py new file mode 100644 index 0000000000000000000000000000000000000000..7412b6ceeacdf76fe816741fc9f22644d3099a14 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/tool_object.py @@ -0,0 +1,10 @@ +# coding=utf-8 + + +class ToolObject(object): + _instance = None + + def __new__(cls, *args, **kwargs): + if not cls._instance: + cls._instance = super(ToolObject, cls).__new__(cls, *args, **kwargs) + return cls._instance diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/util.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/util.py new file mode 100644 index 0000000000000000000000000000000000000000..b81edae6a34928430456bc0c12a1d923a9c32ef1 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/lib/util.py @@ -0,0 +1,513 @@ +# coding=utf-8 +import csv +import re +import sys +import os +import shutil +import numpy as np +import logging +import subprocess +from lib.constant import Constant +from lib.precision_tool_exception import PrecisionToolException +from lib.precision_tool_exception import catch_tool_exception +from lib.file_desc import * +import config as cfg + +try: + from rich.traceback import install + from rich.panel import Panel + from rich.table import Table + from rich import print as rich_print + from rich.columns import Columns + install() +except ImportError as import_err: + install = None + Panel = None + Table = None + Columns = None + rich_print = print + print("Failed to import rich. some function may disable. Run 'pip3 install rich' to fix it.", + import_err) + +try: + import readline + readline.parse_and_bind('tab: complete') +except ImportError as import_error: + print("Unable to import module: readline. Run 'pip3 install gnureadline pyreadline' to fix it.") + +# patterns +OFFLINE_DUMP_PATTERN = r"^([A-Za-z0-9_-]+)\.([A-Za-z0-9_-]+)\.([0-9]+)\.?([0-9]+)?\.([0-9]{1,255})" +OFFLINE_DUMP_DECODE_PATTERN = \ + r"^([A-Za-z0-9_-]+)\.([A-Za-z0-9_-]+)\.([0-9]+)(\.[0-9]+)?\.([0-9]{1,255})\.([a-z]+)\.([0-9]{1,255})\.npy$" +OFFLINE_DUMP_CONVERT_PATTERN = \ + r"^([A-Za-z0-9_-]+)\.([A-Za-z0-9_-]+)\.([0-9]+)(\.[0-9]+)?\.([0-9]{1,255})" \ + r"\.([a-z]+)\.([0-9]{1,255})(\.[x0-9]+)?\.npy$" +OFFLINE_FILE_NAME = 'op_type.op_name.task_id(.stream_id).timestamp' +OP_DEBUG_NAME = 'OpDebug.Node_OpDebug.taskid.timestamp' +CPU_DUMP_DECODE_PATTERN = r"^([A-Za-z0-9_-]+)\.([0-9]+)(\.[0-9]+)?\.([0-9]{1,255})\.npy$" +CPU_FILE_DECODE_NAME = 'op_name.0(.0).timestamp.npy' +OP_DEBUG_PATTERN = r"Opdebug\.Node_OpDebug\.([0-9]+)(\.[0-9]+)?\.([0-9]{1,255})" +OP_DEBUG_DECODE_PATTERN = r"Opdebug\.Node_OpDebug\.([0-9]+)(\.[0-9]+)?\.([0-9]{1,255})\.([a-z]+)\.([0-9]{1,255})\.json" +VECTOR_COMPARE_RESULT_PATTERN = r"result_([0-9]{1,255})\.csv" +TIMESTAMP_DIR_PATTERN = '[0-9]{1,255}' +NUMPY_PATTERN = r".*\.npy$" +CSV_SHUFFIX = '.csv' +NUMPY_SHUFFIX = '.npy' +CKPT_META_SHUFFIX = r".*.meta$" +MAPPING_CSV = "mapping.csv" + + +class Util(object): + def __init__(self): + self.atc = None + self.ms_accu_cmp = None + logging.basicConfig(level=cfg.LOG_LEVEL, format="%(asctime)s (%(process)d) -[%(levelname)s]%(message)s", + datefmt="%Y-%m-%d %H:%M:%S") + self.log = logging.getLogger() + self.python = sys.executable + + def get_log(self): + return self.log + + def execute_command(self, cmd: str): + """ Execute shell command + :param cmd: command + :return: status code + """ + if cmd is None: + self.log.error("Command is None.") + return -1 + self.log.debug("[Run CMD]: %s", cmd) + complete_process = subprocess.run(cmd, shell=True) + return complete_process.returncode + + @staticmethod + def empty_dir(dir_path: str) -> bool: + """ Check if target dir is empty + :param dir_path: target dir + :return: bool + """ + if not os.path.exists(dir_path): + return True + if len(os.listdir(dir_path)) == 0: + return True + return False + + def convert_proto_to_json(self, src_file, dst_file): + """Convert GE proto graphs to json format. + command: atc --mode=5 --om=ge_proto_Build.txt --json=xxx.json + :param src_file: proto file + :param dst_file: output json file + :return: result json file + """ + if not os.path.exists(src_file): + raise PrecisionToolException("Source proto file %s not exist." % src_file) + # src_file = os.path.join(cfg.GRAPH_DIR_ALL, proto_file) + # json_file = proto_file + '.json' + # dst_file = os.path.join(cfg.GRAPH_DIR_BUILD, json_file) + if os.path.exists(dst_file) and os.path.getmtime(dst_file) > os.path.getmtime(src_file): + self.log.debug("GE graph build json already exist.") + return dst_file + cmd = '%s --mode=5 --om=%s --json=%s' % (self._get_atc(), src_file, dst_file) + self.execute_command(cmd) + if not os.path.isfile(dst_file): + raise PrecisionToolException("Convert GE build graph to json failed. can not find any json file.") + self.log.info('Finish convert [%s] build graph from proto to json format.', src_file) + return dst_file + + def convert_dump_to_npy(self, src_file, dst_path, data_format=None): + """Convert npu dump files to npy format. + :param src_file: src file + :param dst_path: dst path + :param data_format: target data format + :return: status code + """ + self.create_dir(dst_path) + format_cmd = '' if data_format is None else '-f %s' % data_format + cmd = '%s %s convert -d %s -out %s %s' % (self.python, self._get_ms_accu_cmp(), src_file, dst_path, format_cmd) + return self.execute_command(cmd) + + def compare_vector(self, npu_dump_dir, cpu_dump_dir, graph_json, result_path): + """Run compare vector command. + :param npu_dump_dir: npu dump data dir + :param cpu_dump_dir: cpu dump data dir + :param graph_json: graph json + :param result_path: result path + :return: status code + """ + self.create_dir(result_path) + if graph_json is None: + cmd = '%s %s compare -m %s -g %s -out %s' % ( + self.python, self._get_ms_accu_cmp(), npu_dump_dir, cpu_dump_dir, result_path) + else: + cmd = '%s %s compare -m %s -g %s -f %s -out %s' % ( + self.python, self._get_ms_accu_cmp(), npu_dump_dir, cpu_dump_dir, graph_json, result_path) + return self.execute_command(cmd) + + def list_dump_files(self, path, sub_path=''): + """List npu dump files in npu dump dir. + default only list the newest sub dir ordered by timestamp. set sub_path to specific other sub_path + :param path: dump path + :param sub_path: sub dir + :return: dump_files, parent_dirs + """ + parent_dirs = {} + dump_files = {} + newest_sub_path = self.get_newest_dir(path) if sub_path == '' else sub_path + dump_pattern = re.compile(OFFLINE_DUMP_PATTERN) + for dir_path, dir_names, file_names in os.walk(os.path.join(path, newest_sub_path), followlinks=True): + for name in file_names: + dump_match = dump_pattern.match(name) + if dump_match is None: + continue + dump_files[name] = self._gen_dump_file_info(name, dump_match, dir_path) + if dir_path not in parent_dirs: + parent_dirs[dir_path] = {} + parent_dirs[dir_path][name] = dump_files[name] + return dump_files, parent_dirs + + def parse_mapping_csv(self, path, pattern, extern_pattern=''): + """parse mapping csv in dump path""" + dump_files = {} + re_pattern = re.compile(pattern) + for dir_path, dir_names, file_names in os.walk(path, followlinks=True): + if MAPPING_CSV not in file_names: + continue + mapping = self.read_csv(os.path.join(dir_path, MAPPING_CSV)) + for item in mapping: + src_file = os.path.abspath(os.path.join(dir_path, item[0])) + if not os.path.isfile(src_file): + self.log.warning("Can not find file %s in mapping.csv, dir: %s.", item[0], dir_path) + continue + match = re_pattern.match(item[1]) + if match is None: + self.log.warning("file name [%s] in mapping.csv is invalid.", item[1]) + continue + file_desc = self._gen_dump_file_info(item[0], match, dir_path) + dst_file_name = '.'.join([file_desc.op_type, file_desc.file_name, str(file_desc.task_id), + str(file_desc.stream_id), str(file_desc.timestamp)]) + dst_file = os.path.abspath(os.path.join(dir_path, dst_file_name)) + if not os.path.islink(src_file): + os.rename(src_file, dst_file) + os.symlink(dst_file, src_file) + file_desc.path = dst_file + file_desc.file_name = dst_file_name + dump_files[item[1]] = file_desc + return dump_files + + def list_npu_dump_files(self, path, extern_pattern=''): + npu_dump_files = self._list_file_with_pattern(path, OFFLINE_DUMP_PATTERN, extern_pattern, + self._gen_dump_file_info) + npu_dump_files.update(self.parse_mapping_csv(path, OFFLINE_DUMP_PATTERN, extern_pattern)) + return npu_dump_files + + def list_ge_graph_files(self, path, extern_pattern=''): + return self._list_file_with_pattern(path, Constant.Pattern.GE_PROTO_GRAPH_PATTERN, extern_pattern, + self._gen_build_graph_file_info) + + def list_npu_dump_decode_files(self, path, extern_pattern=''): + return self._list_file_with_pattern(path, OFFLINE_DUMP_DECODE_PATTERN, extern_pattern, + self._gen_npu_dump_decode_file_info) + + def list_debug_decode_files(self, path, extern_pattern=''): + return self._list_file_with_pattern(path, OP_DEBUG_DECODE_PATTERN, extern_pattern, + self._gen_overflow_debug_decode_file_info) + + def list_cpu_dump_decode_files(self, path, extern_pattern=''): + return self._list_file_with_pattern(path, CPU_DUMP_DECODE_PATTERN, extern_pattern, + self._gen_cpu_dump_decode_file_info) + + def list_cpu_graph_files(self, path, extern_pattern=''): + return self._list_file_with_pattern(path, CKPT_META_SHUFFIX, extern_pattern, + self._gen_cpu_graph_files_info) + + def list_vector_compare_result_files(self, path, extern_pattern=''): + return self._list_file_with_pattern(path, VECTOR_COMPARE_RESULT_PATTERN, extern_pattern, + self._gen_vector_compare_result_file_info) + + def list_npu_dump_convert_files(self, path, extern_pattern=''): + return self._list_file_with_pattern(path, OFFLINE_DUMP_CONVERT_PATTERN, extern_pattern, + self._gen_npu_dump_convert_file_info) + + def list_numpy_files(self, path, extern_pattern=''): + return self._list_file_with_pattern(path, NUMPY_PATTERN, extern_pattern, + self._gen_numpy_file_info) + + def create_dir(self, path): + """Create dir if not exist + :param path: path + :return: bool + """ + if os.path.exists(path): + return True + try: + os.makedirs(path, mode=0o700) + except OSError as err: + self.log.error("Failed to create %s. %s", path, str(err)) + return False + return True + + def clear_dir(self, path: str, pattern=''): + """Clear dir with pattern (file/path name match pattern will be removed) + :param path: path + :param pattern: pattern + :return: None + """ + if not os.path.exists(path): + return + try: + for f in os.listdir(path): + if not re.match(pattern, f): + continue + file_path = os.path.join(path, f) + if os.path.isfile(file_path): + os.remove(file_path) + elif os.path.isdir(file_path): + shutil.rmtree(file_path) + except OSError as err: + self.log.error("Failed to remove %s. %s", path, str(err)) + + @staticmethod + def npy_info(source_data): + """Get npy information + :param source_data: npy path + :return: (shape, dtype) + """ + if isinstance(source_data, str): + if not str(source_data).endswith(NUMPY_SHUFFIX): + raise PrecisionToolException("Npy file [%s] is invalid" % source_data) + data = np.load(source_data, allow_pickle=True) + elif isinstance(source_data, np.ndarray): + data = source_data + else: + raise PrecisionToolException("Invalid source data:%s" % source_data) + if np.size(data) == 0: + raise PrecisionToolException("Empty source data:%s" % source_data) + return data.shape, data.dtype, data.max(), data.min(), data.mean() + + @catch_tool_exception + def gen_npy_info_txt(self, source_data): + """ Generate numpy info txt. + :param source_data: source path or np.ndarray + :return: txt + """ + try: + shape, dtype, max_data, min_data, mean = self.npy_info(source_data) + return '[Shape: %s] [Dtype: %s] [Max: %s] [Min: %s] [Mean: %s]' % (shape, dtype, max_data, min_data, mean) + except PrecisionToolException: + return '' + + def print_npy_summary(self, path, file_name, is_convert=False, extern_content=''): + """Print summary of npy data + :param path: file path + :param file_name: file name + :param is_convert: if convert to txt file + :param extern_content: extern content append to the summary + :return: None + """ + target_file = os.path.join(path, file_name) + if not os.path.exists(target_file): + raise PrecisionToolException("File [%s] not exist" % target_file) + data = np.load(target_file, allow_pickle=True) + table = self.create_table('', ['Index', 'Data']) + flatten_data = data.flatten() + for i in range(min(16, int(np.ceil(flatten_data.size / 8)))): + last_idx = min(flatten_data.size, i*8+8) + table.add_row(str(i * 8), ' '.join(flatten_data[i*8: last_idx].astype('str').tolist())) + summary = ['[yellow]%s[/yellow]' % self.gen_npy_info_txt(data), 'Path: %s' % target_file] + if is_convert: + summary.append('TxtFile: %s.txt' % target_file) + if extern_content != '': + summary.append('%s' % extern_content) + self.print_panel(self.create_columns([table, Constant.NEW_LINE.join(summary)]), file_name) + if is_convert: + self.save_npy_to_txt(data, target_file + '.txt') + + def save_npy_to_txt(self, src_file, dst_file='', align=0): + """save numpy file to txt file. + default data will be aligned to the last axis of data.shape + :param src_file: src file name + :param dst_file: dst file name + :param align: data align + :return: None + """ + if dst_file == '': + dst_file = src_file + '.txt' + if os.path.exists(dst_file): + self.log.debug("Dst file %s exists, will not save new one.", dst_file) + return + if isinstance(src_file, str): + data = np.load(src_file, allow_pickle=True) + elif isinstance(src_file, np.ndarray): + data = src_file + else: + raise PrecisionToolException("invalid src_file: %s", src_file) + shape = data.shape + data = data.flatten() + if align == 0: + if len(shape) == 0: + align = 1 + else: + align = shape[-1] + elif data.size % align != 0: + pad_array = np.zeros((align - data.size % align,)) + data = np.append(data, pad_array) + np.savetxt(dst_file, data.reshape((-1, align)), delimiter=' ', fmt='%g') + + def read_csv(self, path): + """Read csv file to list. + :param path: csv file path + :return: list + """ + if not str(path).endswith(CSV_SHUFFIX): + self.log.error("csv path [%s] is invalid", path) + return + rows = [] + with open(path) as f: + csv_handle = csv.reader(f) + for row in csv_handle: + rows.append(row) + return rows + + @staticmethod + def print(content): + rich_print(content) + + @staticmethod + def create_table(title, columns): + if Table is None: + raise PrecisionToolException("No rich module error.") + table = Table(title=title) + for column_name in columns: + table.add_column(column_name, overflow='fold') + return table + + @staticmethod + def create_columns(content): + if Columns is None: + raise PrecisionToolException("No rich module error.") + return Columns(content) + + def print_panel(self, content, title='', fit=True): + """ Print panel. + :param content: content + :param title: title + :param fit: if panel size fit the content + :return:Node + """ + if Panel is None: + print(content) + return + if fit: + self.print(Panel.fit(content, title=title)) + else: + self.print(Panel(content, title=title)) + + @staticmethod + def _detect_file(file_name, root_dir): + """Find file in root dir""" + result = [] + for dir_path, dir_names, file_names in os.walk(root_dir, followlinks=True): + for name in file_names: + if re.match(file_name, name): + result.append(os.path.join(dir_path, name)) + return result + + def _detect_file_if_not_exist(self, target_file): + """Find specific file in cmd root path""" + self.log.info("Try to auto detect file with name: %s.", target_file) + res = self._detect_file(target_file, cfg.CMD_ROOT_PATH) + if len(res) == 0: + raise PrecisionToolException("Cannot find any file named %s in dir %s" % (target_file, cfg.CMD_ROOT_PATH)) + self.log.info("Detect [%s] success. %s", target_file, res) + return res[0] + + def _get_atc(self): + if self.atc is None: + self.atc = self._detect_file_if_not_exist('^atc$') + return self.atc + + def _get_ms_accu_cmp(self): + if self.ms_accu_cmp is None: + self.ms_accu_cmp = self._detect_file_if_not_exist(cfg.MS_ACCU_CMP) + return self.ms_accu_cmp + + def get_newest_dir(self, path: str): + """Find the newest subdir in specific path, subdir should named by timestamp.""" + if not os.path.isdir(path): + self.log.warning("Path [%s] not exists", path) + return '' + paths = os.listdir(path) + sub_paths = [] + for p in paths: + if re.match(TIMESTAMP_DIR_PATTERN, p): + sub_paths.append(p) + if len(sub_paths) == 0: + self.log.debug("Path [%s] has no timestamp dirs.", path) + return '' + newest_sub_path = sorted(sub_paths)[-1] + self.log.info("Sub path num:[%d]. Dirs[%s], choose[%s]", len(sub_paths), str(sub_paths), newest_sub_path) + return newest_sub_path + + @staticmethod + def _list_file_with_pattern(path, pattern, extern_pattern, gen_info_func): + if path is None or not os.path.exists(path): + raise PrecisionToolException("Path %s not exist." % path) + file_list = {} + re_pattern = re.compile(pattern) + for dir_path, dir_names, file_names in os.walk(path, followlinks=True): + for name in file_names: + match = re_pattern.match(name) + if match is None: + continue + if extern_pattern != '' and not re.match(extern_pattern, name): + continue + file_list[name] = gen_info_func(name, match, dir_path) + return file_list + + @staticmethod + def _gen_numpy_file_info(name, math, dir_path): + return FileDesc(name, dir_path) + + @staticmethod + def _gen_build_graph_file_info(name, match, dir_path): + return BuildGraphFileDesc(name, dir_path, -1, int(match.group(1)), match.group(2)) + + @staticmethod + def _gen_dump_file_info(name, match, dir_path): + return NpuDumpFileDesc(name, dir_path, int(match.groups()[-1]), op_name=match.group(2), op_type=match.group(1), + task_id=int(match.group(3)), stream_id=match.group(4)) + + @staticmethod + def _gen_npu_dump_decode_file_info(name, match, dir_path): + return DumpDecodeFileDesc(name, dir_path, int(match.groups()[-3]), op_name=match.group(2), + op_type=match.group(1), task_id=int(match.group(3)), + anchor_type=match.groups()[-2], anchor_idx=int(match.groups()[-1])) + + @staticmethod + def _gen_cpu_dump_decode_file_info(name, match, dir_path): + return DumpDecodeFileDesc(name, dir_path, -1, op_name=match.group(1), op_type='', task_id=0, + anchor_type='output', anchor_idx=int(match.group(2))) + + @staticmethod + def _gen_cpu_graph_files_info(name, match, dir_path): + return FileDesc(name, dir_path, -1) + + @staticmethod + def _gen_overflow_debug_decode_file_info(name, match, dir_path): + return DumpDecodeFileDesc(name, dir_path, int(match.groups()[-3]), op_name='Node_OpDebug', op_type='Opdebug', + task_id=int(match.group(1)), anchor_type=match.groups()[-2], + anchor_idx=int(match.groups()[-1])) + + @staticmethod + def _gen_vector_compare_result_file_info(name, match, dir_path): + return FileDesc(name, dir_path, int(match.group(1))) + + @staticmethod + def _gen_npu_dump_convert_file_info(name, match, dir_path): + return DumpDecodeFileDesc(name, dir_path, int(match.groups()[-4]), op_name=match.group(2), + op_type=match.group(1), task_id=int(match.group(3)), anchor_type=match.groups()[-3], + anchor_idx=int(match.groups()[-2])) + + +util = Util() diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/tf_config.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/tf_config.py new file mode 100644 index 0000000000000000000000000000000000000000..e727238b41e143f129cae69b65a18d6bd7cd9ef5 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/precision_tool/tf_config.py @@ -0,0 +1,219 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# 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. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# 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. +# coding=utf-8 +import os +import random +from tensorflow.core.protobuf import config_pb2 +from tensorflow.core.protobuf.rewriter_config_pb2 import RewriterConfig +from tensorflow.python import debug as tf_debug +import tensorflow as tf +from . import config as cfg + +FLAG_DUMP_GE_GRAPH = 'DUMP_GE_GRAPH' +FLAG_DUMP_GRAPH_LEVEL = 'DUMP_GRAPH_LEVEL' +FLAG_DUMP_GRAPH_PATH = 'DUMP_GRAPH_PATH' + +# Fusion switch file path +FUSION_SWITCH_FILE = os.path.join(os.path.dirname(__file__), 'fusion_switch.cfg') +FUSION_OFF_FILE = os.path.join(os.path.dirname(__file__), 'fusion_off.cfg') + +DEFAULT_OP_DEBUG_DIR = cfg.DEFAULT_OP_DEBUG_DIR + + +def seed_everything(seed=cfg.DUMP_SEED): + # set random seed + os.environ['PYTHONHASHSEED'] = str(seed) + random.seed(seed) + tf.random.set_random_seed(seed) + print("[PrecisionTool] Set Tensorflow random seed to %d success." % seed) + try: + import numpy as np + np.random.seed(seed) + print("[PrecisionTool] Set numpy random seed to %d success." % seed) + except ImportError as err: + np = None + print("[PrecisionTool] No numpy module.", err) + + +# set global random seed +seed_everything() + + +def sess_dump(sess): + """wrapper session with dumping debug wrapper. + In session run mode. Use sess=sess_dump(sess) + :param sess: origin session + :return: Session + """ + _init() + return tf_debug.DumpingDebugWrapperSession(sess, cfg.TF_DEBUG_DUMP_DIR) + + +def estimator_dump(): + """In estimator mode. estim_spec = tf.estimator.EstimatorSpec(traing_hooks=[estimator_dump()]) + :return: + """ + _init() + return tf_debug.DumpingDebugHook(cfg.TF_DEBUG_DUMP_DIR) + + +def estimator_dump_config(action=None): + """return DumpConfig. + In estimator mode. set dump_config in NPURunConfig(). + exp. config = NPURunConfig(dump_config=estimator_dum_config(), session_config=session_config) + :return: DumpConfig + """ + from npu_bridge.npu_init import DumpConfig + _init() + if _is_overflow(action): + config = DumpConfig(enable_dump_debug=True, dump_path=cfg.NPU_OVERFLOW_DUMP_DIR, dump_mode="all") + elif _is_dump(action): + config = DumpConfig(enable_dump=True, dump_path=cfg.DEFAULT_NPU_DUMP_DIR, dump_step=cfg.TF_DUMP_STEP, + dump_mode="all") + else: + config = DumpConfig() + return config + + +def session_dump_config(session_config=None, action=None): + """ + In TF session mode. set dump_config in session_config. + exp. config = session_dump_config() + config.[set your own configs] + with tf.Session(config=config) as sess: + sess.run(_) + tf_debug.LocalCLIDebugWrapperSession(sess=sess, ui_type="readline") + :param session_config: original session config + :param action: if set action, no need to start app with cli wrapper + :return: config_pb2.ConfigProto + """ + if ((not isinstance(session_config, config_pb2.ConfigProto)) and + (not issubclass(type(session_config), config_pb2.ConfigProto))): + session_config = config_pb2.ConfigProto() + custom_op = None + for existed_custom_op in session_config.graph_options.rewrite_options.custom_optimizers: + if existed_custom_op.name == 'NpuOptimizer': + custom_op = existed_custom_op + if custom_op is None: + custom_op = session_config.graph_options.rewrite_options.custom_optimizers.add() + custom_op.name = 'NpuOptimizer' + custom_op.parameter_map['use_off_line'].b = True + update_custom_op(custom_op, action) + session_config.graph_options.rewrite_options.remapping = RewriterConfig.OFF + return session_config + + +def update_custom_op(custom_op, action=None): + """Update custom_op + :param custom_op: origin custom op + :param action: dump | overflow | fusion_off | fusion_switch + :return: + """ + _init() + custom_op.parameter_map['debug_dir'].s = tf.compat.as_bytes(cfg.DEFAULT_OP_DEBUG_DIR) + if _is_overflow(action): + custom_op.parameter_map['enable_dump_debug'].b = True + custom_op.parameter_map['dump_debug_mode'].s = tf.compat.as_bytes("all") + custom_op.parameter_map['dump_path'].s = tf.compat.as_bytes(cfg.NPU_OVERFLOW_DUMP_DIR) + custom_op.parameter_map['op_debug_level'].i = cfg.OP_DEBUG_LEVEL + elif _is_dump(action): + custom_op.parameter_map['enable_dump'].b = True + custom_op.parameter_map['dump_mode'].s = tf.compat.as_bytes("all") + custom_op.parameter_map['dump_path'].s = tf.compat.as_bytes(cfg.DEFAULT_NPU_DUMP_DIR) + custom_op.parameter_map['op_debug_level'].i = cfg.OP_DEBUG_LEVEL + custom_op.parameter_map['dump_step'].s = tf.compat.as_bytes(cfg.TF_DUMP_STEP) + if _is_fusion_off(action): + custom_op.parameter_map['fusion_switch_file'].s = tf.compat.as_bytes(FUSION_OFF_FILE) + print("[PrecisionTool] Set fusion switch file: ", FUSION_OFF_FILE) + elif _is_fusion_switch(action): + custom_op.parameter_map['fusion_switch_file'].s = tf.compat.as_bytes(FUSION_SWITCH_FILE) + print("[PrecisionTool] Set fusion switch file: ", FUSION_SWITCH_FILE) + return custom_op + + +def _init(): + _create_dir(cfg.DEFAULT_OP_DEBUG_DIR) + _create_dir(cfg.NPU_OVERFLOW_DUMP_DIR) + _create_dir(cfg.DEFAULT_NPU_DUMP_DIR) + _create_dir(cfg.DEFAULT_NPU_GRAPH_DIR) + _set_dump_graph_flags() + + +def _create_dir(path): + """ create dir """ + if os.path.exists(path): + return + try: + os.makedirs(path, mode=0o700) + except OSError as err_msg: + print("[PrecisionTool] Failed to create %s. %s" % (path, str(err_msg))) + + +def _unset_dump_graph_flags(): + if FLAG_DUMP_GE_GRAPH in os.environ: + del os.environ[FLAG_DUMP_GE_GRAPH] + if FLAG_DUMP_GRAPH_LEVEL in os.environ: + del os.environ[FLAG_DUMP_GRAPH_LEVEL] + if FLAG_DUMP_GRAPH_PATH in os.environ: + del os.environ[FLAG_DUMP_GRAPH_PATH] + + +def _set_dump_graph_flags(): + os.environ[FLAG_DUMP_GE_GRAPH] = str(cfg.DUMP_GE_GRAPH_VALUE) + os.environ[FLAG_DUMP_GRAPH_LEVEL] = str(cfg.DUMP_GRAPH_LEVEL_VALUE) + os.environ[FLAG_DUMP_GRAPH_PATH] = cfg.DEFAULT_NPU_GRAPH_DIR + + +def _is_dump(action): + if action is not None: + return 'dump' in action + if cfg.PRECISION_TOOL_DUMP_FLAG in os.environ and os.environ[cfg.PRECISION_TOOL_DUMP_FLAG] == 'True': + print("[PrecisionTool] enable npu dump >======") + return True + return False + + +def _is_overflow(action): + if action is not None: + return 'overflow' in action + if cfg.PRECISION_TOOL_OVERFLOW_FLAG in os.environ and os.environ[cfg.PRECISION_TOOL_OVERFLOW_FLAG] == 'True': + print("[PrecisionTool] enable npu overflow >======") + return True + return False + + +def _is_fusion_off(action): + if action is not None: + return 'fusion_off' in action + return False + + +def _is_fusion_switch(action): + if action is not None: + return 'fusion_switch' in action + return False diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/.DS_Store b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..76567042224a5ba158e66f3f5fa90ef5665ae91f Binary files /dev/null and b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/.DS_Store differ diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/2/train_2.log b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/2/train_2.log new file mode 100644 index 0000000000000000000000000000000000000000..796be1b7d6b48e90e2f6cb54e273e37479de7706 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/2/train_2.log @@ -0,0 +1,48 @@ +WARNING:tensorflow:From /home/HwHiAiUser/wubo/vit/vit-ckpt/precision_tool/tf_config.py:25: The name tf.random.set_random_seed is deprecated. Please use tf.compat.v1.random.set_random_seed instead. + +WARNING:tensorflow:From /usr/local/Ascend/tfplugin/latest/tfplugin/python/site-packages/npu_bridge/estimator/npu/npu_optimizer.py:127: The name tf.train.Optimizer is deprecated. Please use tf.compat.v1.train.Optimizer instead. + +WARNING:tensorflow:From /usr/local/python3.7.5/lib/python3.7/site-packages/tensorflow_core/python/ops/resource_variable_ops.py:1630: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version. +Instructions for updating: +If using Keras pass *_constraint arguments to layers. +WARNING:tensorflow:From /usr/local/python3.7.5/lib/python3.7/site-packages/tensorflow_core/python/data/util/random_seed.py:58: where (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version. +Instructions for updating: +Use tf.where in 2.0, which has the same broadcast rule as np.where +WARNING:tensorflow:From ./vit_allpipeline_fusion_accelerate.py:124: The name tf.train.MomentumOptimizer is deprecated. Please use tf.compat.v1.train.MomentumOptimizer instead. + +WARNING:tensorflow:From /usr/local/Ascend/tfplugin/latest/tfplugin/python/site-packages/npu_bridge/estimator/npu/npu_loss_scale_optimizer.py:58: The name tf.get_default_graph is deprecated. Please use tf.compat.v1.get_default_graph instead. + +WARNING:tensorflow:From ./vit_allpipeline_fusion_accelerate.py:142: The name tf.ConfigProto is deprecated. Please use tf.compat.v1.ConfigProto instead. + +WARNING:tensorflow:From ./vit_allpipeline_fusion_accelerate.py:156: The name tf.Session is deprecated. Please use tf.compat.v1.Session instead. + +2022-05-15 09:48:43.822834: W tensorflow/core/platform/profile_utils/cpu_utils.cc:98] Failed to find bogomips in /proc/cpuinfo; cannot determine CPU frequency +2022-05-15 09:48:43.828896: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x458aa510 initialized for platform Host (this does not guarantee that XLA will be used). Devices: +2022-05-15 09:48:43.828943: I tensorflow/compiler/xla/service/service.cc:176] StreamExecutor device (0): Host, Default Version +WARNING:tensorflow:From ./vit_allpipeline_fusion_accelerate.py:157: The name tf.global_variables_initializer is deprecated. Please use tf.compat.v1.global_variables_initializer instead. + +[PrecisionTool] Set Tensorflow random seed to 0 success. +[PrecisionTool] Set numpy random seed to 0 success. +load dataset ================================= +load dataset ================================= +[PrecisionTool] Set fusion switch file: /home/HwHiAiUser/wubo/vit/vit-ckpt/precision_tool/fusion_off.cfg +2022-05-15 09:48:53.112488: I /home/phisik3/jenkins/workspace/work_code/tmp/host-prefix/src/host-build/asl/tfadaptor/CMakeFiles/tf_adapter.dir/compiler_depend.ts:805] The model has been compiled on the Ascend AI processor, current graph id is: 1 +WARNING:tensorflow:From ./vit_allpipeline_fusion_accelerate.py:160: The name tf.train.Saver is deprecated. Please use tf.compat.v1.train.Saver instead. + +2022-05-15 09:49:04.981514: I /home/phisik3/jenkins/workspace/work_code/tmp/host-prefix/src/host-build/asl/tfadaptor/CMakeFiles/tf_adapter.dir/compiler_depend.ts:805] The model has been compiled on the Ascend AI processor, current graph id is: 11 +2022-05-15 09:49:25.298880: I /home/phisik3/jenkins/workspace/work_code/tmp/host-prefix/src/host-build/asl/tfadaptor/CMakeFiles/tf_adapter.dir/compiler_depend.ts:805] The model has been compiled on the Ascend AI processor, current graph id is: 21 +2022-05-15 09:53:30.029074: I /home/phisik3/jenkins/workspace/work_code/tmp/host-prefix/src/host-build/asl/tfadaptor/CMakeFiles/tf_adapter.dir/compiler_depend.ts:805] The model has been compiled on the Ascend AI processor, current graph id is: 31 +============ start load pretrained model ======================================= +============ load success 6.5804 ===================== +epoch:1 step: 0 , loss: 0.0681 , time: 113.6311 acc: 1.0000 +epoch:1 step: 1 , loss: 0.2198 , time: 15.5381 acc: 0.7500 +epoch:1 step: 2 , loss: 0.0095 , time: 15.2189 acc: 1.0000 +epoch:1 step: 3 , loss: 0.0476 , time: 22.9079 acc: 1.0000 +epoch:1 step: 4 , loss: 0.0578 , time: 15.2788 acc: 1.0000 +epoch:1 step: 5 , loss: 0.6772 , time: 15.5429 acc: 0.7500 +epoch:1 step: 6 , loss: 0.0049 , time: 15.0698 acc: 1.0000 +epoch:1 step: 7 , loss: 0.1065 , time: 15.2203 acc: 1.0000 +epoch:1 step: 8 , loss: 0.1218 , time: 15.2791 acc: 1.0000 +epoch:1 step: 9 , loss: 0.0144 , time: 15.3114 acc: 1.0000 +Train ACC: 0.9500 +Final Average Distances : 0.871 diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/2/vit-ckpt_bs2_1p_acc.log b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/2/vit-ckpt_bs2_1p_acc.log new file mode 100644 index 0000000000000000000000000000000000000000..73ffd2a7fa0b518ed8e4614b6a626895b28e4790 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/2/vit-ckpt_bs2_1p_acc.log @@ -0,0 +1,6 @@ +Network = vit-ckpt +RankSize = 1 +BatchSize = 2 +DeviceType = aarch64 +CaseName = vit-ckpt_bs2_1p_acc +E2ETrainingTime = 584 diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/3/train_3.log b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/3/train_3.log new file mode 100644 index 0000000000000000000000000000000000000000..5b6c1eb5e109145f48ca56dbef4829881cf67785 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/3/train_3.log @@ -0,0 +1,38 @@ +WARNING:tensorflow:From /home/HwHiAiUser/wubo/vit/vit-ckpt/precision_tool/tf_config.py:25: The name tf.random.set_random_seed is deprecated. Please use tf.compat.v1.random.set_random_seed instead. + +WARNING:tensorflow:From /usr/local/Ascend/tfplugin/latest/tfplugin/python/site-packages/npu_bridge/estimator/npu/npu_optimizer.py:127: The name tf.train.Optimizer is deprecated. Please use tf.compat.v1.train.Optimizer instead. + +WARNING:tensorflow:From /usr/local/python3.7.5/lib/python3.7/site-packages/tensorflow_core/python/ops/resource_variable_ops.py:1630: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version. +Instructions for updating: +If using Keras pass *_constraint arguments to layers. +WARNING:tensorflow:From /usr/local/python3.7.5/lib/python3.7/site-packages/tensorflow_core/python/data/util/random_seed.py:58: where (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version. +Instructions for updating: +Use tf.where in 2.0, which has the same broadcast rule as np.where +WARNING:tensorflow:From ./vit_allpipeline_fusion_accelerate.py:124: The name tf.train.MomentumOptimizer is deprecated. Please use tf.compat.v1.train.MomentumOptimizer instead. + +WARNING:tensorflow:From /usr/local/Ascend/tfplugin/latest/tfplugin/python/site-packages/npu_bridge/estimator/npu/npu_loss_scale_optimizer.py:58: The name tf.get_default_graph is deprecated. Please use tf.compat.v1.get_default_graph instead. + +WARNING:tensorflow:From ./vit_allpipeline_fusion_accelerate.py:142: The name tf.ConfigProto is deprecated. Please use tf.compat.v1.ConfigProto instead. + +WARNING:tensorflow:From ./vit_allpipeline_fusion_accelerate.py:156: The name tf.Session is deprecated. Please use tf.compat.v1.Session instead. + +2022-05-15 08:49:19.650985: W tensorflow/core/platform/profile_utils/cpu_utils.cc:98] Failed to find bogomips in /proc/cpuinfo; cannot determine CPU frequency +2022-05-15 08:49:19.657272: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x204c59a0 initialized for platform Host (this does not guarantee that XLA will be used). Devices: +2022-05-15 08:49:19.657332: I tensorflow/compiler/xla/service/service.cc:176] StreamExecutor device (0): Host, Default Version +WARNING:tensorflow:From ./vit_allpipeline_fusion_accelerate.py:157: The name tf.global_variables_initializer is deprecated. Please use tf.compat.v1.global_variables_initializer instead. + +[PrecisionTool] Set Tensorflow random seed to 0 success. +[PrecisionTool] Set numpy random seed to 0 success. +load dataset ================================= +load dataset ================================= +[PrecisionTool] Set fusion switch file: /home/HwHiAiUser/wubo/vit/vit-ckpt/precision_tool/fusion_off.cfg +2022-05-15 08:49:28.988384: I /home/phisik3/jenkins/workspace/work_code/tmp/host-prefix/src/host-build/asl/tfadaptor/CMakeFiles/tf_adapter.dir/compiler_depend.ts:805] The model has been compiled on the Ascend AI processor, current graph id is: 1 +WARNING:tensorflow:From ./vit_allpipeline_fusion_accelerate.py:160: The name tf.train.Saver is deprecated. Please use tf.compat.v1.train.Saver instead. + +2022-05-15 08:49:40.726232: I /home/phisik3/jenkins/workspace/work_code/tmp/host-prefix/src/host-build/asl/tfadaptor/CMakeFiles/tf_adapter.dir/compiler_depend.ts:805] The model has been compiled on the Ascend AI processor, current graph id is: 11 +2022-05-15 08:50:00.871987: I /home/phisik3/jenkins/workspace/work_code/tmp/host-prefix/src/host-build/asl/tfadaptor/CMakeFiles/tf_adapter.dir/compiler_depend.ts:805] The model has been compiled on the Ascend AI processor, current graph id is: 21 +2022-05-15 08:51:43.736154: I /home/phisik3/jenkins/workspace/work_code/tmp/host-prefix/src/host-build/asl/tfadaptor/CMakeFiles/tf_adapter.dir/compiler_depend.ts:805] The model has been compiled on the Ascend AI processor, current graph id is: 31 +============ start load pretrained model ======================================= +============ load success 6.3959 ===================== +Train ACC: 1.0000 +Final Average Distances : 0.871 diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/3/vit-ckpt_bs2_1p_acc.log b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/3/vit-ckpt_bs2_1p_acc.log new file mode 100644 index 0000000000000000000000000000000000000000..be827945be43a2000da74730b3438fc39c452462 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/3/vit-ckpt_bs2_1p_acc.log @@ -0,0 +1,6 @@ +Network = vit-ckpt +RankSize = 1 +BatchSize = 2 +DeviceType = aarch64 +CaseName = vit-ckpt_bs2_1p_acc +E2ETrainingTime = 442 diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/train_.log b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/train_.log new file mode 100644 index 0000000000000000000000000000000000000000..8b45908e9607713b0a12289a59bb172110665984 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/train_.log @@ -0,0 +1,2519 @@ +[PrecisionTool] Set Tensorflow random seed to 0 success. +[PrecisionTool] Set numpy random seed to 0 success. +load dataset ================================= +load dataset ================================= +[PrecisionTool] Set fusion switch file: /home/HwHiAiUser/wubo/vit/vit-ckpt/precision_tool/fusion_off.cfg +============ start load pretrained model ======================================= +============ load success 9.9240 ===================== +epoch:1 step: 0 , loss: 0.0681 , time: 158.2043 acc: 1.0000 +epoch:1 step: 1 , loss: 0.2198 , time: 17.0998 acc: 0.7500 +epoch:1 step: 2 , loss: 0.0095 , time: 16.9246 acc: 1.0000 +epoch:1 step: 3 , loss: 0.0476 , time: 16.7616 acc: 1.0000 +epoch:1 step: 4 , loss: 0.0578 , time: 16.7317 acc: 1.0000 +epoch:1 step: 5 , loss: 0.6772 , time: 17.4740 acc: 0.7500 +epoch:1 step: 6 , loss: 0.0049 , time: 16.2555 acc: 1.0000 +epoch:1 step: 7 , loss: 0.1065 , time: 18.1569 acc: 1.0000 +epoch:1 step: 8 , loss: 0.1218 , time: 16.9833 acc: 1.0000 +epoch:1 step: 9 , loss: 0.0144 , time: 17.7995 acc: 1.0000 +Train ACC: 0.9500 +0.75 (4, 100) +0.25 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.25 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.25 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.25 (4, 100) +0.5 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.25 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.25 (4, 100) +0.25 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.25 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.25 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.25 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.25 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.25 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.25 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.5 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.25 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.25 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.25 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.25 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.25 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.5 (4, 100) +0.75 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +0.75 (4, 100) +1.0 (4, 100) +Final Average Distances : 0.871 diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/vit-ckpt_bs1_1p_acc.log b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/vit-ckpt_bs1_1p_acc.log new file mode 100644 index 0000000000000000000000000000000000000000..47b73b5ba822c296f078aadf7529c65c101d29d6 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/output/vit-ckpt_bs1_1p_acc.log @@ -0,0 +1,6 @@ +Network = vit-ckpt +RankSize = 1 +BatchSize = 1 +DeviceType = aarch64 +CaseName = vit-ckpt_bs1_1p_acc +E2ETrainingTime = 671 diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/train_full_1p.sh b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/train_full_1p.sh new file mode 100644 index 0000000000000000000000000000000000000000..8c33c765f395b87c908a7a9f85c66208679e218f --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/train_full_1p.sh @@ -0,0 +1,201 @@ +#!/bin/bash +export RANK_INDEX=2 +export RANK_SIZE=1 +export RANK_ID=2 +export DEVICE_ID=2 +export DEVICE_INDEX=2 +export ASCEND_DEVICE_ID=2 + +########################################################## +#########第3行 至 100行,请一定不要、不要、不要修改########## +#########第3行 至 100行,请一定不要、不要、不要修改########## +#########第3行 至 100行,请一定不要、不要、不要修改########## +########################################################## +# shell脚本所在路径 +cur_path=`echo $(cd $(dirname $0);pwd)` + +# 判断当前shell是否是performance +perf_flag=`echo $0 | grep performance | wc -l` + +# 当前执行网络的名称 +Network=`echo $(cd $(dirname $0);pwd) | awk -F"/" '{print $(NF-1)}'` + +export RANK_SIZE=1 +export RANK_ID=0 +export JOB_ID=10087 + +# 路径参数初始化 +data_path="" +output_path="" + +# 帮助信息,不需要修改 +if [[ $1 == --help || $1 == -h ]];then + echo"usage:./train_performance_1P.sh " + echo " " + echo "parameter explain: + --data_path # dataset of training + --output_path # output of training + --train_steps # max_step for training + --train_epochs # max_epoch for training + --batch_size # batch size + -h/--help show help message + " + exit 1 +fi + +# 参数校验,不需要修改 +for para in $* +do + if [[ $para == --data_path* ]];then + data_path=`echo ${para#*=}` + elif [[ $para == --output_path* ]];then + output_path=`echo ${para#*=}` + elif [[ $para == --train_steps* ]];then + train_steps=`echo ${para#*=}` + elif [[ $para == --train_epochs* ]];then + train_epochs=`echo ${para#*=}` + elif [[ $para == --batch_size* ]];then + batch_size=`echo ${para#*=}` + fi +done + +# 校验是否传入data_path,不需要修改 +if [[ $data_path == "" ]];then + echo "[Error] para \"data_path\" must be config" + exit 1 +fi + +# 校验是否传入output_path,不需要修改 +if [[ $output_path == "" ]];then + output_path="./test/output/${ASCEND_DEVICE_ID}" +fi + +# 设置打屏日志文件名,请保留,文件名为${print_log} +print_log="./test/output/${ASCEND_DEVICE_ID}/train_${ASCEND_DEVICE_ID}.log" +modelarts_flag=${MODELARTS_MODEL_PATH} +if [ x"${modelarts_flag}" != x ]; +then + echo "running without etp..." + print_log_name=`ls /home/ma-user/modelarts/log/ | grep proc-rank` + print_log="/home/ma-user/modelarts/log/${print_log_name}" +fi +echo "### get your log here : ${print_log}" + +CaseName="" +function get_casename() +{ + if [ x"${perf_flag}" = x1 ]; + then + CaseName=${Network}_bs${batch_size}_${RANK_SIZE}'p'_'perf' + else + CaseName=${Network}_bs${batch_size}_${RANK_SIZE}'p'_'acc' + fi +} + +# 跳转到code目录 +cd ${cur_path}/../ +rm -rf ./test/output/${ASCEND_DEVICE_ID} +mkdir -p ./test/output/${ASCEND_DEVICE_ID} + +# 训练开始时间记录,不需要修改 +start_time=$(date +%s) +########################################################## +#########第3行 至 100行,请一定不要、不要、不要修改########## +#########第3行 至 100行,请一定不要、不要、不要修改########## +#########第3行 至 100行,请一定不要、不要、不要修改########## +########################################################## + +#========================================================= +#========================================================= +#========训练执行命令,需要根据您的网络进行修改============== +#========================================================= +#========================================================= +# 基础参数,需要模型审视修改 +# 您的训练数据集在${data_path}路径下,请直接使用这个变量获取 +# 您的训练输出目录在${output_path}路径下,请直接使用这个变量获取 +# 您的其他基础参数,可以自定义增加,但是batch_size请保留,并且设置正确的值 +batch_size=2 + + +export LD_LIBRARY_PATH=/usr/local/python3.7.5/lib:$LD_LIBRARY_PATH +#如果用户环境存在多个python3版本,则指定使用python3.7.5版本 + +export PATH=/usr/local/python3.7.5/bin:$PATH +export install_path=/usr/local/Ascend/ascend-toolkit/latest #软件包安装路径,请根据实际情况修改 +export LD_LIBRARY_PATH=${install_path}/fwkacllib/lib64:/usr/lib:$LD_LIBRARY_PATH +export PATH=${install_path}/fwkacllib/ccec_compiler/bin:${install_path}/fwkacllib/bin:$PATH +export PYTHONPATH=${install_path}/fwkacllib/python/site-packages:${install_path}/toolkit/python/site-packages:$PYTHONPATH +export PYTHONPATH=/usr/local/Ascend/tfplugin/latest/tfplugin/python/site-packages:$PYTHONPATH +export ASCEND_OPP_PATH=${install_path}/opp +export ASCEND_AICPU_PATH=${install_path}/{arch}-linux #其中{arch}请根据实际情况替换(arm64或x86_64) +export TOOLCHAIN_HOME=${install_path}/toolkit + +if [ x"${modelarts_flag}" != x ]; +then + python3.7 ./vit_allpipeline_fusion_accelerate.py --data_path=${data_path} --output_path=${output_path} > ${print_log} 2>&1 : +else + python3.7 ./vit_allpipeline_fusion_accelerate.py --data_path=${data_path} --output_path=${output_path} > ${print_log} 2>&1 +fi + +# 性能相关数据计算 +# StepTime=`grep "sec/step :" ${print_log} | tail -n 10 | awk '{print $NF}' | awk '{sum+=$1} END {print sum/NR}'` +# FPS=`awk 'BEGIN{printf "%.2f\n", '${batch_size}'/'${StepTime}'}'` + +# 精度相关数据计算 +train_accuracy=`grep "Final Average Distances :" ${print_log} | awk '{print $NF}'` + +########################################################### +#########后面的所有内容请不要修改########################### +#########后面的所有内容请不要修改########################### +#########后面的所有内容请不要修改########################### +########################################################### + +# 判断本次执行是否正确使用Ascend NPU +use_npu_flag=`grep "The model has been compiled on the Ascend AI processor" ${print_log} | wc -l` + +if [ x"${use_npu_flag}" == x0 ]; +then + echo "------------------ ERROR NOTICE START ------------------" + echo "ERROR, your task haven't used Ascend NPU, please check your npu Migration." + echo "------------------ ERROR NOTICE END------------------" +else + echo "------------------ INFO NOTICE START------------------" + echo "INFO, your task have used Ascend NPU, please check your result." + echo "------------------ INFO NOTICE END------------------" +fi + +# 获取最终的casename,请保留,case文件名为${CaseName} +get_casename + +# 重命名loss文件 +if [ -f ./test/output/${ASCEND_DEVICE_ID}/my_output_loss.txt ]; +then + mv ./test/output/${ASCEND_DEVICE_ID}/my_output_loss.txt ./test/output/${ASCEND_DEVICE_ID}/${CaseName}_loss.txt +fi + +# 训练端到端耗时 +end_time=$(date +%s) +e2e_time=$(( $end_time - $start_time )) + +echo "------------------ Final result ------------------" +# 输出性能FPS/单step耗时/端到端耗时 +# echo "Final Performance images/sec : $FPS" +# echo "Final Performance sec/step : $StepTime" +echo "E2E Training Duration sec : $e2e_time" + +# 输出训练精度 +echo "Final Train Accuracy : ${train_accuracy}" + +# 最后一个迭代loss值,不需要修改 +# ActualLoss=(`awk 'END {print $NF}' $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}_loss.txt`) + +#关键信息打印到${CaseName}.log中,不需要修改 +echo "Network = ${Network}" > $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "RankSize = ${RANK_SIZE}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "BatchSize = ${batch_size}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "DeviceType = `uname -m`" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "CaseName = ${CaseName}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +# echo "ActualFPS = ${FPS}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +# echo "TrainingTime = ${StepTime}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +# echo "ActualLoss = ${ActualLoss}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "E2ETrainingTime = ${e2e_time}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/train_performance_1p.sh b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/train_performance_1p.sh new file mode 100644 index 0000000000000000000000000000000000000000..3ee8df9d48f144214fe5935540519ec9b0003e27 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/test/train_performance_1p.sh @@ -0,0 +1,184 @@ +#!/bin/bash + +########################################################## +#########第3行 至 100行,请一定不要、不要、不要修改########## +#########第3行 至 100行,请一定不要、不要、不要修改########## +#########第3行 至 100行,请一定不要、不要、不要修改########## +########################################################## +# shell脚本所在路径 +cur_path=`echo $(cd $(dirname $0);pwd)` + +# 判断当前shell是否是performance +perf_flag=`echo $0 | grep performance | wc -l` + +# 当前执行网络的名称 +Network=`echo $(cd $(dirname $0);pwd) | awk -F"/" '{print $(NF-1)}'` + +export RANK_SIZE=1 +export RANK_ID=0 +export JOB_ID=10087 + +# 路径参数初始化 +data_path="" +output_path="" + +# 帮助信息,不需要修改 +if [[ $1 == --help || $1 == -h ]];then + echo"usage:./train_performance_1P.sh " + echo " " + echo "parameter explain: + --data_path # dataset of training + --output_path # output of training + --train_steps # max_step for training + --train_epochs # max_epoch for training + --batch_size # batch size + -h/--help show help message + " + exit 1 +fi + +# 参数校验,不需要修改 +for para in $* +do + if [[ $para == --data_path* ]];then + data_path=`echo ${para#*=}` + elif [[ $para == --output_path* ]];then + output_path=`echo ${para#*=}` + elif [[ $para == --train_steps* ]];then + train_steps=`echo ${para#*=}` + elif [[ $para == --train_epochs* ]];then + train_epochs=`echo ${para#*=}` + elif [[ $para == --batch_size* ]];then + batch_size=`echo ${para#*=}` + fi +done + +# 校验是否传入data_path,不需要修改 +if [[ $data_path == "" ]];then + echo "[Error] para \"data_path\" must be config" + exit 1 +fi + +# 校验是否传入output_path,不需要修改 +if [[ $output_path == "" ]];then + output_path="./test/output/${ASCEND_DEVICE_ID}" +fi + +# 设置打屏日志文件名,请保留,文件名为${print_log} +print_log="./test/output/${ASCEND_DEVICE_ID}/train_${ASCEND_DEVICE_ID}.log" +modelarts_flag=${MODELARTS_MODEL_PATH} +if [ x"${modelarts_flag}" != x ]; +then + echo "running with modelarts..." + print_log_name=`ls /home/ma-user/modelarts/log/ | grep proc-rank` + print_log="/home/ma-user/modelarts/log/${print_log_name}" +fi +echo "### get your log here : ${print_log}" + +CaseName="" +function get_casename() +{ + if [ x"${perf_flag}" = x1 ]; + then + CaseName=${Network}_bs${batch_size}_${RANK_SIZE}'p'_'perf' + else + CaseName=${Network}_bs${batch_size}_${RANK_SIZE}'p'_'acc' + fi +} + +# 跳转到code目录 +cd ${cur_path}/../ +rm -rf ./test/output/${ASCEND_DEVICE_ID} +mkdir -p ./test/output/${ASCEND_DEVICE_ID} + +# 训练开始时间记录,不需要修改 +start_time=$(date +%s) +########################################################## +#########第3行 至 100行,请一定不要、不要、不要修改########## +#########第3行 至 100行,请一定不要、不要、不要修改########## +#########第3行 至 100行,请一定不要、不要、不要修改########## +########################################################## + +#========================================================= +#========================================================= +#========训练执行命令,需要根据您的网络进行修改============== +#========================================================= +#========================================================= +# 基础参数,需要模型审视修改 +# 您的训练数据集在${data_path}路径下,请直接使用这个变量获取 +# 您的训练输出目录在${output_path}路径下,请直接使用这个变量获取 +# 您的其他基础参数,可以自定义增加,但是batch_size请保留,并且设置正确的值 +batch_size=1 +epoch=1 + +if [ x"${modelarts_flag}" != x ]; +then + python3.7 ./vit_allpipeline_fusion_accelerate.py --data_path=${data_path} --output_path=${output_path} +else + python3.7 ./vit_allpipeline_fusion_accelerate.py --data_path=${data_path} --output_path=${output_path} > ${print_log} +fi + +# 性能相关数据计算 +StepTime=`grep "sec/step :" ${print_log} | tail -n 10 | awk '{print $NF}' | awk '{sum+=$1} END {print sum/NR}'` +FPS=`awk 'BEGIN{printf "%.2f\n", '${batch_size}'/'${StepTime}'}'` + +# 精度相关数据计算 +train_accuracy=`grep "Final Average Distances :" ${print_log} | awk '{print $NF}'` +# 提取所有loss打印信息 +#grep "loss :" ${print_log} | awk -F ":" '{print $4}' | awk -F "-" '{print $1}' > ./test/output/${ASCEND_DEVICE_ID}/my_output_loss.txt +grep "d_loss :" ${print_log} | awk -F "|" '{print $2}' > ./test/output/${ASCEND_DEVICE_ID}/my_output_loss.txt + +########################################################### +#########后面的所有内容请不要修改########################### +#########后面的所有内容请不要修改########################### +#########后面的所有内容请不要修改########################### +########################################################### + +# 判断本次执行是否正确使用Ascend NPU +use_npu_flag=`grep "The model has been compiled on the Ascend AI processor" ${print_log} | wc -l` +if [ x"${use_npu_flag}" == x0 ]; +then + echo "------------------ ERROR NOTICE START ------------------" + echo "ERROR, your task haven't used Ascend NPU, please check your npu Migration." + echo "------------------ ERROR NOTICE END------------------" +else + echo "------------------ INFO NOTICE START------------------" + echo "INFO, your task have used Ascend NPU, please check your result." + echo "------------------ INFO NOTICE END------------------" +fi + +# 获取最终的casename,请保留,case文件名为${CaseName} +get_casename + +# 重命名loss文件 +if [ -f ./test/output/${ASCEND_DEVICE_ID}/my_output_loss.txt ]; +then + mv ./test/output/${ASCEND_DEVICE_ID}/my_output_loss.txt ./test/output/${ASCEND_DEVICE_ID}/${CaseName}_loss.txt +fi + +# 训练端到端耗时 +end_time=$(date +%s) +e2e_time=$(( $end_time - $start_time )) + +echo "------------------ Final result ------------------" +# 输出性能FPS/单step耗时/端到端耗时 +echo "Final Performance images/sec : $FPS" +echo "Final Performance sec/step : $StepTime" +echo "E2E Training Duration sec : $e2e_time" + +# 输出训练精度 +echo "Final Train Accuracy : ${train_accuracy}" + +# 最后一个迭代loss值,不需要修改 +ActualLoss=(`awk 'END {print $NF}' $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}_loss.txt`) + +#关键信息打印到${CaseName}.log中,不需要修改 +echo "Network = ${Network}" > $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "RankSize = ${RANK_SIZE}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "BatchSize = ${batch_size}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "DeviceType = `uname -m`" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "CaseName = ${CaseName}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "ActualFPS = ${FPS}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "TrainingTime = ${StepTime}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "ActualLoss = ${ActualLoss}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "E2ETrainingTime = ${e2e_time}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_allpipeline_fusion_accelerate.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_allpipeline_fusion_accelerate.py new file mode 100644 index 0000000000000000000000000000000000000000..eee0106b43799ca25dea304df7c639bf723e714a --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_allpipeline_fusion_accelerate.py @@ -0,0 +1,226 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# 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. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# 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. + + +import tensorflow as tf +from vit_keras import vit, utils +import os +import time +import tensorflow.keras.backend as K +from PIL import Image +import pickle +import numpy as np +import argparse + +from npu_bridge.estimator import npu_ops +from tensorflow.core.protobuf.rewriter_config_pb2 import RewriterConfig +# import moxing as mox +import precision_tool.tf_config as npu_tf_config +import os +os.environ['TF_CPP_MIN_VLOG_LEVEL'] = '3' +from npu_bridge.npu_init import * +###################### +from npu_bridge.estimator.npu.npu_config import NPURunConfig +from npu_bridge.estimator.npu.npu_config import ProfilingConfig + +def parse_args(): + parser = argparse.ArgumentParser() + # parser.add_argument('--model_path', type=str, default='', help='Pretrained model location') + parser.add_argument('--data_path', type=str, default='./datasets', help='Datasets location') + parser.add_argument('--output_path', type=str, default='./output', help='Output location,saving trained models') + parser.add_argument('--learning_rate', type=float, default=0.001, help='learning rate') + parser.add_argument('--batch_size', type=int, default=4, help='learning rate') + return parser.parse_args() + +args = parse_args() + + + +MODEL_CACHE_PATH=args.output_path +PRETRAINED_MODEL_PATH= os.path.join(args.data_path,"model") +HPARAMS = { + "batch_size": 4, + "image_size": 384, + 'learning_rate': 0.001, +} +DATA_CACHE_PATH= args.data_path +image_size = HPARAMS['image_size'] +batch_size = HPARAMS['batch_size'] + +def read_data(filename, training): + with open(filename, 'rb') as fo: + dict = pickle.load(fo, encoding='bytes') + if training: + images = dict[b'data'].reshape([50000, 3, 32, 32]) + else: + images = dict[b'data'].reshape([10000, 3, 32, 32]) + images = np.transpose(images, [0, 2, 3, 1]) + labels = np.array(dict[b'fine_labels']) + def _augment(image, label): + if np.random.rand() < 0.3: + image = tf.image.flip_left_right(image) + if np.random.rand() < 0.3: + image = tf.image.flip_up_down(image) + if np.random.rand() < 0.3: + image = tf.image.random_contrast(image, lower=0.5, upper=2) + return image, label + + def _preprocess(image, label): + image = tf.image.resize(image, (image_size, image_size)) + image = (image - 127.5) / 127.5 + return image, label + + ds = tf.data.Dataset.from_tensor_slices((images, labels)) + if training: + # ds = ds.map(_augment) + ds = ds.map(_preprocess) + ds = ds.shuffle(HPARAMS['batch_size'] * 10) + ds = ds.repeat() + else: + ds = ds.map(_preprocess) + ds = ds.repeat() + + ds = ds.batch(batch_size=HPARAMS['batch_size'], drop_remainder=True) + iterator = tf.compat.v1.data.make_one_shot_iterator(ds) + image_batch, label_batch = iterator.get_next() + print("load dataset =================================") + return image_batch, label_batch + + +model = vit.vit_b16_load_pretrain( + image_size=HPARAMS['image_size'], + activation='linear', + pretrained=True, + classes=100, + include_top=True, + pretrained_top=True, + pretrained_path="./" +) + +images_batch, labels_batch = read_data(filename=os.path.join(DATA_CACHE_PATH,"train"), training=True) +val_image_batch, val_labels_batch = read_data(filename=os.path.join(DATA_CACHE_PATH,"test"), training=False) + +loss_fun = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True) + +inputx = tf.compat.v1.placeholder( + tf.float32, shape=[HPARAMS['batch_size'], HPARAMS['image_size'], HPARAMS['image_size'], 3], name="inputx") + +inputy = tf.compat.v1.placeholder( + tf.int64, shape=[HPARAMS['batch_size'], ], name="inputy") + +inputTrain = tf.compat.v1.placeholder( + tf.bool, name='training') + + +def eval(pred, label): + prediction = np.argmax(pred, 1).tolist() + return calc(prediction, label) + + +def calc(prediction, label): + a = [prediction[i] == label[i] for i in range(len(prediction))] + return sum(a) / len(a) + + +out = model(inputx, training=inputTrain) +loss = loss_fun(inputy, out) + +optimizer = tf.train.MomentumOptimizer( + learning_rate=HPARAMS['learning_rate'], + momentum=0.9, + use_locking=False, + use_nesterov=False, + name='Momentum' +) + + + +loss_scale_manager = FixedLossScaleManager(loss_scale=2**32) + +opt = NPULossScaleOptimizer(optimizer, loss_scale_manager) + + +train_op = opt.minimize(loss) + + +config = tf.ConfigProto() +custom_op = config.graph_options.rewrite_options.custom_optimizers.add() +custom_op.name = "NpuOptimizer" +custom_op.parameter_map["use_off_line"].b = True # 在昇腾AI处理器执行训练 +custom_op.parameter_map["precision_mode"].s=tf.compat.as_bytes("allow_mix_precision") + +config.graph_options.rewrite_options.remapping = RewriterConfig.OFF # 关闭remap开关 +config.gpu_options.allow_growth = True +# 混合训练 +custom_op.parameter_map["precision_mode"].s = tf.compat.as_bytes("allow_mix_precision") + +session_config = npu_tf_config.session_dump_config(config, action='overflow|fusion_off') # 新增行 + + +sess = tf.Session(config=session_config) +sess.run(tf.global_variables_initializer()) + + +saver = tf.train.Saver(max_to_keep=10) +s = time.time() +print("============ start load pretrained model =======================================") +saver.restore(sess, "{}/vit-base-5".format(PRETRAINED_MODEL_PATH)) # 0.8709 for 5 # 2 0.8719 # 3 0.8767 +print("============ load success {:.4f} =====================".format(time.time() - s)) + +for epoch in range(1, 2): + # train + label_col = [] + pred_col = [] + for step in range(HPARAMS['batch_size']*10 // HPARAMS['batch_size']): + s = time.time() + x_in, y_in = sess.run([images_batch, labels_batch], + feed_dict={inputTrain: True}) + out_, loss_, _ = sess.run([out, loss, train_op], feed_dict={ + inputx: x_in, inputy: y_in, inputTrain: True}) + label_col += y_in.tolist() + pred_col += np.argmax(out_, 1).tolist() + print("epoch:{} step: {} , loss: {:.4f} , time: {:.4f} acc: {:.4f}".format( + epoch, step, loss_.item(), time.time() - s, eval(out_, y_in))) # print 到文件里面 + print("Train ACC: {:.4f}".format(calc(pred_col, label_col))) + saver.save(sess, "{}/vit-base-5fusion-mix2".format(MODEL_CACHE_PATH), global_step=epoch) + # break + prediction = [] + labels = [] + for _ in range(10000 // HPARAMS['batch_size']): + x_in, y_in = sess.run([val_image_batch, val_labels_batch]) + pred = sess.run(out, feed_dict={inputx: x_in, inputy: y_in, inputTrain: False}) + # pred = model.predict(x_in) + # print(calc(np.argmax(pred, 1).tolist(), y_in.tolist()), pred.shape, ) + prediction += np.argmax(pred, 1).tolist() + labels += y_in.tolist() + print( + "Final Average Distances :", + sum(prediction[i] == labels[i] for i in range(len(labels))) + / len(labels), + ) + diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__init__.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/__init__.cpython-36.pyc b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7955d764f164a49213292f0b4af1fc813e212685 Binary files /dev/null and b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/__init__.cpython-36.pyc differ diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/__init__.cpython-37.pyc b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3acb61bede29dd810e5ef9f56d1b08c8d70f738e Binary files /dev/null and b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/__init__.cpython-37.pyc differ diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/layers.cpython-36.pyc b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/layers.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..92b737741401927e836d8ae6c8dd4d80c9430dd3 Binary files /dev/null and b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/layers.cpython-36.pyc differ diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/layers.cpython-37.pyc b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/layers.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..67b06472c6c461119eccbf66d3d287bcee9f2b00 Binary files /dev/null and b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/layers.cpython-37.pyc differ diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/utils.cpython-36.pyc b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/utils.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3a52975d913da3c9ba63eea8c7cb571b1e1901b4 Binary files /dev/null and b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/utils.cpython-36.pyc differ diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/utils.cpython-37.pyc b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/utils.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c77867ec2d11cd2bb0c0600f9e2c88648e71657c Binary files /dev/null and b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/utils.cpython-37.pyc differ diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/vit.cpython-36.pyc b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/vit.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..30e6c5cd670cf3b81921fe463854eeee1a0c4a93 Binary files /dev/null and b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/vit.cpython-36.pyc differ diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/vit.cpython-37.pyc b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/vit.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a16095d88b4d2e7d563fbcd88caa60e428298f02 Binary files /dev/null and b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/__pycache__/vit.cpython-37.pyc differ diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/layers copy.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/layers copy.py new file mode 100644 index 0000000000000000000000000000000000000000..0ad2e8e075f5dc9ff669f51508b93ab9369bffe0 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/layers copy.py @@ -0,0 +1,321 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# 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. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# 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. + +# pylint: disable=arguments-differ,missing-function-docstring,missing-class-docstring,unexpected-keyword-arg,no-value-for-parameter +import tensorflow as tf +import threading +# modify record : +# remove super version : tfa . use tf.keras.activations.gelu() replace tfa.activations.gelu() + +import tensorflow.keras.backend as K + + +# 更改地方 +def swish(x, beta): + return x * K.sigmoid(beta * x) + + +def gelu(x, approximate="xxx"): + return swish(x, 1.702) + + +class CustomObjectsContext(threading.local): + + def __init__(self): + super(CustomObjectsContext, self).__init__() + self.objects = {} + self.names = {} + + +GLOBAL_CUSTOM_OBJECTS = CustomObjectsContext() + + +# @keras_export('keras.utils.register_keras_serializable') +def register_keras_serializable(package='Custom', name=None): + """Registers an object with the Keras serialization framework. + This decorator injects the decorated class or function into the Keras custom + object dictionary, so that it can be serialized and deserialized without + needing an entry in the user-provided custom object dict. It also injects a + function that Keras will call to get the object's serializable string key. + Note that to be serialized and deserialized, classes must implement the + `get_config()` method. Functions do not have this requirement. + The object will be registered under the key 'package>name' where `name`, + defaults to the object name if not passed. + Args: + package: The package that this class belongs to. + name: The name to serialize this class under in this package. If None, the + class' name will be used. + Returns: + A decorator that registers the decorated class with the passed names. + """ + + def decorator(arg): + """Registers a class with the Keras serialization framework.""" + class_name = name if name is not None else arg.__name__ + registered_name = package + '>' + class_name + + # if tf_inspect.isclass(arg) and not hasattr(arg, 'get_config'): + # raise ValueError( + # 'Cannot register a class that does not have a get_config() method.') + + if registered_name in GLOBAL_CUSTOM_OBJECTS.objects: + raise ValueError(f'{registered_name} has already been registered to ' + f'{GLOBAL_CUSTOM_OBJECTS.objects[registered_name]}') + + if arg in GLOBAL_CUSTOM_OBJECTS.names: + raise ValueError( + f'{arg} has already been registered to {GLOBAL_CUSTOM_OBJECTS.names[arg]}' + ) + GLOBAL_CUSTOM_OBJECTS.objects[registered_name] = arg + GLOBAL_CUSTOM_OBJECTS.names[arg] = registered_name + + return arg + + return decorator + + +@register_keras_serializable() +class ClassToken(tf.keras.layers.Layer): + """Append a class token to an input layer.""" + + def build(self, input_shape): + cls_init = tf.zeros_initializer() + self.hidden_size = input_shape[-1] + self.cls = tf.Variable( + name="cls", + initial_value=cls_init(shape=(1, 1, self.hidden_size), dtype="float32"), + trainable=True, + ) + + def call(self, inputs): + batch_size = tf.shape(inputs)[0] + cls_broadcasted = tf.cast( + tf.broadcast_to(self.cls, [batch_size, 1, self.hidden_size]), + dtype=inputs.dtype, + ) + return tf.concat([cls_broadcasted, inputs], 1) + + def get_config(self): + config = super().get_config() + return config + + @classmethod + def from_config(cls, config): + return cls(**config) + + +@register_keras_serializable() +class AddPositionEmbs(tf.keras.layers.Layer): + """Adds (optionally learned) positional embeddings to the inputs.""" + + def build(self, input_shape): + assert ( + len(input_shape) == 3 + ), f"Number of dimensions should be 3, got {len(input_shape)}" + self.pe = tf.Variable( + name="pos_embedding", + initial_value=tf.random_normal_initializer(stddev=0.06)( + shape=(1, input_shape[1], input_shape[2]) + ), + dtype="float32", + trainable=True, + ) + + def call(self, inputs): + return inputs + tf.cast(self.pe, dtype=inputs.dtype) + + def get_config(self): + config = super().get_config() + return config + + @classmethod + def from_config(cls, config): + return cls(**config) + + +@register_keras_serializable() +class MultiHeadSelfAttention(tf.keras.layers.Layer): + def __init__(self, *args, num_heads, **kwargs): + super().__init__(*args, **kwargs) + self.num_heads = num_heads + + def build(self, input_shape): + hidden_size = input_shape[-1] + num_heads = self.num_heads + if hidden_size % num_heads != 0: + raise ValueError( + f"embedding dimension = {hidden_size} should be divisible by number of heads = {num_heads}" + ) + self.hidden_size = hidden_size + self.projection_dim = hidden_size // num_heads + self.query_dense = tf.keras.layers.Dense(hidden_size, name="query") + self.key_dense = tf.keras.layers.Dense(hidden_size, name="key") + self.value_dense = tf.keras.layers.Dense(hidden_size, name="value") + self.combine_heads = tf.keras.layers.Dense(hidden_size, name="out") + + # pylint: disable=no-self-use + def attention(self, query, key, value): + score = tf.matmul(query, key, transpose_b=True) + dim_key = tf.cast(tf.shape(key)[-1], score.dtype) + scaled_score = score / tf.math.sqrt(dim_key) + weights = tf.nn.softmax(scaled_score, axis=-1) + output = tf.matmul(weights, value) + return output, weights + + def separate_heads(self, x, batch_size): + x = tf.reshape(x, (batch_size, -1, self.num_heads, self.projection_dim)) + return tf.transpose(x, perm=[0, 2, 1, 3]) + + def call(self, inputs): + batch_size = tf.shape(inputs)[0] + query = self.query_dense(inputs) + key = self.key_dense(inputs) + value = self.value_dense(inputs) + query = self.separate_heads(query, batch_size) + key = self.separate_heads(key, batch_size) + value = self.separate_heads(value, batch_size) + + attention, weights = self.attention(query, key, value) + attention = tf.transpose(attention, perm=[0, 2, 1, 3]) + concat_attention = tf.reshape(attention, (batch_size, -1, self.hidden_size)) + output = self.combine_heads(concat_attention) + return output, weights + + def get_config(self): + config = super().get_config() + config.update({"num_heads": self.num_heads}) + return config + + @classmethod + def from_config(cls, config): + return cls(**config) + + +# pylint: disable=too-many-instance-attributes +@register_keras_serializable() +class TransformerBlock(tf.keras.layers.Layer): + """Implements a Transformer block.""" + + def __init__(self, *args, num_heads, mlp_dim, dropout, **kwargs): + super().__init__(*args, **kwargs) + self.num_heads = num_heads + self.mlp_dim = mlp_dim + self.dropout = dropout + + def build(self, input_shape): + self.att = MultiHeadSelfAttention( + num_heads=self.num_heads, + name="MultiHeadDotProductAttention_1", + ) + ''' + self.mlpblock = tf.keras.Sequential( + [ + tf.keras.layers.Dense( + self.mlp_dim, + activation="linear", + name=f"{self.name}/Dense_0", + ), + tf.keras.layers.Lambda( + lambda x: gelu(x, approximate=False) + ) + if hasattr(tf.keras.activations, "gelu") + else tf.keras.layers.Lambda( + lambda x: gelu(x, approximate=False) + ), + tf.keras.layers.Dropout(self.dropout), + tf.keras.layers.Dense(input_shape[-1], name=f"{self.name}/Dense_1"), + tf.keras.layers.Dropout(self.dropout), + ], + name="MlpBlock_3", + ) + ''' + self.mlpblock1 = tf.keras.Sequential( + [ + tf.keras.layers.Dense( + self.mlp_dim, + activation="linear", + name=f"{self.name}/Dense_0", + ), + tf.keras.layers.Lambda( + lambda x: gelu(x, approximate=False) + ) + if hasattr(tf.keras.activations, "gelu") + else tf.keras.layers.Lambda( + lambda x: gelu(x, approximate=False) + ), + #tf.keras.layers.Dropout(self.dropout), + #tf.keras.layers.Dense(input_shape[-1], name=f"{self.name}/Dense_1"), + #tf.keras.layers.Dropout(self.dropout), + ], + name="MlpBlock_3", + ) + + self.mlpblock2 = tf.keras.Sequential( + [ + + tf.keras.layers.Dense(input_shape[-1], name=f"{self.name}/Dense_1"), + + ], + name="MlpBlock_3", + ) + self.layernorm1 = tf.keras.layers.LayerNormalization( + epsilon=1e-6, name="LayerNorm_0" + ) + self.layernorm2 = tf.keras.layers.LayerNormalization( + epsilon=1e-6, name="LayerNorm_2" + ) + self.dropout_layer = tf.keras.layers.Dropout(self.dropout) + + def call(self, inputs): + # modify + x = self.layernorm1(inputs) + x, weights = self.att(x) + #x = self.dropout_layer(x) + x = npu_ops.dropout_layer(x, 0.5) + x = x + inputs + y = self.layernorm2(x) + y = self.mlpblock_1(y) + y = npu_ops.dropout_layer(y, 0.5) + y = self.mlpblock_2(y) + y = npu_ops.dropout_layer(y, 0.5) + return x + y, weights + + def get_config(self): + config = super().get_config() + config.update( + { + "num_heads": self.num_heads, + "mlp_dim": self.mlp_dim, + "dropout": self.dropout, + } + ) + return config + + @classmethod + def from_config(cls, config): + return cls(**config) diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/layers.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/layers.py new file mode 100644 index 0000000000000000000000000000000000000000..fe33b96d39891f1606fdae5955846e43cfc33fc3 --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/layers.py @@ -0,0 +1,286 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# 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. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# 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. + +# pylint: disable=arguments-differ,missing-function-docstring,missing-class-docstring,unexpected-keyword-arg,no-value-for-parameter +import tensorflow as tf +import threading +# modify record : +# remove super version : tfa . use tf.keras.activations.gelu() replace tfa.activations.gelu() + +import tensorflow.keras.backend as K + + +# 更改地方 +def swish(x, beta): + return x * K.sigmoid(beta * x) + + +def gelu(x, approximate="xxx"): + return swish(x, 1.702) + + +class CustomObjectsContext(threading.local): + + def __init__(self): + super(CustomObjectsContext, self).__init__() + self.objects = {} + self.names = {} + + +GLOBAL_CUSTOM_OBJECTS = CustomObjectsContext() + + +# @keras_export('keras.utils.register_keras_serializable') +def register_keras_serializable(package='Custom', name=None): + """Registers an object with the Keras serialization framework. + This decorator injects the decorated class or function into the Keras custom + object dictionary, so that it can be serialized and deserialized without + needing an entry in the user-provided custom object dict. It also injects a + function that Keras will call to get the object's serializable string key. + Note that to be serialized and deserialized, classes must implement the + `get_config()` method. Functions do not have this requirement. + The object will be registered under the key 'package>name' where `name`, + defaults to the object name if not passed. + Args: + package: The package that this class belongs to. + name: The name to serialize this class under in this package. If None, the + class' name will be used. + Returns: + A decorator that registers the decorated class with the passed names. + """ + + def decorator(arg): + """Registers a class with the Keras serialization framework.""" + class_name = name if name is not None else arg.__name__ + registered_name = package + '>' + class_name + + # if tf_inspect.isclass(arg) and not hasattr(arg, 'get_config'): + # raise ValueError( + # 'Cannot register a class that does not have a get_config() method.') + + if registered_name in GLOBAL_CUSTOM_OBJECTS.objects: + raise ValueError(f'{registered_name} has already been registered to ' + f'{GLOBAL_CUSTOM_OBJECTS.objects[registered_name]}') + + if arg in GLOBAL_CUSTOM_OBJECTS.names: + raise ValueError( + f'{arg} has already been registered to {GLOBAL_CUSTOM_OBJECTS.names[arg]}' + ) + GLOBAL_CUSTOM_OBJECTS.objects[registered_name] = arg + GLOBAL_CUSTOM_OBJECTS.names[arg] = registered_name + + return arg + + return decorator + + +@register_keras_serializable() +class ClassToken(tf.keras.layers.Layer): + """Append a class token to an input layer.""" + + def build(self, input_shape): + cls_init = tf.zeros_initializer() + self.hidden_size = input_shape[-1] + self.cls = tf.Variable( + name="cls", + initial_value=cls_init(shape=(1, 1, self.hidden_size), dtype="float32"), + trainable=True, + ) + + def call(self, inputs): + batch_size = tf.shape(inputs)[0] + cls_broadcasted = tf.cast( + tf.broadcast_to(self.cls, [batch_size, 1, self.hidden_size]), + dtype=inputs.dtype, + ) + return tf.concat([cls_broadcasted, inputs], 1) + + def get_config(self): + config = super().get_config() + return config + + @classmethod + def from_config(cls, config): + return cls(**config) + + +@register_keras_serializable() +class AddPositionEmbs(tf.keras.layers.Layer): + """Adds (optionally learned) positional embeddings to the inputs.""" + + def build(self, input_shape): + assert ( + len(input_shape) == 3 + ), f"Number of dimensions should be 3, got {len(input_shape)}" + self.pe = tf.Variable( + name="pos_embedding", + initial_value=tf.random_normal_initializer(stddev=0.06)( + shape=(1, input_shape[1], input_shape[2]) + ), + dtype="float32", + trainable=True, + ) + + def call(self, inputs): + return inputs + tf.cast(self.pe, dtype=inputs.dtype) + + def get_config(self): + config = super().get_config() + return config + + @classmethod + def from_config(cls, config): + return cls(**config) + + +@register_keras_serializable() +class MultiHeadSelfAttention(tf.keras.layers.Layer): + def __init__(self, *args, num_heads, **kwargs): + super().__init__(*args, **kwargs) + self.num_heads = num_heads + + def build(self, input_shape): + hidden_size = input_shape[-1] + num_heads = self.num_heads + if hidden_size % num_heads != 0: + raise ValueError( + f"embedding dimension = {hidden_size} should be divisible by number of heads = {num_heads}" + ) + self.hidden_size = hidden_size + self.projection_dim = hidden_size // num_heads + self.query_dense = tf.keras.layers.Dense(hidden_size, name="query") + self.key_dense = tf.keras.layers.Dense(hidden_size, name="key") + self.value_dense = tf.keras.layers.Dense(hidden_size, name="value") + self.combine_heads = tf.keras.layers.Dense(hidden_size, name="out") + + # pylint: disable=no-self-use + def attention(self, query, key, value): + score = tf.matmul(query, key, transpose_b=True) + dim_key = tf.cast(tf.shape(key)[-1], score.dtype) + scaled_score = score / tf.math.sqrt(dim_key) + weights = tf.nn.softmax(scaled_score, axis=-1) + output = tf.matmul(weights, value) + return output, weights + + def separate_heads(self, x, batch_size): + x = tf.reshape(x, (batch_size, -1, self.num_heads, self.projection_dim)) + return tf.transpose(x, perm=[0, 2, 1, 3]) + + def call(self, inputs): + batch_size = tf.shape(inputs)[0] + query = self.query_dense(inputs) + key = self.key_dense(inputs) + value = self.value_dense(inputs) + query = self.separate_heads(query, batch_size) + key = self.separate_heads(key, batch_size) + value = self.separate_heads(value, batch_size) + + attention, weights = self.attention(query, key, value) + attention = tf.transpose(attention, perm=[0, 2, 1, 3]) + concat_attention = tf.reshape(attention, (batch_size, -1, self.hidden_size)) + output = self.combine_heads(concat_attention) + return output, weights + + def get_config(self): + config = super().get_config() + config.update({"num_heads": self.num_heads}) + return config + + @classmethod + def from_config(cls, config): + return cls(**config) + + +# pylint: disable=too-many-instance-attributes +@register_keras_serializable() +class TransformerBlock(tf.keras.layers.Layer): + """Implements a Transformer block.""" + + def __init__(self, *args, num_heads, mlp_dim, dropout, **kwargs): + super().__init__(*args, **kwargs) + self.num_heads = num_heads + self.mlp_dim = mlp_dim + self.dropout = dropout + + def build(self, input_shape): + self.att = MultiHeadSelfAttention( + num_heads=self.num_heads, + name="MultiHeadDotProductAttention_1", + ) + self.mlpblock = tf.keras.Sequential( + [ + tf.keras.layers.Dense( + self.mlp_dim, + activation="linear", + name=f"{self.name}/Dense_0", + ), + tf.keras.layers.Lambda( + lambda x: gelu(x, approximate=False) + ) + if hasattr(tf.keras.activations, "gelu") + else tf.keras.layers.Lambda( + lambda x: gelu(x, approximate=False) + ), + tf.keras.layers.Dropout(self.dropout), + tf.keras.layers.Dense(input_shape[-1], name=f"{self.name}/Dense_1"), + tf.keras.layers.Dropout(self.dropout), + ], + name="MlpBlock_3", + ) + self.layernorm1 = tf.keras.layers.LayerNormalization( + epsilon=1e-6, name="LayerNorm_0" + ) + self.layernorm2 = tf.keras.layers.LayerNormalization( + epsilon=1e-6, name="LayerNorm_2" + ) + self.dropout_layer = tf.keras.layers.Dropout(self.dropout) + + def call(self, inputs): + # modify + x = self.layernorm1(inputs) + x, weights = self.att(x) + x = self.dropout_layer(x) + x = x + inputs + y = self.layernorm2(x) + y = self.mlpblock(y) + return x + y, weights + + def get_config(self): + config = super().get_config() + config.update( + { + "num_heads": self.num_heads, + "mlp_dim": self.mlp_dim, + "dropout": self.dropout, + } + ) + return config + + @classmethod + def from_config(cls, config): + return cls(**config) diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/utils.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..0eebe5647b88115e721ebd234d82e2f7e3fb2c1d --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/utils.py @@ -0,0 +1,366 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# 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. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# 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. + +import os +import typing +import warnings +from urllib import request +from http import client +import io +import pkg_resources +# import validators +import numpy as np +import scipy as sp +import cv2 +from tqdm import tqdm +try: + import PIL + import PIL.Image +except ImportError: # pragma: no cover + PIL = None + +ImageInputType = typing.Union[str, np.ndarray, "PIL.Image.Image", io.BytesIO] + + +def get_imagenet_classes() -> typing.List[str]: + """Get the list of ImageNet 2012 classes.""" + filepath = pkg_resources.resource_filename("vit_keras", "imagenet2012.txt") + with open(filepath) as f: + classes = [l.strip() for l in f.readlines()] + return classes + + +def read(filepath_or_buffer: ImageInputType, size, timeout=None): + """Read a file into an image object + Args: + filepath_or_buffer: The path to the file or any object + with a `read` method (such as `io.BytesIO`) + size: The size to resize the image to. + timeout: If filepath_or_buffer is a URL, the timeout to + use for making the HTTP request. + """ + if PIL is not None and isinstance(filepath_or_buffer, PIL.Image.Image): + return np.array(filepath_or_buffer.convert("RGB")) + if isinstance(filepath_or_buffer, (io.BytesIO, client.HTTPResponse)): + image = np.asarray(bytearray(filepath_or_buffer.read()), dtype=np.uint8) + image = cv2.imdecode(image, cv2.IMREAD_UNCHANGED) + elif isinstance(filepath_or_buffer, str) :#and validators.url(filepath_or_buffer) + with request.urlopen(filepath_or_buffer, timeout=timeout) as r: + return read(r, size=size) + else: + if not os.path.isfile(filepath_or_buffer): + raise FileNotFoundError( + "Could not find image at path: " + filepath_or_buffer + ) + image = cv2.imread(filepath_or_buffer) + if image is None: + raise ValueError(f"An error occurred reading {filepath_or_buffer}.") + # We use cvtColor here instead of just ret[..., ::-1] + # in order to ensure that we provide a contiguous + # array for later processing. Some hashers use ctypes + # to pass the array and non-contiguous arrays can lead + # to erroneous results. + image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) + return cv2.resize(image, (size, size)) + + +def apply_embedding_weights(target_layer, source_weights, num_x_patches, num_y_patches): + """Apply embedding weights to a target layer. + + Args: + target_layer: The target layer to which weights will + be applied. + source_weights: The source weights, which will be + resized as necessary. + num_x_patches: Number of patches in width of image. + num_y_patches: Number of patches in height of image. + """ + expected_shape = target_layer.weights[0].shape + if expected_shape != source_weights.shape: + warnings.warn( + "expected_shape and source_weight.shape not matched. expected_shape: {} souce_weights: {}".format(expected_shape,source_weights.shape), + UserWarning, + ) + target_layer.set_weights([source_weights]) + +def apply_embedding_weights_customized(target_layer, source_weights, num_x_patches, num_y_patches): + """Apply embedding weights to a target layer. + + Args: + target_layer: The target layer to which weights will + be applied. + source_weights: The source weights, which will be + resized as necessary. + num_x_patches: Number of patches in width of image. + num_y_patches: Number of patches in height of image. + """ + expected_shape = target_layer.weights[0].shape + if expected_shape != source_weights.shape: + ValueError("error") + target_layer.set_weights([source_weights]) + + +def load_weights_numpy_customized( + model, params_path, pretrained_top, num_x_patches, num_y_patches +): + """Load weights saved using Flax as a numpy array. + + Args: + model: A Keras model to load the weights into. + params_path: Filepath to a numpy archive. + pretrained_top: Whether to load the top layer weights. + num_x_patches: Number of patches in width of image. + num_y_patches: Number of patches in height of image. + """ + params_dict = np.load( + params_path, allow_pickle=False + ) # pylint: disable=unexpected-keyword-arg + pre_logits = any(l.name == "pre_logits" for l in model.layers) + source_keys = list(params_dict.keys()) + n_transformers = len( + set( + "/".join(k.split("/")[:2]) + for k in source_keys + if k.startswith("Transformer/encoderblock_") + ) + ) # equal with 12 + n_transformers_out = sum( + l.name.startswith("Transformer/encoderblock_") for l in model.layers + ) + matches = [] + for tidx in range(n_transformers): # each transformer layer content + encoder = model.get_layer(f"Transformer/encoderblock_{tidx}") + source_prefix = f"Transformer/encoderblock_{tidx}" + matches.extend( + [ + { + "layer": layer, + "keys": [ + f"{source_prefix}/{norm}/{name}" for name in ["scale", "bias"] + ], + } + for norm, layer in [ + ("LayerNorm_0", encoder.layernorm1), + ("LayerNorm_2", encoder.layernorm2), + ] + ] + + [ + { + "layer": encoder.mlpblock.get_layer( + f"{source_prefix}/Dense_{mlpdense}" + ), + "keys": [ + f"{source_prefix}/MlpBlock_3/Dense_{mlpdense}/{name}" + for name in ["kernel", "bias"] + ], + } + for mlpdense in [0, 1] + ] + + [ + { + "layer": layer, + "keys": [ + f"{source_prefix}/MultiHeadDotProductAttention_1/{attvar}/{name}" + for name in ["kernel", "bias"] + ], + "reshape": True, + } + for attvar, layer in [ + ("query", encoder.att.query_dense), + ("key", encoder.att.key_dense), + ("value", encoder.att.value_dense), + ("out", encoder.att.combine_heads), + ] + ] + ) + + for layer_name in ["embedding", "head", "pre_logits"]: + if layer_name == "head" and not pretrained_top: + matches.extend(["head/kernel", "head/bias"]) + continue + if layer_name == "pre_logits" and not pre_logits: + continue + matches.append( + { + "layer": model.get_layer(layer_name), + "keys": [f"{layer_name}/{name}" for name in ["kernel", "bias"]], + } + ) + matches.append({"layer": model.get_layer("class_token"), "keys": ["cls"]}) + matches.append( + { + "layer": model.get_layer("Transformer/encoder_norm"), + "keys": [f"Transformer/encoder_norm/{name}" for name in ["scale", "bias"]], + } + ) + apply_embedding_weights_customized( + target_layer=model.get_layer("Transformer/posembed_input"), + source_weights=params_dict["Transformer/posembed_input/pos_embedding"], + num_x_patches=num_x_patches, + num_y_patches=num_y_patches, + ) + get = ["Transformer/posembed_input/pos_embedding"] + for match in tqdm(matches): + source_weights = [params_dict[k] for k in match["keys"]] + get.extend(match["keys"]) + if match.get("reshape", False): + source_weights = [ + source.reshape(expected.shape) + for source, expected in zip( + source_weights, match["layer"].get_weights() + ) + ] + match["layer"].set_weights(source_weights) + print("================ load done =========================") + + +def load_weights_numpy( + model, params_path, pretrained_top, num_x_patches, num_y_patches +): + """Load weights saved using Flax as a numpy array. + + Args: + model: A Keras model to load the weights into. + params_path: Filepath to a numpy archive. + pretrained_top: Whether to load the top layer weights. + num_x_patches: Number of patches in width of image. + num_y_patches: Number of patches in height of image. + """ + params_dict = np.load( + params_path, allow_pickle=False + ) # pylint: disable=unexpected-keyword-arg + source_keys = list(params_dict.keys()) + pre_logits = any(l.name == "pre_logits" for l in model.layers) + source_keys_used = [] + n_transformers = len( + set( + "/".join(k.split("/")[:2]) + for k in source_keys + if k.startswith("Transformer/encoderblock_") + ) + ) # equal with 12 + n_transformers_out = sum( + l.name.startswith("Transformer/encoderblock_") for l in model.layers + ) + assert n_transformers == n_transformers_out, ( + f"Wrong number of transformers (" + f"{n_transformers_out} in model vs. {n_transformers} in weights)." + ) + + matches = [] + for tidx in range(n_transformers): # each transformer layer content + encoder = model.get_layer(f"Transformer/encoderblock_{tidx}") + source_prefix = f"Transformer/encoderblock_{tidx}" + matches.extend( + [ + { + "layer": layer, + "keys": [ + f"{source_prefix}/{norm}/{name}" for name in ["scale", "bias"] + ], + } + for norm, layer in [ + ("LayerNorm_0", encoder.layernorm1), + ("LayerNorm_2", encoder.layernorm2), + ] + ] + + [ + { + "layer": encoder.mlpblock.get_layer( + f"{source_prefix}/Dense_{mlpdense}" + ), + "keys": [ + f"{source_prefix}/MlpBlock_3/Dense_{mlpdense}/{name}" + for name in ["kernel", "bias"] + ], + } + for mlpdense in [0, 1] + ] + + [ + { + "layer": layer, + "keys": [ + f"{source_prefix}/MultiHeadDotProductAttention_1/{attvar}/{name}" + for name in ["kernel", "bias"] + ], + "reshape": True, + } + for attvar, layer in [ + ("query", encoder.att.query_dense), + ("key", encoder.att.key_dense), + ("value", encoder.att.value_dense), + ("out", encoder.att.combine_heads), + ] + ] + ) + for layer_name in ["embedding", "head", "pre_logits"]: + if layer_name == "head" and not pretrained_top: + source_keys_used.extend(["head/kernel", "head/bias"]) + continue + if layer_name == "pre_logits" and not pre_logits: + continue + matches.append( + { + "layer": model.get_layer(layer_name), + "keys": [f"{layer_name}/{name}" for name in ["kernel", "bias"]], + } + ) + matches.append({"layer": model.get_layer("class_token"), "keys": ["cls"]}) + matches.append( + { + "layer": model.get_layer("Transformer/encoder_norm"), + "keys": [f"Transformer/encoder_norm/{name}" for name in ["scale", "bias"]], + } + ) + apply_embedding_weights( + target_layer=model.get_layer("Transformer/posembed_input"), + source_weights=params_dict["Transformer/posembed_input/pos_embedding"], + num_x_patches=num_x_patches, + num_y_patches=num_y_patches, + ) + source_keys_used.append("Transformer/posembed_input/pos_embedding") + for match in matches: + source_keys_used.extend(match["keys"]) + source_weights = [params_dict[k] for k in match["keys"]] + if match.get("reshape", False): + source_weights = [ + source.reshape(expected.shape) + for source, expected in zip( + source_weights, match["layer"].get_weights() + ) + ] + match["layer"].set_weights(source_weights) + unused = set(source_keys).difference(source_keys_used) + if unused: + warnings.warn(f"Did not use the following weights: {unused}", UserWarning) + target_keys_set = len(source_keys_used) + target_keys_all = len(model.weights) + if target_keys_set < target_keys_all: + warnings.warn( + f"Only set {target_keys_set} of {target_keys_all} weights.", UserWarning + ) diff --git a/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/vit.py b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/vit.py new file mode 100644 index 0000000000000000000000000000000000000000..45c7bb9e669825096c4506c2252eacbc0a675bdb --- /dev/null +++ b/TensorFlow/contrib/cv/VisionTransformer_ID1217_for_Tensorflow/vit_keras/vit.py @@ -0,0 +1,405 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# 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. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# 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. + +import typing +import warnings +import tensorflow as tf +import typing_extensions as tx + +from . import layers, utils + +ConfigDict = tx.TypedDict( + "ConfigDict", + { + "dropout": float, + "mlp_dim": int, + "num_heads": int, + "num_layers": int, + "hidden_size": int, + }, +) + +CONFIG_B: ConfigDict = { + "dropout": 0.1, + "mlp_dim": 3072, + "num_heads": 12, + "num_layers": 12, + "hidden_size": 768, +} + +CONFIG_L: ConfigDict = { + "dropout": 0.1, + "mlp_dim": 4096, + "num_heads": 16, + "num_layers": 24, + "hidden_size": 1024, +} + +BASE_URL = "https://github.com/faustomorales/vit-keras/releases/download/dl" +WEIGHTS = {"imagenet21k": 21_843, "imagenet21k+imagenet2012": 1_000} +SIZES = {"B_16", "B_32", "L_16", "L_32"} + +ImageSizeArg = typing.Union[typing.Tuple[int, int], int] + + +def preprocess_inputs(X): + """Preprocess images""" + return tf.keras.applications.imagenet_utils.preprocess_input( + X, data_format=None, mode="tf" + ) + + +def interpret_image_size(image_size_arg: ImageSizeArg) -> typing.Tuple[int, int]: + """Process the image_size argument whether a tuple or int.""" + if isinstance(image_size_arg, int): + return (image_size_arg, image_size_arg) + if ( + isinstance(image_size_arg, tuple) + and len(image_size_arg) == 2 + and all(map(lambda v: isinstance(v, int), image_size_arg)) + ): + return image_size_arg + raise ValueError( + f"The image_size argument must be a tuple of 2 integers or a single integer. Received: {image_size_arg}" + ) + + +def build_model( + image_size: ImageSizeArg, + patch_size: int, + num_layers: int, + hidden_size: int, + num_heads: int, + name: str, + mlp_dim: int, + classes: int, + dropout=0.1, + activation="linear", + include_top=True, + representation_size=None, + training=False, +): + """Build a ViT model. + + Args: + image_size: The size of input images. + patch_size: The size of each patch (must fit evenly in image_size) + classes: optional number of classes to classify images + into, only to be specified if `include_top` is True, and + if no `weights` argument is specified. + num_layers: The number of transformer layers to use. + hidden_size: The number of filters to use + num_heads: The number of transformer heads + mlp_dim: The number of dimensions for the MLP output in the transformers. + dropout_rate: fraction of the units to drop for dense layers. + activation: The activation to use for the final layer. + include_top: Whether to include the final classification layer. If not, + the output will have dimensions (batch_size, hidden_size). + representation_size: The size of the representation prior to the + classification layer. If None, no Dense layer is inserted. + """ + image_size_tuple = interpret_image_size(image_size) + assert (image_size_tuple[0] % patch_size == 0) and ( + image_size_tuple[1] % patch_size == 0 + ), "image_size must be a multiple of patch_size" + x = tf.keras.layers.Input(shape=(image_size_tuple[0], image_size_tuple[1], 3)) + y = tf.keras.layers.Conv2D( + filters=hidden_size, + kernel_size=patch_size, + strides=patch_size, + padding="valid", + name="embedding", + )(x) + y = tf.keras.layers.Reshape((y.shape[1] * y.shape[2], hidden_size))(y)# NONE, 576, 768 + y = layers.ClassToken(name="class_token")(y) # NONE 577 768 class only take one 1,1,768 + y = layers.AddPositionEmbs(name="Transformer/posembed_input")(y) # 577,768 + for n in range(num_layers): + y, _ = layers.TransformerBlock( + num_heads=num_heads, + mlp_dim=mlp_dim, + dropout=dropout, + name=f"Transformer/encoderblock_{n}", + )(y) # I remove the training parameter in layers.TransformerBlock + y = tf.keras.layers.LayerNormalization( + epsilon=1e-6, name="Transformer/encoder_norm" + )(y) + y = tf.keras.layers.Lambda(lambda v: v[:, 0], name="ExtractToken")(y) + if representation_size is not None: + y = tf.keras.layers.Dense( + representation_size, name="pre_logits", activation="tanh" + )(y) + if include_top: + y = tf.keras.layers.Dense(classes, name="head", activation=activation)(y) + return tf.keras.models.Model(inputs=x, outputs=y, name=name) + + +def validate_pretrained_top( + include_top: bool, pretrained: bool, classes: int, weights: str +): + """Validate that the pretrained weight configuration makes sense.""" + assert weights in WEIGHTS, f"Unexpected weights: {weights}." + expected_classes = WEIGHTS[weights] + if classes != expected_classes: + warnings.warn( + f"Can only use pretrained_top with {weights} if classes = {expected_classes}. Setting manually.", + UserWarning, + ) + assert include_top, "Can only use pretrained_top with include_top." + assert pretrained, "Can only use pretrained_top with pretrained." + return expected_classes + + +def load_pretrained( + size: str, + weights: str, + pretrained_top: bool, + model: tf.keras.models.Model, + image_size: ImageSizeArg, + patch_size: int, +): + """Load model weights for a known configuration.""" + image_size_tuple = interpret_image_size(image_size) + fname = f"ViT-{size}_{weights}.npz" + origin = f"{BASE_URL}/{fname}" + local_filepath = tf.keras.utils.get_file(fname, origin, cache_subdir="weights") + utils.load_weights_numpy( + model=model, + params_path=local_filepath, + pretrained_top=pretrained_top, + num_x_patches=image_size_tuple[1] // patch_size, + num_y_patches=image_size_tuple[0] // patch_size, + ) + +def load_pretrained_customized( + size: str, + weights: str, + pretrained_top: bool, + model: tf.keras.models.Model, + image_size: ImageSizeArg, + patch_size: int, + pretrained_path: str, +): + """Load model weights for a known configuration. Customized model weight.""" + image_size_tuple = interpret_image_size(image_size) + local_filepath = pretrained_path + utils.load_weights_numpy_customized( + model=model, + params_path=local_filepath, + pretrained_top=pretrained_top, + num_x_patches=image_size_tuple[1] // patch_size, + num_y_patches=image_size_tuple[0] // patch_size, + ) + +def vit_b16_load_pretrain( + image_size: ImageSizeArg = (224, 224), + classes=1000, + activation="linear", + include_top=True, + pretrained=True, + pretrained_top=True, + pretrained_path="", + weights="imagenet21k+imagenet2012", +): + """Build ViT-B16. All arguments passed to build_model.""" + model = build_model( + **CONFIG_B, + name="vit-b16", + patch_size=16, + image_size=image_size, + classes=classes, + activation=activation, + include_top=include_top, + representation_size=768 if weights == "imagenet21k" else None, + ) + + # load_pretrained_customized( + # size="B_16", + # weights=weights, + # model=model, + # pretrained_top=pretrained_top, + # image_size=image_size, + # patch_size=16, + # pretrained_path=pretrained_path + # ) + return model + +def vit_b16( + image_size: ImageSizeArg = (224, 224), + classes=1000, + activation="linear", + include_top=True, + pretrained=True, + pretrained_top=True, + weights="imagenet21k+imagenet2012", +): + """Build ViT-B16. All arguments passed to build_model.""" + if pretrained_top: + classes = validate_pretrained_top( + include_top=include_top, + pretrained=pretrained, + classes=classes, + weights=weights, + ) + model = build_model( + **CONFIG_B, + name="vit-b16", + patch_size=16, + image_size=image_size, + classes=classes, + activation=activation, + include_top=include_top, + representation_size=768 if weights == "imagenet21k" else None, + ) + + if pretrained: + load_pretrained( + size="B_16", + weights=weights, + model=model, + pretrained_top=pretrained_top, + image_size=image_size, + patch_size=16, + ) + return model + + +def vit_b32( + image_size: ImageSizeArg = (224, 224), + classes=1000, + activation="linear", + include_top=True, + pretrained=True, + pretrained_top=True, + weights="imagenet21k+imagenet2012", +): + """Build ViT-B32. All arguments passed to build_model.""" + if pretrained_top: + classes = validate_pretrained_top( + include_top=include_top, + pretrained=pretrained, + classes=classes, + weights=weights, + ) + model = build_model( + **CONFIG_B, + name="vit-b32", + patch_size=32, + image_size=image_size, + classes=classes, + activation=activation, + include_top=include_top, + representation_size=768 if weights == "imagenet21k" else None, + ) + if pretrained: + load_pretrained( + size="B_32", + weights=weights, + model=model, + pretrained_top=pretrained_top, + patch_size=32, + image_size=image_size, + ) + return model + + +def vit_l16( + image_size: ImageSizeArg = (384, 384), + classes=1000, + activation="linear", + include_top=True, + pretrained=True, + pretrained_top=True, + weights="imagenet21k+imagenet2012", +): + """Build ViT-L16. All arguments passed to build_model.""" + if pretrained_top: + classes = validate_pretrained_top( + include_top=include_top, + pretrained=pretrained, + classes=classes, + weights=weights, + ) + model = build_model( + **CONFIG_L, + patch_size=16, + name="vit-l16", + image_size=image_size, + classes=classes, + activation=activation, + include_top=include_top, + representation_size=1024 if weights == "imagenet21k" else None, + ) + if pretrained: + load_pretrained( + size="L_16", + weights=weights, + model=model, + pretrained_top=pretrained_top, + patch_size=16, + image_size=image_size, + ) + return model + + +def vit_l32( + image_size: ImageSizeArg = (384, 384), + classes=1000, + activation="linear", + include_top=True, + pretrained=True, + pretrained_top=True, + weights="imagenet21k+imagenet2012", +): + """Build ViT-L32. All arguments passed to build_model.""" + if pretrained_top: + classes = validate_pretrained_top( + include_top=include_top, + pretrained=pretrained, + classes=classes, + weights=weights, + ) + model = build_model( + **CONFIG_L, + patch_size=32, + name="vit-l32", + image_size=image_size, + classes=classes, + activation=activation, + include_top=include_top, + representation_size=1024 if weights == "imagenet21k" else None, + ) + if pretrained: + load_pretrained( + size="L_32", + weights=weights, + model=model, + pretrained_top=pretrained_top, + patch_size=32, + image_size=image_size, + ) + return model