From 820196749b4b8a02b9171cc9e08d92f348d0fdde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=85=A7=E5=89=91?= Date: Sun, 16 Oct 2022 14:43:51 +0000 Subject: [PATCH 01/10] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20OOD=5FID2046=5Ffor?= =?UTF-8?q?=5FACL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/.keep diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/.keep b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/.keep new file mode 100644 index 000000000..e69de29bb -- Gitee From 4b9ed3ee3738c5f8031769d82ad3482aaef82ba1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=85=A7=E5=89=91?= Date: Sun, 16 Oct 2022 14:57:39 +0000 Subject: [PATCH 02/10] =?UTF-8?q?=E6=8E=A8=E7=90=86=E6=88=90=E5=8A=9F?= =?UTF-8?q?=EF=BC=8C=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 周慧剑 --- .../contrib/cv/OOD_ID2046_for_ACL/LICENSE | 284 +++++++++ .../cv/OOD_ID2046_for_ACL/ModelZoo_level.txt | 4 + .../contrib/cv/OOD_ID2046_for_ACL/auroc.py | 69 +++ .../contrib/cv/OOD_ID2046_for_ACL/ckpt2pb.py | 106 ++++ .../cv/OOD_ID2046_for_ACL/config/om_in.sh | 1 + .../cv/OOD_ID2046_for_ACL/config/om_ood.sh | 1 + .../cv/OOD_ID2046_for_ACL/config/pb2om.sh | 8 + .../contrib/cv/OOD_ID2046_for_ACL/data2bin.py | 90 +++ .../cv/OOD_ID2046_for_ACL/generative.py | 539 ++++++++++++++++++ .../contrib/cv/OOD_ID2046_for_ACL/msame | Bin 0 -> 299480 bytes .../contrib/cv/OOD_ID2046_for_ACL/utils.py | 204 +++++++ 11 files changed, 1306 insertions(+) create mode 100644 ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/LICENSE create mode 100644 ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/ModelZoo_level.txt create mode 100644 ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/auroc.py create mode 100644 ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/ckpt2pb.py create mode 100644 ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/config/om_in.sh create mode 100644 ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/config/om_ood.sh create mode 100644 ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/config/pb2om.sh create mode 100644 ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/data2bin.py create mode 100644 ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/generative.py create mode 100644 ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/msame create mode 100644 ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/utils.py diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/LICENSE b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/LICENSE new file mode 100644 index 000000000..5ea8a5f7b --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/LICENSE @@ -0,0 +1,284 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +------------------ +Files: third_party/compute_library/... + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +------------------ +Files: ACKNOWLEDGEMENTS +LICENSE + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------ +Files: third_party/hexagon + +Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted (subject to the limitations in the +disclaimer below) provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE +GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT +HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/ModelZoo_level.txt b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/ModelZoo_level.txt new file mode 100644 index 000000000..319c4d196 --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/ModelZoo_level.txt @@ -0,0 +1,4 @@ +ModelConvert:OK +QuantStatus:OK +FuncStatus:OK +PerfStatus:OK diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/auroc.py b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/auroc.py new file mode 100644 index 000000000..f5c342609 --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/auroc.py @@ -0,0 +1,69 @@ +# coding=utf-8 +# Copyright 2022 The Google Research Authors. +# +# 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 numpy as np +import tensorflow as tf +import os + +from numpy import mean +from sklearn.metrics import roc_auc_score + +in_val_output_dir = "./log/result/in_val_result" +ood_val_output_dir ="./log/result/ood_val_result" + +def main(): + #in-distribution validation + in_val_output_file_list = [ + os.path.join(in_val_output_dir, x) + for x in tf.gfile.ListDirectory(in_val_output_dir) + if '.txt' in x + ] + + # ood validation + ood_val_output_file_list = [ + os.path.join(ood_val_output_dir, x) + for x in tf.gfile.ListDirectory(ood_val_output_dir) + if '.txt' in x + ] + i = 0 + auc_list = [] + while(i<100): + in_loss_i = [] + ood_loss_i = [] + with open(in_val_output_file_list[i], 'r') as f: + in_data = f.readlines() # txt中所有字符串读入data,得到的是一个list + # 对list中的数据做分隔和类型转换 + for line in in_data: + line_data = line.split() + in_loss_i = list(map(float, line_data)) + with open(ood_val_output_file_list[i], 'r') as f: + ood_data = f.readlines() # txt中所有字符串读入data,得到的是一个list + # 对list中的数据做分隔和类型转换 + for line in ood_data: + line_data = line.split() + ood_loss_i = list(map(float, line_data)) + # auc using raw likelihood, larger for OOD + neg = np.array(in_loss_i) + pos = np.array(ood_loss_i) + auc = roc_auc_score([0] * neg.shape[0] + [1] * pos.shape[0], + np.concatenate((neg, pos), axis=0)) + auc_list.append(auc) + i = i+1 + + print(mean(auc_list)) + + + +if __name__ == '__main__': + main() diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/ckpt2pb.py b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/ckpt2pb.py new file mode 100644 index 000000000..b42f3c5d0 --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/ckpt2pb.py @@ -0,0 +1,106 @@ +# coding=utf-8 +# Copyright 2022 The Google Research Authors. +# +# 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 tensorflow.python.tools import freeze_graph +from npu_bridge.estimator import npu_ops +from tensorflow.python.framework import graph_util +#from ops import * +#from data import * +#from net import * +#from utils import * +# 添加导入NPU库的头文件 +import npu_bridge +from npu_bridge.npu_init import * +from npu_bridge.estimator.npu import util +from tensorflow.core.protobuf.rewriter_config_pb2 import RewriterConfig + +from absl import flags +from tensorflow.contrib import training as contrib_training +from generative import SeqModel +from generative import load_datasets +from generative import create_out_dir + +# parameters +FLAGS = tf.app.flags.FLAGS + +flags.DEFINE_string('ckpt_path', './log/ckpt_file/model_218000.ckpt', + 'directory of ckpt') +FLAGS = tf.app.flags.FLAGS +config = tf.ConfigProto() +# keras迁移添加内容 +custom_op = config.graph_options.rewrite_options.custom_optimizers.add() +custom_op.name = "NpuOptimizer" +custom_op.parameter_map["use_off_line"].b = True +config.graph_options.rewrite_options.memory_optimization = RewriterConfig.OFF +config.graph_options.rewrite_options.remapping = RewriterConfig.OFF # 必须显示关闭remap + + +#ckpt_path = "./log/ckpt_file/model_218000.ckpt" + + +def main(): + tf.reset_default_graph() + ckpt_path = FLAGS.ckpt_path + params = contrib_training.HParams( + num_steps=FLAGS.num_steps, + val_freq=FLAGS.val_freq, + seq_len=FLAGS.seq_len, + batch_size=FLAGS.batch_size, + emb_variable=FLAGS.emb_variable, + emb_size=FLAGS.emb_size, + vocab_size=4, + hidden_lstm_size=FLAGS.hidden_lstm_size, + norm_lstm=FLAGS.norm_lstm, + dropout_rate=FLAGS.dropout_rate, + learning_rate=FLAGS.learning_rate, + reg_type=FLAGS.reg_type, + reg_weight=FLAGS.reg_weight, + out_dir=FLAGS.out_dir, + in_tr_data_dir=FLAGS.in_tr_data_dir, + in_val_data_dir=FLAGS.in_val_data_dir, + ood_val_data_dir=FLAGS.ood_val_data_dir, + master=FLAGS.master, + save_meta=FLAGS.save_meta, + filter_label=FLAGS.filter_label, + mutation_rate=FLAGS.mutation_rate, + ) + create_out_dir(params) + x_in =tf.placeholder(tf.int32,shape=[100,250],name="x_in") + y_in =tf.placeholder(tf.int32,shape=[100,],name="y_in") + model = SeqModel(params,x_in,y_in) + model.reset() + loss_i = tf.identity(model.loss_i, name='loss_i') + with tf.Session(config=config) as sess: + graph_def = tf.get_default_graph().as_graph_def(add_shapes=True) + node_list = [n.name for n in graph_def.node] + for node in node_list: + print("node_name", node) + tf.train.write_graph(sess.graph_def, './log/frozen_pb_file', 'model.pb') + freeze_graph.freeze_graph( + input_graph='./log/frozen_pb_file/model.pb', + input_saver='', + input_binary=False, + input_checkpoint=ckpt_path, + output_node_names='loss_i', + restore_op_name='save/restore_all', + filename_tensor_name='save/Const:0', + output_graph='./log/pb_file/result.pb', + clear_devices=False, + initializer_nodes='') + print("done") + + +if __name__ == '__main__': + main() diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/config/om_in.sh b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/config/om_in.sh new file mode 100644 index 000000000..d4b93c07f --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/config/om_in.sh @@ -0,0 +1 @@ +./msame --model "./log/om_file/result.om" --input "./log/bin_data/in_val_data/" --output "./log/result/" --outfmt TXT diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/config/om_ood.sh b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/config/om_ood.sh new file mode 100644 index 000000000..e58e427b0 --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/config/om_ood.sh @@ -0,0 +1 @@ +./msame --model "./log/om_file/result.om" --input "./log/bin_data/ood_val_data/" --output "./log/result/" --outfmt TXT diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/config/pb2om.sh b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/config/pb2om.sh new file mode 100644 index 000000000..12fe9e8a5 --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/config/pb2om.sh @@ -0,0 +1,8 @@ +export PATH=/usr/local/python3.7.5/bin:$PATH +export PYTHONPATH=/usr/local/Ascend/ascend-toolkit/latest/atc/python/site-packages/te:$PYTHONPATH +export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/atc/lib64:${LD_LIBRARY_PATH} + +/usr/local/Ascend/ascend-toolkit/latest/atc/bin/atc --model=./log/pb_file/result.pb --framework=3 --output=./log/om_file/result --soc_version=Ascend910 \ + --input_shape="x_in:100,250" \ + --log=info \ + --out_nodes="loss_i:0" diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/data2bin.py b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/data2bin.py new file mode 100644 index 000000000..7bce24044 --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/data2bin.py @@ -0,0 +1,90 @@ +# coding=utf-8 +# Copyright 2022 The Google Research Authors. +# +# 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 absl.app as app +import absl.flags as flags + +import numpy +import tensorflow as tf +import utils + +# in_val_data_dir = r"C:\Users\zhj\Desktop\study_files\CANN\llr_ood_genomics\between_2011-2016_in_val" +# ood_val_data_dir = r"C:\Users\zhj\Desktop\study_files\CANN\llr_ood_genomics\between_2011-2016_ood_val" +FLAGS = tf.app.flags.FLAGS +flags.DEFINE_boolean( + 'in_val_data', True, + 'False is ood_val_data, True is in_val_data') +flags.DEFINE_string('out_dir', './log/bin_data/in_val_data', + 'Directory where to write log and models.') +in_val_data_dir = r"./log/original_data/between_2011-2016_in_val" +ood_val_data_dir = r"./log/original_data/between_2011-2016_ood_val" +in_val_file_pattern = 'in_val' +ood_val_file_pattern = 'ood_val' + +def main(): + num_epoch=1 + batch_size=1 + in_val_data = FLAGS.in_val_data + out_dir = FLAGS.out_dir + #in_val_num = 999774 + #ood_val_num = 6000000 + if in_val_data: + data_dir = in_val_data_dir + file_pattern = in_val_file_pattern + else: + data_dir = ood_val_data_dir + file_pattern = ood_val_file_pattern + + data_file_list = [ + os.path.join(data_dir, x) + for x in tf.gfile.ListDirectory(data_dir) + if file_pattern in x and '.tfrecord' in x + ] + tf.logging.info('data_file_list=%s', data_file_list) + dataset = tf.data.TFRecordDataset( + data_file_list).map(lambda v: utils.parse_single_tfexample(v, v)) + + dataset = dataset.repeat(num_epoch) + dataset = dataset.batch(batch_size) # Batch size to use + iterator = dataset.make_one_shot_iterator() + features = iterator.get_next() + + val_x = [] + val_y = [] + + + i=1 + + with tf.Session() as sess: + try: + while(i<10001): + x,y = sess.run([features['x'],features['y']]) + val_x.append(x) + val_y.append(y) + if i%100==0: + val_x = numpy.array(val_x) + val_x = val_x.reshape([100, 250]) + val_y = numpy.array(val_y) + val_y = val_y.reshape([100, 1]) + val_x.tofile(os.path.join(out_dir, "{}.bin".format(i))) + val_x = [] + val_y = [] + print(i) + i = i+1 + except tf.errors.OutOfRangeError: + print(i) + +if __name__ == '__main__': + main() diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/generative.py b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/generative.py new file mode 100644 index 000000000..fe39b1a99 --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/generative.py @@ -0,0 +1,539 @@ +# coding=utf-8 +# Copyright 2022 The Google Research Authors. +# +# 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. + +r"""Build an autoregressive generative model for DNA sequences.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from npu_bridge.npu_init import * +import json +import os +import random +from absl import flags +import numpy as np +from sklearn.metrics import roc_auc_score +import tensorflow as tf +import utils +from tensorflow.contrib import rnn as contrib_rnn +from tensorflow.contrib import training as contrib_training + +import time + +# parameters +FLAGS = flags.FLAGS + +flags.DEFINE_integer('random_seed', 1234, 'The random seed') +flags.DEFINE_integer('batch_size', 100, 'The number of images in each batch.') +flags.DEFINE_integer('num_steps', 1000000, 'The number of trainig steps') +flags.DEFINE_integer('val_freq', 1000, 'How often to eval validation (# steps)') +flags.DEFINE_float('learning_rate', 0.0005, 'The learning rate') +flags.DEFINE_boolean( + 'emb_variable', False, + 'If the word embedding is variables. If not, use one-hot encoding.') +flags.DEFINE_integer('emb_size', 4, 'The word embedding dimensions') +flags.DEFINE_integer('hidden_lstm_size', 2000, + 'The number of hidden units in LSTM.') +flags.DEFINE_boolean('norm_lstm', False, + 'If turn on the layer normalization for LSTM.') +flags.DEFINE_float('dropout_rate', 0.1, 'The learning rate') +flags.DEFINE_string( + 'reg_type', 'l2', + 'l2 or l1 regularization for parameters in lstm and dense layers.') +flags.DEFINE_float( + 'reg_weight', 0.0, + 'The regularization weight for parameters in lstm and dense layers.') +flags.DEFINE_integer('seq_len', 250, 'sequence length') +flags.DEFINE_float('mutation_rate', 0.0, 'Mutation rate for data augmentation.') +flags.DEFINE_integer( + 'filter_label', -1, + ('If only sequences from the class=filter_label are used for training.' + 'if -1, no filter.')) +flags.DEFINE_string('in_tr_data_dir', '/home/test_user04/dataset/before_2011_in_tr', + 'data directory of in-distribution training') +flags.DEFINE_string('in_val_data_dir', '/home/test_user04/dataset/between_2011-2016_in_val', + 'data directory of in-distribution validation') +flags.DEFINE_string('ood_val_data_dir', '/home/test_user04/dataset/between_2011-2016_ood_val', + 'data directory of OOD validation') +flags.DEFINE_string('out_dir', '/tmp/out_generative', + 'Directory where to write log and models.') +flags.DEFINE_boolean('save_meta', False, 'Save meta graph file for each ckpt.') +flags.DEFINE_string('master', '', 'TensorFlow master to use.') + +FLAGS = flags.FLAGS + + +def create_out_dir(params): + """Setup the output directory.""" + params.in_tr_data_dir = utils.clean_last_slash_if_any(params.in_tr_data_dir) + params.in_val_data_dir = utils.clean_last_slash_if_any(params.in_val_data_dir) + params.ood_val_data_dir = utils.clean_last_slash_if_any( + params.ood_val_data_dir) + + sub_dir = ('generative_l%d_bs%d_lr%.4f' + '_hr%d_nr%s_reg%s_regw%.6f_fi%d_mt%.2f') % ( + params.seq_len, params.batch_size, params.learning_rate, + params.hidden_lstm_size, params.norm_lstm, params.reg_type, + params.reg_weight, params.filter_label, params.mutation_rate) + log_dir = os.path.join(params.out_dir, sub_dir, 'log') + params.add_hparam('log_dir_in_tr', os.path.join(log_dir, 'in_tr')) + params.add_hparam('log_dir_in_val', os.path.join(log_dir, 'in_val')) + params.add_hparam('model_dir', log_dir.replace('log', 'model')) + + if not tf.gfile.Exists(params.out_dir): + tf.gfile.MakeDirs(params.out_dir) + if not tf.gfile.Exists(params.log_dir_in_tr): + tf.gfile.MakeDirs(params.log_dir_in_tr) + if not tf.gfile.Exists(params.log_dir_in_val): + tf.gfile.MakeDirs(params.log_dir_in_val) + if not tf.gfile.Exists(params.model_dir): + tf.gfile.MakeDirs(params.model_dir) + + tf.logging.info('model_dir=%s', params.model_dir) + + +def filter_for_label(features, target_label): + """A filter for dataset to get seqs with a specific label.""" + ### TODO(jjren) not working + return tf.equal(features['y'], + tf.convert_to_tensor(target_label, dtype=tf.int32)) + + +def load_datasets(params, mode_eval=False): + """load class labels, in_tr_data, in_val_data, ood_val_data.""" + if mode_eval: # For evaluation, no need to prepare training data + in_tr_dataset = None + else: + in_tr_file_list = [ + os.path.join(params.in_tr_data_dir, x) + for x in tf.gfile.ListDirectory(params.in_tr_data_dir) + if params.in_tr_file_pattern in x + ] + + # load in-distribution training sequence + in_tr_data_file_list = [x for x in in_tr_file_list if '.tfrecord' in x] + tf.logging.info('in_tr_data_file_list=%s', in_tr_data_file_list) + + def parse_single_tfexample_addmutations_short(unused_key, v): + return utils.parse_single_tfexample_addmutations(unused_key, v, + params.mutation_rate, + params.seq_len) + + # for training a background model, we mutate input sequences + if params.mutation_rate == 0: + in_tr_dataset = tf.data.TFRecordDataset(in_tr_data_file_list).map( + lambda v: utils.parse_single_tfexample(v, v)) + else: + in_tr_dataset = tf.data.TFRecordDataset(in_tr_data_file_list).map( + lambda v: parse_single_tfexample_addmutations_short(v, v)) + + if params.filter_label != -1: + + def filter_fn(v): + return filter_for_label(v, params.filter_label) + + in_tr_dataset = in_tr_dataset.filter(filter_fn) + + # in-distribution validation + in_val_data_file_list = [ + os.path.join(params.in_val_data_dir, x) + for x in tf.gfile.ListDirectory(params.in_val_data_dir) + if params.in_val_file_pattern in x and '.tfrecord' in x + ] + tf.logging.info('in_val_data_file_list=%s', in_val_data_file_list) + in_val_dataset = tf.data.TFRecordDataset( + in_val_data_file_list).map(lambda v: utils.parse_single_tfexample(v, v)) + + # ood validation + ood_val_data_file_list = [ + os.path.join(params.ood_val_data_dir, x) + for x in tf.gfile.ListDirectory(params.ood_val_data_dir) + if params.ood_val_file_pattern in x and '.tfrecord' in x + ] + tf.logging.info('ood_val_data_file_list=%s', ood_val_data_file_list) + ood_val_dataset = tf.data.TFRecordDataset( + ood_val_data_file_list).map(lambda v: utils.parse_single_tfexample(v, v)) + + return in_tr_dataset, in_val_dataset, ood_val_dataset + + +class SeqModel(object): + """DNA sequence modeling.""" + + def __init__(self, params,x,y0): + """Create the model.""" + self._params = params + + self.x = x#tf.placeholder(tf.int32,shape=[None,250]) + self.y0 =y0#tf.placeholder(tf.int32,shape=[None]) + #self._make_dataset() + self._make_placeholders() + if self._params.emb_variable: + self._make_variables() + else: + self._one_hot_encode_x() + self._make_rnn_model() + self._make_losses() + self._make_summary_stats() + self._make_train_op() + + def _make_dataset(self): + """make data generators.""" + self.handle = tf.placeholder(tf.string, shape=[]) + self.iterator = tf.data.Iterator.from_string_handle(self.handle, { + 'x': tf.int32, + 'y': tf.int32 + }, { + 'x': [None, self._params.seq_len], + 'y': [None] + }) + features = self.iterator.get_next() + self.x, self.y0 = features['x'], features['y'] + + def _make_placeholders(self): + """Make placeholders for dropout rate.""" + self.dropout_rate = tf.placeholder_with_default( + self._params.dropout_rate, shape=(), name='dropout_rnn') + + def _make_variables(self): + """make variables.""" + # emb_size must equal to vocab_size, + # otherwise exceed vocab will be encoded as zeros + tf.logging.info('using variable dict for embedding') + self.emb_dict = tf.Variable( + tf.one_hot( + list(range(self._params.vocab_size)), depth=self._params.emb_size)) + self.x_emb = tf.nn.embedding_lookup( + self.emb_dict, tf.cast(self.x, dtype=tf.int64), name='embx') + + def _one_hot_encode_x(self): + """Make embedding layer.""" + # input for encoder + tf.logging.info('use one hot encoding') + self.x_emb = tf.one_hot( + tf.cast(self.x, dtype=tf.int64), depth=self._params.vocab_size) + tf.logging.info('shape of x_emb=%s', self.x_emb.shape) + + def _make_rnn_model(self): + """Make rnn model.""" + self.y = tf.cast(self.x[:, 1:], dtype=tf.int64) + self.y_emb = tf.one_hot(self.y, depth=self._params.emb_size) + tf.logging.info('y.shape=%s', self.y.shape) + + lstm_fw_cell_g = contrib_rnn.LayerNormBasicLSTMCell( + self._params.hidden_lstm_size, + layer_norm=self._params.norm_lstm, + dropout_keep_prob=1 - self.dropout_rate) + lstm_hidden, _ = tf.nn.dynamic_rnn( + lstm_fw_cell_g, self.x_emb, dtype=tf.float32) + # stagger two directional vectors so that the backward RNN does not reveal + # medium.com/@plusepsilon/the-bidirectional-language-model-1f3961d1fb27 + self.logits = tf.layers.dense( + lstm_hidden[:, :-1, :], + units=self._params.vocab_size, + activation=None, + name='logits') + tf.logging.info('shape of logits=%s', self.logits.shape) + + # cross entropy + self.loss_i_t = tf.nn.softmax_cross_entropy_with_logits( + labels=self.y_emb, logits=self.logits) + self.loss_i = tf.reduce_mean(self.loss_i_t, axis=1) + + def _make_losses(self): + """make loss functions.""" + self.loss = tf.reduce_mean(self.loss_i) + # l2 norm + self.variables = tf.trainable_variables() + if self._params.reg_type == 'l2': + self.loss_reg = tf.add_n( + [tf.nn.l2_loss(v) for v in self.variables if 'bias' not in v.name]) + else: + self.loss_reg = tf.add_n([ + tf.reduce_sum(tf.abs(v)) + for v in self.variables + if 'bias' not in v.name + ]) + # total loss + self.loss_total = self.loss + self._params.reg_weight * self.loss_reg + + def _make_summary_stats(self): + """make summary stats.""" + probs = tf.nn.softmax(self.logits) + pred_words = tf.argmax(probs, axis=2) + self.acc_i_t = tf.equal(pred_words, tf.cast(self.y, dtype=tf.int64)) + self.acc_i = tf.reduce_mean(tf.cast(self.acc_i_t, dtype=tf.float32), axis=1) + self.acc = tf.reduce_mean(self.acc_i) + + self.summary = tf.summary.merge([ + tf.summary.scalar('loss', self.loss), + tf.summary.scalar('acc', self.acc), + tf.summary.scalar('loss_total', self.loss_total), + tf.summary.scalar('loss_reg', self.loss_reg) + ]) + + def _make_train_op(self): + """make train op.""" + # training operations + optimizer = tf.train.AdamOptimizer(self._params.learning_rate) + grads = optimizer.compute_gradients( + self.loss_total, var_list=self.variables) + self.minimize = optimizer.apply_gradients(grads) + + def reset(self): + """prepare sess.""" + # setup session and + 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["mix_compile_mode"].b = False #关闭混合计算 + custom_op.parameter_map["precision_mode"].s = tf.compat.as_bytes("allow_mix_precision") #开启混合精度 + #custom_op.parameter_map["auto_tune_mode"].s = tf.compat.as_bytes("RL,GA") #开启Auto tune 自动调优 + #custom_op.parameter_map["customize_dtypes"].s=tf.compat.as_bytes("./customize_dtypes.cfg") + config.graph_options.rewrite_options.remapping = RewriterConfig.OFF # 必须显式关闭 + config.graph_options.rewrite_options.memory_optimization = RewriterConfig.OFF # 必须显式关闭 + self.sess = tf.Session(config=config) + self.sess.run(tf.global_variables_initializer()) + self.tr_writer = tf.summary.FileWriter(self._params.log_dir_in_tr, + self.sess.graph) + self.val_writer = tf.summary.FileWriter(self._params.log_dir_in_val, + self.sess.graph) + self.saver = tf.train.Saver(max_to_keep=500) + + + def print_log(self, str, print_time=True): + if print_time: + # localtime = time.asctime(time.localtime(time.time())) + str = time.strftime("[%m.%d.%y|%X] ", time.localtime()) + str + with open("work_dir/oodback.log", 'a') as f: + print(str, file=f) + + def train(self, in_tr_dataset, in_val_dataset, ood_val_dataset, prev_steps): + """training steps.""" + in_tr_dataset = in_tr_dataset.repeat().shuffle(1000).batch( + self._params.batch_size) + in_val_dataset = in_val_dataset.repeat().shuffle(1000).batch( + self._params.batch_size) + ood_val_dataset = ood_val_dataset.repeat().shuffle(1000).batch( + self._params.batch_size) + + in_tr_iterator = in_tr_dataset.make_one_shot_iterator() + in_val_iterator = in_val_dataset.make_one_shot_iterator() + ood_val_iterator = ood_val_dataset.make_one_shot_iterator() + + self.in_tr_handle = self.sess.run(in_tr_iterator.string_handle()) + self.in_val_handle = self.sess.run(in_val_iterator.string_handle()) + self.ood_val_handle = self.sess.run(ood_val_iterator.string_handle()) + start = 0 + end = 0 + num_steps = self._params.num_steps + for i in range(prev_steps, num_steps, 1): + print(i,"step") + start = time.time() + _, in_tr_loss, _, in_tr_acc, in_tr_summary = self.sess.run( + [self.minimize, self.loss, self.loss_i, self.acc, self.summary], + feed_dict={ + self. + self.dropout_rate: self._params.dropout_rate + }) + end = time.time() + print(end-start) + if i % self._params.val_freq == 0: + in_val_loss, in_val_loss_i, in_val_acc, in_val_summary = self.sess.run( + [self.loss, self.loss_i, self.acc, self.summary], + feed_dict={ + self.handle: self.in_val_handle, + self.dropout_rate: 0 + }) + + ood_val_loss, ood_val_loss_i, ood_val_acc, _ = self.sess.run( + [self.loss, self.loss_i, self.acc, self.summary], + feed_dict={ + self.handle: self.ood_val_handle, + self.dropout_rate: 0 + }) + + # auc using raw likelihood, larger for OOD + neg = in_val_loss_i + pos = ood_val_loss_i + auc = roc_auc_score([0] * neg.shape[0] + [1] * pos.shape[0], + np.concatenate((neg, pos), axis=0)) + + tf.logging.info( + ('i=%d \t in_tr_loss=%.4f, in_val_loss=%.4f, ood_val_loss=%.4f\n' + 'in_tr_acc=%.4f, in_val_acc=%.4f, ood_val_acc=%.4f\n' + 'auc=%.4f'), i, in_tr_loss, in_val_loss, ood_val_loss, in_tr_acc, + in_val_acc, ood_val_acc, auc) + self.print_log('i={} \t in_tr_loss={:.4f}, in_val_loss={:.4f}, ood_val_loss={:.4f}\n' + 'in_tr_acc={:.4f}, in_val_acc={:.4f}, ood_val_acc={:.4f}\n' + 'auc={:.4f}'.format(i, in_tr_loss, in_val_loss, ood_val_loss, in_tr_acc, + in_val_acc, ood_val_acc, auc)) + + _ = self.saver.save( + self.sess, + os.path.join(self._params.model_dir, 'model_{}.ckpt'.format(i)), + write_meta_graph=self._params.save_meta) # if meta file is too big + + self.tr_writer.add_summary(in_tr_summary, i) + self.tr_writer.flush() + self.val_writer.add_summary(in_val_summary, i) + self.val_writer.flush() + + auc_summary = tf.Summary() + auc_summary.value.add( + tag='AUROC_using_raw_likelihood', simple_value=auc) + self.val_writer.add_summary(auc_summary, i) + self.val_writer.flush() + + def finish(self): + tf.logging.info('training is done') + self.tr_writer.close() + self.val_writer.close() + self.saver.close() + + def restore_from_ckpt(self, ckpt_path): + """restore model from a ckpt.""" + # meta_file = ckpt_path + '.meta' + # saver = tf.train.import_meta_graph(meta_file) + self.saver.restore(self.sess, ckpt_path) + + def pred_from_ckpt(self, x_in,y_in,x_out,y_out, num_samples): + #in_val_dataset = in_val_dataset.batch(self._params.batch_size) + #ood_val_dataset = ood_val_dataset.batch(self._params.batch_size) + #in_val_iterator = in_val_dataset.make_one_shot_iterator() + #ood_val_iterator = ood_val_dataset.make_one_shot_iterator() + #self.in_val_handle = self.sess.run(in_val_iterator.string_handle()) + #self.ood_val_handle = self.sess.run(ood_val_iterator.string_handle()) + x_in = x_in.eval(session=self.sess)#np.array(x_in) + y_in = y_in.eval(session=self.sess)#np.array(y_in) + x_out = x_out.eval(session=self.sess)#np.array(x_out) + y_out = y_out.eval(session=self.sess)#np.array(y_out) + for _ in range(num_samples // self._params.batch_size): + in_val_loss, in_val_loss_i, in_val_acc, in_val_summary = self.sess.run( + [self.loss, self.loss_i, self.acc, self.summary], + feed_dict={ + self.x: x_in, + self.y0: y_in, + self.dropout_rate: self._params.dropout_rate + }) + + ood_val_loss, ood_val_loss_i, ood_val_acc, _ = self.sess.run( + [self.loss, self.loss_i, self.acc, self.summary], + feed_dict={ + self.x: x_out, + self.y0: y_out, + self.dropout_rate: self._params.dropout_rate + }) + + # auc using raw likelihood, larger for OOD + neg = in_val_loss_i + pos = ood_val_loss_i + auc = roc_auc_score([0] * neg.shape[0] + [1] * pos.shape[0], + np.concatenate((neg, pos), axis=0)) + self.print_log(' in_val_loss={:.4f}, ood_val_loss={:.4f}\n' + ' in_val_acc={:.4f}, ood_val_acc={:.4f}\n' + 'auc={:.4f}'.format( in_val_loss, ood_val_loss, in_val_acc, ood_val_acc, auc)) + + # """make prediction from a ckpt.""" + # test_dataset = test_dataset.batch(self._params.batch_size) + # test_iterator = test_dataset.make_one_shot_iterator() + # + # self.test_handle = self.sess.run(test_iterator.string_handle()) + # + # loss_test = [] + # loss_total_test = [] + # acc_test = [] + # y_test = [] + # x_test = [] + # for _ in range(num_samples // self._params.batch_size): + # out = self.sess.run( + # [self.loss_i, self.loss_total, self.acc_i, self.y0, self.y], + # feed_dict={ + # self.handle: self.test_handle, + # self.dropout_rate: 0 + # }) + # loss_test.append(out[0]) + # loss_total_test.append(out[1]) + # acc_test.append(out[2]) + # y_test.append(out[3]) + # x_test.append(out[4]) + # return loss_test, loss_total_test, acc_test, y_test, x_test + + + + + +def main(_): + + tf.logging.set_verbosity(tf.logging.INFO) + random.seed(FLAGS.random_seed) + + params = contrib_training.HParams( + num_steps=FLAGS.num_steps, + val_freq=FLAGS.val_freq, + seq_len=FLAGS.seq_len, + batch_size=FLAGS.batch_size, + emb_variable=FLAGS.emb_variable, + emb_size=FLAGS.emb_size, + vocab_size=4, + hidden_lstm_size=FLAGS.hidden_lstm_size, + norm_lstm=FLAGS.norm_lstm, + dropout_rate=FLAGS.dropout_rate, + learning_rate=FLAGS.learning_rate, + reg_type=FLAGS.reg_type, + reg_weight=FLAGS.reg_weight, + out_dir=FLAGS.out_dir, + in_tr_data_dir=FLAGS.in_tr_data_dir, + in_val_data_dir=FLAGS.in_val_data_dir, + ood_val_data_dir=FLAGS.ood_val_data_dir, + master=FLAGS.master, + save_meta=FLAGS.save_meta, + filter_label=FLAGS.filter_label, + mutation_rate=FLAGS.mutation_rate, + ) + + # setup output directory + create_out_dir(params) + + # load datasets + params.add_hparam('in_tr_file_pattern', 'in_tr') + params.add_hparam('in_val_file_pattern', 'in_val') + params.add_hparam('ood_val_file_pattern', 'ood_val') + (in_tr_dataset, in_val_dataset, ood_val_dataset) = load_datasets(params) + + # print parameter settings + tf.logging.info(params) + with tf.gfile.GFile( + os.path.join(params.model_dir, 'params.json'), mode='w') as f: + f.write(json.dumps(params.to_json(), sort_keys=True)) + + # construct model + model = SeqModel(params) + model.reset() + + ## if previous model ckpt exists, restore the model from there + tf.logging.info('model dir=%s', os.path.join(params.out_dir, '*.ckpt.index')) + prev_steps, ckpt_file = utils.get_latest_ckpt(params.model_dir) + if ckpt_file: + tf.logging.info('previous ckpt exist, prev_steps=%s', prev_steps) + model.restore_from_ckpt(ckpt_file) + + # training + model.train(in_tr_dataset, in_val_dataset, ood_val_dataset, prev_steps) + + +if __name__ == '__main__': + tf.app.run() diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/msame b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/msame new file mode 100644 index 0000000000000000000000000000000000000000..23f78bc08b510a5631f695639ade3a25c7ee85a0 GIT binary patch literal 299480 zcmb@v31C#!^*=sAqKHc(7De15Zs39e34)3SVRW#dk)=`?lll75Hi-ItZfUlylufS z!MoSl0|g8?yXn=fM{3sVHT8N;J@;Cm>;mr9?H~Kb|7M!<%ef34^(g1}{mVCm(@lGRdKqUrP((r@x7?HOmyl9p(1qY5ei5n$q2e%@)hZ@=)jeLp<;u9lzg zecFIMUc2@`QI@@c|6IFW_i|xQ&b~8uC2kY`+k*dwA9(!%rv=~qc;NCguU*)BK-=?w zzv+r~iGT0;)+MtK7t9PFS@~nT4?hyzK%2G07_w4v)=p!5b z&AVjB*P#R1=&Sb2j(-obWTU^z2Y(3^m5u%jpLWmjk@Lm9vh#TthRnwQ0XSYZe2A{+m?KJ-fmXQyA}qi6bDHvT~${crSXx7|l?gMIpY zoR5D#(k$_ed6L{CuE~KL6$84~*AN!8+iKBKO{Bj>TulK=^^ubs7=>J2X{>FX$|85^Y{KO}3 z{KdzAF80ySOFs6!$VdMxeE47MW0y00`um)ZztzEcviZ+9K6&*?pFFV8N1pwC;%) z*L~#Qg7t7V`bj==Ugd*7->1Keed6>&A35Vb^N>QHc8B};=chh#J=Vu>r}*&s)`!mu zAN(L6e>l*m-B~{Vb};Y-_%HMCNgq4j@6&FN&$uwuN1qdY=2tKH=%>j?4^w>XIM|1N zwU2&o^lA4ZANm`7`qcLdTFKJx4h`S%L!7bvJ5CN2&4kiRv+=Ld#(c!Lfcig9XK zV9&r|%N4WK6r2G$iJy6sB2IvQ`S-l=*)Pyir~DNg2)u)vL4n-@EkPHf*T)ULE00_H zwokhwjQqnhsHE z)`iP!!=Lryk%jYht)UvE4do50{@- zKYxB@?To6+D}ORN0Ca75a%Ek(wtCr&aBXGzVxkt$TQmvx;YyTLC=Du4uU|5)dS0c% z(<|%1uJY2V3WJzdzGzW(MX0(iY&gu&=0G;Ha!Flvt?(+XT2dthwPBP8msV8PgsZBT zOj$C&dJ-7SEw8xPR7ZnTmekaTPp__BT<-F8k&~A#DPLSwF}Z4S9m#=CwJ~wtyxPh- z!J{82Vy7X6_S=xB6hU$#Ys2JHUU%`7d8gM_FHRGU<)<&IE)S0yJF{ADh?!!#a(dO0 z@_U~TQR zx&^ESvRO+Y%{*nHiZ=zprIi)+VI#`vwUw2wLDE!Yi2!C(!HQizy$T+r{6VcUWC#pu zO03#Htvp<@kOW4K%Ei!fCIc#Z=CT@#u`x%=U|L-rF3krag}8ue?~Kaw+DX;*OWZcJ z#>6G_C~Zy3RoQLwG?qx2n#eRgq}w%H8h^d3Mpa3#~Zl&`7A>~6SD zD-Ngq^>I0&Q1|em0C#lA?YctRmWd1-)yEQQ;*8FrhKYR*o0LH()z@kbw+G5xaVb@% zYNu&|a$0_4*jhG9a~|o0#K~#PC?Ls|aUZSI`Vud$SheA4m5VECmSr?yQke>kAd@ES zG@;Uk&SkwcHxVB%osZOISh6pw9q`d!x{Olc5jt1uA(_{O=T#hiG#`wN4V0dD){O88 zrKJ^1myQ}WYBUmkRRvOeZPk(mQz~YJM~$jjSYBHit}U+$*G;Ji&M3z}!SWfwk{?%~ z?u_svVExFZqu_Yuh&0S(K4oU<%)-*(j1x+y|Jc9X8DmOk6qU{#RT>OZz8_lxjmsC{FErIUFc_d3P&Xq#&${B^F(`P8V9kE(UnDDr& z>N;ULhU13U&+0{W!IIOb�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

2m%LV*;*!@&S6uR1V-=UYR)*q| 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 1 + # mute the untargeted positions by multiple mask (1 for targeted) + # adding the mutations to the original, mod 4 if necessary + tf.set_random_seed(time.time()) + + def true_fn(): + """no mutations.""" + return x + + def false_fn(): + """add mutations.""" + mask = tf.cast( + tf.multinomial(tf.log([[1 - mutation_rate, mutation_rate]]), seq_len), + tf.int32)[0] + possible_mutations = tf.random_uniform([seq_len], + minval=1, + maxval=4, + dtype=tf.int32) + x_new = tf.mod(x + mask * possible_mutations, 4) + return x_new + + return tf.cond(tf.equal(mutation_rate, 0), true_fn, false_fn) + + +def parse_single_tfexample_addmutations(_, serialized_example, mutation_rate, + seq_len): + """Parsing serialized pb2 example and add mutations.""" + # read data from serialized examples + features = tf.parse_single_example( + serialized_example, + features={ + 'x': tf.FixedLenFeature([], tf.string), + 'y': tf.FixedLenFeature([], tf.int64), + # z is for sequence origins, + # i.e. which genome and which position the seq is from + # 'z': tf.VarLenFeature(tf.string) + }) + seq_str = features['x'] + + x_str0 = tf.string_split([seq_str], delimiter=' ').values + x = tf.string_to_number(x_str0, out_type=tf.int32) + + x_new = mutate_x(x, mutation_rate, seq_len) + + features['x'] = x_new + features['y'] = tf.cast(features['y'], dtype=tf.int32) + + return features + + +def compute_label_weights_using_sample_size(label_dict, label_sample_size): + """Compute weights for each class according to their sample sizes. + + Args: + label_dict: a dictionary with class labels as keys (strings) and encoded + label index as values (ints). + label_sample_size: a dictionary with class labels as keys (strings) and + sample size as values (ints). + + Returns: + label_weights: weights for labels. + """ + + # keys: encoded class labels, values: sample size + label_code_sample_size = { + label_dict[label]: label_sample_size[label] + for label in label_sample_size.keys() + } + print('label_code_sample_size={}'.format(label_code_sample_size)) + # create label weights = 1/label_sample_size + label_weights = [ + 1 / float(label_code_sample_size[idx]) + for idx in range(len(label_code_sample_size)) + ] + # label_weights = [ + # x / float(sum(label_weights0)) * len(label_weights0) / float( + # params.batch_size) for x in label_weights0 + # ] + return label_weights + + +def get_latest_ckpt(tr_model_dir): + """find previous ckpt and return the filename of the latest ckpt.""" + tf.logging.info('model dir={}'.format( + os.path.join(tr_model_dir, '*.ckpt.index'))) + list_of_ckpt = tf.gfile.Glob(os.path.join( + tr_model_dir, + '*.ckpt.index')) # * means all if need specific format then *.csv + # tf.logging.info('list_of_ckpt={}'.format(list_of_ckpt)) + if list_of_ckpt: + steps = [ + int(os.path.basename(x).split('model_')[1].split('.ckpt')[0]) + for x in list_of_ckpt + ] + prev_steps, latest_file0 = [ + (x, y) for x, y in sorted(zip(steps, list_of_ckpt), reverse=True) + ][0] + latest_file = latest_file0.replace('.index', '') + # latest_file = max(list_of_ckpt, key=os.path.getctime) does not work + tf.logging.info('previous model exists: {}'.format(latest_file)) + # prev_steps = int(latest_file.split('.')[0].split('_')[1]) + return prev_steps, latest_file.replace('.meta', '') + else: + prev_steps = 0 + return 0, None + + +def get_ckpt_at_step(tr_model_dir, step): + """find previous ckpt and return the filename of the latest ckpt.""" + tf.logging.info('model dir={}'.format( + os.path.join(tr_model_dir, '*.ckpt.index'))) + ckpt_file_pattern = os.path.join(tr_model_dir, '*_{}.ckpt.index'.format(step)) + ckpt_file = tf.gfile.Glob( + ckpt_file_pattern) # * means all if need specific format then *.csv + if ckpt_file: + return step, ckpt_file[0].replace('.index', '') + else: + tf.logging.info('Cannot find the ckpt file at step {}'.format(step)) + return step, None + + +def clean_last_slash_if_any(path): + return path[:-1] if path.endswith('/') else path + + +def generate_hparams(params_yaml_file): + """Create tf.HParams object based on params loaded from yaml file.""" + with tf.gfile.Open(params_yaml_file, mode='rb') as f: + params_json = yaml.safe_load(f) + params_dict = json.loads(params_json) + params = contrib_training.HParams() + for key, value in params_dict.items(): + params.add_hparam(key, value) + params.master = '' # should be 'local' or '' + params.dropout_rate = 0.0 # turn off dropout for eval + + return params -- Gitee From e1ef3f12b268cbbd87bdaca250bd3ea8223974b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=85=A7=E5=89=91?= Date: Sun, 16 Oct 2022 15:28:05 +0000 Subject: [PATCH 03/10] add ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/README.md. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 周慧剑 --- .../contrib/cv/OOD_ID2046_for_ACL/README.md | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/README.md diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/README.md b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/README.md new file mode 100644 index 000000000..449f2be91 --- /dev/null +++ b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/README.md @@ -0,0 +1,117 @@ +# README + +## 1、关于项目 +OOD是一个细菌检测网络,其主要特点是提出Likelihood Ratios并用以提高网络对于分布外细菌检测的准确性 + +论文: [paper](https://arxiv.org/abs/1906.02845) + +论文源代码: [code](https://github.com/google-research/google-research/tree/master/genomics_ood) + +## 2、代码结构 +``` + + +├── config +│ ├── om_in.sh #msame推理in_val_data +│ ├── om_ood.sh #msame推理ood_val_data +│ └── pb2om.sh #act命令 +├── log +│ ├── bin_data #存放转化为的bin格式的数据 +│ ├── in_val_data #分布内数据 +│ └── ood_val_data #分布外数据 +│ ├── ckpt_file #存放ckpt文件 +│ ├── frozen_pb_file #存放冻结后的pb模型 +│ ├── om_file #存放om模型 +│ ├── original_data #存放原始数据 +│ ├── between_2011-2016_in_val #分布内数据 +│ └── between_2011-2016_ood_val #分布外数据 +│ ├── pb_file #存放pb模型 +│ └── result #存放离线推理结果的文件夹 +├── auroc.py #根据推理结果计算模型最终指标AUROC +├── ckpt2pb.py #将ckpt文件转化为pb文件 +├── data2bin.py #将原始数据转化为bin格式 +├── generative.py #网络结构,用于ckpt转pb +├── LICENSE +├── modelzoo_level.txt +├── msame #msame,具体的环境需要自己编译 +├── README.md +├── requirements.txt #需要安装的第三方库文件 +└── utils.py + + +``` +## 3、关于测试集和模型 + +测试集放在./log/original_data/下。 +测试数据集和模型文件都放在百度网盘上:[百度网盘链接](链接:https://pan.baidu.com/s/1wDSn-rkcyE2Hjr6lQCxw9w?pwd=mqpt +) +提取码:mqpt +## 4、pb模型 + +原始ckpt文件下载后,放在路径log/ckpt_file/目录下,使用的是ckpt-218000。执行以下命令转换为pb模型并生成冻结后的pb模型。 + +``` +python3 ckpt2pb.py +``` +ckpt2pb.py中固定了pb模型(且用于pb转om)的输出目录:./log/pb_file/ \ +冻结后的pb模型的输出目录:./log/frozen_pb_file/ + + +## 5、生成om模型。 + +使用atc命令将pb模型转换为om模型,执行以下命令转换为om模型。 + +``` +bash ./config/pb2om.sh +``` + +注意配置对应的文件路径,soc_version默认是Ascend910 + +## 6、测试集内文件转换为bin文件 + +执行以下命令将测试集数据经过处理转换为用于网络输入的bin文件。data2bin.py文件中固定了生成bin文件存放的目录为./log/bin_data。 +测试数据集分为分布内数据(存放目录为./log/original_data/between_2011-2016_in_val)和分布外数据(存放目录为./log/original_data/between_2011-2016_in_val) +这两部分数据均包含10,000个样本,每100个样本生成一个.bin文件。 +使用如下命令转换分布内数据 +``` +python3 data2bin.py --in_val_data=True --out_dir ./log/bin_data/in_val_data +``` +使用如下命令转换分布外数据 +``` +python3 data2bin.py --in_val_data=False --out_dir ./log/bin_data/ood_val_data +``` +转换得到的bin文件分别存放于目录./log/bin_data/in_val_data(分布内数据)和./log/bin_data/ood_val_data(分布外数据) +## 7、使用om模型进行推理 + +使用msame工具进行推理。参考[msame简介](https://gitee.com/ascend/tools/tree/master/msame),参考命令如下。 +推理分布内数据 + +``` +bash config/om_in.sh +``` +推理得到结果存放在目录./log/result,注意将结果目录更名为in_val_result,否则须在auroc.py中更改文件路径 + +推理分布外数据 +``` +bash config/om_ood.sh +``` +推理得到结果存放在目录./log/result,注意将结果目录更名为ood_val_result,否则须在auroc.py中更改文件路径 +注意配置对应的文件路径 + + +## 8、om模型离线推理性能 + +每一百个样本推理的平均运行性能为858.35 ms。 + + +## 9、om模型离线推理结果对比NPU及GPU + +执行以下命令得到模型衡量指标AUROC数值 + +``` + python3 auroc.py +``` +| | 论文 | GPU | NPU | om | +|-------|------|------|------|------| +| AUROC | 0.626 | 0.677 | 0.641 | 0.665 | + -- Gitee From f0a470ea997689c88c8d031d013878a5e902445e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=85=A7=E5=89=91?= Date: Sun, 16 Oct 2022 15:29:48 +0000 Subject: [PATCH 04/10] update ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/README.md. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 周慧剑 --- ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/README.md b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/README.md index 449f2be91..bfd75b0fa 100644 --- a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/README.md +++ b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/README.md @@ -43,8 +43,7 @@ OOD是一个细菌检测网络,其主要特点是提出Likelihood Ratios并用 ## 3、关于测试集和模型 测试集放在./log/original_data/下。 -测试数据集和模型文件都放在百度网盘上:[百度网盘链接](链接:https://pan.baidu.com/s/1wDSn-rkcyE2Hjr6lQCxw9w?pwd=mqpt -) +测试数据集和模型文件都放在百度网盘上:[百度网盘链接](https://pan.baidu.com/s/1wDSn-rkcyE2Hjr6lQCxw9w?pwd=mqpt) 提取码:mqpt ## 4、pb模型 -- Gitee From 93dcbecc6900fe0e0d29b35005593d63b32bc375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=85=A7=E5=89=91?= Date: Sun, 16 Oct 2022 15:32:18 +0000 Subject: [PATCH 05/10] update ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/README.md. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 周慧剑 --- ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/README.md b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/README.md index bfd75b0fa..8a138041e 100644 --- a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/README.md +++ b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/README.md @@ -45,6 +45,7 @@ OOD是一个细菌检测网络,其主要特点是提出Likelihood Ratios并用 测试集放在./log/original_data/下。 测试数据集和模型文件都放在百度网盘上:[百度网盘链接](https://pan.baidu.com/s/1wDSn-rkcyE2Hjr6lQCxw9w?pwd=mqpt) 提取码:mqpt +百度网盘中对应目录下也包含已成功转换的pb、om等模型及bin数据文件 ## 4、pb模型 原始ckpt文件下载后,放在路径log/ckpt_file/目录下,使用的是ckpt-218000。执行以下命令转换为pb模型并生成冻结后的pb模型。 -- Gitee From f658ed0913781878546b1934ec5a7f311b0364a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=85=A7=E5=89=91?= Date: Sun, 16 Oct 2022 15:42:22 +0000 Subject: [PATCH 06/10] update ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/data2bin.py. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 周慧剑 --- ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/data2bin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/data2bin.py b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/data2bin.py index 7bce24044..e306fe6ac 100644 --- a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/data2bin.py +++ b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/data2bin.py @@ -70,7 +70,7 @@ def main(): with tf.Session() as sess: try: while(i<10001): - x,y = sess.run([features['x'],features['y']]) + x,y = sess.run([features['x'], features['y']]) val_x.append(x) val_y.append(y) if i%100==0: -- Gitee From 817aecfe61ce30e35d6acc118f64446ef21ac479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=85=A7=E5=89=91?= Date: Sun, 16 Oct 2022 15:43:37 +0000 Subject: [PATCH 07/10] update ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/ckpt2pb.py. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 周慧剑 --- ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/ckpt2pb.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/ckpt2pb.py b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/ckpt2pb.py index b42f3c5d0..23518e521 100644 --- a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/ckpt2pb.py +++ b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/ckpt2pb.py @@ -77,9 +77,9 @@ def main(): mutation_rate=FLAGS.mutation_rate, ) create_out_dir(params) - x_in =tf.placeholder(tf.int32,shape=[100,250],name="x_in") - y_in =tf.placeholder(tf.int32,shape=[100,],name="y_in") - model = SeqModel(params,x_in,y_in) + x_in =tf.placeholder(tf.int32, shape=[100, 250], name="x_in") + y_in =tf.placeholder(tf.int32, shape=[100, ], name="y_in") + model = SeqModel(params, x_in, y_in) model.reset() loss_i = tf.identity(model.loss_i, name='loss_i') with tf.Session(config=config) as sess: -- Gitee From 0789033dab640c2b60762b47dcdae1c1e9e38b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=85=A7=E5=89=91?= Date: Sun, 16 Oct 2022 15:45:03 +0000 Subject: [PATCH 08/10] update ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/generative.py. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 周慧剑 --- ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/generative.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/generative.py b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/generative.py index fe39b1a99..80851ef01 100644 --- a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/generative.py +++ b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/generative.py @@ -172,7 +172,7 @@ def load_datasets(params, mode_eval=False): class SeqModel(object): """DNA sequence modeling.""" - def __init__(self, params,x,y0): + def __init__(self, params, x, y0): """Create the model.""" self._params = params @@ -341,7 +341,7 @@ class SeqModel(object): end = 0 num_steps = self._params.num_steps for i in range(prev_steps, num_steps, 1): - print(i,"step") + print(i, "step") start = time.time() _, in_tr_loss, _, in_tr_acc, in_tr_summary = self.sess.run( [self.minimize, self.loss, self.loss_i, self.acc, self.summary], @@ -410,7 +410,7 @@ class SeqModel(object): # saver = tf.train.import_meta_graph(meta_file) self.saver.restore(self.sess, ckpt_path) - def pred_from_ckpt(self, x_in,y_in,x_out,y_out, num_samples): + def pred_from_ckpt(self, x_in, y_in, x_out, y_out, num_samples): #in_val_dataset = in_val_dataset.batch(self._params.batch_size) #ood_val_dataset = ood_val_dataset.batch(self._params.batch_size) #in_val_iterator = in_val_dataset.make_one_shot_iterator() -- Gitee From c109f45b2cda69a88ab2d3c940df738a9ae87401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=85=A7=E5=89=91?= Date: Sun, 16 Oct 2022 15:49:10 +0000 Subject: [PATCH 09/10] update ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/data2bin.py. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 周慧剑 --- ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/data2bin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/data2bin.py b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/data2bin.py index e306fe6ac..d44c3f2f7 100644 --- a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/data2bin.py +++ b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/data2bin.py @@ -70,7 +70,7 @@ def main(): with tf.Session() as sess: try: while(i<10001): - x,y = sess.run([features['x'], features['y']]) + x, y = sess.run([features['x'], features['y']]) val_x.append(x) val_y.append(y) if i%100==0: -- Gitee From 27f9bf899b3fb94f9cdba7e16db053a96dcc56b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E6=85=A7=E5=89=91?= Date: Sun, 16 Oct 2022 15:53:10 +0000 Subject: [PATCH 10/10] update ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/utils.py. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 周慧剑 --- ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/utils.py b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/utils.py index a5b18b2e0..5604632c9 100644 --- a/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/utils.py +++ b/ACL_TensorFlow/contrib/cv/OOD_ID2046_for_ACL/utils.py @@ -195,6 +195,7 @@ def generate_hparams(params_yaml_file): with tf.gfile.Open(params_yaml_file, mode='rb') as f: params_json = yaml.safe_load(f) params_dict = json.loads(params_json) + params = contrib_training.HParams() for key, value in params_dict.items(): params.add_hparam(key, value) -- Gitee