From 5e3e62344843fcb5c353104e9a215edaf60881b5 Mon Sep 17 00:00:00 2001 From: chengyujuan Date: Wed, 18 Jul 2018 13:54:34 +0800 Subject: [PATCH 01/51] add inception parse and resize op in framework --- framework/operators/resize.cpp | 91 +++++++++++ framework/operators/resize.h | 99 ++++++++++++ .../kill_caffe/caffe_layer_param_transmit.py | 14 +- .../parser/kill_caffe/parser_caffe.py | 145 ++++++++++++++++++ .../parser/operations/ops.py | 2 + 5 files changed, 350 insertions(+), 1 deletion(-) create mode 100644 framework/operators/resize.cpp create mode 100644 framework/operators/resize.h diff --git a/framework/operators/resize.cpp b/framework/operators/resize.cpp new file mode 100644 index 000000000..773f206b3 --- /dev/null +++ b/framework/operators/resize.cpp @@ -0,0 +1,91 @@ +#include "framework/operators/resize.h" + +namespace anakin { + +namespace ops { + +#define INSTANCE_RESIZE(Ttype, Dtype, Ptype) \ +template<> \ +void Resize::operator()(OpContext& ctx, \ + const std::vector >& ins,\ + std::vector >& outs) { \ + auto* impl = \ + static_cast*>(this->_helper); \ + auto& param = impl->_param_resize; \ + impl->_funcs_resize(ins, outs, param, ctx); \ +} + + +template +Status ResizeHelper::InitParam() { + DLOG(WARNING) << "Parsing Resize op parameter."; + + // get resize param + auto width_scale = GET_PARAMETER(float, width_scale); + auto height_scale = GET_PARAMETER(float, height_scale); + + ResizeParam> resize_param(height_scale, width_scale); + _param_resize = resize_param; + return Status::OK(); +} + +template +Status ResizeHelper::Init(OpContext &ctx, const std::vector> &ins, + std::vector> &outs) { + SABER_CHECK(_funcs_resize.init(ins, outs, _param_resize, SPECIFY, SABER_IMPL, ctx)); + return Status::OK(); +} + +template +Status ResizeHelper::InferShape(const std::vector> &ins, + std::vector> &outs) { + SABER_CHECK(_funcs_resize.compute_output_shape(ins, outs, _param_resize)); + return Status::OK(); +} + +#ifdef USE_CUDA +INSTANCE_RESIZE(NV, AK_FLOAT, Precision::FP32); +template <> +Status ResizeHelper::Init(OpContext &ctx, + const std::vector >& ins, + std::vector >& outs) { + SABER_CHECK(_funcs_resize.init(ins, outs, _param_resize, SPECIFY, SABER_IMPL, ctx)); + return Status::OK(); +} +ANAKIN_REGISTER_OP_HELPER(Resize, ResizeHelper, NV, AK_FLOAT, Precision::FP32); +#endif + +#ifdef USE_X86_PLACE +INSTANCE_RESIZE(X86, AK_FLOAT, Precision::FP32); +template class ResizeHelper; +ANAKIN_REGISTER_OP_HELPER(Resize, ResizeHelper, X86, AK_FLOAT, Precision::FP32); +#endif + +#ifdef USE_ARM_PLACE +INSTANCE_RESIZE(ARM, AK_FLOAT, Precision::FP32); +template class ResizeHelper; +ANAKIN_REGISTER_OP_HELPER(Resize, ResizeHelper, ARM, AK_FLOAT, Precision::FP32); +#endif//arm + +//! register op +ANAKIN_REGISTER_OP(Resize) +.Doc("Resize operator") +#ifdef USE_CUDA +.__alias__("Resize") +#endif +#ifdef USE_ARM_PLACE +.__alias__("Resize") +#endif +#ifdef USE_X86_PLACE +.__alias__("Resize") +#endif +.num_in(1) +.num_out(1) +.Args("height_scale", " height scale for resize") +.Args("width_scale", " width scale for resize"); + +} /* namespace ops */ + +} /* namespace anakin */ + + diff --git a/framework/operators/resize.h b/framework/operators/resize.h new file mode 100644 index 000000000..4d6a5a7ef --- /dev/null +++ b/framework/operators/resize.h @@ -0,0 +1,99 @@ +/* Copyright (c) 2018 Anakin Authors, Inc. 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. +*/ + +#ifndef ANAKIN_OPERATOR_RESIZE_H +#define ANAKIN_OPERATOR_RESIZE_H + +#include "framework/core/base.h" +#include "framework/core/data_types.h" +#include "framework/core/operator/operator.h" +#include "utils/logger/logger.h" +#include "saber/funcs/resize.h" + +namespace anakin { + +namespace ops { + +template +class ResizeHelper; + +/// pooling op +/** + * \brief Resize implementation class + * public inherit Operator + */ +template +class Resize : public Operator { +public: + Resize() {} + + /// forward impl + virtual void operator() (OpContext &ctx, + const std::vector >& ins, + std::vector >& outs) { + LOG(ERROR) << "Not Impl Yet Operator power::type>().type_info()<<">"; + } + + friend class ResizeHelper; +}; + +/** + * \brief Resize helper class to implement Resize + * public inherit OperatorHelper + * including init resource and shape size in Resize context + */ +template +class ResizeHelper : public OperatorHelper { +public: + ResizeHelper()=default; + + ~ResizeHelper() {} + + Status InitParam() override; + + /** + * \brief initial all the resource needed by pooling + * \param ctx stand for Resize operation context + * \param ins stand for input tensor vector + * \param outs stand for output tensor vector + * \return status + */ + Status Init(OpContext &ctx, + const std::vector >& ins, + std::vector >& outs) override; + + /** + * \brief infer the shape of output and input. + * \param ins stand for input tensor vector + * \param outs stand for output tensor vector + * \return status + */ + Status InferShape(const std::vector >& ins, + std::vector >& outs) override; + +public: + ///< _param_resize stand for Resize parameter + saber::ResizeParam> _param_resize; + ///< _funcs_resize stand for Resize function + saber::Resize _funcs_resize; + +}; + +} /* namespace ops */ + +} /* namespace anakin */ + +#endif diff --git a/tools/external_converter_v2/parser/kill_caffe/caffe_layer_param_transmit.py b/tools/external_converter_v2/parser/kill_caffe/caffe_layer_param_transmit.py index a16fdcfb9..042c9be2b 100755 --- a/tools/external_converter_v2/parser/kill_caffe/caffe_layer_param_transmit.py +++ b/tools/external_converter_v2/parser/kill_caffe/caffe_layer_param_transmit.py @@ -88,6 +88,17 @@ def Parser_concat(args): concat_param = layer.concat_param OpsRegister()["Concat"].axis = concat_param.axis +@ParserFeedDecorator("Resize") +def Parser_resize(args): + layer = args[1] + # parser caffe parameter + resize_param = layer.resize_param + if resize_param.HasField("out_width_scale"): + OpsRegister()["Resize"].width_scale = resize_param.out_width_scale + if resize_param.HasField("out_height_scale"): + OpsRegister()["Resize"].height_scale = resize_param.out_height_scale + + @ParserFeedDecorator("DeformConvolution") def Parser_deformable_convolution(args): @@ -1113,5 +1124,6 @@ def Parser_normalize(args): "PriorBox": OpsParam().set_parser(Parser_priorbox), # vis add "DetectionOutput": OpsParam().set_parser(Parser_detectionoutput), # vis add "ArgMax": OpsParam().set_parser(Parser_argmax), - "Normalize": OpsParam().set_parser(Parser_normalize) + "Normalize": OpsParam().set_parser(Parser_normalize), + "Resize": OpsParam().set_parser(Parser_resize) } diff --git a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py index f433be3db..47bf511a5 100644 --- a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py +++ b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py @@ -39,10 +39,146 @@ def _DetectionArch(self): self._ParserPrototxt() self._UpgradeNetAsNeeded() self._FilterNet() + self._SplitInception(False) self._InsertSplits() self._ScatterInputLayer() # create input node #self._CreateInputNode() maybe not need + def _SplitInception(self, is_weight): + print is_weight + net = self.net_parameter + + if is_weight: + net = self.net_param_weights + else: + print net + layers = net.layers or net.layer; + new_layers = [] + net_param = NetParameter() + blob_name_dict = {} + for idx, layer in enumerate(layers): + if layer.type != "Inception": + for b_id, blob in enumerate(layer.bottom): + if blob in blob_name_dict: + layer.bottom[b_id] = blob_name_dict[blob] + new_layers.append(layer) + if is_weight: + if (layer.type == "Slice"): + print layer + else: + for b_id, blob in enumerate(layer.bottom): + if blob in blob_name_dict: + layer.bottom[b_id] = blob_name_dict[blob] + #if is_weight: + #print layer + inception_top = layer.top + bottom_name = layer.bottom + inception_param = layer.inception_param + relu_param = inception_param.relu_param + need_relu = inception_param.need_relu + relu_at_top = inception_param.relu_at_top + columns = inception_param.inception_column + columns_top = [] + blob_id = 0 + inception = [] + blobs = layer.blobs + if len(blobs) != 0: + print "****************************************" + for b in blobs: + print "inception blob shape", b.shape + for cl_id, column in enumerate(columns): + convs = column.convolution_param + col_name = inception_top[0] + "_" + column.column_name + bottom = bottom_name[0] + for conv_id, conv in enumerate(convs): + conv_layer = net_param.layer.add() + conv_layer.type = "Convolution" + top = col_name + "_" + str(conv_id + 1) + "_conv" + conv_layer.convolution_param.CopyFrom(conv) + if conv_layer.convolution_param.HasField("kernel_size"): + conv_layer.convolution_param.pad = (conv_layer.convolution_param.kernel_size - 1) / 2 + else: + conv_layer.convolution_param.pad_h = (conv_layer.convolution_param.kernel_h - 1) / 2 + conv_layer.convolution_param.pad_w = (conv_layer.convolution_param.kernel_w - 1) / 2 + + conv_layer.top.append(top) + conv_layer.bottom.append(bottom) + conv_layer.name = top; + inception.append(conv_layer) + if len(blobs) != 0: + if conv_layer.convolution_param.bias_term: + # conv_layer.blobs.append(blobs[blob_id]) + # conv_layer.blobs.append(blobs[blob_id+1]) + blob_id += 2 + else: + # conv_layer.blobs.append(blobs[blob_id+1]) + blob_id += 1 + bottom = top + if (need_relu): + if relu_at_top: + relu_layer = net_param.layer.add() + relu_layer.type = "ReLU" + relu_layer.top.append(bottom) + relu_layer.bottom.append(bottom) + relu_layer.relu_param.CopyFrom(inception_param.relu_param) + relu_layer.name = col_name + "_" + str(conv_id + 1) + "relu"; + inception.append(relu_layer) + else: + relu_layer = net_param.layer.add() + relu_layer.type = "ReLU" + top = col_name + "_relu_" + str(conv_id) + relu_layer.name = col_name + "_" + str(conv_id + 1) + "relu"; + relu_layer.bottom.append(bottom) + relu_layer.top.append(top) + if inception_param.HasField("relu_param"): + relu_layer.relu_param.CopyFrom(inception_param.relu_param) + else: + relu_layer.relu_param = ReLUParameter() + bottom = top + inception.append(relu_layer) + + if column.HasField("pooling_param"): + pool_layer = net_param.layer.add() + pool_layer.type = "Pool" + top = col_name + "_pool" + pool_layer.name = top + pool_layer.top.append(top) + pool_layer.bottom.append(bottom) + pool_layer.pooling_param.CopyFrom(column.pooling_param) + bottom = top + inception.append(pool_layer) + columns_top.append(bottom) + if len(columns_top) > 1: + concat_layer = net_param.layer.add() + for bot in columns_top: + concat_layer.bottom.append(bot) + concat_layer.top.append(inception_top[0]) + concat_layer.type = "Concat" + concat_layer.name = top + "_concat" + inception.append(concat_layer) + bottom = inception_top[0] + else: + blob_name_dict[inception_top[0]] = bottom + + new_layers.extend(inception) + #print inception + #for com in inception: + # new_layers.append(com) + if is_weight: + if self.net_param_weights.layers: + del self.net_param_weights.layers[:] + self.net_param_weights.layers.extend(new_layers) + if self.net_param_weights.layer: + del self.net_param_weights.layer[:] + self.net_param_weights.layer.extend(new_layers) + else: + if self.net_parameter.layers: + del self.net_parameter.layers[:] + self.net_parameter.layers.extend(new_layers) + if self.net_parameter.layer: + del self.net_parameter.layer[:] + self.net_parameter.layer.extend(new_layers) + def _ParserPrototxt(self): """ @@ -51,6 +187,13 @@ def _ParserPrototxt(self): with open(self.PrototxtPath, "r") as f: text_format.Merge(f.read(), self.net_parameter) + def _ParserPrototxtWithModel(self): + """ + don't need to be used. + """ + with open(self.ModelPath, "r") as f: + self.net_parameter.MergeFromString(f.read()) + def _ParserModel(self): with open(self.ModelPath, "r") as f: self.net_param_weights.MergeFromString(f.read()) @@ -314,6 +457,7 @@ def _Parsing_new(self): # parsing model logger(verbose.ERROR).feed(" [CAFFE] Model Parameter Parsing ...") self._ParserModel() + self._SplitInception(True) model_layers = self.net_param_weights.layers or self.net_param_weights.layer # we must setting graph edge first @@ -434,6 +578,7 @@ def _Parsing(self): # parsing model logger(verbose.ERROR).feed(" [CAFFE] Model Parameter Parsing ...") self._ParserModel() + #self._SplitInception(True) model_layers = self.net_param_weights.layers or self.net_param_weights.layer for idx, rlayer in enumerate(real_layers): source_layer_name = rlayer.name diff --git a/tools/external_converter_v2/parser/operations/ops.py b/tools/external_converter_v2/parser/operations/ops.py index 5325e8cdd..5cdf639ad 100755 --- a/tools/external_converter_v2/parser/operations/ops.py +++ b/tools/external_converter_v2/parser/operations/ops.py @@ -348,3 +348,5 @@ begin_norm_axis=int(), eps=float()) +OpsRegister.Register("Resize").set_attr(height_scale=float(), + width_scale=float()) From 506ce3d8350b83090da90357398a43f3dd3f8396 Mon Sep 17 00:00:00 2001 From: chengyujuan Date: Mon, 23 Jul 2018 14:07:51 +0800 Subject: [PATCH 02/51] fix power test bug --- test/saber/cuda/test_saber_func_power.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/saber/cuda/test_saber_func_power.cpp b/test/saber/cuda/test_saber_func_power.cpp index efe837ee5..42372996b 100644 --- a/test/saber/cuda/test_saber_func_power.cpp +++ b/test/saber/cuda/test_saber_func_power.cpp @@ -135,16 +135,16 @@ TEST(TestSaberFuncPowerNV, test_func_constructor) { PowerParam param(/*power*/1.0f, /*scale*/ float(5), /*shift*/0.0f); for (auto input_share : { - false, true + false }) { for (auto output_share : { - false, true + false }) { for (auto input_share_sub : { - false, true + false }) { for (auto output_share_sub : { - false, true + false }) { for (auto get_time : { false From ce8b4d297c6f10bf0f03ccd0e81a67541babaa8a Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Wed, 29 Aug 2018 19:41:38 +0800 Subject: [PATCH 03/51] update --- tools/external_converter_v2/config.py | 1 - .../external_converter_v2/parser/graph_io.py | 19 +++++++++---------- .../parser/pbs/__init__.py | 11 +++++++---- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/tools/external_converter_v2/config.py b/tools/external_converter_v2/config.py index 74b249674..ee2ccfdbe 100644 --- a/tools/external_converter_v2/config.py +++ b/tools/external_converter_v2/config.py @@ -60,7 +60,6 @@ def __init__(self, config_file_path=ConfigFilePath): def generate_pbs_of_anakin(self): protoFilesStr = subprocess.check_output(["ls", "parser/proto/"]) - print(protoFilesStr) filesList = protoFilesStr.split('\n') protoFilesList = [] for file in filesList: diff --git a/tools/external_converter_v2/parser/graph_io.py b/tools/external_converter_v2/parser/graph_io.py index a471afa39..ba9acc70c 100644 --- a/tools/external_converter_v2/parser/graph_io.py +++ b/tools/external_converter_v2/parser/graph_io.py @@ -336,26 +336,25 @@ def rm_out(self, node_name): self.graph_proto.outs[:] = graph_outs def format_edge_from_nodes(self): - in_set=set() + in_set = set() out_set = set() for node in self.graph_proto.nodes: - name=node.name + name = node.name for node_name in node.ins: - self.add_in_edge(node_name,name) - in_set.add((node_name,name)) + self.add_in_edge(node_name, name) + in_set.add((node_name, name)) for node_name in node.outs: - self.add_out_edge(name,node_name) - out_set.add((name,node_name)) - ab_set=in_set-out_set - ba_set=out_set-in_set + self.add_out_edge(name, node_name) + out_set.add((name, node_name)) + ab_set = in_set - out_set + ba_set = out_set - in_set print(ab_set) print('------') print(ba_set) - assert len(ab_set)==0 and len(ba_set)==0,'in edge must equal with out edge' + assert len(ab_set) == 0 and len(ba_set) == 0, 'in edge must equal with out edge' def __call__(self): - return self.graph_proto diff --git a/tools/external_converter_v2/parser/pbs/__init__.py b/tools/external_converter_v2/parser/pbs/__init__.py index 40e5a387c..0eaeeff5b 100644 --- a/tools/external_converter_v2/parser/pbs/__init__.py +++ b/tools/external_converter_v2/parser/pbs/__init__.py @@ -2,8 +2,11 @@ # Copyright (c) 2017, Cuichaowen. All rights reserved. # -*- coding: utf-8 -*- -try: - from caffe_pb2 import * -except ImportError: - raise ImportError(' No module named caffe_pb2 . ') +import os +for module in os.listdir(os.path.dirname(__file__)): + if module == '__init__.py' or module[-3:] != '.py': + continue + __import__(module[:-3], locals(), globals()) + logger(verbose.WARNING).feed("Import Module: ", module) +del module From 62799267adba713aaa10a41b9318684aec171fe9 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Thu, 30 Aug 2018 20:14:11 +0800 Subject: [PATCH 04/51] go back: config.yaml --- tools/external_converter_v2/config.yaml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tools/external_converter_v2/config.yaml b/tools/external_converter_v2/config.yaml index 2c00def1d..e9486857d 100644 --- a/tools/external_converter_v2/config.yaml +++ b/tools/external_converter_v2/config.yaml @@ -40,15 +40,14 @@ ##-------------------------------------------------------------- # OPTIONS: - Framework: TENSORFLOW - SavePath: /ak_model/save/path - ResultName: resnet50_v1 - + Framework: CAFFE + SavePath: ./output + ResultName: googlenet Config: LaunchBoard: ON Server: ip: 0.0.0.0 - port: 8889 + port: 8888 OptimizedGraph: enable: OFF path: /path/to/anakin_optimized/googlenet.anakin.bin.saved @@ -77,10 +76,9 @@ TARGET: ModelPath: TENSORFLOW: - ProtoPaths: /path/to/your/model/ + ProtoPath: PrototxtPath: ModelPath: - OutPuts: ONNX: ProtoPath: From ed86bb693f9ba6c6248d2c051f8323a27435e1f7 Mon Sep 17 00:00:00 2001 From: shixiaowei02 Date: Mon, 3 Sep 2018 15:00:16 +0800 Subject: [PATCH 05/51] modify pbs init --- tools/external_converter_v2/parser/pbs/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/external_converter_v2/parser/pbs/__init__.py b/tools/external_converter_v2/parser/pbs/__init__.py index 0eaeeff5b..b6b39e318 100644 --- a/tools/external_converter_v2/parser/pbs/__init__.py +++ b/tools/external_converter_v2/parser/pbs/__init__.py @@ -3,6 +3,7 @@ # -*- coding: utf-8 -*- import os +from ..logger import * for module in os.listdir(os.path.dirname(__file__)): if module == '__init__.py' or module[-3:] != '.py': From a5c90d02ffe750c4b38820c97571cc354f539911 Mon Sep 17 00:00:00 2001 From: chengyujuan Date: Mon, 3 Sep 2018 15:42:27 +0800 Subject: [PATCH 06/51] add resize in ops --- framework/operators/ops.h | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/operators/ops.h b/framework/operators/ops.h index 046b80b37..5bd3d20e6 100644 --- a/framework/operators/ops.h +++ b/framework/operators/ops.h @@ -54,6 +54,7 @@ #include "framework/operators/priorbox.h" #include "framework/operators/relu.h" #include "framework/operators/reshape.h" +#include "framework/operators/resize.h" #include "framework/operators/scale.h" #include "framework/operators/sequence_pool.h" #include "framework/operators/slice.h" From 6debad1e8b96fe0abdb5d435fae5c4e1424b7ab8 Mon Sep 17 00:00:00 2001 From: shixiaowei02 Date: Mon, 3 Sep 2018 16:36:39 +0800 Subject: [PATCH 07/51] fix init py --- tools/external_converter_v2/parser/pbs/__init__.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tools/external_converter_v2/parser/pbs/__init__.py b/tools/external_converter_v2/parser/pbs/__init__.py index b6b39e318..fbee30db2 100644 --- a/tools/external_converter_v2/parser/pbs/__init__.py +++ b/tools/external_converter_v2/parser/pbs/__init__.py @@ -1,13 +1,20 @@ #! /usr/bin/env python # Copyright (c) 2017, Cuichaowen. All rights reserved. # -*- coding: utf-8 -*- - import os from ..logger import * +import caffe_pb2 + for module in os.listdir(os.path.dirname(__file__)): if module == '__init__.py' or module[-3:] != '.py': continue - __import__(module[:-3], locals(), globals()) - logger(verbose.WARNING).feed("Import Module: ", module) + m = __import__(module[:-3], locals(), globals()) + try: + attrlist = m.__all__ + except AttributeError: + attrlist = dir(m) + for attr in attrlist: + globals()[attr] = getattr(m, attr) + logger(verbose.INFO).feed("Import Module: ", module[:-3]) del module From 42f440da8106a544ab64b67aa3bb023a3adeb024 Mon Sep 17 00:00:00 2001 From: shixiaowei02 Date: Mon, 3 Sep 2018 16:45:11 +0800 Subject: [PATCH 08/51] add fix --- tools/external_converter_v2/parser/pbs/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/external_converter_v2/parser/pbs/__init__.py b/tools/external_converter_v2/parser/pbs/__init__.py index fbee30db2..f79d97d1c 100644 --- a/tools/external_converter_v2/parser/pbs/__init__.py +++ b/tools/external_converter_v2/parser/pbs/__init__.py @@ -4,7 +4,7 @@ import os from ..logger import * -import caffe_pb2 +#import caffe_pb2 for module in os.listdir(os.path.dirname(__file__)): if module == '__init__.py' or module[-3:] != '.py': From faf237f53eb3219e8c5b2c168904f1d43a7e891a Mon Sep 17 00:00:00 2001 From: shixiaowei02 Date: Mon, 3 Sep 2018 19:18:07 +0800 Subject: [PATCH 09/51] update caffe parser --- .../parser/kill_caffe/parser_caffe.py | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py index f83ba2557..467a2f61b 100644 --- a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py +++ b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py @@ -36,6 +36,7 @@ def __call__(self): def _DetectionArch(self): """ """ + self._InsSplitBtwSliceConcat() self._ParserPrototxt() self._UpgradeNetAsNeeded() self._FilterNet() @@ -70,7 +71,7 @@ def _UpgradeNetAsNeeded(self): logger(verbose.FATAL).feed("[ Upgrade Level 1 ] Details: need to upgrade from V0 to V1 [ FAILED ]") exit() if NetNeedsDataUpgrade(self.net_parameter): - logger(verbose.INFO).feed("[ Upgrade Level 2 ] Details: need Data upgrade [ IGNORED ]") + logger(verbose.ERROR).feed("[ Upgrade Level 2 ] Details: need Data upgrade [ IGNORED ]") if NetNeedsV1ToV2Upgrade(self.net_parameter): logger(verbose.INFO).feed("[ Upgrade Level 3 ] Details: need to upgrade from V1 to V2 [ ... ]") original_param = NetParameter() @@ -89,6 +90,31 @@ def _UpgradeNetAsNeeded(self): UpgradeNetBatchNorm(self.net_parameter) logger(verbose.INFO).feed("[ Upgrade Level 5 ] Details: need BatchNorm upgrade [ ... ]") + def _InsSplitBtwSliceConcat(self): + ''' + Currently, the connection between Slice and Concat must be implemented via Split. + ''' + param_split = NetParameter() + layers = self.net_parameter.layer or self.net_parameter.layers + top_blobs_of_slices = list() + btm_blobs_of_concats = list() + for idx, layer in enumerate(layers): + if layer.type == 'Slice': + top_blobs_of_slices.extend(layer.top) + elif layer.type == 'Concat': + btm_blobs_of_concats.extend(layer.bottom) + intersection_blobs = list(set(top_blobs_of_slices).intersection(set(btm_blobs_of_concats))) + for blob in intersection_blobs: + layer_param = param_split.layer.add() + layer_param.bottom.append(blob) + layer_param.top.append(blob) + layer_param.name = 'Split_' + blob + layer_param.type = 'Split' + if self.net_parameter.layer: + self.net_parameter.layer.extend(param_split.layer) + else: + self.net_parameter.layers.extend(param_split.layer) + def _InsertSplits(self): """ Same as caffe InsertSplits. @@ -309,10 +335,10 @@ def _Parsing_new(self): blob_top_to_layer_name[top].put(tmp_rlayer.name) # set graph proto's name self.graphIO.set_name(self.net_parameter.name) - logger(verbose.INFO).feed(" [CAFFE] Archtecture Parsing ...") + logger(verbose.ERROR).feed(" [CAFFE] Archtecture Parsing ...") # parsing model - logger(verbose.INFO).feed(" [CAFFE] Model Parameter Parsing ...") + logger(verbose.ERROR).feed(" [CAFFE] Model Parameter Parsing ...") self._ParserModel() model_layers = self.net_param_weights.layers or self.net_param_weights.layer @@ -429,10 +455,10 @@ def _Parsing(self): #blob_btm_to_layer_name[top] = tmp_rlayer.name # set graph proto's name self.graphIO.set_name(self.net_parameter.name) - logger(verbose.INFO).feed(" [CAFFE] Archtecture Parsing ...") + logger(verbose.ERROR).feed(" [CAFFE] Archtecture Parsing ...") # parsing model - logger(verbose.INFO).feed(" [CAFFE] Model Parameter Parsing ...") + logger(verbose.ERROR).feed(" [CAFFE] Model Parameter Parsing ...") self._ParserModel() model_layers = self.net_param_weights.layers or self.net_param_weights.layer for idx, rlayer in enumerate(real_layers): From 46c2da252b52576812988547b86f6bed674c8f56 Mon Sep 17 00:00:00 2001 From: shixiaowei02 Date: Mon, 3 Sep 2018 19:19:26 +0800 Subject: [PATCH 10/51] update caffe parser --- tools/external_converter_v2/parser/kill_caffe/parser_caffe.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py index 467a2f61b..899d9250a 100644 --- a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py +++ b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py @@ -96,8 +96,8 @@ def _InsSplitBtwSliceConcat(self): ''' param_split = NetParameter() layers = self.net_parameter.layer or self.net_parameter.layers - top_blobs_of_slices = list() - btm_blobs_of_concats = list() + top_blobs_of_slices = list() + btm_blobs_of_concats = list() for idx, layer in enumerate(layers): if layer.type == 'Slice': top_blobs_of_slices.extend(layer.top) From 99937792c00d0c11e9cfa777e9436f0057945bf5 Mon Sep 17 00:00:00 2001 From: chengyujuan Date: Mon, 3 Sep 2018 20:04:15 +0800 Subject: [PATCH 11/51] add load graph from buffer --- framework/graph/graph.cpp | 15 ++ framework/graph/graph.h | 5 + framework/model_parser/parser/parser.cpp | 180 +++++++++++++---------- framework/model_parser/parser/parser.h | 3 + 4 files changed, 124 insertions(+), 79 deletions(-) diff --git a/framework/graph/graph.cpp b/framework/graph/graph.cpp index f8ca3183f..8832b15ca 100644 --- a/framework/graph/graph.cpp +++ b/framework/graph/graph.cpp @@ -40,6 +40,21 @@ Status Graph::load(std::string model_path) EXCLUSIVE_LOCKS_ return ret; } +template +Status Graph::load(const char* buffer, size_t len) EXCLUSIVE_LOCKS_REQUIRED(_mut) { + std::unique_lock lock(this->_mut); + Status ret = Status::OK(); + if(len != _len || buffer != _buffer) { + this->Clean(); + ret = parser::load(this, buffer, len); + _buffer = buffer; + _len = len; + } + + return ret; +} + + template Status Graph::load(const char* model_path) { return parser::load(this, model_path); diff --git a/framework/graph/graph.h b/framework/graph/graph.h index e456a461e..5ae9dea27 100644 --- a/framework/graph/graph.h +++ b/framework/graph/graph.h @@ -71,6 +71,8 @@ class Graph : public GraphBase_mut); /// this make the graph optimized. bool _has_graph_optimized{false}; GUARDED_BY(this->_mut); + + const char* _buffer{NULL} GUARDED_BY(this->_mut); + size_t _len{0} GUARDED_BY(this->_mut); std::mutex _mut; }; diff --git a/framework/model_parser/parser/parser.cpp b/framework/model_parser/parser/parser.cpp index 540abdb4c..c0ff9ba6a 100644 --- a/framework/model_parser/parser/parser.cpp +++ b/framework/model_parser/parser/parser.cpp @@ -22,8 +22,29 @@ Status load(graph::Graph* graph, std::string& model_path) { return load(graph, model_path.c_str()); } -template -Status load(graph::Graph* graph, const char* model_path) { +Status parse_graph_proto(GraphProto& graph_proto, const char* buffer, size_t len) { + google::protobuf::io::ArrayInputStream* raw_input = new google::protobuf::io::ArrayInputStream(buffer, len); + google::protobuf::io::CodedInputStream* coded_input = new google::protobuf::io::CodedInputStream(raw_input); + coded_input->SetTotalBytesLimit(INT_MAX, 536870912); + bool success = graph_proto.ParseFromCodedStream(coded_input) && coded_input->ConsumedEntireMessage(); + if (!success) { + LOG(FATAL) << " Parsing GraphProto " << " ERROR"; + } + + delete coded_input; + delete raw_input; + return Status::OK(); +} + +Status parse_graph_proto(GraphProto& graph_proto, std::istream* instream){ + if (!graph_proto.ParseFromIstream(instream)) { + DLOG(ERROR) << "Fail to parse GraphProto."; + return Status::FAIL("Fail to parse GraphProto."); + } + return Status::OK(); +} + +Status parse_graph_proto(GraphProto& graph_proto, const char* model_path) { #if 0 std::fstream input(model_path, std::ios::in | std::ios::binary); @@ -41,7 +62,6 @@ Status load(graph::Graph* graph, const char* model_path) { } #else - GraphProto graph_proto; int file_descriptor = open(model_path, O_RDONLY); if (file_descriptor == -1) { @@ -65,7 +85,13 @@ Status load(graph::Graph* graph, const char* model_path) { delete coded_input; delete raw_input; close(file_descriptor); + return Status::OK(); #endif +} + +template +Status generate_graph_with_graph_proto(graph::Graph* graph, GraphProto& graph_proto) { + // fill the graph with name LOG(INFO) << "graph name: " << graph_proto.name(); graph->set_name(graph_proto.name()); @@ -158,87 +184,26 @@ Status load(graph::Graph* graph, const char* model_path) { } template -Status load(graph::Graph* graph, std::istream* instream) { - +Status load(graph::Graph* graph, const char* model_path) { GraphProto graph_proto; + parse_graph_proto(graph_proto, model_path); + return generate_graph_with_graph_proto(graph, graph_proto); +} - // parsing GraphProto from model - if (!graph_proto.ParseFromIstream(instream)) { - DLOG(ERROR) << "Fail to parse GraphProto."; - return Status::FAIL("Fail to parse GraphProto."); - } - - // fill the graph with name - LOG(INFO) << "graph name: " << graph_proto.name(); - graph->set_name(graph_proto.name()); - - // fill the graph with ins/outs - for (int i = 0; i < graph_proto.ins().size(); i++) { - LOG(INFO) << "graph in: " << graph_proto.ins()[i]; - std::string in_name(graph_proto.ins()[i]); - graph->add_in(in_name); - } - - for (int i = 0; i < graph_proto.outs().size(); i++) { - LOG(INFO) << "graph out: " << graph_proto.outs()[i]; - std::string out_name(graph_proto.outs()[i]); - graph->add_out(out_name); - } - - // fill the graph with nodes - NodeIO node_io; - - for (int i = 0; i < graph_proto.nodes().size(); i++) { - node_io >> graph_proto.nodes()[i]; - } - - node_io << *graph; - - // fill the graph with edges - auto it_in = graph_proto.edges_in().begin(); - - for (; it_in != graph_proto.edges_in().end(); ++it_in) { - DLOG(WARNING) << " Parsing in edges of node : " << it_in->first; - auto& key = it_in->first; - auto& second = it_in->second; - - for (int i = 0; i < second.val().size(); i++) { - //Tensor4dPtr tensor_p = std::make_shared>(); - graph::Edge edge(second.val()[i], key); - //edge.weight() = new Tensor4d(); - //edge.weight() = std::make_shared >(); - edge.shared() = (*graph_proto.mutable_edges_info())[edge.name()].shared(); - edge.share_from() = (*graph_proto.mutable_edges_info())[edge.name()].share_from(); - graph->add_in_arc(edge); - } - } - - auto it_out = graph_proto.edges_out().begin(); - - for (; it_out != graph_proto.edges_out().end(); ++it_out) { - auto& key = it_out->first; - auto& second = it_out->second; +template +Status load(graph::Graph* graph, std::istream* instream) { - for (int i = 0; i < second.val().size(); i++) { - //Tensor4dPtr tensor_p = std::make_shared>(); - graph::Edge edge(key, second.val()[i]); - //edge.weight() = new Tensor4d(); - //edge.weight() = std::make_shared >(); - edge.shared() = (*graph_proto.mutable_edges_info())[edge.name()].shared(); - edge.share_from() = (*graph_proto.mutable_edges_info())[edge.name()].share_from(); - graph->add_out_arc(edge); - } - } + GraphProto graph_proto; + parse_graph_proto(graph_proto, instream); + return generate_graph_with_graph_proto(graph, graph_proto);; +} - // fill the graph with info (only use the key value: is_optimized) - graph->statistics.template set_info(graph_proto.summary().is_optimized()); - graph->statistics.template set_info(graph_proto.summary().temp_mem_used()); - graph->statistics.template set_info - (graph_proto.summary().original_temp_mem_used()); - graph->statistics.template set_info(graph_proto.summary().system_mem_used()); - graph->statistics.template set_info(graph_proto.summary().model_mem_used()); +template +Status load(graph::Graph* graph, const char* buffer, size_t len) { - return Status::OK(); + GraphProto graph_proto; + parse_graph_proto(graph_proto, buffer, len); + return generate_graph_with_graph_proto(graph, graph_proto);; } template @@ -382,6 +347,25 @@ Status save(graph::Graph(graph::Graph* graph, const char* model_path); + +template +Status load(graph::Graph* graph, + const char* buffer, size_t len); +template +Status load(graph::Graph* graph, + const char* buffer, size_t len); +template +Status load(graph::Graph* graph, + const char* buffer, size_t len); + +template +Status generate_graph_with_graph_proto(graph::Graph* graph, GraphProto& graph_proto); + +template +Status generate_graph_with_graph_proto(graph::Graph* graph, GraphProto& graph_proto); + +template +Status generate_graph_with_graph_proto(graph::Graph* graph, GraphProto& graph_proto); #endif #if defined(USE_X86_PLACE) || defined(BUILD_LITE) @@ -434,6 +418,23 @@ Status save(graph::Graph(graph::Graph* graph, const char* model_path); + +template +Status load(graph::Graph* graph, + const char* buffer, size_t len); +template +Status load(graph::Graph* graph, + const char* buffer, size_t len); +template +Status load(graph::Graph* graph, + const char* buffer, size_t len); + +template +Status generate_graph_with_graph_proto(graph::Graph* graph, GraphProto& graph_proto); +template +Status generate_graph_with_graph_proto(graph::Graph* graph, GraphProto& graph_proto); +template +Status generate_graph_with_graph_proto(graph::Graph* graph, GraphProto& graph_proto); #endif #ifdef USE_ARM_PLACE @@ -453,6 +454,13 @@ Status load(graph::Graph(graph::Graph* graph, const char* model_path); + +template +Status load(graph::Graph* graph, + const char* buffer, size_t len); + +template +Status generate_graph_with_graph_proto(graph::Graph* graph, GraphProto& graph_proto); #endif #ifdef ANAKIN_TYPE_FP16 @@ -472,6 +480,13 @@ Status load(graph::Graph(graph::Graph* graph, const char* model_path); + +template +Status load(graph::Graph* graph, + const char* buffer, size_t len); + +template +Status generate_graph_with_graph_proto(graph::Graph* graph, GraphProto& graph_proto); #endif #ifdef ANAKIN_TYPE_INT8 @@ -490,6 +505,13 @@ Status load(graph::Graph(graph::Graph* graph, const char* model_path); + +template +Status load(graph::Graph* graph, + const char* buffer, size_t len); + +template +Status generate_graph_with_graph_proto(graph::Graph* graph, GraphProto& graph_proto); #endif #endif //USE_ARM_PLACE diff --git a/framework/model_parser/parser/parser.h b/framework/model_parser/parser/parser.h index b200bf00e..9d442b916 100644 --- a/framework/model_parser/parser/parser.h +++ b/framework/model_parser/parser/parser.h @@ -36,6 +36,9 @@ Status load(graph::Graph* graph, const char* model_path); template Status load(graph::Graph* graph, std::istream* instream); +template +Status load(graph::Graph* graph, const char* buffer, size_t len); + //! save graph to disk. use to save improved Graph. template Status save(graph::Graph* graph, std::string& model_path); From bc96e45d6333c75176d573a5ab497b5d89150bb8 Mon Sep 17 00:00:00 2001 From: shixiaowei02 Date: Mon, 3 Sep 2018 20:28:18 +0800 Subject: [PATCH 12/51] fix caffe parser --- .../parser/kill_caffe/parser_caffe.py | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py index 4481e24ee..3f0f5828f 100644 --- a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py +++ b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py @@ -419,19 +419,20 @@ def _CreateInputNode(self): if not input_dim: if len(self.net_parameter.input_shape) > 0: input_dim = map(int, self.net_parameter.input_shape[0].dim) - node_io.set_name(in_name) - node_io.add_in(in_name) - # leak out name , need to be added later. - shape = TensorShape() - shape.dim.value[:] = input_dim - shape.dim.size = len(input_dim) - node_io.add_attr("shape", shape, "shape") - op_io.set_name("Input") - op_io.set_in_num(1) - op_io.set_commutative(True) - node_io.set_op(op_io()) - self.graphIO.add_node(node_io()) - self.graphIO.add_in(in_name) + for in_name in inputs: + node_io.set_name(in_name) + node_io.add_in(in_name) + # leak out name , need to be added later. + shape = TensorShape() + shape.dim.value[:] = input_dim + shape.dim.size = len(input_dim) + node_io.add_attr("shape", shape, "shape") + op_io.set_name("Input") + op_io.set_in_num(1) + op_io.set_commutative(True) + node_io.set_op(op_io()) + self.graphIO.add_node(node_io()) + self.graphIO.add_in(in_name) else: # parser InputParameter instead. logger(verbose.INFO).feed(" Need to parse the layer of type InputParameter.") From fbb0af0bd194bc7a753689905c8365f7c493dde9 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Mon, 3 Sep 2018 22:23:31 +0800 Subject: [PATCH 13/51] fix style --- tools/external_converter_v2/parser/graph.py | 6 + .../parser/kill_caffe/parser_caffe.py | 6 +- .../parser/kill_fluid/fluid_debugger.py | 105 +- .../parser/kill_fluid/fluid_helper.py | 1042 +++++----- .../kill_fluid/fluid_layer_param_transmit.py | 715 +++---- .../parser/kill_fluid/parser_fluid.py | 1740 +++++++++-------- .../parser/kill_tf/__init__.py | 5 - .../parser/kill_tf/auto_debug.py | 124 -- .../parser/kill_tf/freeze.py | 62 - .../parser/kill_tf/freeze_graph.py | 404 ---- .../parser/kill_tf/get_empt_infer_pb.py | 39 - .../parser/kill_tf/med_graph.py | 154 -- .../parser/kill_tf/parse_med_2_ak.py | 149 -- .../parser/kill_tf/parse_tf_2_med.py | 181 -- .../parser/kill_tf/parser_tf.py | 57 - .../parser/kill_tf/run_pb.py | 74 - .../parser/kill_tf/run_pb_get_ckp.py | 51 - .../parser/kill_tf/summary.py | 45 - .../parser/kill_tf/tf_trans_util.py | 559 ------ .../parser/kill_tf/tf_util.py | 33 - .../parser/pbs/__init__.py | 7 +- 21 files changed, 1878 insertions(+), 3680 deletions(-) delete mode 100644 tools/external_converter_v2/parser/kill_tf/__init__.py delete mode 100644 tools/external_converter_v2/parser/kill_tf/auto_debug.py delete mode 100644 tools/external_converter_v2/parser/kill_tf/freeze.py delete mode 100644 tools/external_converter_v2/parser/kill_tf/freeze_graph.py delete mode 100644 tools/external_converter_v2/parser/kill_tf/get_empt_infer_pb.py delete mode 100644 tools/external_converter_v2/parser/kill_tf/med_graph.py delete mode 100644 tools/external_converter_v2/parser/kill_tf/parse_med_2_ak.py delete mode 100644 tools/external_converter_v2/parser/kill_tf/parse_tf_2_med.py delete mode 100644 tools/external_converter_v2/parser/kill_tf/parser_tf.py delete mode 100644 tools/external_converter_v2/parser/kill_tf/run_pb.py delete mode 100644 tools/external_converter_v2/parser/kill_tf/run_pb_get_ckp.py delete mode 100644 tools/external_converter_v2/parser/kill_tf/summary.py delete mode 100644 tools/external_converter_v2/parser/kill_tf/tf_trans_util.py delete mode 100644 tools/external_converter_v2/parser/kill_tf/tf_util.py diff --git a/tools/external_converter_v2/parser/graph.py b/tools/external_converter_v2/parser/graph.py index 030817195..e3fa90c4b 100644 --- a/tools/external_converter_v2/parser/graph.py +++ b/tools/external_converter_v2/parser/graph.py @@ -105,11 +105,17 @@ def serialization(self): self.graph_io.serialization(self.save_file_path) def info_table(self): + """ + print input table. + """ tables = list() in_table = PrettyTable(["Input Name", "Shape", "Alias", "Data Type"]) out_table = PrettyTable(["Output Name"]) def ins_attr(): + """ + get inputs attr. + """ ins = list() for graph_in in self.ins(): attr = dict() diff --git a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py index 3f0f5828f..f91103958 100644 --- a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py +++ b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py @@ -40,11 +40,13 @@ def _DetectionArch(self): self._ParserPrototxt() self._UpgradeNetAsNeeded() self._FilterNet() - self._SplitInception(False) + #self._SplitInception(False) self._InsertSplits() self._ScatterInputLayer() # create input node #self._CreateInputNode() maybe not need + + ''' def _SplitInception(self, is_weight): print is_weight net = self.net_parameter @@ -179,7 +181,7 @@ def _SplitInception(self, is_weight): if self.net_parameter.layer: del self.net_parameter.layer[:] self.net_parameter.layer.extend(new_layers) - + ''' def _ParserPrototxt(self): """ diff --git a/tools/external_converter_v2/parser/kill_fluid/fluid_debugger.py b/tools/external_converter_v2/parser/kill_fluid/fluid_debugger.py index d07e97799..9cfa4499c 100644 --- a/tools/external_converter_v2/parser/kill_fluid/fluid_debugger.py +++ b/tools/external_converter_v2/parser/kill_fluid/fluid_debugger.py @@ -7,54 +7,59 @@ class Fluid_debugger: + def var_names_of_fetch(self, fetch_targets): + """ + """ + var_names_list = [] + for var in fetch_targets: + var_names_list.append(var.name) + return var_names_list + def fetch_tmp_vars(self, block, fetch_targets, var_names_list=None): + """ + """ + fetch_var = block.var('fetch') + old_fetch_names = self.var_names_of_fetch(fetch_targets) + new_fetch_vars = [] + for var_name in old_fetch_names: + var = block.var(var_name) + new_fetch_vars.append(var) + i = len(new_fetch_vars) + if var_names_list is None: + var_names_list = block.vars.keys() + for var_name in var_names_list: + if '.tmp_' in var_name and var_name not in old_fetch_names: + var = block.var(var_name) + new_fetch_vars.append(var) + block.append_op( + type='fetch', + inputs={'X': [var_name]}, + outputs={'Out': [fetch_var]}, + attrs={'col': i}) + i = i + 1 + return new_fetch_vars - def var_names_of_fetch(self, fetch_targets): - var_names_list = [] - for var in fetch_targets: - var_names_list.append(var.name) - return var_names_list - - def fetch_tmp_vars(self, block, fetch_targets, var_names_list = None): - fetch_var = block.var('fetch') - old_fetch_names = self.var_names_of_fetch(fetch_targets) - new_fetch_vars = [] - for var_name in old_fetch_names: - var = block.var(var_name) - new_fetch_vars.append(var) - i = len(new_fetch_vars) - if var_names_list is None: - var_names_list = block.vars.keys() - for var_name in var_names_list: - if '.tmp_' in var_name and var_name not in old_fetch_names: - var = block.var(var_name) - new_fetch_vars.append(var) - block.append_op( - type='fetch', - inputs={'X': [var_name]}, - outputs={'Out': [fetch_var]}, - attrs={'col': i}) - i = i + 1 - return new_fetch_vars - - def print_tmp_vars(self, block, var_names_list = []): - for var_name in var_names_list: - var_to_print = block.var(var_name) - out_to_print = block.create_var( - name=var_name+'.print', - dtype="float32", - persistable=True, - stop_gradient=False) - block.append_op( - type='print', - inputs={'In': var_to_print}, - attrs={ - 'first_n': -1, - 'summarize': -1, - 'message': "", - 'print_tensor_name': True, - 'print_tensor_type': True, - 'print_tensor_shape': True, - 'print_tensor_lod': True, - 'print_phase': 'FORWARD' - }, - outputs={'Out': out_to_print}) + def print_tmp_vars(self, block, var_names_list): + """ + Print the temporary variable for fluid. + """ + for var_name in var_names_list: + var_to_print = block.var(var_name) + out_to_print = block.create_var( + name=var_name + '.print', + dtype="float32", + persistable=True, + stop_gradient=False) + block.append_op( + type='print', + inputs={'In': var_to_print}, + attrs={ + 'first_n': -1, + 'summarize': -1, + 'message': "", + 'print_tensor_name': True, + 'print_tensor_type': True, + 'print_tensor_shape': True, + 'print_tensor_lod': True, + 'print_phase': 'FORWARD' + }, + outputs={'Out': out_to_print}) diff --git a/tools/external_converter_v2/parser/kill_fluid/fluid_helper.py b/tools/external_converter_v2/parser/kill_fluid/fluid_helper.py index f702a0679..a17ff10ec 100644 --- a/tools/external_converter_v2/parser/kill_fluid/fluid_helper.py +++ b/tools/external_converter_v2/parser/kill_fluid/fluid_helper.py @@ -6,511 +6,607 @@ def union(list_a, list_b): - return list(set(list_a).union(set(list_b))) + ''' + ''' + return list(set(list_a).union(set(list_b))) def difference(list_a, list_b): - return list(set(list_a).difference(set(list_b))) + ''' + ''' + return list(set(list_a).difference(set(list_b))) class Edge_for_fluid: - def __init__(self, param, target, var): - self.param = param - self.target = target - self.var = var + def __init__(self, param, target, var): + ''' + ''' + self.param = param + self.target = target + self.var = var class Fluid_edger: - def __init__(self, param = None, target = None, var = None): - self.edges = [] - if param is not None and target is not None: - edge = Edge_for_fluid(param, target, var) - self.edges.append(edge) - - def __call__(self): - return self.all_targets() - - def add(self, param, target, var = None): - edge = Edge_for_fluid(param, target, var) - self.edges.append(edge) - - def rm_edges_by_param(self, param): - for edge in self.edges: - if edge.param == param: - edge_idx = self.edges.index(edge) - del self.edges[edge_idx] - - def rm(self, target): - res = -1 - for edge in self.edges: - if target == edge.target: - edge_idx = self.edges.index(edge) - del self.edges[edge_idx] - res = res + 1 - if res != 0: - pass - - def mv(self, old_target, new_target): - res = -1 - for edge in self.edges: - if old_target == edge.target: - edge.target = new_target - res = res + 1 - if res != 0: - pass - - def all_params(self): - params = [] - for edge in self.edges: - if edge.param not in params: - params.append(edge.param) - return params - - def all_targets(self): - targets = [] - for edge in self.edges: - targets.append(edge.target) - return targets - - def targets(self, param): - targets = [] - for edge in self.edges: - if edge.param == param: - targets.append(edge.target) - return targets - - def target(self, param, idx = 0): - return self.targets(param)[idx] - - def clear(self): - targets_list = self.all_targets() - for target in targets_list: - self.rm(target) - - def targets_with_params(self): - list_of_targets_and_params = [] - for edge in self.edges: - target_and_param = [edge.target, edge.param] - list_of_targets_and_params.append(target_and_param) - return list_of_targets_and_params - - def vars_by_target(self, target): - vars = [] - for edge in self.edges: - if edge.target == target and edge.var is not None: - vars.append(edge.var) - return vars - - def __getitem__(self, idx): - if idx < len(self.edges): - return self.edges[idx] - return None + def __init__(self, param = None, target = None, var = None): + ''' + ''' + self.edges = [] + if param is not None and target is not None: + edge = Edge_for_fluid(param, target, var) + self.edges.append(edge) + + def __call__(self): + ''' + ''' + return self.all_targets() + + def add(self, param, target, var = None): + ''' + ''' + edge = Edge_for_fluid(param, target, var) + self.edges.append(edge) + + def rm_edges_by_param(self, param): + ''' + ''' + for edge in self.edges: + if edge.param == param: + edge_idx = self.edges.index(edge) + del self.edges[edge_idx] + + def rm(self, target): + ''' + ''' + res = -1 + for edge in self.edges: + if target == edge.target: + edge_idx = self.edges.index(edge) + del self.edges[edge_idx] + res = res + 1 + if res != 0: + pass + + def mv(self, old_target, new_target): + ''' + ''' + res = -1 + for edge in self.edges: + if old_target == edge.target: + edge.target = new_target + res = res + 1 + if res != 0: + pass + + def all_params(self): + ''' + ''' + params = [] + for edge in self.edges: + if edge.param not in params: + params.append(edge.param) + return params + + def all_targets(self): + ''' + ''' + targets = [] + for edge in self.edges: + targets.append(edge.target) + return targets + + def targets(self, param): + ''' + ''' + targets = [] + for edge in self.edges: + if edge.param == param: + targets.append(edge.target) + return targets + + def target(self, param, idx = 0): + ''' + ''' + return self.targets(param)[idx] + + def clear(self): + ''' + ''' + targets_list = self.all_targets() + for target in targets_list: + self.rm(target) + + def targets_with_params(self): + ''' + ''' + list_of_targets_and_params = [] + for edge in self.edges: + target_and_param = [edge.target, edge.param] + list_of_targets_and_params.append(target_and_param) + return list_of_targets_and_params + + def vars_by_target(self, target): + ''' + ''' + vars = [] + for edge in self.edges: + if edge.target == target and edge.var is not None: + vars.append(edge.var) + return vars + + def __getitem__(self, idx): + ''' + ''' + if idx < len(self.edges): + return self.edges[idx] + return None class Fluid_helper: - - def __init__(self, scope, block): - self.scope = scope - self.block = block - - def args_by_input_param(self, op, param_name): - if param_name in op.input_names: - return op.input(param_name) - else: - raise NameError('ERROR: param_name %s is not exists.' % ( param_name ) ) - - def args_by_output_param(self, op, param_name): - if param_name in op.output_names: - return op.output(param_name) - else: - raise NameError('ERROR: param_name %s is not exists.' % ( param_name ) ) - - def var_by_input_param(self, op, param_name, var_idx = 0): - var_name = self.args_by_input_param(op, param_name)[var_idx] - var = self.block.var(var_name) - return var - - def var_by_output_param(self, op, param_name, var_idx = 0): - var_name = self.args_by_output_param(op, param_name)[var_idx] - var = self.block.var(var_name) - return var - - def var_name_by_param(self, op, param_name, var_idx = 0): - if param_name not in op.input_names + op.output_names: - raise NameError('ERROR: param_name %s is not exists.' % ( param_name ) ) - elif param_name in op.input_names: - if len(op.input(param_name)) > 0: - var_name_unicode = op.input(param_name)[var_idx] - else: - raise NameError('ERROR: param %s has not var.' % ( param_name ) ) - elif param_name in op.output_names: - if len(op.output(param_name)) > 0: - var_name_unicode = op.output(param_name)[var_idx] - else: - raise NameError('ERROR: param %s has not var.' % ( param_name ) ) - var = self.block.var(var_name_unicode) - var_name = var.name - return var_name - - def var_by_param(self, op, param_name, var_idx = 0): - var_name = self.var_name_by_param(op, param_name, var_idx) - var = self.block.var(var_name) - return var - - def shape_by_var_name(self, var_name, layout = 'NCHW'): - var = self.block.var(var_name) - long_tuple = var.shape - long_list = list(long_tuple) - if layout == 'NCHW': - int_list_4d = map(int, [1]*(4-len(long_list)) + long_list) - return int_list_4d - elif layout == 'UNMODIFIED': - return long_list - else: - raise NameError('ERROR: layout %s is not implemented yet.' % ( layout ) ) - - def np_data_by_var_name(self, var_name): - numpy_array = fluid.executor.fetch_var(var_name, self.scope, True) - return numpy_array - - def dtype_by_var_name(self, var_name): - var = self.block.var(var_name) - fluid_var_type = var.dtype - dtype = ANAKIN_TENSOR_DTYPE[fluid_var_type] - return dtype - - def is_persistable_param(self, op, param_name, var_idx = 0): - var = self.var_by_param(op, param_name, var_idx) - is_persistable_var = var.persistable - return is_persistable_var - - def var_shape_by_param(self, transpose, op, param_name, var_idx = 0, layout = 'NCHW'): - if transpose is True: - raise NameError('ERROR: var_shape transpose is not implemented yet.') - else: - var_name = self.var_name_by_param(op, param_name, var_idx) - shape = self.shape_by_var_name(var_name, layout) - return shape - - def data_with_shape_by_param(self, - op, - param_name, - transpose = False, - axes = None, - var_idx = 0, - is_flat_list = True, - layout = 'NCHW'): - - np.set_printoptions(threshold=np.inf, suppress=True) - - var_name = self.var_name_by_param(op, param_name, var_idx) - np_array = self.np_data_by_var_name(var_name) - if transpose is True: - np_array = np.transpose(np_array, axes) - np_shape = np.shape(np_array) - if layout == 'NCHW': - np_shape = map(int, [1]*(4-len(np_shape)) + list(np_shape)) - if is_flat_list is True: - flat_list = list(np_array.flatten()) - return [flat_list, np_shape] - else: - return [np_array, np_shape] - - def np_param(self, - op, - param_name, - transpose = False, - axes = None, - var_idx = 0): - - [data, np_shape] = self.data_with_shape_by_param(op, param_name, transpose, \ - axes, var_idx, False) - return data - - def dtype_by_param(self, op, param_name, var_idx = 0): - var_name = self.var_name_by_param(op, param_name, var_idx) - dtype = self.dtype_by_var_name(var_name) - return dtype - - def is_list_type(self, op, attr_name): - if op.has_attr(attr_name): - fluid_attr_type = op.attr_type(attr_name) - if fluid_attr_type in ANAKIN_ATTR_IS_LIST.keys(): - return ANAKIN_ATTR_IS_LIST[fluid_attr_type] - else: - return False # AttrType.LONG - else: - raise NameError('ERROR: attr_name %s is not exists.' % ( attr_name ) ) - - def dtype_of_attr(self, op, attr_name): - if op.has_attr(attr_name): - fluid_attr_type = op.attr_type(attr_name) - if fluid_attr_type in ANAKIN_ATTR_DTYPE.keys(): - return ANAKIN_ATTR_DTYPE[fluid_attr_type] - else: - return INT32 # AttrType.LONG - else: - raise NameError('ERROR: attr_name %s is not exists.' % ( attr_name ) ) - - def attr_data_required(self, op, attr_name): - data = op.attr(attr_name) - is_list = self.is_list_type(op, attr_name) - dtype = self.dtype_of_attr(op, attr_name) - if dtype not in [INT32, FLOAT, STR]: - return data - elif dtype == INT32: - return map(int, data) if is_list else int(data) - elif dtype == FLOAT: - return map(float, data) if is_list else float(data) - elif dtype == STR: - return bytes(data) - - def attr_data(self, op, attr_name, default_value = 0, type = None): - if op.has_attr(attr_name): - return self.attr_data_required(op, attr_name) - else: - #raise NameError('ERROR: attr_name %s is not exists.' % ( attr_name ) ) - return default_value - - def param_tensor_sh(self, - op, - param_name, - transpose = False, - axes = None, - reshape = None, - var_idx = 0, - layout = 'NCHW'): - - tensor = TensorProtoIO() - [flat_data, shape] = self.data_with_shape_by_param(op, param_name, transpose, \ - axes, var_idx, True, layout) - dtype = self.dtype_by_param(op, param_name, var_idx) - tensor.set_data_type(dtype) - if dtype in ANAKIN_TENSOR_DTYPESTR.keys(): - tensor.set_data(flat_data, ANAKIN_TENSOR_DTYPESTR[dtype]) - #pass #debug - else: - raise NameError('ERROR: Unknown data type (%s)' % ( dtype ) ) - if reshape is not None: - tensor.set_shape(reshape) - else: - tensor.set_shape(shape) - return [tensor, shape] - - def param_tensor(self, - op, - param_name, - transpose = False, - axes = None, - reshape = None, - var_idx = 0, - layout = 'NCHW'): - - [tensor, shape] = self.param_tensor_sh(op, param_name, transpose, axes, \ - reshape, var_idx, layout) - return tensor - - def create_tensor(self, data_list, data_shape, dtype): - tensor = TensorProtoIO() - tensor.set_data_type(dtype) - tensor.set_data(data_list, ANAKIN_TENSOR_DTYPESTR[dtype]) - tensor.set_shape(data_shape) - return tensor - - def gru_tensor_convert(self, origin_h2h, origin_i2h, origin_b, offset=[2, 1, 0]): - hidden_size = int(origin_b.size // 3) - word_size = int(origin_i2h.size // hidden_size // 3) - tar_h2h=np.array(origin_h2h.flatten().tolist()[2*hidden_size*hidden_size:]\ - +np.array(origin_h2h.flatten().tolist()[:2*hidden_size*hidden_size])\ - .reshape(hidden_size,2,hidden_size)[:,[1,0],:].flatten().tolist())\ - .reshape(1,1,hidden_size,3*hidden_size) - tar_i2h=origin_i2h.reshape(word_size,3,hidden_size)[:,offset,:]\ - .reshape(1,1,word_size,3*hidden_size) - tar_b=origin_b.reshape(3, hidden_size)[offset, :].reshape(1,1,1,3 * hidden_size) - tar_i2h_h2h=np.concatenate([tar_i2h.flatten(),tar_h2h.flatten()])\ - .reshape(1,1,1,3*hidden_size*hidden_size+3*word_size*hidden_size) - return tar_i2h_h2h, tar_b - - def lstm_fc_tensor_merge_convert(self, origin_hidden_size, origin_lstm_w, origin_lstm_b, origin_fc_w, origin_fc_b): - - layer_size = int (origin_hidden_size // 4) - input_size = int (origin_fc_w.size // origin_hidden_size) - lstm_bias_num = int (origin_lstm_b.size // layer_size) - tar_w = np.vstack((np.hstack((origin_fc_w[:, 1 * layer_size : 2 * layer_size], - origin_fc_w[:, 2 * layer_size : 3 * layer_size], - origin_fc_w[:, : 1 * layer_size], - origin_fc_w[:, 3 * layer_size :])), - np.hstack((origin_lstm_w[:, 1 * layer_size : 2 * layer_size], - origin_lstm_w[:, 2 * layer_size : 3 * layer_size], - origin_lstm_w[:, : 1 * layer_size], - origin_lstm_w[:, 3 * layer_size : ])))) - - if origin_fc_b is not None: - split_fc_bc = origin_fc_b.flatten()[: 1 * layer_size] - split_fc_bi = origin_fc_b.flatten()[1 * layer_size : 2 * layer_size] - split_fc_bf = origin_fc_b.flatten()[2 * layer_size : 3 * layer_size] - split_fc_bo = origin_fc_b.flatten()[3 * layer_size : 4 * layer_size] - else: - split_fc_bc = np.zeros(layer_size) - split_fc_bi = np.zeros(layer_size) - split_fc_bf = np.zeros(layer_size) - split_fc_bo = np.zeros(layer_size) - - split_lstm_bc = origin_lstm_b.flatten()[: 1 * layer_size] - split_lstm_bi = origin_lstm_b.flatten()[1 * layer_size: 2 * layer_size] - split_lstm_bf = origin_lstm_b.flatten()[2 * layer_size: 3 * layer_size] - split_lstm_bo = origin_lstm_b.flatten()[3 * layer_size: 4 * layer_size] - split_lstm_bc = np.add(split_lstm_bc, split_fc_bc) - split_lstm_bi = np.add(split_lstm_bi, split_fc_bi) - split_lstm_bf = np.add(split_lstm_bf, split_fc_bf) - split_lstm_bo = np.add(split_lstm_bo, split_fc_bo) - - if lstm_bias_num == 4: - tar_b = np.array(split_lstm_bi.flatten().tolist() - + split_lstm_bf.flatten().tolist() - + split_lstm_bc.flatten().tolist() - + split_lstm_bo.flatten().tolist()) - else: - split_lstm_wic = origin_lstm_b.flatten()[4 * layer_size : 5 * layer_size] - split_lstm_wfc = origin_lstm_b.flatten()[5 * layer_size : 6 * layer_size] - split_lstm_woc = origin_lstm_b.flatten()[6 * layer_size :] - tar_b = np.array(split_lstm_bi.flatten().tolist() - + split_lstm_bf.flatten().tolist() - + split_lstm_bc.flatten().tolist() - + split_lstm_bo.flatten().tolist() - + split_lstm_wic.flatten().tolist() - + split_lstm_wfc.flatten().tolist() - + split_lstm_woc.flatten().tolist()) - return tar_w.reshape(input_size+ layer_size, 4 * layer_size, 1, 1),\ - tar_b.reshape(1, origin_lstm_b.size, 1, 1) + ''' + ''' + def __init__(self, scope, block): + ''' + ''' + self.scope = scope + self.block = block + + def args_by_input_param(self, op, param_name): + ''' + ''' + if param_name in op.input_names: + return op.input(param_name) + else: + raise NameError('ERROR: param_name %s is not exists.' % (param_name)) + + def args_by_output_param(self, op, param_name): + ''' + ''' + if param_name in op.output_names: + return op.output(param_name) + else: + raise NameError('ERROR: param_name %s is not exists.' % (param_name)) + + def var_by_input_param(self, op, param_name, var_idx = 0): + ''' + ''' + var_name = self.args_by_input_param(op, param_name)[var_idx] + var = self.block.var(var_name) + return var + + def var_by_output_param(self, op, param_name, var_idx = 0): + ''' + ''' + var_name = self.args_by_output_param(op, param_name)[var_idx] + var = self.block.var(var_name) + return var + + def var_name_by_param(self, op, param_name, var_idx = 0): + ''' + ''' + if param_name not in op.input_names + op.output_names: + raise NameError('ERROR: param_name %s is not exists.' % (param_name)) + elif param_name in op.input_names: + if len(op.input(param_name)) > 0: + var_name_unicode = op.input(param_name)[var_idx] + else: + raise NameError('ERROR: param %s has not var.' % (param_name)) + elif param_name in op.output_names: + if len(op.output(param_name)) > 0: + var_name_unicode = op.output(param_name)[var_idx] + else: + raise NameError('ERROR: param %s has not var.' % (param_name)) + var = self.block.var(var_name_unicode) + var_name = var.name + return var_name + + def var_by_param(self, op, param_name, var_idx = 0): + ''' + ''' + var_name = self.var_name_by_param(op, param_name, var_idx) + var = self.block.var(var_name) + return var + + def shape_by_var_name(self, var_name, layout = 'NCHW'): + ''' + ''' + var = self.block.var(var_name) + long_tuple = var.shape + long_list = list(long_tuple) + if layout == 'NCHW': + int_list_4d = map(int, [1] * (4 - len(long_list)) + long_list) + return int_list_4d + elif layout == 'UNMODIFIED': + return long_list + else: + raise NameError('ERROR: layout %s is not implemented yet.' % (layout)) + + def np_data_by_var_name(self, var_name): + ''' + ''' + numpy_array = fluid.executor.fetch_var(var_name, self.scope, True) + return numpy_array + + def dtype_by_var_name(self, var_name): + ''' + ''' + var = self.block.var(var_name) + fluid_var_type = var.dtype + dtype = ANAKIN_TENSOR_DTYPE[fluid_var_type] + return dtype + + def is_persistable_param(self, op, param_name, var_idx = 0): + ''' + ''' + var = self.var_by_param(op, param_name, var_idx) + is_persistable_var = var.persistable + return is_persistable_var + + def var_shape_by_param(self, transpose, op, param_name, var_idx = 0, layout = 'NCHW'): + ''' + ''' + if transpose is True: + raise NameError('ERROR: var_shape transpose is not implemented yet.') + else: + var_name = self.var_name_by_param(op, param_name, var_idx) + shape = self.shape_by_var_name(var_name, layout) + return shape + + def data_with_shape_by_param(self, + op, + param_name, + transpose = False, + axes = None, + var_idx = 0, + is_flat_list = True, + layout = 'NCHW'): + ''' + ''' + np.set_printoptions(threshold=np.inf, suppress=True) + + var_name = self.var_name_by_param(op, param_name, var_idx) + np_array = self.np_data_by_var_name(var_name) + if transpose is True: + np_array = np.transpose(np_array, axes) + np_shape = np.shape(np_array) + if layout == 'NCHW': + np_shape = map(int, [1] * (4 - len(np_shape)) + list(np_shape)) + if is_flat_list is True: + flat_list = list(np_array.flatten()) + return [flat_list, np_shape] + else: + return [np_array, np_shape] + + def np_param(self, + op, + param_name, + transpose = False, + axes = None, + var_idx = 0): + ''' + ''' + [data, np_shape] = self.data_with_shape_by_param(op, param_name, transpose, \ + axes, var_idx, False) + return data + + def dtype_by_param(self, op, param_name, var_idx = 0): + ''' + ''' + var_name = self.var_name_by_param(op, param_name, var_idx) + dtype = self.dtype_by_var_name(var_name) + return dtype + + def is_list_type(self, op, attr_name): + ''' + ''' + if op.has_attr(attr_name): + fluid_attr_type = op.attr_type(attr_name) + if fluid_attr_type in ANAKIN_ATTR_IS_LIST.keys(): + return ANAKIN_ATTR_IS_LIST[fluid_attr_type] + else: + return False # AttrType.LONG + else: + raise NameError('ERROR: attr_name %s is not exists.' % (attr_name)) + + def dtype_of_attr(self, op, attr_name): + ''' + ''' + if op.has_attr(attr_name): + fluid_attr_type = op.attr_type(attr_name) + if fluid_attr_type in ANAKIN_ATTR_DTYPE.keys(): + return ANAKIN_ATTR_DTYPE[fluid_attr_type] + else: + return INT32 # AttrType.LONG + else: + raise NameError('ERROR: attr_name %s is not exists.' % (attr_name)) + + def attr_data_required(self, op, attr_name): + ''' + ''' + data = op.attr(attr_name) + is_list = self.is_list_type(op, attr_name) + dtype = self.dtype_of_attr(op, attr_name) + if dtype not in [INT32, FLOAT, STR]: + return data + elif dtype == INT32: + return map(int, data) if is_list else int(data) + elif dtype == FLOAT: + return map(float, data) if is_list else float(data) + elif dtype == STR: + return bytes(data) + + def attr_data(self, op, attr_name, default_value = 0, type = None): + ''' + ''' + if op.has_attr(attr_name): + return self.attr_data_required(op, attr_name) + else: + #raise NameError('ERROR: attr_name %s is not exists.' % ( attr_name ) ) + return default_value + + def param_tensor_sh(self, + op, + param_name, + transpose = False, + axes = None, + reshape = None, + var_idx = 0, + layout = 'NCHW'): + ''' + ''' + tensor = TensorProtoIO() + [flat_data, shape] = self.data_with_shape_by_param(op, param_name, transpose, \ + axes, var_idx, True, layout) + dtype = self.dtype_by_param(op, param_name, var_idx) + tensor.set_data_type(dtype) + if dtype in ANAKIN_TENSOR_DTYPESTR.keys(): + tensor.set_data(flat_data, ANAKIN_TENSOR_DTYPESTR[dtype]) + #pass #debug + else: + raise NameError('ERROR: Unknown data type (%s)' % (dtype)) + if reshape is not None: + tensor.set_shape(reshape) + else: + tensor.set_shape(shape) + return [tensor, shape] + + def param_tensor(self, + op, + param_name, + transpose = False, + axes = None, + reshape = None, + var_idx = 0, + layout = 'NCHW'): + ''' + ''' + [tensor, shape] = self.param_tensor_sh(op, param_name, transpose, axes, \ + reshape, var_idx, layout) + return tensor + + def create_tensor(self, data_list, data_shape, dtype): + ''' + ''' + tensor = TensorProtoIO() + tensor.set_data_type(dtype) + tensor.set_data(data_list, ANAKIN_TENSOR_DTYPESTR[dtype]) + tensor.set_shape(data_shape) + return tensor + + def gru_tensor_convert(self, origin_h2h, origin_i2h, origin_b, offset=[2, 1, 0]): + ''' + ''' + hidden_size = int(origin_b.size // 3) + word_size = int(origin_i2h.size // hidden_size // 3) + tar_h2h = np.array(origin_h2h.flatten().tolist()[2 * hidden_size * hidden_size:]\ + + np.array(origin_h2h.flatten().tolist()[: 2 * hidden_size * hidden_size])\ + .reshape(hidden_size, 2, hidden_size)[:, [1, 0], :].flatten().tolist())\ + .reshape(1, 1, hidden_size, 3 * hidden_size) + tar_i2h = origin_i2h.reshape(word_size, 3, hidden_size)[:, offset, :]\ + .reshape(1, 1, word_size, 3 * hidden_size) + tar_b = origin_b.reshape(3, hidden_size)[offset, :].reshape(1, 1, 1, 3 * hidden_size) + tar_i2h_h2h = np.concatenate([tar_i2h.flatten(), tar_h2h.flatten()])\ + .reshape(1, 1, 1, 3 * hidden_size * hidden_size + 3 * word_size * hidden_size) + return tar_i2h_h2h, tar_b + + def lstm_fc_tensor_merge_convert(self, + origin_hidden_size, + origin_lstm_w, + origin_lstm_b, + origin_fc_w, + origin_fc_b): + ''' + ''' + layer_size = int(origin_hidden_size // 4) + input_size = int(origin_fc_w.size // origin_hidden_size) + lstm_bias_num = int(origin_lstm_b.size // layer_size) + tar_w = np.vstack((np.hstack((origin_fc_w[:, 1 * layer_size: 2 * layer_size], + origin_fc_w[:, 2 * layer_size: 3 * layer_size], + origin_fc_w[:,: 1 * layer_size], + origin_fc_w[:, 3 * layer_size:])), + np.hstack((origin_lstm_w[:, 1 * layer_size: 2 * layer_size], + origin_lstm_w[:, 2 * layer_size: 3 * layer_size], + origin_lstm_w[:, : 1 * layer_size], + origin_lstm_w[:, 3 * layer_size:])))) + + if origin_fc_b is not None: + split_fc_bc = origin_fc_b.flatten()[: 1 * layer_size] + split_fc_bi = origin_fc_b.flatten()[1 * layer_size : 2 * layer_size] + split_fc_bf = origin_fc_b.flatten()[2 * layer_size : 3 * layer_size] + split_fc_bo = origin_fc_b.flatten()[3 * layer_size : 4 * layer_size] + else: + split_fc_bc = np.zeros(layer_size) + split_fc_bi = np.zeros(layer_size) + split_fc_bf = np.zeros(layer_size) + split_fc_bo = np.zeros(layer_size) + + split_lstm_bc = origin_lstm_b.flatten()[: 1 * layer_size] + split_lstm_bi = origin_lstm_b.flatten()[1 * layer_size: 2 * layer_size] + split_lstm_bf = origin_lstm_b.flatten()[2 * layer_size: 3 * layer_size] + split_lstm_bo = origin_lstm_b.flatten()[3 * layer_size: 4 * layer_size] + split_lstm_bc = np.add(split_lstm_bc, split_fc_bc) + split_lstm_bi = np.add(split_lstm_bi, split_fc_bi) + split_lstm_bf = np.add(split_lstm_bf, split_fc_bf) + split_lstm_bo = np.add(split_lstm_bo, split_fc_bo) + + if lstm_bias_num == 4: + tar_b = np.array(split_lstm_bi.flatten().tolist() + + split_lstm_bf.flatten().tolist() + + split_lstm_bc.flatten().tolist() + + split_lstm_bo.flatten().tolist()) + else: + split_lstm_wic = origin_lstm_b.flatten()[4 * layer_size : 5 * layer_size] + split_lstm_wfc = origin_lstm_b.flatten()[5 * layer_size : 6 * layer_size] + split_lstm_woc = origin_lstm_b.flatten()[6 * layer_size :] + tar_b = np.array(split_lstm_bi.flatten().tolist() + + split_lstm_bf.flatten().tolist() + + split_lstm_bc.flatten().tolist() + + split_lstm_bo.flatten().tolist() + + split_lstm_wic.flatten().tolist() + + split_lstm_wfc.flatten().tolist() + + split_lstm_woc.flatten().tolist()) + return tar_w.reshape(input_size + layer_size, 4 * layer_size, 1, 1),\ + tar_b.reshape(1, origin_lstm_b.size, 1, 1) class Fluid_comparator: - - def __init__(self, helper): - self.helper = helper - self.only_list = ['feed', 'fetch'] - - def compare_by_param(self, op_a, op_b, param): - is_weight_a = self.helper.is_persistable_param(op_a, param) - is_weight_b = self.helper.is_persistable_param(op_b, param) - if is_weight_a and is_weight_b: - np_a = self.helper.np_param(op_a, param) - np_b = self.helper.np_param(op_b, param) - if (np_a == np_b).all() == True: - return True - else: - return False - elif is_weight_a is is_weight_b: - return True - else: - return False - - def have_same_weights(self, op_a, op_b): - is_same = True - if op_a.input_names == op_b.input_names: - params = op_a.input_names - for param in params: - if self.compare_by_param(op_a, op_b, param) is False: - is_same = False - return is_same - else: - return False - - def compare_by_attr(self, op_a, op_b, attr_name): - data_a = self.helper.attr_data(op_a, attr_name) - data_b = self.helper.attr_data(op_b, attr_name) - return data_a == data_b - - def have_same_attrs(self, op_a, op_b): - is_same = True - if op_a.attr_names == op_b.attr_names: - attrs = op_a.attr_names - for attr in attrs: - if self.compare_by_attr(op_a, op_b, attr) is False: - is_same = False - return is_same - else: - return False - - def brothers(self, op_list): - is_same = True - if len(op_list) > 1: - idx = 0 - for op_b in op_list[1:]: - if op_b.type not in self.only_list: - idx = op_list.index(op_b) - op_a = op_list[idx - 1] - if op_a.type not in self.only_list: - same_weights = self.have_same_weights(op_a, op_b) - same_attrs = self.have_same_attrs(op_a, op_b) - if (same_weights and same_attrs) is False: - is_same = False - else: - raise NameError('ERROR: %s is in only_list.' % ( op_a.type )) - else: - raise NameError('ERROR: %s is in only_list.' % ( op_b.type )) - return is_same - else: - raise NameError('ERROR: Members of op_list must be greater than 2.') + """ + """ + def __init__(self, helper): + """ + """ + self.helper = helper + self.only_list = ['feed', 'fetch'] + + def compare_by_param(self, op_a, op_b, param): + """ + """ + is_weight_a = self.helper.is_persistable_param(op_a, param) + is_weight_b = self.helper.is_persistable_param(op_b, param) + if is_weight_a and is_weight_b: + np_a = self.helper.np_param(op_a, param) + np_b = self.helper.np_param(op_b, param) + if (np_a == np_b).all() == True: + return True + else: + return False + elif is_weight_a is is_weight_b: + return True + else: + return False + + def have_same_weights(self, op_a, op_b): + """ + """ + is_same = True + if op_a.input_names == op_b.input_names: + params = op_a.input_names + for param in params: + if self.compare_by_param(op_a, op_b, param) is False: + is_same = False + return is_same + else: + return False + + def compare_by_attr(self, op_a, op_b, attr_name): + """ + """ + data_a = self.helper.attr_data(op_a, attr_name) + data_b = self.helper.attr_data(op_b, attr_name) + return data_a == data_b + + def have_same_attrs(self, op_a, op_b): + """ + """ + is_same = True + if op_a.attr_names == op_b.attr_names: + attrs = op_a.attr_names + for attr in attrs: + if self.compare_by_attr(op_a, op_b, attr) is False: + is_same = False + return is_same + else: + return False + + def brothers(self, op_list): + """ + """ + is_same = True + if len(op_list) > 1: + idx = 0 + for op_b in op_list[1:]: + if op_b.type not in self.only_list: + idx = op_list.index(op_b) + op_a = op_list[idx - 1] + if op_a.type not in self.only_list: + same_weights = self.have_same_weights(op_a, op_b) + same_attrs = self.have_same_attrs(op_a, op_b) + if (same_weights and same_attrs) is False: + is_same = False + else: + raise NameError('ERROR: %s is in only_list.' % (op_a.type)) + else: + raise NameError('ERROR: %s is in only_list.' % (op_b.type)) + return is_same + else: + raise NameError('ERROR: Members of op_list must be greater than 2.') ANAKIN_TENSOR_DTYPE = { - VarDesc.VarType.BOOL: BOOLEN, - VarDesc.VarType.INT32: INT32, - VarDesc.VarType.FP16: FLOAT16, - VarDesc.VarType.FP32: FLOAT, - VarDesc.VarType.FP64: DOUBLE, + VarDesc.VarType.BOOL: BOOLEN, + VarDesc.VarType.INT32: INT32, + VarDesc.VarType.FP16: FLOAT16, + VarDesc.VarType.FP32: FLOAT, + VarDesc.VarType.FP64: DOUBLE, } ANAKIN_TENSOR_DTYPESTR = { - STR: "string", - INT32: "int", - FLOAT: "float", - BOOLEN: "bool", + STR: "string", + INT32: "int", + FLOAT: "float", + BOOLEN: "bool", } ANAKIN_ATTR_DTYPE = { - AttrType.INT: INT32, - AttrType.INTS: INT32, - AttrType.FLOAT: FLOAT, - AttrType.FLOATS: FLOAT, - AttrType.STRING: STR, - AttrType.STRINGS: STR, - AttrType.BOOL: BOOLEN, - AttrType.BOOLS: BOOLEN, + AttrType.INT: INT32, + AttrType.INTS: INT32, + AttrType.FLOAT: FLOAT, + AttrType.FLOATS: FLOAT, + AttrType.STRING: STR, + AttrType.STRINGS: STR, + AttrType.BOOL: BOOLEN, + AttrType.BOOLS: BOOLEN, } ANAKIN_ATTR_IS_LIST = { - AttrType.INT: False, - AttrType.INTS: True, - AttrType.FLOAT: False, - AttrType.FLOATS: True, - AttrType.STRING: False, - AttrType.STRINGS: True, - AttrType.BOOL: False, - AttrType.BOOLS: True, + AttrType.INT: False, + AttrType.INTS: True, + AttrType.FLOAT: False, + AttrType.FLOATS: True, + AttrType.STRING: False, + AttrType.STRINGS: True, + AttrType.BOOL: False, + AttrType.BOOLS: True, } APPEND_BIAS_OP_TYPE = [ - 'FC', - 'mul', - 'sequence_conv', - 'conv2d', - 'conv2d_transpose', - 'depthwise_conv2d', - 'elementwise_mul', + 'FC', + 'mul', + 'sequence_conv', + 'conv2d', + 'conv2d_transpose', + 'depthwise_conv2d', + 'elementwise_mul', ] APPEND_ACT_OP_TYPE = [ - 'FC', - 'mul', - 'sequence_conv', - 'conv2d', - 'conv2d_transpose', - 'batch_norm', - 'layer_norm', - 'row_conv', - 'reshape', + 'FC', + 'mul', + 'sequence_conv', + 'conv2d', + 'conv2d_transpose', + 'batch_norm', + 'layer_norm', + 'row_conv', + 'reshape', ] diff --git a/tools/external_converter_v2/parser/kill_fluid/fluid_layer_param_transmit.py b/tools/external_converter_v2/parser/kill_fluid/fluid_layer_param_transmit.py index 46ed42324..eb97be479 100644 --- a/tools/external_converter_v2/parser/kill_fluid/fluid_layer_param_transmit.py +++ b/tools/external_converter_v2/parser/kill_fluid/fluid_layer_param_transmit.py @@ -5,486 +5,487 @@ def ParserFeedDecorator(OpName): - def warpper(Parser): - def warpper_args(args): - Parser(args) - OpsRegister()[OpName].feed_node_attr(args[0]) - args[2].set_name(OpName) - args[0].set_op(args[2]()) - return warpper_args - return warpper + def warpper(Parser): + def warpper_args(args): + Parser(args) + OpsRegister()[OpName].feed_node_attr(args[0]) + args[2].set_name(OpName) + args[0].set_op(args[2]()) + return warpper_args + return warpper # common def NotNeededInInference(args): - # args is tuple object - node_io = args[0] - layer = args[1] + # args is tuple object + node_io = args[0] + layer = args[1] @ParserFeedDecorator("Input") def Parser_feed(args): - private_data = args[4] - input_shape = private_data['input_shape'] - alias = private_data['alias'] - OpsRegister()["Input"].input_shape = input_shape - OpsRegister()["Input"].alias = alias + private_data = args[4] + input_shape = private_data['input_shape'] + alias = private_data['alias'] + OpsRegister()["Input"].input_shape = input_shape + OpsRegister()["Input"].alias = alias @ParserFeedDecorator("Convolution") def Parser_conv2d(args): - op = args[1] - helper = args[3] - private_data = args[4] - [weights_tensor, weights_shape] = helper.param_tensor_sh(op, 'Filter') - OpsRegister()["Convolution"].weight_1 = weights_tensor - OpsRegister()["Convolution"].filter_num = weights_shape[0] - OpsRegister()["Convolution"].kernel_size = weights_shape[-2:] - OpsRegister()["Convolution"].strides = helper.attr_data(op, 'strides') - OpsRegister()["Convolution"].padding = helper.attr_data(op, 'paddings') - OpsRegister()["Convolution"].dilation_rate = helper.attr_data(op, 'dilations') - OpsRegister()["Convolution"].group = helper.attr_data(op, 'groups') - OpsRegister()["Convolution"].axis = 1 - if 'bias' in private_data.keys(): - OpsRegister()["Convolution"].bias_term = True - OpsRegister()["Convolution"].weight_2 = private_data['bias'] - else: - OpsRegister()["Convolution"].bias_term = False + op = args[1] + helper = args[3] + private_data = args[4] + [weights_tensor, weights_shape] = helper.param_tensor_sh(op, 'Filter') + OpsRegister()["Convolution"].weight_1 = weights_tensor + OpsRegister()["Convolution"].filter_num = weights_shape[0] + OpsRegister()["Convolution"].kernel_size = weights_shape[-2:] + OpsRegister()["Convolution"].strides = helper.attr_data(op, 'strides') + OpsRegister()["Convolution"].padding = helper.attr_data(op, 'paddings') + OpsRegister()["Convolution"].dilation_rate = helper.attr_data(op, 'dilations') + OpsRegister()["Convolution"].group = helper.attr_data(op, 'groups') + OpsRegister()["Convolution"].axis = 1 + if 'bias' in private_data.keys(): + OpsRegister()["Convolution"].bias_term = True + OpsRegister()["Convolution"].weight_2 = private_data['bias'] + else: + OpsRegister()["Convolution"].bias_term = False @ParserFeedDecorator("ReLU") def Parser_relu(args): - OpsRegister()["ReLU"].alpha = 0.0 + OpsRegister()["ReLU"].alpha = 0.0 @ParserFeedDecorator("Pooling") def Parser_pool2d(args): - op = args[1] - helper = args[3] - OpsRegister()["Pooling"].pool_size = helper.attr_data(op, 'ksize') - OpsRegister()["Pooling"].strides = helper.attr_data(op, 'strides') - OpsRegister()["Pooling"].padding = helper.attr_data(op, 'paddings') - OpsRegister()["Pooling"].global_pooling = helper.attr_data(op, 'global_pooling') - if helper.attr_data(op, 'pooling_type') == 'max': - OpsRegister()["Pooling"].method = "MAX" - elif helper.attr_data(op, 'pooling_type') in ['average', 'avg']: - OpsRegister()["Pooling"].method = "AVG" - if helper.attr_data(op, 'ceil_mode') == False: - OpsRegister()["Pooling"].cmp_out_shape_floor_as_conv = True - else: - OpsRegister()["Pooling"].cmp_out_shape_floor_as_conv = False + op = args[1] + helper = args[3] + OpsRegister()["Pooling"].pool_size = helper.attr_data(op, 'ksize') + OpsRegister()["Pooling"].strides = helper.attr_data(op, 'strides') + OpsRegister()["Pooling"].padding = helper.attr_data(op, 'paddings') + OpsRegister()["Pooling"].global_pooling = helper.attr_data(op, 'global_pooling') + if helper.attr_data(op, 'pooling_type') == 'max': + OpsRegister()["Pooling"].method = "MAX" + elif helper.attr_data(op, 'pooling_type') in ['average', 'avg']: + OpsRegister()["Pooling"].method = "AVG" + if helper.attr_data(op, 'ceil_mode') == False: + OpsRegister()["Pooling"].cmp_out_shape_floor_as_conv = True + else: + OpsRegister()["Pooling"].cmp_out_shape_floor_as_conv = False @ParserFeedDecorator("Dense") def Parser_mul(args): - op = args[1] - helper = args[3] - private_data = args[4] - weights_needs_trans = True - [weights_tensor, weights_shape] = helper.param_tensor_sh(op, 'Y', weights_needs_trans) - OpsRegister()["Dense"].weight_1 = weights_tensor - OpsRegister()["Dense"].out_dim = weights_shape[2] - OpsRegister()["Dense"].axis = helper.attr_data(op, 'x_num_col_dims') - if 'bias' in private_data.keys(): - OpsRegister()["Dense"].bias_term = True - OpsRegister()["Dense"].weight_2 = private_data['bias'] - else: - OpsRegister()["Dense"].bias_term = False + op = args[1] + helper = args[3] + private_data = args[4] + weights_needs_trans = True + [weights_tensor, weights_shape] = helper.param_tensor_sh(op, 'Y', weights_needs_trans) + OpsRegister()["Dense"].weight_1 = weights_tensor + OpsRegister()["Dense"].out_dim = weights_shape[2] + OpsRegister()["Dense"].axis = helper.attr_data(op, 'x_num_col_dims') + if 'bias' in private_data.keys(): + OpsRegister()["Dense"].bias_term = True + OpsRegister()["Dense"].weight_2 = private_data['bias'] + else: + OpsRegister()["Dense"].bias_term = False @ParserFeedDecorator("Softmax") def Parser_softmax(args): - private_data = args[4] - if 'axis' in private_data.keys(): - axis = private_data['axis'] - else: - axis = 1 - OpsRegister()["Softmax"].axis = axis + private_data = args[4] + if 'axis' in private_data.keys(): + axis = private_data['axis'] + else: + axis = 1 + OpsRegister()["Softmax"].axis = axis @ParserFeedDecorator("Activation") def Parser_sigmoid(args): - OpsRegister()["Activation"].type = "Sigmoid" + OpsRegister()["Activation"].type = "Sigmoid" @ParserFeedDecorator("Axpy") def Parser_axpy(args): - pass + pass @ParserFeedDecorator("BatchNorm") def Parser_batch_norm(args): - op = args[1] - helper = args[3] - OpsRegister()["BatchNorm"].weight_1 = helper.param_tensor(op, 'Mean') - OpsRegister()["BatchNorm"].weight_2 = helper.param_tensor(op, 'Variance') - OpsRegister()["BatchNorm"].weight_3 = helper.create_tensor([1], [1, 1, 1, 1], FLOAT) - OpsRegister()["BatchNorm"].momentum = helper.attr_data(op, 'momentum') - OpsRegister()["BatchNorm"].epsilon = helper.attr_data(op, 'epsilon') + op = args[1] + helper = args[3] + OpsRegister()["BatchNorm"].weight_1 = helper.param_tensor(op, 'Mean') + OpsRegister()["BatchNorm"].weight_2 = helper.param_tensor(op, 'Variance') + OpsRegister()["BatchNorm"].weight_3 = helper.create_tensor([1], [1, 1, 1, 1], FLOAT) + OpsRegister()["BatchNorm"].momentum = helper.attr_data(op, 'momentum') + OpsRegister()["BatchNorm"].epsilon = helper.attr_data(op, 'epsilon') @ParserFeedDecorator("Scale") def Parser_scale_disc_bn(args): - op = args[1] - helper = args[3] - mean = helper.np_param(op, 'Mean') - var = helper.np_param(op, 'Variance') - alpha = helper.np_param(op, 'Scale') - beta = helper.np_param(op, 'Bias') - eps = helper.attr_data(op, 'epsilon') - var = np.sqrt(var + eps) - np_scale = alpha / var - np_bias = beta - (alpha * mean / var) - np_scale_shape = map(int, [1]*(4-len(np_scale.shape)) + list(np_scale.shape)) - np_bias_shape = map(int, [1]*(4-len(np_bias.shape)) + list(np_bias.shape)) - np_scale_tensor = helper.create_tensor(list(np_scale.flatten()), np_scale_shape, FLOAT) - np_bias_tensor = helper.create_tensor(list(np_bias.flatten()), np_bias_shape, FLOAT) - OpsRegister()["Scale"].bias_term = True - OpsRegister()["Scale"].weight_1 = np_scale_tensor - OpsRegister()["Scale"].weight_2 = np_bias_tensor - OpsRegister()["Scale"].axis = 1 - OpsRegister()["Scale"].num_axes = 1 + op = args[1] + helper = args[3] + mean = helper.np_param(op, 'Mean') + var = helper.np_param(op, 'Variance') + alpha = helper.np_param(op, 'Scale') + beta = helper.np_param(op, 'Bias') + eps = helper.attr_data(op, 'epsilon') + var = np.sqrt(var + eps) + np_scale = alpha / var + np_bias = beta - (alpha * mean / var) + np_scale_shape = map(int, [1] * (4 - len(np_scale.shape)) + list(np_scale.shape)) + np_bias_shape = map(int, [1] * (4 - len(np_bias.shape)) + list(np_bias.shape)) + np_scale_tensor = helper.create_tensor(list(np_scale.flatten()), np_scale_shape, FLOAT) + np_bias_tensor = helper.create_tensor(list(np_bias.flatten()), np_bias_shape, FLOAT) + OpsRegister()["Scale"].bias_term = True + OpsRegister()["Scale"].weight_1 = np_scale_tensor + OpsRegister()["Scale"].weight_2 = np_bias_tensor + OpsRegister()["Scale"].axis = 1 + OpsRegister()["Scale"].num_axes = 1 @ParserFeedDecorator("Scale") def Parser_scale_of_bn(args): - op = args[1] - helper = args[3] - OpsRegister()["Scale"].weight_1 = helper.param_tensor(op, 'Scale') - OpsRegister()["Scale"].axis = 1 - OpsRegister()["Scale"].num_axes = 1 - has_bias = helper.is_persistable_param(op, 'Bias') - if has_bias is True: - OpsRegister()["Scale"].bias_term = True - OpsRegister()["Scale"].weight_2 = helper.param_tensor(op, 'Bias') - else: - OpsRegister()["Scale"].bias_term = False + op = args[1] + helper = args[3] + OpsRegister()["Scale"].weight_1 = helper.param_tensor(op, 'Scale') + OpsRegister()["Scale"].axis = 1 + OpsRegister()["Scale"].num_axes = 1 + has_bias = helper.is_persistable_param(op, 'Bias') + if has_bias is True: + OpsRegister()["Scale"].bias_term = True + OpsRegister()["Scale"].weight_2 = helper.param_tensor(op, 'Bias') + else: + OpsRegister()["Scale"].bias_term = False @ParserFeedDecorator("Split") def Parser_split(args): - private_data = args[4] - split_num = private_data['split_num'] - OpsRegister()["Split"].split_num = split_num + private_data = args[4] + split_num = private_data['split_num'] + OpsRegister()["Split"].split_num = split_num -@ParserFeedDecorator("Reshape") # NMT +@ParserFeedDecorator("Reshape") def Parser_reshape(args): - op = args[1] - helper = args[3] - private_data = args[4] - if 'new_shape' in private_data.keys(): - shape = private_data['new_shape'] - else: - shape = helper.attr_data(op, 'shape') - shape = map(int, shape + [1] * (4 - len(shape))) - OpsRegister()["Reshape"].dims = shape + op = args[1] + helper = args[3] + private_data = args[4] + if 'new_shape' in private_data.keys(): + shape = private_data['new_shape'] + else: + shape = helper.attr_data(op, 'shape') + shape = map(int, shape + [1] * (4 - len(shape))) + OpsRegister()["Reshape"].dims = shape @ParserFeedDecorator("Concat") def Parser_concat(args): - op = args[1] - helper = args[3] - OpsRegister()["Concat"].axis = helper.attr_data(op, 'axis') + op = args[1] + helper = args[3] + OpsRegister()["Concat"].axis = helper.attr_data(op, 'axis') @ParserFeedDecorator("Concat") def Parser_concat_btw_priorbox_boxcoder(args): - op = args[1] - helper = args[3] - OpsRegister()["Concat"].axis = 3 + op = args[1] + helper = args[3] + OpsRegister()["Concat"].axis = 3 @ParserFeedDecorator("Permute") def Parser_transpose(args): - op = args[1] - helper = args[3] - fluid_dims = helper.attr_data(op, 'axis') - n = 4 - len(fluid_dims) - dims = range(0, n) - tail_dims = [i + n for i in fluid_dims] - dims.extend(tail_dims) - OpsRegister()["Permute"].dims = dims + op = args[1] + helper = args[3] + fluid_dims = helper.attr_data(op, 'axis') + n = 4 - len(fluid_dims) + dims = range(0, n) + tail_dims = [i + n for i in fluid_dims] + dims.extend(tail_dims) + OpsRegister()["Permute"].dims = dims ########## SSD Model ########## @ParserFeedDecorator("PriorBox") def Parser_prior_box(args): - op = args[1] - helper = args[3] - OpsRegister()["PriorBox"].min_size = helper.attr_data(op, 'min_sizes') - OpsRegister()["PriorBox"].max_size = helper.attr_data(op, 'max_sizes') - OpsRegister()["PriorBox"].aspect_ratio = helper.attr_data(op, 'aspect_ratios') - OpsRegister()["PriorBox"].is_flip = helper.attr_data(op, 'flip') - OpsRegister()["PriorBox"].is_clip = helper.attr_data(op, 'clip') - OpsRegister()["PriorBox"].variance = helper.attr_data(op, 'variances') - OpsRegister()["PriorBox"].img_h = 0 - OpsRegister()["PriorBox"].img_w = 0 - OpsRegister()["PriorBox"].step_h = helper.attr_data(op, 'step_h') - OpsRegister()["PriorBox"].step_w = helper.attr_data(op, 'step_w') - OpsRegister()["PriorBox"].offset = helper.attr_data(op, 'offset') - OpsRegister()["PriorBox"].order = ['MIN', 'COM', 'MAX'] + op = args[1] + helper = args[3] + OpsRegister()["PriorBox"].min_size = helper.attr_data(op, 'min_sizes') + OpsRegister()["PriorBox"].max_size = helper.attr_data(op, 'max_sizes') + OpsRegister()["PriorBox"].aspect_ratio = helper.attr_data(op, 'aspect_ratios') + OpsRegister()["PriorBox"].is_flip = helper.attr_data(op, 'flip') + OpsRegister()["PriorBox"].is_clip = helper.attr_data(op, 'clip') + OpsRegister()["PriorBox"].variance = helper.attr_data(op, 'variances') + OpsRegister()["PriorBox"].img_h = 0 + OpsRegister()["PriorBox"].img_w = 0 + OpsRegister()["PriorBox"].step_h = helper.attr_data(op, 'step_h') + OpsRegister()["PriorBox"].step_w = helper.attr_data(op, 'step_w') + OpsRegister()["PriorBox"].offset = helper.attr_data(op, 'offset') + OpsRegister()["PriorBox"].order = ['MIN', 'COM', 'MAX'] @ParserFeedDecorator("box_coder") def Parser_box_coder(args): - pass + pass @ParserFeedDecorator("DetectionOutput") def Parser_multiclass_nms(args): - op = args[1] - helper = args[3] - private_data = args[4] - OpsRegister()["DetectionOutput"].share_location = True - OpsRegister()["DetectionOutput"].variance_encode_in_target = False - OpsRegister()["DetectionOutput"].class_num = 0 - OpsRegister()["DetectionOutput"].background_id = helper.attr_data(op, 'background_label') - OpsRegister()["DetectionOutput"].keep_top_k = helper.attr_data(op, 'keep_top_k') - OpsRegister()["DetectionOutput"].conf_thresh = helper.attr_data(op, 'score_threshold') - OpsRegister()["DetectionOutput"].nms_top_k = helper.attr_data(op, 'nms_top_k') - OpsRegister()["DetectionOutput"].nms_thresh = helper.attr_data(op, 'nms_threshold') - OpsRegister()["DetectionOutput"].nms_eta = helper.attr_data(op, 'nms_eta') - if 'code_type' in private_data.keys(): - if private_data['code_type'] == 'decode_center_size': - OpsRegister()["DetectionOutput"].code_type = "CENTER_SIZE" - else: - OpsRegister()["DetectionOutput"].code_type = "CORNER" + op = args[1] + helper = args[3] + private_data = args[4] + OpsRegister()["DetectionOutput"].share_location = True + OpsRegister()["DetectionOutput"].variance_encode_in_target = False + OpsRegister()["DetectionOutput"].class_num = 0 + OpsRegister()["DetectionOutput"].background_id = helper.attr_data(op, 'background_label') + OpsRegister()["DetectionOutput"].keep_top_k = helper.attr_data(op, 'keep_top_k') + OpsRegister()["DetectionOutput"].conf_thresh = helper.attr_data(op, 'score_threshold') + OpsRegister()["DetectionOutput"].nms_top_k = helper.attr_data(op, 'nms_top_k') + OpsRegister()["DetectionOutput"].nms_thresh = helper.attr_data(op, 'nms_threshold') + OpsRegister()["DetectionOutput"].nms_eta = helper.attr_data(op, 'nms_eta') + if 'code_type' in private_data.keys(): + if private_data['code_type'] == 'decode_center_size': + OpsRegister()["DetectionOutput"].code_type = "CENTER_SIZE" + else: + OpsRegister()["DetectionOutput"].code_type = "CORNER" ########## VIS Model ########## @ParserFeedDecorator("Im2Sequence") def Parser_im2sequence(args): - op = args[1] - helper = args[3] - OpsRegister()["Im2Sequence"].paddings = helper.attr_data(op, 'paddings') - OpsRegister()["Im2Sequence"].strides = helper.attr_data(op, 'strides') - OpsRegister()["Im2Sequence"].window_size = helper.attr_data(op, 'kernels') - OpsRegister()["Im2Sequence"].dilations = helper.attr_data(op, 'dilations', [1, 1]) + op = args[1] + helper = args[3] + OpsRegister()["Im2Sequence"].paddings = helper.attr_data(op, 'paddings') + OpsRegister()["Im2Sequence"].strides = helper.attr_data(op, 'strides') + OpsRegister()["Im2Sequence"].window_size = helper.attr_data(op, 'kernels') + OpsRegister()["Im2Sequence"].dilations = helper.attr_data(op, 'dilations', [1, 1]) @ParserFeedDecorator("Cast") def Parser_cast(args): - op = args[1] - helper = args[3] - OpsRegister()["Cast"].in_type = helper.attr_data(op, 'in_dtype') - OpsRegister()["Cast"].out_type = helper.attr_data(op, 'out_dtype') + op = args[1] + helper = args[3] + OpsRegister()["Cast"].in_type = helper.attr_data(op, 'in_dtype') + OpsRegister()["Cast"].out_type = helper.attr_data(op, 'out_dtype') @ParserFeedDecorator("Argmax") # new256 def Parser_top_k(args): - op = args[1] - helper = args[3] - OpsRegister()["Argmax"].out_max_val = True - OpsRegister()["Argmax"].top_k = helper.attr_data(op, 'k') - OpsRegister()["Argmax"].axis_term = False + op = args[1] + helper = args[3] + OpsRegister()["Argmax"].out_max_val = True + OpsRegister()["Argmax"].top_k = helper.attr_data(op, 'k') + OpsRegister()["Argmax"].axis_term = False @ParserFeedDecorator("CtcAlign") def Parser_ctc_align(args): - op = args[1] - helper = args[3] - OpsRegister()["CtcAlign"].merge_repeated = helper.attr_data(op, 'merge_repeated') - OpsRegister()["CtcAlign"].blank = helper.attr_data(op, 'blank') + op = args[1] + helper = args[3] + OpsRegister()["CtcAlign"].merge_repeated = helper.attr_data(op, 'merge_repeated') + OpsRegister()["CtcAlign"].blank = helper.attr_data(op, 'blank') @ParserFeedDecorator("Eltwise") def Parser_sum(args): - OpsRegister()["Eltwise"].type = "Add" - OpsRegister()["Eltwise"].coeff = [1.0, 1.0] + OpsRegister()["Eltwise"].type = "Add" + OpsRegister()["Eltwise"].coeff = [1.0, 1.0] @ParserFeedDecorator("LRN") def Parser_lrn(args): - op = args[1] - helper = args[3] - OpsRegister()["LRN"].local_size = helper.attr_data(op, 'n') - OpsRegister()["LRN"].alpha = helper.attr_data(op, 'alpha') - OpsRegister()["LRN"].beta = helper.attr_data(op, 'beta') - OpsRegister()["LRN"].norm_region = "ACROSS_CHANNELS" - OpsRegister()["LRN"].k = helper.attr_data(op, 'k') + op = args[1] + helper = args[3] + OpsRegister()["LRN"].local_size = helper.attr_data(op, 'n') + OpsRegister()["LRN"].alpha = helper.attr_data(op, 'alpha') + OpsRegister()["LRN"].beta = helper.attr_data(op, 'beta') + OpsRegister()["LRN"].norm_region = "ACROSS_CHANNELS" + OpsRegister()["LRN"].k = helper.attr_data(op, 'k') @ParserFeedDecorator("Gru") def Parser_gru(args): - op = args[1] - helper = args[3] - private_data = args[4] - OpsRegister()["Gru"].is_reverse = helper.attr_data(op, 'is_reverse') - OpsRegister()["Gru"].gate_activation = helper.attr_data(op, 'gate_activation') + '_fluid' - OpsRegister()["Gru"].activation = helper.attr_data(op, 'activation') + '_fluid' - OpsRegister()["Gru"].gru_formula = "gru_origin" - if bool(private_data) is True: - ori_bx = private_data['np_bias_x'] - ori_bh = helper.np_param(op, 'Bias') - ori_b = ori_bx + ori_bh - ori_wx = private_data['np_weight_x'] - ori_wh = helper.np_param(op, 'Weight') - new_tensors = helper.gru_tensor_convert(ori_wh, ori_wx, ori_b) - weights = [] - for tensor in new_tensors: - weights.append(helper.create_tensor(list(tensor.flatten()), list(np.shape(tensor)), FLOAT)) - OpsRegister()["Gru"].weight_1 = weights[0] - OpsRegister()["Gru"].weight_2 = weights[1] - else: - OpsRegister()["Gru"].weight_1 = helper.param_tensor(op, 'Weight') - OpsRegister()["Gru"].weight_2 = helper.create_tensor([0], [-1], FLOAT) + op = args[1] + helper = args[3] + private_data = args[4] + OpsRegister()["Gru"].is_reverse = helper.attr_data(op, 'is_reverse') + OpsRegister()["Gru"].gate_activation = helper.attr_data(op, 'gate_activation') + '_fluid' + OpsRegister()["Gru"].activation = helper.attr_data(op, 'activation') + '_fluid' + OpsRegister()["Gru"].gru_formula = "gru_origin" + if bool(private_data) is True: + ori_bx = private_data['np_bias_x'] + ori_bh = helper.np_param(op, 'Bias') + ori_b = ori_bx + ori_bh + ori_wx = private_data['np_weight_x'] + ori_wh = helper.np_param(op, 'Weight') + new_tensors = helper.gru_tensor_convert(ori_wh, ori_wx, ori_b) + weights = [] + for tensor in new_tensors: + weights.append(helper.create_tensor(list(tensor.flatten()), \ + list(np.shape(tensor)), FLOAT)) + OpsRegister()["Gru"].weight_1 = weights[0] + OpsRegister()["Gru"].weight_2 = weights[1] + else: + OpsRegister()["Gru"].weight_1 = helper.param_tensor(op, 'Weight') + OpsRegister()["Gru"].weight_2 = helper.create_tensor([0], [-1], FLOAT) @ParserFeedDecorator("LSTM") def Parser_lstm(args): - op = args[1] - helper = args[3] - private_data = args[4] - OpsRegister()["LSTM"].candidate_activation = helper.attr_data(op, 'candidate_activation') - OpsRegister()["LSTM"].cell_activation = helper.attr_data(op, 'cell_activation') - OpsRegister()["LSTM"].gate_activation = helper.attr_data(op, 'gate_activation') - OpsRegister()["LSTM"].is_reverse = helper.attr_data(op, 'is_reverse') - OpsRegister()["LSTM"].use_peepholes = helper.attr_data(op, 'use_peepholes') - OpsRegister()["LSTM"].num_direction = 1 - OpsRegister()["LSTM"].dropout_param = 1.0 - OpsRegister()["LSTM"].num_layers = 1 - OpsRegister()["LSTM"].input_activation = "null" - if bool(private_data) is True: - np_fc_bias = private_data['np_flat_fc_bias'] - np_fc_weight = private_data['np_flat_fc_weight'] - np_fc_outdim = private_data['np_fc_outdim'] - np_lstm_bias = helper.np_param(op, 'Bias') - np_lstm_weight = helper.np_param(op, 'Weight') - np_tensors = helper.lstm_fc_tensor_merge_convert(np_fc_outdim, np_lstm_weight, \ - np_lstm_bias, np_fc_weight, np_fc_bias) - np_weight = np_tensors[0] - np_bias = np_tensors[1] - np_weight_shape = map(int, [1]*(4-len(np_weight.shape)) + list(np_weight.shape)) - np_bias_shape = map(int, [1]*(4-len(np_bias.shape)) + list(np_bias.shape)) - np_weight_tensor = helper.create_tensor(list(np_weight.flatten()), np_weight_shape, FLOAT) - np_bias_tensor = helper.create_tensor(list(np_bias.flatten()), np_bias_shape, FLOAT) - OpsRegister()["LSTM"].weight_1 = np_weight_tensor - OpsRegister()["LSTM"].weight_2 = np_bias_tensor - else: - OpsRegister()["LSTM"].weight_1 = helper.param_tensor(op, 'Weight') - OpsRegister()["LSTM"].weight_2 = helper.create_tensor([0], [-1], FLOAT) + op = args[1] + helper = args[3] + private_data = args[4] + OpsRegister()["LSTM"].candidate_activation = helper.attr_data(op, 'candidate_activation') + OpsRegister()["LSTM"].cell_activation = helper.attr_data(op, 'cell_activation') + OpsRegister()["LSTM"].gate_activation = helper.attr_data(op, 'gate_activation') + OpsRegister()["LSTM"].is_reverse = helper.attr_data(op, 'is_reverse') + OpsRegister()["LSTM"].use_peepholes = helper.attr_data(op, 'use_peepholes') + OpsRegister()["LSTM"].num_direction = 1 + OpsRegister()["LSTM"].dropout_param = 1.0 + OpsRegister()["LSTM"].num_layers = 1 + OpsRegister()["LSTM"].input_activation = "null" + if bool(private_data) is True: + np_fc_bias = private_data['np_flat_fc_bias'] + np_fc_weight = private_data['np_flat_fc_weight'] + np_fc_outdim = private_data['np_fc_outdim'] + np_lstm_bias = helper.np_param(op, 'Bias') + np_lstm_weight = helper.np_param(op, 'Weight') + np_tensors = helper.lstm_fc_tensor_merge_convert(np_fc_outdim, np_lstm_weight, \ + np_lstm_bias, np_fc_weight, np_fc_bias) + np_weight = np_tensors[0] + np_bias = np_tensors[1] + np_weight_shape = map(int, [1] * (4 - len(np_weight.shape)) + list(np_weight.shape)) + np_bias_shape = map(int, [1] * (4 - len(np_bias.shape)) + list(np_bias.shape)) + np_weight_tensor = helper.create_tensor(list(np_weight.flatten()), np_weight_shape, FLOAT) + np_bias_tensor = helper.create_tensor(list(np_bias.flatten()), np_bias_shape, FLOAT) + OpsRegister()["LSTM"].weight_1 = np_weight_tensor + OpsRegister()["LSTM"].weight_2 = np_bias_tensor + else: + OpsRegister()["LSTM"].weight_1 = helper.param_tensor(op, 'Weight') + OpsRegister()["LSTM"].weight_2 = helper.create_tensor([0], [-1], FLOAT) ############### RNN ############### @ParserFeedDecorator("Embedding") def Parser_lookup_table(args): - op = args[1] - helper = args[3] - [weights_tensor, weights_shape] = helper.param_tensor_sh(op, 'W') - OpsRegister()["Embedding"].weight_1 = weights_tensor - OpsRegister()["Embedding"].padding_idx = helper.attr_data(op, 'padding_idx') - OpsRegister()["Embedding"].word_num = weights_shape[2] - OpsRegister()["Embedding"].emb_dim = weights_shape[3] + op = args[1] + helper = args[3] + [weights_tensor, weights_shape] = helper.param_tensor_sh(op, 'W') + OpsRegister()["Embedding"].weight_1 = weights_tensor + OpsRegister()["Embedding"].padding_idx = helper.attr_data(op, 'padding_idx') + OpsRegister()["Embedding"].word_num = weights_shape[2] + OpsRegister()["Embedding"].emb_dim = weights_shape[3] @ParserFeedDecorator("SequencePool") def Parser_sequence_pool(args): - op = args[1] - helper = args[3] - OpsRegister()["SequencePool"].pooltype = helper.attr_data(op, 'pooltype') + op = args[1] + helper = args[3] + OpsRegister()["SequencePool"].pooltype = helper.attr_data(op, 'pooltype') @ParserFeedDecorator("Activation") def Parser_tanh(args): - OpsRegister()["Activation"].type = "TanH" + OpsRegister()["Activation"].type = "TanH" @ParserFeedDecorator("SequenceConv") def Parser_sequence_conv(args): - op = args[1] - helper = args[3] - private_data = args[4] - [weights_tensor, weights_shape] = helper.param_tensor_sh(op, 'Filter') - OpsRegister()["SequenceConv"].weight_1 = weights_tensor - OpsRegister()["SequenceConv"].filter_num = weights_shape[0] - OpsRegister()["SequenceConv"].kernel_size = weights_shape[-2:] - OpsRegister()["SequenceConv"].padding_trainable = helper.attr_data(op, 'paddingTrainable') - OpsRegister()["SequenceConv"].context_stride = helper.attr_data(op, 'contextStride') - OpsRegister()["SequenceConv"].context_start = helper.attr_data(op, 'contextStart') - OpsRegister()["SequenceConv"].context_length = helper.attr_data(op, 'contextLength') - if 'bias' in private_data.keys(): - OpsRegister()["SequenceConv"].bias_term = True - OpsRegister()["SequenceConv"].weight_2 = private_data['bias'] - else: - OpsRegister()["SequenceConv"].bias_term = False + op = args[1] + helper = args[3] + private_data = args[4] + [weights_tensor, weights_shape] = helper.param_tensor_sh(op, 'Filter') + OpsRegister()["SequenceConv"].weight_1 = weights_tensor + OpsRegister()["SequenceConv"].filter_num = weights_shape[0] + OpsRegister()["SequenceConv"].kernel_size = weights_shape[-2:] + OpsRegister()["SequenceConv"].padding_trainable = helper.attr_data(op, 'paddingTrainable') + OpsRegister()["SequenceConv"].context_stride = helper.attr_data(op, 'contextStride') + OpsRegister()["SequenceConv"].context_start = helper.attr_data(op, 'contextStart') + OpsRegister()["SequenceConv"].context_length = helper.attr_data(op, 'contextLength') + if 'bias' in private_data.keys(): + OpsRegister()["SequenceConv"].bias_term = True + OpsRegister()["SequenceConv"].weight_2 = private_data['bias'] + else: + OpsRegister()["SequenceConv"].bias_term = False @ParserFeedDecorator("CrfDecoding") def Parser_crf_decoding(args): - op = args[1] - helper = args[3] - [weights_tensor, weights_shape] = helper.param_tensor_sh(op, 'Transition') - OpsRegister()["CrfDecoding"].weight_1 = weights_tensor + op = args[1] + helper = args[3] + [weights_tensor, weights_shape] = helper.param_tensor_sh(op, 'Transition') + OpsRegister()["CrfDecoding"].weight_1 = weights_tensor @ParserFeedDecorator("MatMul") def Parser_matmul(args): - op = args[1] - helper = args[3] - private_data = args[4] - if 'coeff' in private_data.keys(): - coeff = private_data['coeff'] - else: - coeff = 1.0 - OpsRegister()["MatMul"].transpose_x = helper.attr_data(op, 'transpose_X') - OpsRegister()["MatMul"].transpose_y = helper.attr_data(op, 'transpose_Y') - OpsRegister()["MatMul"].coeff = coeff + op = args[1] + helper = args[3] + private_data = args[4] + if 'coeff' in private_data.keys(): + coeff = private_data['coeff'] + else: + coeff = 1.0 + OpsRegister()["MatMul"].transpose_x = helper.attr_data(op, 'transpose_X') + OpsRegister()["MatMul"].transpose_y = helper.attr_data(op, 'transpose_Y') + OpsRegister()["MatMul"].coeff = coeff @ParserFeedDecorator("Scale") def Parser_scale(args): - op = args[1] - helper = args[3] - scale_val = helper.attr_data(op, 'scale') - OpsRegister()["Scale"].axis = 0 - OpsRegister()["Scale"].num_axes = 0 - OpsRegister()["Scale"].bias_term = False - OpsRegister()["Scale"].weight_1 = helper.create_tensor([scale_val], [1, 1, 1, 1], FLOAT) + op = args[1] + helper = args[3] + scale_val = helper.attr_data(op, 'scale') + OpsRegister()["Scale"].axis = 0 + OpsRegister()["Scale"].num_axes = 0 + OpsRegister()["Scale"].bias_term = False + OpsRegister()["Scale"].weight_1 = helper.create_tensor([scale_val], [1, 1, 1, 1], FLOAT) @ParserFeedDecorator("LayerNorm") def Parser_layer_norm(args): - op = args[1] - helper = args[3] - OpsRegister()["LayerNorm"].weight_1 = helper.param_tensor(op, 'Scale') - OpsRegister()["LayerNorm"].weight_2 = helper.param_tensor(op, 'Bias') - OpsRegister()["LayerNorm"].begin_norm_axis = helper.attr_data(op, 'begin_norm_axis') - OpsRegister()["LayerNorm"].eps = helper.attr_data(op, 'epsilon') + op = args[1] + helper = args[3] + OpsRegister()["LayerNorm"].weight_1 = helper.param_tensor(op, 'Scale') + OpsRegister()["LayerNorm"].weight_2 = helper.param_tensor(op, 'Bias') + OpsRegister()["LayerNorm"].begin_norm_axis = helper.attr_data(op, 'begin_norm_axis') + OpsRegister()["LayerNorm"].eps = helper.attr_data(op, 'epsilon') @ParserFeedDecorator("Scale") def Parser_dropout(args): - op = args[1] - helper = args[3] - scale_val = 1 - helper.attr_data(op, 'dropout_prob') - OpsRegister()["Scale"].axis = 0 - OpsRegister()["Scale"].num_axes = 0 - OpsRegister()["Scale"].bias_term = False - OpsRegister()["Scale"].weight_1 = helper.create_tensor([scale_val], [1, 1, 1, 1], FLOAT) + op = args[1] + helper = args[3] + scale_val = 1 - helper.attr_data(op, 'dropout_prob') + OpsRegister()["Scale"].axis = 0 + OpsRegister()["Scale"].num_axes = 0 + OpsRegister()["Scale"].bias_term = False + OpsRegister()["Scale"].weight_1 = helper.create_tensor([scale_val], [1, 1, 1, 1], FLOAT) @ParserFeedDecorator("Scale") def Parser_elementwise_mul(args): - op = args[1] - helper = args[3] - private_data = args[4] - OpsRegister()["Scale"].weight_1 = helper.param_tensor(op, 'Y') - OpsRegister()["Scale"].axis = helper.attr_data(op, 'axis') - OpsRegister()["Scale"].num_axes = 1 - if 'bias' in private_data.keys(): - OpsRegister()["Scale"].bias_term = True - OpsRegister()["Scale"].weight_2 = private_data['bias'] - else: - OpsRegister()["Scale"].bias_term = False + op = args[1] + helper = args[3] + private_data = args[4] + OpsRegister()["Scale"].weight_1 = helper.param_tensor(op, 'Y') + OpsRegister()["Scale"].axis = helper.attr_data(op, 'axis') + OpsRegister()["Scale"].num_axes = 1 + if 'bias' in private_data.keys(): + OpsRegister()["Scale"].bias_term = True + OpsRegister()["Scale"].weight_2 = private_data['bias'] + else: + OpsRegister()["Scale"].bias_term = False FLUID_NODE_FILLER = { - "feed":OpsParam().set_parser(Parser_feed), - "conv2d":OpsParam().set_parser(Parser_conv2d), - "elementwise_add":OpsParam().set_parser(Parser_sum), - "relu":OpsParam().set_parser(Parser_relu), - "pool2d":OpsParam().set_parser(Parser_pool2d), - "mul":OpsParam().set_parser(Parser_mul), - "softmax":OpsParam().set_parser(Parser_softmax), - "sigmoid":OpsParam().set_parser(Parser_sigmoid), - "axpy":OpsParam().set_parser(Parser_axpy), - "batch_norm":OpsParam().set_parser(Parser_batch_norm), - "disc_bn":OpsParam().set_parser(Parser_scale_disc_bn), - "scale_of_bn":OpsParam().set_parser(Parser_scale_of_bn), - "elementwise_mul":OpsParam().set_parser(Parser_elementwise_mul), - "split":OpsParam().set_parser(Parser_split), - "depthwise_conv2d":OpsParam().set_parser(Parser_conv2d), - "reshape":OpsParam().set_parser(Parser_reshape), - "concat":OpsParam().set_parser(Parser_concat), - "transpose":OpsParam().set_parser(Parser_transpose), - "prior_box":OpsParam().set_parser(Parser_prior_box), - "box_coder":OpsParam().set_parser(Parser_box_coder), - "multiclass_nms":OpsParam().set_parser(Parser_multiclass_nms), - "concat_btw_priorbox_boxcoder":OpsParam().set_parser(Parser_concat_btw_priorbox_boxcoder), - "im2sequence":OpsParam().set_parser(Parser_im2sequence), - "gru":OpsParam().set_parser(Parser_gru), - "sum":OpsParam().set_parser(Parser_sum), - "lrn":OpsParam().set_parser(Parser_lrn), - "top_k":OpsParam().set_parser(Parser_top_k), - "ctc_align":OpsParam().set_parser(Parser_ctc_align), - "cast":OpsParam().set_parser(Parser_cast), - "lookup_table":OpsParam().set_parser(Parser_lookup_table), - "sequence_pool":OpsParam().set_parser(Parser_sequence_pool), - "tanh":OpsParam().set_parser(Parser_tanh), - "sequence_conv":OpsParam().set_parser(Parser_sequence_conv), - "crf_decoding":OpsParam().set_parser(Parser_crf_decoding), - "lstm":OpsParam().set_parser(Parser_lstm), - "matmul":OpsParam().set_parser(Parser_matmul), - "layer_norm":OpsParam().set_parser(Parser_layer_norm), - "dropout":OpsParam().set_parser(Parser_dropout), - "scale":OpsParam().set_parser(Parser_scale), + "feed":OpsParam().set_parser(Parser_feed), + "conv2d":OpsParam().set_parser(Parser_conv2d), + "elementwise_add":OpsParam().set_parser(Parser_sum), + "relu":OpsParam().set_parser(Parser_relu), + "pool2d":OpsParam().set_parser(Parser_pool2d), + "mul":OpsParam().set_parser(Parser_mul), + "softmax":OpsParam().set_parser(Parser_softmax), + "sigmoid":OpsParam().set_parser(Parser_sigmoid), + "axpy":OpsParam().set_parser(Parser_axpy), + "batch_norm":OpsParam().set_parser(Parser_batch_norm), + "disc_bn":OpsParam().set_parser(Parser_scale_disc_bn), + "scale_of_bn":OpsParam().set_parser(Parser_scale_of_bn), + "elementwise_mul":OpsParam().set_parser(Parser_elementwise_mul), + "split":OpsParam().set_parser(Parser_split), + "depthwise_conv2d":OpsParam().set_parser(Parser_conv2d), + "reshape":OpsParam().set_parser(Parser_reshape), + "concat":OpsParam().set_parser(Parser_concat), + "transpose":OpsParam().set_parser(Parser_transpose), + "prior_box":OpsParam().set_parser(Parser_prior_box), + "box_coder":OpsParam().set_parser(Parser_box_coder), + "multiclass_nms":OpsParam().set_parser(Parser_multiclass_nms), + "concat_btw_priorbox_boxcoder":OpsParam().set_parser(Parser_concat_btw_priorbox_boxcoder), + "im2sequence":OpsParam().set_parser(Parser_im2sequence), + "gru":OpsParam().set_parser(Parser_gru), + "sum":OpsParam().set_parser(Parser_sum), + "lrn":OpsParam().set_parser(Parser_lrn), + "top_k":OpsParam().set_parser(Parser_top_k), + "ctc_align":OpsParam().set_parser(Parser_ctc_align), + "cast":OpsParam().set_parser(Parser_cast), + "lookup_table":OpsParam().set_parser(Parser_lookup_table), + "sequence_pool":OpsParam().set_parser(Parser_sequence_pool), + "tanh":OpsParam().set_parser(Parser_tanh), + "sequence_conv":OpsParam().set_parser(Parser_sequence_conv), + "crf_decoding":OpsParam().set_parser(Parser_crf_decoding), + "lstm":OpsParam().set_parser(Parser_lstm), + "matmul":OpsParam().set_parser(Parser_matmul), + "layer_norm":OpsParam().set_parser(Parser_layer_norm), + "dropout":OpsParam().set_parser(Parser_dropout), + "scale":OpsParam().set_parser(Parser_scale), } diff --git a/tools/external_converter_v2/parser/kill_fluid/parser_fluid.py b/tools/external_converter_v2/parser/kill_fluid/parser_fluid.py index 088b0d84c..ebdcc3790 100644 --- a/tools/external_converter_v2/parser/kill_fluid/parser_fluid.py +++ b/tools/external_converter_v2/parser/kill_fluid/parser_fluid.py @@ -8,861 +8,885 @@ class FluidParser: - def __init__(self, fluid_config_dict): - # anakin graph model io - self.graphIO = None - # config info - self.ModelPath = fluid_config_dict['ModelPath'] - self.NetType = fluid_config_dict['NetType'] - self.Debug = fluid_config_dict['Debug'] - # config fluid - self.place = fluid.CPUPlace() - self.exe = fluid.Executor(self.place) - self.scope = fluid.core.Scope() - # in and out edges of node - self.ins = {} - self.outs = {} - # inplaced main node - self.inplace_nodes = {} - self.graph_ins = [] - self.graph_outs = [] - - def __call__(self): - return self._Parsing() - - def _NameNodeMid(self, op): - first_outparam = op.output_names[0] - arg_name = str(op.output(first_outparam)[0]).split('.')[0] - #new_name = op.type + '_' + bytes(op.idx) - new_name = op.type + '#' + bytes(op.idx) + '(' + arg_name + ')' - return new_name - - def _NameNodeIn(self, in_name): - new_name = 'input_' + bytes(self.graph_ins.index(in_name)) - return new_name - - def _NameNodeOut(self, out_name): - new_name = out_name + '_gout' - return new_name - - def _AddPairEdges(self, start_node_name, end_node_name, out_param, in_param): - self.outs[start_node_name].add(out_param, end_node_name) - self.ins[end_node_name].add(in_param, start_node_name) - - def _RmPairEdges(self, start_node_name, end_node_name): - self.outs[start_node_name].rm(end_node_name) - self.ins[end_node_name].rm(start_node_name) - - def _InitEdges(self, node_name): - self.ins[node_name] = Fluid_edger() - self.outs[node_name] = Fluid_edger() - - def _ClearEdges(self, node_name): - if node_name.startswith('input_') is False: - del self.ins[node_name] - if node_name.endswith('_gout') is False: - del self.outs[node_name] - - def _GetOp(self, ops, mid_node_name): - mid_op = None - for op in ops: - node_name = self._NameNodeMid(op) - if mid_node_name == node_name: - mid_op = op - return mid_op - - def _OpTypes(self, ops): - types_cache = [] - for op in ops: - if op.type not in types_cache: - types_cache.append(op.type) - return types_cache - - def _AddProtoNode(self, node_name, op_of_node, helper, private_data, op_type = None): - nodeIO = NodeProtoIO() - opIO = OpsProtoIO() - nodeIO.set_name(node_name) - if op_type is None: - op_type = op_of_node.type - FLUID_NODE_FILLER[op_type](nodeIO, op_of_node, opIO, helper, private_data) - self.graphIO.add_node(nodeIO()) - - def _RmProtoNode(self, node_name): - self.graphIO.rm_node(self.graphIO.find_node_proto(node_name)) - - def _InplaceNodes(self, position): - inplace_heads = self.inplace_nodes.keys() - inplace_mids = [] - inplace_ends = [] - for main_node_name in self.inplace_nodes.keys(): - mid_nodes_name = self.inplace_nodes[main_node_name][1: -1] - inplace_mids.extend(mid_nodes_name) - for main_node_name in self.inplace_nodes.keys(): - end_node_name = self.inplace_nodes[main_node_name][-1] - inplace_ends.append(end_node_name) - if position == 'Head': - return inplace_heads - elif position == 'Mid': - return inplace_mids - elif position == 'End': - return inplace_ends - elif position == 'All': - return inplace_heads + inplace_mids + inplace_ends - - def _EdgeInplace(self, source_ops, helper): - for source_op in source_ops: - if source_op.type not in ['feed', 'fetch']: - if len(source_op.input_arg_names) == 1 \ - and source_op.input_arg_names == source_op.output_arg_names: - source_node_name = self._NameNodeMid(source_op) - inplace_arg = source_op.input_arg_names[0] - for tmp_op in source_ops: - if tmp_op.idx != source_op.idx and inplace_arg in tmp_op.output_arg_names: - main_node_name = self._NameNodeMid(tmp_op) - if main_node_name not in self.inplace_nodes.keys(): - self.inplace_nodes[main_node_name] = [main_node_name] - self.inplace_nodes[main_node_name].append(source_node_name) - for main_node_name in self.inplace_nodes.keys(): - inplace_list = self.inplace_nodes[main_node_name] - for inplace_node in inplace_list: - idx = inplace_list.index(inplace_node) - if idx != 0: - self.ins[inplace_node] = Fluid_edger('_In', inplace_list[idx - 1]) - if idx != len(inplace_list) - 1: - self.outs[inplace_node] = Fluid_edger('_Out', inplace_list[idx + 1]) - - def _GetDebugOuts(self, source_ops, helper): - if self.Debug == 'DEBUG': - debug_fetch_list = [] - for source_op in source_ops: - if source_op.type == 'fetch': - var_name = source_op.input_arg_names[0] - for tmp_op in source_ops: - if tmp_op.idx != source_op.idx and var_name in tmp_op.input_arg_names: - if var_name not in debug_fetch_list: - debug_fetch_list.append(var_name) - elif tmp_op.type == 'gru' and var_name in tmp_op.output_arg_names: - if var_name not in debug_fetch_list: - debug_fetch_list.append(var_name) - else: - pass - return debug_fetch_list - else: - return [] - - def _ParseBase(self, source_ops, helper, sub_graph_nodes = []): - # Create the original base graph as described in fluid program. - self.graphIO = GraphProtoIO() - self.graphIO.set_name('default_graph_name') - debug_fetch_list = self._GetDebugOuts(source_ops, helper) - self._EdgeInplace(source_ops, helper) - for source_op in source_ops: - if source_op.type not in ['feed', 'fetch']: - main_node_name = self._NameNodeMid(source_op) - in_edges = Fluid_edger() - out_edges = Fluid_edger() - for param in source_op.input_names: - for idx in range(0, len(helper.args_by_input_param(source_op, param))): - arg = helper.var_name_by_param(source_op, param, idx) - for tmp_op in source_ops: - if tmp_op.idx != source_op.idx and arg in tmp_op.output_arg_names: - if tmp_op.type == 'feed': - if arg not in self.graph_ins: - self.graph_ins.append(arg) - self.graphIO.add_in(self._NameNodeIn(arg)) - in_edges.add(param, self._NameNodeIn(arg), arg) - else: - tmp_node_name = self._NameNodeMid(tmp_op) - if tmp_node_name in self.inplace_nodes.keys(): - inplace_node_name = self.inplace_nodes[tmp_node_name][-1] - in_edges.add(param, inplace_node_name, arg) - elif tmp_node_name not in self._InplaceNodes('All'): - in_edges.add(param, tmp_node_name, arg) - for param in source_op.output_names: - for idx in range(0, len(helper.args_by_output_param(source_op, param))): - arg = helper.var_name_by_param(source_op, param, idx) - for tmp_op in source_ops: - if tmp_op.idx != source_op.idx and arg in tmp_op.input_arg_names: - if tmp_op.type == 'fetch': - if arg not in debug_fetch_list: - arg_node_name = self._NameNodeOut(arg) - if arg not in self.graph_outs: - self.graph_outs.append(arg) - self.graphIO.add_out_fluid(arg_node_name, main_node_name) - out_edges.add(param, arg_node_name, arg) - self.ins[arg_node_name] = Fluid_edger(bytes(source_op.idx), \ - main_node_name) - else: - out_edges.add(param, self._NameNodeMid(tmp_op), arg) - self._AddProtoNode(main_node_name, source_op, helper, {}) - if main_node_name not in self._InplaceNodes('Mid'): - if main_node_name not in self._InplaceNodes('End'): - self.ins[main_node_name] = in_edges - if main_node_name not in self._InplaceNodes('Head'): - if main_node_name not in self._InplaceNodes('End'): - self.outs[main_node_name] = out_edges - else: - inplace_node_name = self.inplace_nodes[main_node_name][-1] - self.outs[inplace_node_name] = out_edges - for redundant_target in self.inplace_nodes[main_node_name][1:]: - self.outs[inplace_node_name].rm(redundant_target) - - def _PrintEdge(self, node, target, direction): - var_name = 'Unknown' - if direction == 'in': - var = self.ins[node].vars_by_target(target) - elif direction == 'out': - var = self.outs[node].vars_by_target(target) - if len(var) > 0: - var_name = var[0] - print node + ",\t" + target + ",\t" + var_name - - def _Graph(self, need_print = False): - for node in self.ins.keys(): - targets_list = self.ins[node]() - for target in targets_list: - self.graphIO.add_in_edge(target, node) - for node in self.outs.keys(): - targets_list = self.outs[node]() - for target in targets_list: - self.graphIO.add_out_edge(node, target) - if need_print is True: - self._PrintEdge(node, target, 'out') - - def _ReplaceInputs(self, source_ops, helper, reshape_dict = {}, layout = 'NCHW'): - for source_op in source_ops: - if source_op.type in ['feed']: - out_edges = Fluid_edger() - for param in source_op.output_names: - private_data = {} - arg = helper.var_name_by_param(source_op, param) - input_node_name = self._NameNodeIn(arg) - for tmp_op in source_ops: - if tmp_op.idx != source_op.idx and arg in tmp_op.input_arg_names: - out_edges.add(param, self._NameNodeMid(tmp_op)) - arg_idx = source_op.output_arg_names.index(arg) - shape = helper.var_shape_by_param(False, source_op, "Out", arg_idx, 'UNMODIFIED') - if shape[0] == -1: - shape[0] = 1 - if layout == 'NCHW': - shape = map(int, [1] * (4 - len(shape)) + shape) - if input_node_name in reshape_dict.keys(): - shape = reshape_dict[input_node_name] - private_data['input_shape'] = shape - private_data['alias'] = arg - self.outs[input_node_name] = out_edges - self._AddProtoNode(input_node_name, source_op, helper, private_data) - - def _InsertSplit(self, source_ops, helper): - # If a layer has two identical output tensors, add a split layer. - for node in self.outs.keys(): - if node.startswith('split#') is False: - out_edges = self.outs[node] - for param in out_edges.all_params(): - out_targets_list = out_edges.targets(param) - if len(out_targets_list) > 1: - private_data = {} - private_data['split_num'] = len(out_targets_list) - split_node_name = 'split#' + bytes(out_edges.all_params().index(param)) + '#' + node - self._InitEdges(split_node_name) - for out_target in out_targets_list: - self.outs[node].rm(out_target) - self.ins[out_target].mv(node, split_node_name) - self.outs[split_node_name].add('_Out', out_target) - self._AddPairEdges(node, split_node_name, param, '_In') - self._AddProtoNode(split_node_name, None, helper, private_data, 'split') - - def _Subgraph(self, starts, ends): - out_idx = {} - results = union(starts, ends) - def outs(node): - if node in self.outs.keys(): - return self.outs[node]() - else: - return [] - def next_out(node): - next_out = '' - if len(outs(node)) == 0: - return -1 - elif node not in out_idx.keys(): - out_idx[node] = 0 - if out_idx[node] < len(outs(node)): - next_out = outs(node)[out_idx[node]] - out_idx[node] += 1 - return next_out - for start in starts: - cache = [start] - while len(cache) > 0: - target = next_out(cache[-1]) - while target != -1 and target not in results: - if bool(target) is True: - cache.append(target) - target = next_out(target) - else: - if cache[-1] in results: - results = union(results, cache) - break - if target in results: - cache.append(target) - results = union(results, cache) - cache.pop() - return results - - def _CropGraph(self, ins_of_subgraph, outs_of_subgraph, helper, need_io = True): - def all_nodes(): - all_nodes = [] - for main_node in self.ins.keys(): - all_nodes.extend(self.ins[main_node].all_targets()) - for main_node in self.outs.keys(): - all_nodes.extend(self.outs[main_node].all_targets()) - return list(set(all_nodes)) - stayed_nodes = self._Subgraph(ins_of_subgraph, outs_of_subgraph) - all_nodes = all_nodes() - extra_nodes = difference(all_nodes, stayed_nodes) - for node_name in extra_nodes: - self._RmProtoNode(node_name) - self._ClearEdges(node_name) - if node_name in self.graphIO.ins(): - self.graphIO.rm_in(node_name) - if node_name in self.graphIO.outs(): - self.graphIO.rm_out(node_name) - for node_name in ins_of_subgraph: - if node_name in self.ins: - self.ins[node_name].clear() - for node_name in outs_of_subgraph: - if node_name in self.outs: - self.outs[node_name].clear() - if need_io is True: - for node_name in outs_of_subgraph: - if node_name not in self.graphIO.outs(): - out_node_name = node_name + '_crop_out' - self.ins[out_node_name] = Fluid_edger('_In', node_name) - self.outs[node_name] = Fluid_edger('_Out', out_node_name) - self.graphIO.add_out_fluid(out_node_name, node_name) - for node_name in ins_of_subgraph: - if node_name not in self.graphIO.ins(): - in_node_name = node_name + '_crop_in' - private_data = {'input_shape': [-1, -1, -1, -1]} - self.ins[node_name] = Fluid_edger('_In', in_node_name) - self.outs[in_node_name] = Fluid_edger('_Out', node_name) - self._AddProtoNode(in_node_name, None, helper, private_data, 'feed') - - def _IntegrateNodes(self, main_op, main_node_name, sec_node_name, helper, private_data): - # Merge secondary nodes to the primary node and process the edges. - self._RmProtoNode(main_node_name) - self._RmProtoNode(sec_node_name) - target_nodes_names = self.outs[sec_node_name]() - for target_node_name in target_nodes_names: - self.ins[target_node_name].mv(sec_node_name, main_node_name) - self.outs[main_node_name].mv(sec_node_name, target_node_name) - self.ins[target_node_name].rm(sec_node_name) - self.outs[sec_node_name].rm(target_node_name) - self.ins[sec_node_name].rm(main_node_name) - self.outs[main_node_name].rm(sec_node_name) - self._AddProtoNode(main_node_name, main_op, helper, private_data) - - def _DealWithBias(self, source_ops, helper): - # In fluid, the bias parameter of the conv2d is split into elementwise_add. - for source_op in source_ops: - if source_op.type in APPEND_BIAS_OP_TYPE: - private_data = {} - main_node_name = self._NameNodeMid(source_op) - if main_node_name in self.outs.keys(): - tmp_nodes_names = self.outs[main_node_name]() - if len(tmp_nodes_names) == 1 and tmp_nodes_names[0].startswith('elementwise_add'): - elt_node_name = tmp_nodes_names[0] - elt_op = self._GetOp(source_ops, elt_node_name) - has_weights = helper.is_persistable_param(elt_op, 'Y') - if self._NameNodeMid(elt_op) == elt_node_name and has_weights: - [elt_tensor, shape] = helper.param_tensor_sh(elt_op, 'Y') - new_shape = [1, shape[3], 1, 1] - elt_tensor.set_shape(new_shape) - private_data['bias'] = elt_tensor - self._IntegrateNodes(source_op, main_node_name, elt_node_name, helper, private_data) - - def _DealWithBatchnorm(self, source_ops, helper): - # In anakin, the scale part of batchnorm layer is independent. - for source_op in source_ops: - if source_op.type == 'batch_norm': - discrete_flag = True - main_node_name = self._NameNodeMid(source_op) - input_name = self.ins[main_node_name].target('X') - has_scale = helper.is_persistable_param(source_op, 'Scale') - if input_name.startswith('elementwise_add'): - elt_op = self._GetOp(source_ops, input_name) - x_of_elt = self.ins[input_name].target('X') - has_weights = helper.is_persistable_param(elt_op, 'Y') - if (x_of_elt.startswith('conv2d') or x_of_elt.startswith('depthwise_conv2d')) and has_weights: - discrete_flag = False - elif input_name.startswith('conv2d') or input_name.startswith('depthwise_conv2d'): - discrete_flag = False - if discrete_flag is True: - self._RmProtoNode(main_node_name) - self._AddProtoNode(main_node_name, source_op, helper, {}, 'disc_bn') - elif has_scale is True: - append_node_name = main_node_name + '__scale' - tmp_all_targets_params = self.outs[main_node_name].targets_with_params() - self._InitEdges(append_node_name) - for [tmp_node_name, tmp_param_name] in tmp_all_targets_params: - self.outs[append_node_name].add(tmp_param_name, tmp_node_name) - self.ins[tmp_node_name].mv(main_node_name, append_node_name) - self.outs[main_node_name].rm(tmp_node_name) - self.ins[tmp_node_name].rm(main_node_name) - self.outs[main_node_name].add('_Scale_out', append_node_name) - self.ins[append_node_name].add('_Ins', main_node_name) - self._AddProtoNode(append_node_name, source_op, helper, {}, 'scale_of_bn') - - def _DealWithAxpy(self, source_ops, helper): - for source_op in source_ops: - if source_op.type == 'elementwise_mul': - mul_node_name = self._NameNodeMid(source_op) - out_targets = self.outs[mul_node_name]() - if len(out_targets) == 1 and out_targets[0].startswith('elementwise_add'): - add_node_name = out_targets[0] - self._RmProtoNode(add_node_name) - a_node_name = self.ins[mul_node_name].target('Y') - x_node_name = self.ins[mul_node_name].target('X') - y_node_name = self.ins[add_node_name].target('X') - self._ClearEdges(mul_node_name) - self.ins[add_node_name].clear() - self.outs[a_node_name].mv(mul_node_name, add_node_name) - self.outs[x_node_name].mv(mul_node_name, add_node_name) - self.ins[add_node_name].add('A', a_node_name) - self.ins[add_node_name].add('X', x_node_name) - self.ins[add_node_name].add('Y', y_node_name) - self._RmProtoNode(mul_node_name) - self._AddProtoNode(add_node_name, None, helper, {}, 'axpy') - - def _DealWithPriorBox(self, source_ops, helper): - nodes_to_del = [] - for source_op in source_ops: - if source_op.type == 'prior_box': - pb_node_name = self._NameNodeMid(source_op) - br_node_name = self.outs[pb_node_name].target('Boxes') - vr_node_name = self.outs[pb_node_name].target('Variances') - bc_node_name = self.outs[br_node_name].target('Out') - vc_node_name = self.outs[vr_node_name].target('Out') - boxcoder_node_name = self.outs[bc_node_name].target('Out') - self.outs[pb_node_name].mv(br_node_name, bc_node_name) - self.outs[pb_node_name].rm(vr_node_name) - self.ins[bc_node_name].mv(br_node_name, pb_node_name) - self.ins[boxcoder_node_name].rm(vc_node_name) - for node_name in [br_node_name, vr_node_name, vc_node_name]: - if node_name not in nodes_to_del: - nodes_to_del.append(node_name) - input_node_name = self.ins[pb_node_name].target('Input') - image_node_name = self.ins[pb_node_name].target('Image') - self.ins[pb_node_name].rm(input_node_name) - self.ins[pb_node_name].rm(image_node_name) - self.ins[pb_node_name].add('Input', input_node_name) - self.ins[pb_node_name].add('Image', image_node_name) - self._RmProtoNode(bc_node_name) - self._AddProtoNode(bc_node_name, None, helper, {}, 'concat_btw_priorbox_boxcoder') - for node_name in nodes_to_del: - self._RmProtoNode(node_name) - self._ClearEdges(node_name) - - def _DealWithDetectionOutput(self, source_ops, helper): - for source_op in source_ops: - if source_op.type == 'box_coder': - bc_node_name = self._NameNodeMid(source_op) - out_targets = self.outs[bc_node_name]() - if len(out_targets) == 1 and out_targets[0].startswith('multiclass_nms'): - private_data = {} - private_data['code_type'] = helper.attr_data(source_op, 'code_type') - bc_out_arg = helper.var_name_by_param(source_op, 'OutputBox') - for tmp_op in source_ops: - if tmp_op.idx != source_op.idx and bc_out_arg in tmp_op.input_arg_names: - nms_op = tmp_op - nms_node_name = out_targets[0] - loc_node_name = self.ins[bc_node_name].target('TargetBox') - conf_node_name = self.ins[nms_node_name].target('Scores') - box_node_name = self.ins[bc_node_name].target('PriorBox') - self._ClearEdges(bc_node_name) - self.ins[nms_node_name].clear() - self.outs[loc_node_name].mv(bc_node_name, nms_node_name) - self.outs[box_node_name].mv(bc_node_name, nms_node_name) - self.ins[nms_node_name].add('mbox_loc', loc_node_name) - self.ins[nms_node_name].add('mbox_conf_flatten', conf_node_name) - self.ins[nms_node_name].add('mbox_prior_box', box_node_name) - self._RmProtoNode(bc_node_name) - self._RmProtoNode(nms_node_name) - self._AddProtoNode(nms_node_name, nms_op, helper, private_data, 'multiclass_nms') - - def _DealWithMultiFC(self, source_ops, helper): - for source_op in source_ops: - if source_op.type == 'sum': - sum_node_name = self._NameNodeMid(source_op) - mul_names_list = self.ins[sum_node_name].targets('X') - elt_node_name = self.outs[sum_node_name].target('Out') - if elt_node_name.startswith('elementwise_add') and len(mul_names_list) > 1: - elt_op = self._GetOp(source_ops, elt_node_name) - elt_has_weights = helper.is_persistable_param(elt_op, 'Y') - fc_flag = True - for mul_node_name in mul_names_list: - if mul_node_name.startswith('mul') is False: - fc_flags = False - if fc_flag and elt_has_weights: - private_data = {} - first_mul_name = mul_names_list[0] - first_mul_op = self._GetOp(source_ops, first_mul_name) - in_of_mul_name = self.ins[first_mul_name].target('X') - out_of_elt_name = self.outs[elt_node_name].target('Out') - self.outs[sum_node_name].mv(elt_node_name, out_of_elt_name) - self.ins[out_of_elt_name].mv(elt_node_name, sum_node_name) - self._ClearEdges(elt_node_name) - [elt_tensor, shape] = helper.param_tensor_sh(elt_op, 'Y') - new_shape = [1, shape[3], 1, 1] - elt_tensor.set_shape(new_shape) - private_data['bias'] = elt_tensor - self._RmProtoNode(elt_node_name) - self._RmProtoNode(first_mul_name) - self._AddProtoNode(first_mul_name, first_mul_op, helper, private_data) - - def _DealWithGru(self, source_ops, helper): - for source_op in source_ops: - if source_op.type == 'gru': - private_data = {} - gru_flags = [False, False] - gru_node_name = self._NameNodeMid(source_op) - gru_op = self._GetOp(source_ops, gru_node_name) - input_list_of_gru = self.ins[gru_node_name].targets('Input') - if len(input_list_of_gru) == 1 and input_list_of_gru[0].startswith('elementwise_add'): - elt_node_name = input_list_of_gru[0] - elt_op = self._GetOp(source_ops, elt_node_name) - has_weights = helper.is_persistable_param(elt_op, 'Y') - if has_weights is True: - private_data['np_bias_x'] = helper.np_param(elt_op, 'Y') - gru_flags[0] = True - input_list_of_elt = self.ins[elt_node_name].targets('X') - if len(input_list_of_elt) == 1 and input_list_of_elt[0].startswith('mul'): - mul_node_name = input_list_of_elt[0] - mul_op = self._GetOp(source_ops, mul_node_name) - if helper.var_name_by_param(mul_op, 'Y').startswith('fc'): - if helper.attr_data(mul_op, 'x_num_col_dims') == 1: - input_list_of_mul = self.ins[mul_node_name].targets('X') - input_name_of_mul = input_list_of_mul[0] - private_data['np_weight_x'] = helper.np_param(mul_op, 'Y') - gru_flags[1] = True - else: - raise NameError('ERROR: Axis of GRU_FC must be 1.') - if gru_flags == [True, True]: - self.outs[input_name_of_mul].mv(mul_node_name, gru_node_name) - self.ins[gru_node_name].mv(elt_node_name, input_name_of_mul) - for node_to_del_name in [mul_node_name, elt_node_name, gru_node_name]: - self._RmProtoNode(node_to_del_name) - if node_to_del_name is not gru_node_name: - self._ClearEdges(node_to_del_name) - self._AddProtoNode(gru_node_name, gru_op, helper, private_data) - - def _SearchBilstm(self, source_ops, helper): - comp = Fluid_comparator(helper) - lstm_ops = [] - for source_op in source_ops: - if source_op.type == 'lstm': - lstm_ops.append(source_op) - if len(lstm_ops) == 2: - lstm_a = lstm_ops[0] - lstm_b = lstm_ops[1] - same_bias = comp.compare_by_param(lstm_a, lstm_b, 'Bias') - same_weight = comp.compare_by_param(lstm_a, lstm_b, 'Weight') - if same_bias and same_weight: - return True - else: - return False - else: - return False - - def _DealWithLstm(self, source_ops, helper): - for source_op in source_ops: - if source_op.type == 'lstm': - private_data = {} - lstm_flags = [False, False] - lstm_node_name = self._NameNodeMid(source_op) - lstm_op = self._GetOp(source_ops, lstm_node_name) - input_list_of_lstm = self.ins[lstm_node_name].targets('Input') - input_list = [] - if len(input_list_of_lstm) == 1: - in_lstm_node_name = input_list_of_lstm[0] - if input_list_of_lstm[0].split('#')[0] == 'elementwise_add': - elt_op = self._GetOp(source_ops, in_lstm_node_name) - has_weights = helper.is_persistable_param(elt_op, 'Y') - if has_weights is True: - private_data['np_flat_fc_bias'] = helper.np_param(elt_op, 'Y') - lstm_flags[0] = True - input_list = self.ins[in_lstm_node_name].targets('X') - elif input_list_of_lstm[0].split('#')[0] == 'mul': - private_data['np_flat_fc_bias'] = None - input_list = input_list_of_lstm - lstm_flags[0] = True - if lstm_flags[0] is True and len(input_list) == 1: - if input_list[0].split('#')[0] == 'mul': - mul_node_name = input_list[0] - mul_op = self._GetOp(source_ops, mul_node_name) - #if helper.var_name_by_param(mul_op, 'Y').startswith('fc'): - if helper.attr_data(mul_op, 'x_num_col_dims') == 1: - input_list_of_mul = self.ins[mul_node_name].targets('X') - input_name_of_mul = input_list_of_mul[0] - [w_np, w_sh] = helper.data_with_shape_by_param(mul_op, 'Y', \ - False, None, 0, False) - private_data['np_flat_fc_weight'] = w_np - private_data['np_fc_outdim'] = w_sh[3] - lstm_flags[1] = True - else: - raise NameError('ERROR: Axis of LSTM_FC must be 1.') - if lstm_flags == [True, True]: - self.outs[input_name_of_mul].mv(mul_node_name, lstm_node_name) - self.ins[lstm_node_name].mv(in_lstm_node_name, input_name_of_mul) - if in_lstm_node_name == mul_node_name: - nodes_to_del = [mul_node_name, lstm_node_name] - else: - nodes_to_del = [mul_node_name, in_lstm_node_name, lstm_node_name] - for node_to_del_name in nodes_to_del: - self._RmProtoNode(node_to_del_name) - if node_to_del_name is not lstm_node_name: - self._ClearEdges(node_to_del_name) - self._AddProtoNode(lstm_node_name, lstm_op, helper, private_data) - - def _DealWithCast(self, source_ops, helper): - for source_op in source_ops: - if source_op.type == 'cast': - if helper.attr_data(source_op, 'out_dtype') == 5: - cast_node_name = self._NameNodeMid(source_op) - if cast_node_name in self.ins: - input_name_of_cast = self.ins[cast_node_name].target('X') - if input_name_of_cast.startswith('top_k') is False: - output_name_of_cast = self.outs[cast_node_name].target('Out') - self.outs[input_name_of_cast].mv(cast_node_name, output_name_of_cast) - self.ins[output_name_of_cast].mv(cast_node_name, input_name_of_cast) - self._RmProtoNode(cast_node_name) - self._ClearEdges(cast_node_name) - else: - print 'Cannot find the layer corresponding to cast.' - else: - raise NameError('The out type of cast must be float32.') - - def _DealWithArgmax(self, source_ops, helper): - for source_op in source_ops: - if source_op.type == 'top_k': - private_data = {} - topk_node_name = self._NameNodeMid(source_op) - out_list = self.outs[topk_node_name].targets('Out') - index_list = self.outs[topk_node_name].targets('Indices') - if len(index_list) > 0: - if len(out_list) == 1 and index_list[0].startswith('cast'): - private_data['out_max_val'] = True - idxcast_node_name = index_list[0] - output_name_of_idxcast = self.outs[idxcast_node_name].target('Out') - if output_name_of_idxcast == out_list[0] and out_list[0].startswith('concat'): - concat_node_name = out_list[0] - output_name_of_concat = self.outs[concat_node_name].target('Out') - self.outs[topk_node_name].rm(idxcast_node_name) - self.outs[topk_node_name].mv(concat_node_name, output_name_of_concat) - self.ins[output_name_of_concat].mv(concat_node_name, topk_node_name) - for node_to_del_name in [concat_node_name, idxcast_node_name]: - self._RmProtoNode(node_to_del_name) - self._ClearEdges(node_to_del_name) - elif output_name_of_idxcast != out_list[0]: - if output_name_of_idxcast.endswith('_gout') and \ - out_list[0].endswith('_gout'): - gout_node_name = out_list[0] - idx_gout_node_name = output_name_of_idxcast - self.outs[topk_node_name].rm(idxcast_node_name) - for node_to_del_name in [idx_gout_node_name, idxcast_node_name]: - self._RmProtoNode(node_to_del_name) - self._ClearEdges(node_to_del_name) - self.graphIO.rm_out(idx_gout_node_name) - elif len(out_list) == 0: - private_data['out_max_val'] = False - self._DealWithCast(source_ops, helper) - else: - raise NameError('ERROR: Unknown top_k layer.') - self._RmProtoNode(topk_node_name) - self._AddProtoNode(topk_node_name, source_op, helper, private_data) - - def _DealWithReshape(self, source_ops, helper): - for source_op in source_ops: - if source_op.type == 'reshape': - reshape_node_name = self._NameNodeMid(source_op) - if reshape_node_name in self.ins: - shape_inputs = self.ins[reshape_node_name].targets('Shape') - tensor_inputs = self.ins[reshape_node_name].targets('X') - if len(shape_inputs) == 1 and len(tensor_inputs) == 1: - self.ins[reshape_node_name].rm(shape_inputs[0]) - self.ins[reshape_node_name].add('Shape', shape_inputs[0]) - else: - pass - - def _DealWithSoftmax(self, source_ops, helper): - for source_op in source_ops: - if source_op.type == 'softmax': - softmax_node_name = self._NameNodeMid(source_op) - outs_of_softmax = self.outs[softmax_node_name].targets('Out') - ins_of_softmax = self.ins[softmax_node_name].targets('X') - def prune(reshape_node_name): - branch = [] - branch.append(reshape_node_name) - shape_inputs = self.ins[reshape_node_name].targets('Shape') - tensor_input = self.ins[reshape_node_name].target('X') - tensor_output = self.outs[reshape_node_name].target('Out') - if len(shape_inputs) == 1: - branch.append(shape_inputs[0]) - if len(branch) == 2 and branch[1].split('#')[0] == 'split': - split_node_name = branch[1] - self.outs[split_node_name].rm(reshape_node_name) - self.ins[reshape_node_name].rm(split_node_name) - if len(self.outs[split_node_name].targets('_Out')) == 0: - input_of_split = self.ins[split_node_name].target('_In') - branch.append(input_of_split) - self._RmProtoNode(split_node_name) - self._ClearEdges(split_node_name) - elif len(branch) == 2 and branch[1].startswith('input'): - raise NameError('ERROR: None-split input of Softmax has not supported.') - self.outs[tensor_input].mv(reshape_node_name, tensor_output) - self.ins[tensor_output].mv(reshape_node_name, tensor_input) - self._RmProtoNode(reshape_node_name) - self._ClearEdges(reshape_node_name) - if len(branch) == 3 and branch[2].startswith('input'): - input_node_name = branch[2] - self._RmProtoNode(input_node_name) - self._ClearEdges(input_node_name) - if outs_of_softmax[0].split('#')[0] == 'reshape' and \ - ins_of_softmax[0].split('#')[0] == 'reshape': - private_data = {} - private_data['axis'] = 3 - prune(outs_of_softmax[0]) - prune(ins_of_softmax[0]) - self._RmProtoNode(softmax_node_name) - self._AddProtoNode(softmax_node_name, source_op, helper, private_data) - - def _DealWithMatmal(self, source_ops, helper): - for source_op in source_ops: - if source_op.type == 'matmul': - matmul_node_name = self._NameNodeMid(source_op) - x_input_name = self.ins[matmul_node_name].target('X') - y_input_name = self.ins[matmul_node_name].target('Y') - flag = False - coeff = 1.0 - for node_name in [x_input_name, y_input_name]: - if node_name.startswith('scale') or node_name.startswith('dropout'): - op = self._GetOp(source_ops, node_name) - if node_name.startswith('scale'): - scale = helper.attr_data(op, 'scale') - elif node_name.startswith('dropout'): - scale = 1 - helper.attr_data(op, 'dropout_prob') - input_node = self.ins[node_name].target('X') - self.outs[input_node].mv(node_name, matmul_node_name) - self.ins[matmul_node_name].mv(node_name, input_node) - self._RmProtoNode(node_name) - self._ClearEdges(node_name) - coeff = coeff * scale - flag = True - if flag is True: - private_data = {} - private_data['coeff'] = coeff - self._RmProtoNode(matmul_node_name) - self._AddProtoNode(matmul_node_name, source_op, helper, private_data) - - def _DealWithDiscBatchNorm(self, source_ops, helper): - for source_op in source_ops: - if source_op.type == 'batch_norm': - discrete_flag = True - bn_node_name = self._NameNodeMid(source_op) - input_name = self.ins[bn_node_name].target('X') - if input_name.startswith('elementwise_add'): - input_of_elt = self.ins[input_name].target('X') - if input_of_elt.startswith('conv2d'): - discrete_flag = False - elif input_name.startswith('conv2d'): - discrete_flag = False - if discrete_flag is True: - self._RmProtoNode(bn_node_name) - self._AddProtoNode(bn_node_name, source_op, helper, {}, 'disc_bn') - - def _DealWithSSD(self, source_ops, helper): - for source_op in source_ops: - if source_op.type == 'reshape': - rh_node_name = self._NameNodeMid(source_op) - if rh_node_name in self.ins: - private_data = dict() - input_name = self.ins[rh_node_name].target('X') - shape = helper.attr_data(source_op, 'shape') - if input_name.startswith('concat'): - private_data['new_shape'] = [0, shape[0], shape[1], 0] - else: - private_data['new_shape'] = [0, -1, 1, 1] - self._RmProtoNode(rh_node_name) - self._AddProtoNode(rh_node_name, source_op, helper, private_data, 'reshape') - for source_op in source_ops: - if source_op.type == 'softmax': - private_data = dict() - sm_node_name = self._NameNodeMid(source_op) - private_data['axis'] = 2 - self._RmProtoNode(sm_node_name) - self._AddProtoNode(sm_node_name, source_op, helper, private_data, 'softmax') - - def _NewCommonLayer(self, - source_ops, - in_target, - in_param, - out_target, - out_param, - layer_type, - private_data, - helper, - insert_mode = True): - main_layer = layer_type + '_after_' + in_target - if insert_mode is True: - if in_target in self.ins[out_target].all_targets() and \ - out_target in self.outs[in_target].all_targets(): - self.ins[out_target].mv(in_target, main_layer) - self.outs[in_target].mv(out_target, main_layer) - else: - raise NameError('ERROR: Usage of InsertCommonLayer has not supported.') - else: - self.ins[out_target].add(in_param + '_insert', main_layer) - self.outs[in_target].add(out_param + '_insert', main_layer) - self.ins[main_layer] = Fluid_edger(in_param, in_target) - self.outs[main_layer] = Fluid_edger(out_param, out_target) - self._AddProtoNode(main_layer, None, helper, private_data, layer_type) - - def _ParseNetwork(self, source_ops, helper): - self._ParseBase(source_ops, helper) - if self.NetType == "FLUIDBASE": - pass - else: - reshape_dict = {} - if self.NetType == "OCR": - reshape_dict['input_0'] = [1, 1, 48, 1500] - self._ReplaceInputs(source_ops, helper, reshape_dict) - self._InsertSplit(source_ops, helper) - self._DealWithGru(source_ops, helper) - self._DealWithLstm(source_ops, helper) - self._DealWithBias(source_ops, helper) - self._DealWithBatchnorm(source_ops, helper) - self._DealWithMultiFC(source_ops, helper) - self._DealWithArgmax(source_ops, helper) - self._DealWithAxpy(source_ops, helper) - if self.NetType == "SSD": - self._DealWithPriorBox(source_ops, helper) - self._DealWithDetectionOutput(source_ops, helper) - self._DealWithSSD(source_ops, helper) - self._Graph() - - - - def _Parsing(self): - with fluid.scope_guard(self.scope): - if os.path.exists(self.ModelPath + 'model') and os.path.exists(self.ModelPath + 'params'): - [self.net_program, feed_target_names, fetch_targets] = \ - fluid.io.load_inference_model(self.ModelPath, self.exe, 'model', 'params') - else: - [self.net_program, feed_target_names, fetch_targets] = \ - fluid.io.load_inference_model(self.ModelPath, self.exe) - - global_block = self.net_program.global_block() - source_ops = list(global_block.ops) - helper = Fluid_helper(self.scope, global_block) - - self._ParseNetwork(source_ops, helper) - return self.graphIO + def __init__(self, fluid_config_dict): + # anakin graph model io + self.graphIO = None + # config info + self.ModelPath = fluid_config_dict['ModelPath'] + self.NetType = fluid_config_dict['NetType'] + self.Debug = fluid_config_dict['Debug'] + # config fluid + self.place = fluid.CPUPlace() + self.exe = fluid.Executor(self.place) + self.scope = fluid.core.Scope() + # in and out edges of node + self.ins = {} + self.outs = {} + # inplaced main node + self.inplace_nodes = {} + self.graph_ins = [] + self.graph_outs = [] + + def __call__(self): + return self._Parsing() + + def _NameNodeMid(self, op): + first_outparam = op.output_names[0] + arg_name = str(op.output(first_outparam)[0]).split('.')[0] + #new_name = op.type + '_' + bytes(op.idx) + new_name = op.type + '#' + bytes(op.idx) + '(' + arg_name + ')' + return new_name + + def _NameNodeIn(self, in_name): + new_name = 'input_' + bytes(self.graph_ins.index(in_name)) + return new_name + + def _NameNodeOut(self, out_name): + new_name = out_name + '_gout' + return new_name + + def _AddPairEdges(self, start_node_name, end_node_name, out_param, in_param): + self.outs[start_node_name].add(out_param, end_node_name) + self.ins[end_node_name].add(in_param, start_node_name) + + def _RmPairEdges(self, start_node_name, end_node_name): + self.outs[start_node_name].rm(end_node_name) + self.ins[end_node_name].rm(start_node_name) + + def _InitEdges(self, node_name): + self.ins[node_name] = Fluid_edger() + self.outs[node_name] = Fluid_edger() + + def _ClearEdges(self, node_name): + if node_name.startswith('input_') is False: + del self.ins[node_name] + if node_name.endswith('_gout') is False: + del self.outs[node_name] + + def _GetOp(self, ops, mid_node_name): + mid_op = None + for op in ops: + node_name = self._NameNodeMid(op) + if mid_node_name == node_name: + mid_op = op + return mid_op + + def _OpTypes(self, ops): + types_cache = [] + for op in ops: + if op.type not in types_cache: + types_cache.append(op.type) + return types_cache + + def _AddProtoNode(self, node_name, op_of_node, helper, private_data, op_type=None): + nodeIO = NodeProtoIO() + opIO = OpsProtoIO() + nodeIO.set_name(node_name) + if op_type is None: + op_type = op_of_node.type + FLUID_NODE_FILLER[op_type](nodeIO, op_of_node, opIO, helper, private_data) + self.graphIO.add_node(nodeIO()) + + def _RmProtoNode(self, node_name): + self.graphIO.rm_node(self.graphIO.find_node_proto(node_name)) + + def _InplaceNodes(self, position): + inplace_heads = self.inplace_nodes.keys() + inplace_mids = [] + inplace_ends = [] + for main_node_name in self.inplace_nodes.keys(): + mid_nodes_name = self.inplace_nodes[main_node_name][1: -1] + inplace_mids.extend(mid_nodes_name) + for main_node_name in self.inplace_nodes.keys(): + end_node_name = self.inplace_nodes[main_node_name][-1] + inplace_ends.append(end_node_name) + if position == 'Head': + return inplace_heads + elif position == 'Mid': + return inplace_mids + elif position == 'End': + return inplace_ends + elif position == 'All': + return inplace_heads + inplace_mids + inplace_ends + + def _EdgeInplace(self, source_ops, helper): + for source_op in source_ops: + if source_op.type not in ['feed', 'fetch']: + if len(source_op.input_arg_names) == 1 \ + and source_op.input_arg_names == source_op.output_arg_names: + source_node_name = self._NameNodeMid(source_op) + inplace_arg = source_op.input_arg_names[0] + for tmp_op in source_ops: + if tmp_op.idx != source_op.idx and inplace_arg in tmp_op.output_arg_names: + main_node_name = self._NameNodeMid(tmp_op) + if main_node_name not in self.inplace_nodes.keys(): + self.inplace_nodes[main_node_name] = [main_node_name] + self.inplace_nodes[main_node_name].append(source_node_name) + for main_node_name in self.inplace_nodes.keys(): + inplace_list = self.inplace_nodes[main_node_name] + for inplace_node in inplace_list: + idx = inplace_list.index(inplace_node) + if idx != 0: + self.ins[inplace_node] = Fluid_edger('_In', inplace_list[idx - 1]) + if idx != len(inplace_list) - 1: + self.outs[inplace_node] = Fluid_edger('_Out', inplace_list[idx + 1]) + + def _GetDebugOuts(self, source_ops, helper): + if self.Debug == 'DEBUG': + debug_fetch_list = [] + for source_op in source_ops: + if source_op.type == 'fetch': + var_name = source_op.input_arg_names[0] + for tmp_op in source_ops: + if tmp_op.idx != source_op.idx and var_name in tmp_op.input_arg_names: + if var_name not in debug_fetch_list: + debug_fetch_list.append(var_name) + elif tmp_op.type == 'gru' and var_name in tmp_op.output_arg_names: + if var_name not in debug_fetch_list: + debug_fetch_list.append(var_name) + else: + pass + return debug_fetch_list + else: + return [] + + def _ParseBase(self, source_ops, helper, sub_graph_nodes=None): + # Create the original base graph as described in fluid program. + if sub_graph_nodes is None: + sub_graph_nodes = list() + self.graphIO = GraphProtoIO() + self.graphIO.set_name('default_graph_name') + debug_fetch_list = self._GetDebugOuts(source_ops, helper) + self._EdgeInplace(source_ops, helper) + for source_op in source_ops: + if source_op.type not in ['feed', 'fetch']: + main_node_name = self._NameNodeMid(source_op) + in_edges = Fluid_edger() + out_edges = Fluid_edger() + for param in source_op.input_names: + for idx in range(0, len(helper.args_by_input_param(source_op, param))): + arg = helper.var_name_by_param(source_op, param, idx) + for tmp_op in source_ops: + if tmp_op.idx != source_op.idx and arg in tmp_op.output_arg_names: + if tmp_op.type == 'feed': + if arg not in self.graph_ins: + self.graph_ins.append(arg) + self.graphIO.add_in(self._NameNodeIn(arg)) + in_edges.add(param, self._NameNodeIn(arg), arg) + else: + tmp_node_name = self._NameNodeMid(tmp_op) + if tmp_node_name in self.inplace_nodes.keys(): + inplace_node_name = self.inplace_nodes[tmp_node_name][-1] + in_edges.add(param, inplace_node_name, arg) + elif tmp_node_name not in self._InplaceNodes('All'): + in_edges.add(param, tmp_node_name, arg) + for param in source_op.output_names: + for idx in range(0, len(helper.args_by_output_param(source_op, param))): + arg = helper.var_name_by_param(source_op, param, idx) + for tmp_op in source_ops: + if tmp_op.idx != source_op.idx and arg in tmp_op.input_arg_names: + if tmp_op.type == 'fetch': + if arg not in debug_fetch_list: + arg_node_name = self._NameNodeOut(arg) + if arg not in self.graph_outs: + self.graph_outs.append(arg) + self.graphIO.add_out_fluid(arg_node_name, \ + main_node_name) + out_edges.add(param, arg_node_name, arg) + self.ins[arg_node_name] = Fluid_edger(bytes(source_op.idx), \ + main_node_name) + else: + out_edges.add(param, self._NameNodeMid(tmp_op), arg) + self._AddProtoNode(main_node_name, source_op, helper, {}) + if main_node_name not in self._InplaceNodes('Mid'): + if main_node_name not in self._InplaceNodes('End'): + self.ins[main_node_name] = in_edges + if main_node_name not in self._InplaceNodes('Head'): + if main_node_name not in self._InplaceNodes('End'): + self.outs[main_node_name] = out_edges + else: + inplace_node_name = self.inplace_nodes[main_node_name][-1] + self.outs[inplace_node_name] = out_edges + for redundant_target in self.inplace_nodes[main_node_name][1:]: + self.outs[inplace_node_name].rm(redundant_target) + + def _PrintEdge(self, node, target, direction): + var_name = 'Unknown' + if direction == 'in': + var = self.ins[node].vars_by_target(target) + elif direction == 'out': + var = self.outs[node].vars_by_target(target) + if len(var) > 0: + var_name = var[0] + print node + ",\t" + target + ",\t" + var_name + + def _Graph(self, need_print=False): + for node in self.ins.keys(): + targets_list = self.ins[node]() + for target in targets_list: + self.graphIO.add_in_edge(target, node) + for node in self.outs.keys(): + targets_list = self.outs[node]() + for target in targets_list: + self.graphIO.add_out_edge(node, target) + if need_print is True: + self._PrintEdge(node, target, 'out') + + def _ReplaceInputs(self, source_ops, helper, reshape_dict=None, layout='NCHW'): + if reshape_dict is None: + reshape_dict = dict() + for source_op in source_ops: + if source_op.type in ['feed']: + out_edges = Fluid_edger() + for param in source_op.output_names: + private_data = {} + arg = helper.var_name_by_param(source_op, param) + input_node_name = self._NameNodeIn(arg) + for tmp_op in source_ops: + if tmp_op.idx != source_op.idx and arg in tmp_op.input_arg_names: + out_edges.add(param, self._NameNodeMid(tmp_op)) + arg_idx = source_op.output_arg_names.index(arg) + shape = helper.var_shape_by_param(False, source_op, \ + "Out", arg_idx, 'UNMODIFIED') + if shape[0] == -1: + shape[0] = 1 + if layout == 'NCHW': + shape = map(int, [1] * (4 - len(shape)) + shape) + if input_node_name in reshape_dict.keys(): + shape = reshape_dict[input_node_name] + private_data['input_shape'] = shape + private_data['alias'] = arg + self.outs[input_node_name] = out_edges + self._AddProtoNode(input_node_name, source_op, helper, private_data) + + def _InsertSplit(self, source_ops, helper): + # If a layer has two identical output tensors, add a split layer. + for node in self.outs.keys(): + if node.startswith('split#') is False: + out_edges = self.outs[node] + for param in out_edges.all_params(): + out_targets_list = out_edges.targets(param) + if len(out_targets_list) > 1: + private_data = {} + private_data['split_num'] = len(out_targets_list) + split_node_name = 'split#' + \ + bytes(out_edges.all_params().index(param)) + '#' + node + self._InitEdges(split_node_name) + for out_target in out_targets_list: + self.outs[node].rm(out_target) + self.ins[out_target].mv(node, split_node_name) + self.outs[split_node_name].add('_Out', out_target) + self._AddPairEdges(node, split_node_name, param, '_In') + self._AddProtoNode(split_node_name, None, helper, private_data, 'split') + + def _Subgraph(self, starts, ends): + """ + """ + out_idx = {} + results = union(starts, ends) + def outs(node): + """ + """ + if node in self.outs.keys(): + return self.outs[node]() + else: + return [] + def next_out(node): + """ + """ + next_out = '' + if len(outs(node)) == 0: + return -1 + elif node not in out_idx.keys(): + out_idx[node] = 0 + if out_idx[node] < len(outs(node)): + next_out = outs(node)[out_idx[node]] + out_idx[node] += 1 + return next_out + for start in starts: + cache = [start] + while len(cache) > 0: + target = next_out(cache[-1]) + while target != -1 and target not in results: + if bool(target) is True: + cache.append(target) + target = next_out(target) + else: + if cache[-1] in results: + results = union(results, cache) + break + if target in results: + cache.append(target) + results = union(results, cache) + cache.pop() + return results + + def _CropGraph(self, ins_of_subgraph, outs_of_subgraph, helper, need_io = True): + ''' + ''' + def all_nodes(): + ''' + ''' + all_nodes = [] + for main_node in self.ins.keys(): + all_nodes.extend(self.ins[main_node].all_targets()) + for main_node in self.outs.keys(): + all_nodes.extend(self.outs[main_node].all_targets()) + return list(set(all_nodes)) + stayed_nodes = self._Subgraph(ins_of_subgraph, outs_of_subgraph) + all_nodes = all_nodes() + extra_nodes = difference(all_nodes, stayed_nodes) + for node_name in extra_nodes: + self._RmProtoNode(node_name) + self._ClearEdges(node_name) + if node_name in self.graphIO.ins(): + self.graphIO.rm_in(node_name) + if node_name in self.graphIO.outs(): + self.graphIO.rm_out(node_name) + for node_name in ins_of_subgraph: + if node_name in self.ins: + self.ins[node_name].clear() + for node_name in outs_of_subgraph: + if node_name in self.outs: + self.outs[node_name].clear() + if need_io is True: + for node_name in outs_of_subgraph: + if node_name not in self.graphIO.outs(): + out_node_name = node_name + '_crop_out' + self.ins[out_node_name] = Fluid_edger('_In', node_name) + self.outs[node_name] = Fluid_edger('_Out', out_node_name) + self.graphIO.add_out_fluid(out_node_name, node_name) + for node_name in ins_of_subgraph: + if node_name not in self.graphIO.ins(): + in_node_name = node_name + '_crop_in' + private_data = {'input_shape': [-1, -1, -1, -1]} + self.ins[node_name] = Fluid_edger('_In', in_node_name) + self.outs[in_node_name] = Fluid_edger('_Out', node_name) + self._AddProtoNode(in_node_name, None, helper, private_data, 'feed') + + def _IntegrateNodes(self, main_op, main_node_name, sec_node_name, helper, private_data): + # Merge secondary nodes to the primary node and process the edges. + self._RmProtoNode(main_node_name) + self._RmProtoNode(sec_node_name) + target_nodes_names = self.outs[sec_node_name]() + for target_node_name in target_nodes_names: + self.ins[target_node_name].mv(sec_node_name, main_node_name) + self.outs[main_node_name].mv(sec_node_name, target_node_name) + self.ins[target_node_name].rm(sec_node_name) + self.outs[sec_node_name].rm(target_node_name) + self.ins[sec_node_name].rm(main_node_name) + self.outs[main_node_name].rm(sec_node_name) + self._AddProtoNode(main_node_name, main_op, helper, private_data) + + def _DealWithBias(self, source_ops, helper): + # In fluid, the bias parameter of the conv2d is split into elementwise_add. + for source_op in source_ops: + if source_op.type in APPEND_BIAS_OP_TYPE: + private_data = {} + main_node_name = self._NameNodeMid(source_op) + if main_node_name in self.outs.keys(): + tmp_nodes_names = self.outs[main_node_name]() + if len(tmp_nodes_names) == 1 and \ + tmp_nodes_names[0].startswith('elementwise_add'): + elt_node_name = tmp_nodes_names[0] + elt_op = self._GetOp(source_ops, elt_node_name) + has_weights = helper.is_persistable_param(elt_op, 'Y') + if self._NameNodeMid(elt_op) == elt_node_name and has_weights: + [elt_tensor, shape] = helper.param_tensor_sh(elt_op, 'Y') + new_shape = [1, shape[3], 1, 1] + elt_tensor.set_shape(new_shape) + private_data['bias'] = elt_tensor + self._IntegrateNodes(source_op, main_node_name, \ + elt_node_name, helper, private_data) + + def _DealWithBatchnorm(self, source_ops, helper): + # In anakin, the scale part of batchnorm layer is independent. + for source_op in source_ops: + if source_op.type == 'batch_norm': + discrete_flag = True + main_node_name = self._NameNodeMid(source_op) + input_name = self.ins[main_node_name].target('X') + has_scale = helper.is_persistable_param(source_op, 'Scale') + if input_name.startswith('elementwise_add'): + elt_op = self._GetOp(source_ops, input_name) + x_of_elt = self.ins[input_name].target('X') + has_weights = helper.is_persistable_param(elt_op, 'Y') + if (x_of_elt.startswith('conv2d') or \ + x_of_elt.startswith('depthwise_conv2d')) and has_weights: + discrete_flag = False + elif input_name.startswith('conv2d') or input_name.startswith('depthwise_conv2d'): + discrete_flag = False + if discrete_flag is True: + self._RmProtoNode(main_node_name) + self._AddProtoNode(main_node_name, source_op, helper, {}, 'disc_bn') + elif has_scale is True: + append_node_name = main_node_name + '__scale' + tmp_all_targets_params = self.outs[main_node_name].targets_with_params() + self._InitEdges(append_node_name) + for [tmp_node_name, tmp_param_name] in tmp_all_targets_params: + self.outs[append_node_name].add(tmp_param_name, tmp_node_name) + self.ins[tmp_node_name].mv(main_node_name, append_node_name) + self.outs[main_node_name].rm(tmp_node_name) + self.ins[tmp_node_name].rm(main_node_name) + self.outs[main_node_name].add('_Scale_out', append_node_name) + self.ins[append_node_name].add('_Ins', main_node_name) + self._AddProtoNode(append_node_name, source_op, helper, {}, 'scale_of_bn') + + def _DealWithAxpy(self, source_ops, helper): + for source_op in source_ops: + if source_op.type == 'elementwise_mul': + mul_node_name = self._NameNodeMid(source_op) + out_targets = self.outs[mul_node_name]() + if len(out_targets) == 1 and out_targets[0].startswith('elementwise_add'): + add_node_name = out_targets[0] + self._RmProtoNode(add_node_name) + a_node_name = self.ins[mul_node_name].target('Y') + x_node_name = self.ins[mul_node_name].target('X') + y_node_name = self.ins[add_node_name].target('X') + self._ClearEdges(mul_node_name) + self.ins[add_node_name].clear() + self.outs[a_node_name].mv(mul_node_name, add_node_name) + self.outs[x_node_name].mv(mul_node_name, add_node_name) + self.ins[add_node_name].add('A', a_node_name) + self.ins[add_node_name].add('X', x_node_name) + self.ins[add_node_name].add('Y', y_node_name) + self._RmProtoNode(mul_node_name) + self._AddProtoNode(add_node_name, None, helper, {}, 'axpy') + + def _DealWithPriorBox(self, source_ops, helper): + nodes_to_del = [] + for source_op in source_ops: + if source_op.type == 'prior_box': + pb_node_name = self._NameNodeMid(source_op) + br_node_name = self.outs[pb_node_name].target('Boxes') + vr_node_name = self.outs[pb_node_name].target('Variances') + bc_node_name = self.outs[br_node_name].target('Out') + vc_node_name = self.outs[vr_node_name].target('Out') + boxcoder_node_name = self.outs[bc_node_name].target('Out') + self.outs[pb_node_name].mv(br_node_name, bc_node_name) + self.outs[pb_node_name].rm(vr_node_name) + self.ins[bc_node_name].mv(br_node_name, pb_node_name) + self.ins[boxcoder_node_name].rm(vc_node_name) + for node_name in [br_node_name, vr_node_name, vc_node_name]: + if node_name not in nodes_to_del: + nodes_to_del.append(node_name) + input_node_name = self.ins[pb_node_name].target('Input') + image_node_name = self.ins[pb_node_name].target('Image') + self.ins[pb_node_name].rm(input_node_name) + self.ins[pb_node_name].rm(image_node_name) + self.ins[pb_node_name].add('Input', input_node_name) + self.ins[pb_node_name].add('Image', image_node_name) + self._RmProtoNode(bc_node_name) + self._AddProtoNode(bc_node_name, None, helper, {}, 'concat_btw_priorbox_boxcoder') + for node_name in nodes_to_del: + self._RmProtoNode(node_name) + self._ClearEdges(node_name) + + def _DealWithDetectionOutput(self, source_ops, helper): + for source_op in source_ops: + if source_op.type == 'box_coder': + bc_node_name = self._NameNodeMid(source_op) + out_targets = self.outs[bc_node_name]() + if len(out_targets) == 1 and out_targets[0].startswith('multiclass_nms'): + private_data = {} + private_data['code_type'] = helper.attr_data(source_op, 'code_type') + bc_out_arg = helper.var_name_by_param(source_op, 'OutputBox') + for tmp_op in source_ops: + if tmp_op.idx != source_op.idx and bc_out_arg in tmp_op.input_arg_names: + nms_op = tmp_op + nms_node_name = out_targets[0] + loc_node_name = self.ins[bc_node_name].target('TargetBox') + conf_node_name = self.ins[nms_node_name].target('Scores') + box_node_name = self.ins[bc_node_name].target('PriorBox') + self._ClearEdges(bc_node_name) + self.ins[nms_node_name].clear() + self.outs[loc_node_name].mv(bc_node_name, nms_node_name) + self.outs[box_node_name].mv(bc_node_name, nms_node_name) + self.ins[nms_node_name].add('mbox_loc', loc_node_name) + self.ins[nms_node_name].add('mbox_conf_flatten', conf_node_name) + self.ins[nms_node_name].add('mbox_prior_box', box_node_name) + self._RmProtoNode(bc_node_name) + self._RmProtoNode(nms_node_name) + self._AddProtoNode(nms_node_name, nms_op, helper, \ + private_data, 'multiclass_nms') + + def _DealWithMultiFC(self, source_ops, helper): + for source_op in source_ops: + if source_op.type == 'sum': + sum_node_name = self._NameNodeMid(source_op) + mul_names_list = self.ins[sum_node_name].targets('X') + elt_node_name = self.outs[sum_node_name].target('Out') + if elt_node_name.startswith('elementwise_add') and len(mul_names_list) > 1: + elt_op = self._GetOp(source_ops, elt_node_name) + elt_has_weights = helper.is_persistable_param(elt_op, 'Y') + fc_flag = True + for mul_node_name in mul_names_list: + if mul_node_name.startswith('mul') is False: + fc_flags = False + if fc_flag and elt_has_weights: + private_data = {} + first_mul_name = mul_names_list[0] + first_mul_op = self._GetOp(source_ops, first_mul_name) + in_of_mul_name = self.ins[first_mul_name].target('X') + out_of_elt_name = self.outs[elt_node_name].target('Out') + self.outs[sum_node_name].mv(elt_node_name, out_of_elt_name) + self.ins[out_of_elt_name].mv(elt_node_name, sum_node_name) + self._ClearEdges(elt_node_name) + [elt_tensor, shape] = helper.param_tensor_sh(elt_op, 'Y') + new_shape = [1, shape[3], 1, 1] + elt_tensor.set_shape(new_shape) + private_data['bias'] = elt_tensor + self._RmProtoNode(elt_node_name) + self._RmProtoNode(first_mul_name) + self._AddProtoNode(first_mul_name, first_mul_op, helper, private_data) + + def _DealWithGru(self, source_ops, helper): + for source_op in source_ops: + if source_op.type == 'gru': + private_data = {} + gru_flags = [False, False] + gru_node_name = self._NameNodeMid(source_op) + gru_op = self._GetOp(source_ops, gru_node_name) + input_list_of_gru = self.ins[gru_node_name].targets('Input') + if len(input_list_of_gru) == 1 and \ + input_list_of_gru[0].startswith('elementwise_add'): + elt_node_name = input_list_of_gru[0] + elt_op = self._GetOp(source_ops, elt_node_name) + has_weights = helper.is_persistable_param(elt_op, 'Y') + if has_weights is True: + private_data['np_bias_x'] = helper.np_param(elt_op, 'Y') + gru_flags[0] = True + input_list_of_elt = self.ins[elt_node_name].targets('X') + if len(input_list_of_elt) == 1 and input_list_of_elt[0].startswith('mul'): + mul_node_name = input_list_of_elt[0] + mul_op = self._GetOp(source_ops, mul_node_name) + if helper.var_name_by_param(mul_op, 'Y').startswith('fc'): + if helper.attr_data(mul_op, 'x_num_col_dims') == 1: + input_list_of_mul = self.ins[mul_node_name].targets('X') + input_name_of_mul = input_list_of_mul[0] + private_data['np_weight_x'] = helper.np_param(mul_op, 'Y') + gru_flags[1] = True + else: + raise NameError('ERROR: Axis of GRU_FC must be 1.') + if gru_flags == [True, True]: + self.outs[input_name_of_mul].mv(mul_node_name, gru_node_name) + self.ins[gru_node_name].mv(elt_node_name, input_name_of_mul) + for node_to_del_name in [mul_node_name, elt_node_name, gru_node_name]: + self._RmProtoNode(node_to_del_name) + if node_to_del_name is not gru_node_name: + self._ClearEdges(node_to_del_name) + self._AddProtoNode(gru_node_name, gru_op, helper, private_data) + + def _SearchBilstm(self, source_ops, helper): + comp = Fluid_comparator(helper) + lstm_ops = [] + for source_op in source_ops: + if source_op.type == 'lstm': + lstm_ops.append(source_op) + if len(lstm_ops) == 2: + lstm_a = lstm_ops[0] + lstm_b = lstm_ops[1] + same_bias = comp.compare_by_param(lstm_a, lstm_b, 'Bias') + same_weight = comp.compare_by_param(lstm_a, lstm_b, 'Weight') + if same_bias and same_weight: + return True + else: + return False + else: + return False + + def _DealWithLstm(self, source_ops, helper): + for source_op in source_ops: + if source_op.type == 'lstm': + private_data = {} + lstm_flags = [False, False] + lstm_node_name = self._NameNodeMid(source_op) + lstm_op = self._GetOp(source_ops, lstm_node_name) + input_list_of_lstm = self.ins[lstm_node_name].targets('Input') + input_list = [] + if len(input_list_of_lstm) == 1: + in_lstm_node_name = input_list_of_lstm[0] + if input_list_of_lstm[0].split('#')[0] == 'elementwise_add': + elt_op = self._GetOp(source_ops, in_lstm_node_name) + has_weights = helper.is_persistable_param(elt_op, 'Y') + if has_weights is True: + private_data['np_flat_fc_bias'] = helper.np_param(elt_op, 'Y') + lstm_flags[0] = True + input_list = self.ins[in_lstm_node_name].targets('X') + elif input_list_of_lstm[0].split('#')[0] == 'mul': + private_data['np_flat_fc_bias'] = None + input_list = input_list_of_lstm + lstm_flags[0] = True + if lstm_flags[0] is True and len(input_list) == 1: + if input_list[0].split('#')[0] == 'mul': + mul_node_name = input_list[0] + mul_op = self._GetOp(source_ops, mul_node_name) + #if helper.var_name_by_param(mul_op, 'Y').startswith('fc'): + if helper.attr_data(mul_op, 'x_num_col_dims') == 1: + input_list_of_mul = self.ins[mul_node_name].targets('X') + input_name_of_mul = input_list_of_mul[0] + [w_np, w_sh] = helper.data_with_shape_by_param(mul_op, 'Y', \ + False, None, 0, False) + private_data['np_flat_fc_weight'] = w_np + private_data['np_fc_outdim'] = w_sh[3] + lstm_flags[1] = True + else: + raise NameError('ERROR: Axis of LSTM_FC must be 1.') + if lstm_flags == [True, True]: + self.outs[input_name_of_mul].mv(mul_node_name, lstm_node_name) + self.ins[lstm_node_name].mv(in_lstm_node_name, input_name_of_mul) + if in_lstm_node_name == mul_node_name: + nodes_to_del = [mul_node_name, lstm_node_name] + else: + nodes_to_del = [mul_node_name, in_lstm_node_name, lstm_node_name] + for node_to_del_name in nodes_to_del: + self._RmProtoNode(node_to_del_name) + if node_to_del_name is not lstm_node_name: + self._ClearEdges(node_to_del_name) + self._AddProtoNode(lstm_node_name, lstm_op, helper, private_data) + + def _DealWithCast(self, source_ops, helper): + for source_op in source_ops: + if source_op.type == 'cast': + if helper.attr_data(source_op, 'out_dtype') == 5: + cast_node_name = self._NameNodeMid(source_op) + if cast_node_name in self.ins: + input_name_of_cast = self.ins[cast_node_name].target('X') + if input_name_of_cast.startswith('top_k') is False: + output_name_of_cast = self.outs[cast_node_name].target('Out') + self.outs[input_name_of_cast].mv(cast_node_name, output_name_of_cast) + self.ins[output_name_of_cast].mv(cast_node_name, input_name_of_cast) + self._RmProtoNode(cast_node_name) + self._ClearEdges(cast_node_name) + else: + print 'Cannot find the layer corresponding to cast.' + else: + raise NameError('The out type of cast must be float32.') + + def _DealWithArgmax(self, source_ops, helper): + for source_op in source_ops: + if source_op.type == 'top_k': + private_data = {} + topk_node_name = self._NameNodeMid(source_op) + out_list = self.outs[topk_node_name].targets('Out') + index_list = self.outs[topk_node_name].targets('Indices') + if len(index_list) > 0: + if len(out_list) == 1 and index_list[0].startswith('cast'): + private_data['out_max_val'] = True + idxcast_node_name = index_list[0] + output_name_of_idxcast = self.outs[idxcast_node_name].target('Out') + if output_name_of_idxcast == out_list[0] and \ + out_list[0].startswith('concat'): + concat_node_name = out_list[0] + output_name_of_concat = self.outs[concat_node_name].target('Out') + self.outs[topk_node_name].rm(idxcast_node_name) + self.outs[topk_node_name].mv(concat_node_name, output_name_of_concat) + self.ins[output_name_of_concat].mv(concat_node_name, topk_node_name) + for node_to_del_name in [concat_node_name, idxcast_node_name]: + self._RmProtoNode(node_to_del_name) + self._ClearEdges(node_to_del_name) + elif output_name_of_idxcast != out_list[0]: + if output_name_of_idxcast.endswith('_gout') and \ + out_list[0].endswith('_gout'): + gout_node_name = out_list[0] + idx_gout_node_name = output_name_of_idxcast + self.outs[topk_node_name].rm(idxcast_node_name) + for node_to_del_name in [idx_gout_node_name, idxcast_node_name]: + self._RmProtoNode(node_to_del_name) + self._ClearEdges(node_to_del_name) + self.graphIO.rm_out(idx_gout_node_name) + elif len(out_list) == 0: + private_data['out_max_val'] = False + self._DealWithCast(source_ops, helper) + else: + raise NameError('ERROR: Unknown top_k layer.') + self._RmProtoNode(topk_node_name) + self._AddProtoNode(topk_node_name, source_op, helper, private_data) + + def _DealWithReshape(self, source_ops, helper): + for source_op in source_ops: + if source_op.type == 'reshape': + reshape_node_name = self._NameNodeMid(source_op) + if reshape_node_name in self.ins: + shape_inputs = self.ins[reshape_node_name].targets('Shape') + tensor_inputs = self.ins[reshape_node_name].targets('X') + if len(shape_inputs) == 1 and len(tensor_inputs) == 1: + self.ins[reshape_node_name].rm(shape_inputs[0]) + self.ins[reshape_node_name].add('Shape', shape_inputs[0]) + else: + pass + + def _DealWithSoftmax(self, source_ops, helper): + for source_op in source_ops: + if source_op.type == 'softmax': + softmax_node_name = self._NameNodeMid(source_op) + outs_of_softmax = self.outs[softmax_node_name].targets('Out') + ins_of_softmax = self.ins[softmax_node_name].targets('X') + def prune(reshape_node_name): + """ + """ + branch = [] + branch.append(reshape_node_name) + shape_inputs = self.ins[reshape_node_name].targets('Shape') + tensor_input = self.ins[reshape_node_name].target('X') + tensor_output = self.outs[reshape_node_name].target('Out') + if len(shape_inputs) == 1: + branch.append(shape_inputs[0]) + if len(branch) == 2 and branch[1].split('#')[0] == 'split': + split_node_name = branch[1] + self.outs[split_node_name].rm(reshape_node_name) + self.ins[reshape_node_name].rm(split_node_name) + if len(self.outs[split_node_name].targets('_Out')) == 0: + input_of_split = self.ins[split_node_name].target('_In') + branch.append(input_of_split) + self._RmProtoNode(split_node_name) + self._ClearEdges(split_node_name) + elif len(branch) == 2 and branch[1].startswith('input'): + raise NameError('ERROR: None-split input of Softmax has not supported.') + self.outs[tensor_input].mv(reshape_node_name, tensor_output) + self.ins[tensor_output].mv(reshape_node_name, tensor_input) + self._RmProtoNode(reshape_node_name) + self._ClearEdges(reshape_node_name) + if len(branch) == 3 and branch[2].startswith('input'): + input_node_name = branch[2] + self._RmProtoNode(input_node_name) + self._ClearEdges(input_node_name) + if outs_of_softmax[0].split('#')[0] == 'reshape' and \ + ins_of_softmax[0].split('#')[0] == 'reshape': + private_data = {} + private_data['axis'] = 3 + prune(outs_of_softmax[0]) + prune(ins_of_softmax[0]) + self._RmProtoNode(softmax_node_name) + self._AddProtoNode(softmax_node_name, source_op, helper, private_data) + + def _DealWithMatmal(self, source_ops, helper): + for source_op in source_ops: + if source_op.type == 'matmul': + matmul_node_name = self._NameNodeMid(source_op) + x_input_name = self.ins[matmul_node_name].target('X') + y_input_name = self.ins[matmul_node_name].target('Y') + flag = False + coeff = 1.0 + for node_name in [x_input_name, y_input_name]: + if node_name.startswith('scale') or node_name.startswith('dropout'): + op = self._GetOp(source_ops, node_name) + if node_name.startswith('scale'): + scale = helper.attr_data(op, 'scale') + elif node_name.startswith('dropout'): + scale = 1 - helper.attr_data(op, 'dropout_prob') + input_node = self.ins[node_name].target('X') + self.outs[input_node].mv(node_name, matmul_node_name) + self.ins[matmul_node_name].mv(node_name, input_node) + self._RmProtoNode(node_name) + self._ClearEdges(node_name) + coeff = coeff * scale + flag = True + if flag is True: + private_data = {} + private_data['coeff'] = coeff + self._RmProtoNode(matmul_node_name) + self._AddProtoNode(matmul_node_name, source_op, helper, private_data) + + def _DealWithDiscBatchNorm(self, source_ops, helper): + for source_op in source_ops: + if source_op.type == 'batch_norm': + discrete_flag = True + bn_node_name = self._NameNodeMid(source_op) + input_name = self.ins[bn_node_name].target('X') + if input_name.startswith('elementwise_add'): + input_of_elt = self.ins[input_name].target('X') + if input_of_elt.startswith('conv2d'): + discrete_flag = False + elif input_name.startswith('conv2d'): + discrete_flag = False + if discrete_flag is True: + self._RmProtoNode(bn_node_name) + self._AddProtoNode(bn_node_name, source_op, helper, {}, 'disc_bn') + + def _DealWithSSD(self, source_ops, helper): + for source_op in source_ops: + if source_op.type == 'reshape': + rh_node_name = self._NameNodeMid(source_op) + if rh_node_name in self.ins: + private_data = dict() + input_name = self.ins[rh_node_name].target('X') + shape = helper.attr_data(source_op, 'shape') + if input_name.startswith('concat'): + private_data['new_shape'] = [0, shape[0], shape[1], 0] + else: + private_data['new_shape'] = [0, -1, 1, 1] + self._RmProtoNode(rh_node_name) + self._AddProtoNode(rh_node_name, source_op, helper, private_data, 'reshape') + for source_op in source_ops: + if source_op.type == 'softmax': + private_data = dict() + sm_node_name = self._NameNodeMid(source_op) + private_data['axis'] = 2 + self._RmProtoNode(sm_node_name) + self._AddProtoNode(sm_node_name, source_op, helper, private_data, 'softmax') + + def _NewCommonLayer(self, + source_ops, + in_target, + in_param, + out_target, + out_param, + layer_type, + private_data, + helper, + insert_mode=True): + main_layer = layer_type + '_after_' + in_target + if insert_mode is True: + if in_target in self.ins[out_target].all_targets() and \ + out_target in self.outs[in_target].all_targets(): + self.ins[out_target].mv(in_target, main_layer) + self.outs[in_target].mv(out_target, main_layer) + else: + raise NameError('ERROR: Usage of InsertCommonLayer has not supported.') + else: + self.ins[out_target].add(in_param + '_insert', main_layer) + self.outs[in_target].add(out_param + '_insert', main_layer) + self.ins[main_layer] = Fluid_edger(in_param, in_target) + self.outs[main_layer] = Fluid_edger(out_param, out_target) + self._AddProtoNode(main_layer, None, helper, private_data, layer_type) + + def _ParseNetwork(self, source_ops, helper): + self._ParseBase(source_ops, helper) + if self.NetType == "FLUIDBASE": + pass + else: + reshape_dict = {} + if self.NetType == "OCR": + reshape_dict['input_0'] = [1, 1, 48, 1500] + self._ReplaceInputs(source_ops, helper, reshape_dict) + self._InsertSplit(source_ops, helper) + self._DealWithGru(source_ops, helper) + self._DealWithLstm(source_ops, helper) + self._DealWithBias(source_ops, helper) + self._DealWithBatchnorm(source_ops, helper) + self._DealWithMultiFC(source_ops, helper) + self._DealWithArgmax(source_ops, helper) + self._DealWithAxpy(source_ops, helper) + if self.NetType == "SSD": + self._DealWithPriorBox(source_ops, helper) + self._DealWithDetectionOutput(source_ops, helper) + self._DealWithSSD(source_ops, helper) + self._Graph() + + def _Parsing(self): + with fluid.scope_guard(self.scope): + if os.path.exists(self.ModelPath + 'model') and \ + os.path.exists(self.ModelPath + 'params'): + [self.net_program, feed_target_names, fetch_targets] = \ + fluid.io.load_inference_model(self.ModelPath, self.exe, 'model', 'params') + else: + [self.net_program, feed_target_names, fetch_targets] = \ + fluid.io.load_inference_model(self.ModelPath, self.exe) + + global_block = self.net_program.global_block() + source_ops = list(global_block.ops) + helper = Fluid_helper(self.scope, global_block) + + self._ParseNetwork(source_ops, helper) + return self.graphIO diff --git a/tools/external_converter_v2/parser/kill_tf/__init__.py b/tools/external_converter_v2/parser/kill_tf/__init__.py deleted file mode 100644 index 5a19cdd07..000000000 --- a/tools/external_converter_v2/parser/kill_tf/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -#! /usr/bin/env python -# Copyright (c) 2017, Cuichaowen. All rights reserved. -# -*- coding: utf-8 -*- - -from parser_tf import TFParser diff --git a/tools/external_converter_v2/parser/kill_tf/auto_debug.py b/tools/external_converter_v2/parser/kill_tf/auto_debug.py deleted file mode 100644 index ffa2c16a5..000000000 --- a/tools/external_converter_v2/parser/kill_tf/auto_debug.py +++ /dev/null @@ -1,124 +0,0 @@ -import tensorflow as tf -import numpy as np -import os -import tempfile -from parse_tf_2_med import ParseTF2Med -from med_graph import MedGraphUtil -from tf_trans_util import load_graph -from tf_util import TfUtil -class AutoDebug: - - def __init__(self,tf_model_path,ak_output_dir,workspace=None): - self.ak_perfix='record_' - self.tf_model_path=tf_model_path - self.ak_output_dir=os.path.dirname(ak_output_dir) - med_graph = ParseTF2Med(self.tf_model_path).parse() - MedGraphUtil.solve(med_graph) - self.med_graph = med_graph - # if workspace is None: - # self.workspace=tempfile.mkdtemp() - # else: - # self.workspace = workspace - # print('workspace is ', self.workspace) - - - def _debug_graph(self,graph): - for i in graph.values(): - print(i) - exit() - - def _convert_name_tf2ak(self,tf_name): - ak_name = tf_name[:] - for index, x in enumerate(tf_name): - if x == '/': - ak_name = ak_name[:index] + '_' + ak_name[index + 1:] - return self.ak_perfix + ak_name - - def _find_ak_output(self): - result = {} - for file_name in os.listdir(self.ak_output_dir): - real_path=os.path.join(self.ak_output_dir,file_name) - if not os.path.isdir(real_path) and file_name.startswith(self.ak_perfix) and not file_name.startswith(self.ak_perfix+'_'): - result[file_name]=[float(i.split(' ')[1]) for i in open(real_path,'r').readlines()] - return result - - def _creat_and_clear_workspace(self): - if os.path.exists(self.workspace): - assert os.path.isdir(self.workspace) - ls = os.listdir(self.workspace) - for i in ls: - c_path = os.path.join(self.workspace, i) - os.remove(c_path) - else: - os.mkdir(self.workspace) - - def _prepare_data(self,med_graph): - input_cnt=0 - inputs={} - result = {} - np.random.seed(1234567) - for i in med_graph.values(): - if i['ak_type'] == 'Input': - shape=i['output'][0]['shape'] - size=1 - for k in shape: - size*=k - tensor=np.random.randn(size).reshape(shape) - inputs['input_'+str(input_cnt)]=tensor - result[i['name']+':0']=tensor - input_cnt+=1 - - for i in inputs.keys(): - import struct - with open(os.path.join(self.ak_output_dir,i), "wb") as file: - x_value_new = inputs[i].transpose((0, 3, 1, 2)) - for value in x_value_new.flatten(): - file.write(struct.pack('f', value)) - - return result - - - def run_ak(self): - self._prepare_data(self.med_graph) - - def run(self): - inputs = self._prepare_data(self.med_graph) - akopname2ak_out=self._find_ak_output() - for i in akopname2ak_out: - print(i) - compare_dic={} - for node in self.med_graph.values(): - print(node['name'], node['ak_type']) - if node['ak_type'] is not None and node['type'] is not None: - - name=node['name'] - if node.get('fusion_out_name') is not None: - name=node['fusion_out_name'] - ak_name=self._convert_name_tf2ak(name) - print('key ',ak_name) - if akopname2ak_out.get(ak_name) is not None: - compare_dic[name+':0']=akopname2ak_out[ak_name] - outlist=compare_dic.keys() - out=TfUtil.tf_run_model(self.tf_model_path,inputs,outlist) - for index,name in enumerate(outlist): - correct=out[index].transpose() - ak_result=akopname2ak_out[name] - assert len() - for i in range(len(ak_result)): - if abs() - # tensor_shape = {} - # graph={} - # for node in tf_ops: - # for out in node.outputs: - # tensor_shape[out.name] = out.get_shape().as_list() - # input_names = [i.name for i in node.inputs] - # output_names = [i.name for i in node.outputs] - # graph[node.name]={'name':node.name,'input':input_names,'output':output_names} - # self._fix_self_output(graph,tensor_shape) - # self._debug_graph(graph) -ak_work_space='/home/ljj/docker_mount_dev2/anakin2_developing_parser/build/' - -debug=AutoDebug('./resnet_model/frozen_resnet_v1_50.pb',ak_work_space) -debug.run_ak() -debug.run() - diff --git a/tools/external_converter_v2/parser/kill_tf/freeze.py b/tools/external_converter_v2/parser/kill_tf/freeze.py deleted file mode 100644 index bc5b77631..000000000 --- a/tools/external_converter_v2/parser/kill_tf/freeze.py +++ /dev/null @@ -1,62 +0,0 @@ -# -*- coding:utf-8 -*- -import os, argparse -import tensorflow as tf -from tensorflow.python.framework import graph_util - -dir = os.path.dirname(os.path.realpath(__file__)) - - -def freeze_graph(model_folder,output_name): - # We retrieve our checkpoint fullpath - checkpoint = tf.train.get_checkpoint_state(model_folder) - input_checkpoint = checkpoint.model_checkpoint_path - - # We precise the file fullname of our freezed graph - absolute_model_folder = "/".join(input_checkpoint.split('/')[:-1]) - output_graph = absolute_model_folder + "/frozen_model.pb" - - # Before exporting our graph, we need to precise what is our output node - # this variables is plural, because you can have multiple output nodes - # freeze之前必须明确哪个是输出结点,也就是我们要得到推论结果的结点 - # 输出结点可以看我们模型的定义 - # 只有定义了输出结点,freeze才会把得到输出结点所必要的结点都保存下来,或者哪些结点可以丢弃 - # 所以,output_node_names必须根据不同的网络进行修改 - output_node_names = output_name - - # We clear the devices, to allow TensorFlow to control on the loading where it wants operations to be calculated - clear_devices = True - - # We import the meta graph and retrive a Saver - saver = tf.train.import_meta_graph(input_checkpoint + '.meta', clear_devices=clear_devices) - - # We retrieve the protobuf graph definition - graph = tf.get_default_graph() - input_graph_def = graph.as_graph_def() - - # We start a session and restore the graph weights - # 这边已经将训练好的参数加载进来,也即最后保存的模型是有图,并且图里面已经有参数了,所以才叫做是frozen - # 相当于将参数已经固化在了图当中 - with tf.Session() as sess: - saver.restore(sess, input_checkpoint) - - # We use a built-in TF helper to export variables to constant - output_graph_def = graph_util.convert_variables_to_constants( - sess, - input_graph_def, - output_node_names.split(",") # We split on comma for convenience - ) - # Finally we serialize and dump the output graph to the filesystem - with tf.gfile.GFile(output_graph, "wb") as f: - f.write(output_graph_def.SerializeToString()) - print("%d ops in the final graph." % len(output_graph_def.node)) - - -if __name__ == '__main__': - # parser = argparse.ArgumentParser() - # parser.add_argument("--model_folder", type=str, help="Model folder to export") - # args = parser.parse_args() - # freeze_graph(args.model_folder) - - # freeze_graph('/tmp/pycharm_project_635/tensorflow/RNN/model/language_model_tf','Softmax') - freeze_graph('./ease_model/', 'add_2') - diff --git a/tools/external_converter_v2/parser/kill_tf/freeze_graph.py b/tools/external_converter_v2/parser/kill_tf/freeze_graph.py deleted file mode 100644 index 73a430866..000000000 --- a/tools/external_converter_v2/parser/kill_tf/freeze_graph.py +++ /dev/null @@ -1,404 +0,0 @@ -# Copyright 2015 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. -# ============================================================================== -r"""Converts checkpoint variables into Const ops in a standalone GraphDef file. - -This script is designed to take a GraphDef proto, a SaverDef proto, and a set of -variable values stored in a checkpoint file, and output a GraphDef with all of -the variable ops converted into const ops containing the values of the -variables. - -It's useful to do this when we need to load a single file in C++, especially in -environments like mobile or embedded where we may not have access to the -RestoreTensor ops and file loading calls that they rely on. - -An example of command-line usage is: -bazel build tensorflow/python/tools:freeze_graph && \ -bazel-bin/tensorflow/python/tools/freeze_graph \ ---input_graph=some_graph_def.pb \ ---input_checkpoint=model.ckpt-8361242 \ ---output_graph=/tmp/frozen_graph.pb --output_node_names=softmax - -You can also look at freeze_graph_test.py for an example of how to use it. - -""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import argparse -import re -import sys - -from google.protobuf import text_format - -from tensorflow.core.framework import graph_pb2 -from tensorflow.core.protobuf import saver_pb2 -from tensorflow.core.protobuf.meta_graph_pb2 import MetaGraphDef -from tensorflow.python import pywrap_tensorflow -from tensorflow.python.client import session -from tensorflow.python.framework import graph_util -from tensorflow.python.framework import importer -from tensorflow.python.platform import app -from tensorflow.python.platform import gfile -from tensorflow.python.saved_model import loader -from tensorflow.python.saved_model import tag_constants -from tensorflow.python.tools import saved_model_utils -from tensorflow.python.training import saver as saver_lib - - -def freeze_graph_with_def_protos(input_graph_def, - input_saver_def, - input_checkpoint, - output_node_names, - restore_op_name, - filename_tensor_name, - output_graph, - clear_devices, - initializer_nodes, - variable_names_whitelist="", - variable_names_blacklist="", - input_meta_graph_def=None, - input_saved_model_dir=None, - saved_model_tags=None, - checkpoint_version=saver_pb2.SaverDef.V2): - """Converts all variables in a graph and checkpoint into constants.""" - del restore_op_name, filename_tensor_name # Unused by updated loading code. - - if not output_node_names: - print("You need to supply the name of a node to --output_node_names.") - return -1 - - # Remove all the explicit device specifications for this node. This helps to - # make the graph more portable. - if clear_devices: - if input_meta_graph_def: - for node in input_meta_graph_def.graph_def.node: - node.device = "" - elif input_graph_def: - for node in input_graph_def.node: - node.device = "" - - if input_graph_def: - _ = importer.import_graph_def(input_graph_def, name="") - with session.Session() as sess: - if input_saver_def: - saver = saver_lib.Saver( - saver_def=input_saver_def, write_version=checkpoint_version) - saver.restore(sess, input_checkpoint) - elif input_meta_graph_def: - restorer = saver_lib.import_meta_graph( - input_meta_graph_def, clear_devices=True) - restorer.restore(sess, input_checkpoint) - if initializer_nodes: - sess.run(initializer_nodes.replace(" ", "").split(",")) - elif input_saved_model_dir: - if saved_model_tags is None: - saved_model_tags = [] - loader.load(sess, saved_model_tags, input_saved_model_dir) - else: - var_list = {} - reader = pywrap_tensorflow.NewCheckpointReader(input_checkpoint) - var_to_shape_map = reader.get_variable_to_shape_map() - - # List of all partition variables. Because the condition is heuristic - # based, the list could include false positives. - all_parition_variable_names = [ - tensor.name.split(":")[0] - for op in sess.graph.get_operations() - for tensor in op.values() - if re.search(r"/part_\d+/", tensor.name) - ] - has_partition_var = False - - for key in var_to_shape_map: - try: - tensor = sess.graph.get_tensor_by_name(key + ":0") - if any(key in name for name in all_parition_variable_names): - has_partition_var = True - except KeyError: - # This tensor doesn't exist in the graph (for example it's - # 'global_step' or a similar housekeeping element) so skip it. - continue - var_list[key] = tensor - - try: - saver = saver_lib.Saver( - var_list=var_list, write_version=checkpoint_version) - except TypeError as e: - # `var_list` is required to be a map of variable names to Variable - # tensors. Partition variables are Identity tensors that cannot be - # handled by Saver. - if has_partition_var: - print("Models containing partition variables cannot be converted " - "from checkpoint files. Please pass in a SavedModel using " - "the flag --input_saved_model_dir.") - return -1 - else: - raise e - - saver.restore(sess, input_checkpoint) - if initializer_nodes: - sess.run(initializer_nodes.replace(" ", "").split(",")) - - variable_names_whitelist = ( - variable_names_whitelist.replace(" ", "").split(",") - if variable_names_whitelist else None) - variable_names_blacklist = ( - variable_names_blacklist.replace(" ", "").split(",") - if variable_names_blacklist else None) - - if input_meta_graph_def: - output_graph_def = graph_util.convert_variables_to_constants( - sess, - input_meta_graph_def.graph_def, - output_node_names.replace(" ", "").split(","), - variable_names_whitelist=variable_names_whitelist, - variable_names_blacklist=variable_names_blacklist) - else: - output_graph_def = graph_util.convert_variables_to_constants( - sess, - input_graph_def, - output_node_names.replace(" ", "").split(","), - variable_names_whitelist=variable_names_whitelist, - variable_names_blacklist=variable_names_blacklist) - - # Write GraphDef to file if output path has been given. - if output_graph: - with gfile.GFile(output_graph, "wb") as f: - f.write(output_graph_def.SerializeToString()) - - return output_graph_def - - -def _parse_input_graph_proto(input_graph, input_binary): - """Parser input tensorflow graph into GraphDef proto.""" - if not gfile.Exists(input_graph): - print("Input graph file '" + input_graph + "' does not exist!") - return -1 - input_graph_def = graph_pb2.GraphDef() - mode = "rb" if input_binary else "r" - with gfile.FastGFile(input_graph, mode) as f: - if input_binary: - input_graph_def.ParseFromString(f.read()) - else: - text_format.Merge(f.read(), input_graph_def) - return input_graph_def - - -def _parse_input_meta_graph_proto(input_graph, input_binary): - """Parser input tensorflow graph into MetaGraphDef proto.""" - if not gfile.Exists(input_graph): - print("Input meta graph file '" + input_graph + "' does not exist!") - return -1 - input_meta_graph_def = MetaGraphDef() - mode = "rb" if input_binary else "r" - with gfile.FastGFile(input_graph, mode) as f: - if input_binary: - input_meta_graph_def.ParseFromString(f.read()) - else: - text_format.Merge(f.read(), input_meta_graph_def) - print("Loaded meta graph file '" + input_graph) - return input_meta_graph_def - - -def _parse_input_saver_proto(input_saver, input_binary): - """Parser input tensorflow Saver into SaverDef proto.""" - if not gfile.Exists(input_saver): - print("Input saver file '" + input_saver + "' does not exist!") - return -1 - mode = "rb" if input_binary else "r" - with gfile.FastGFile(input_saver, mode) as f: - saver_def = saver_pb2.SaverDef() - if input_binary: - saver_def.ParseFromString(f.read()) - else: - text_format.Merge(f.read(), saver_def) - return saver_def - - -def freeze_graph(input_graph, - input_saver, - input_binary, - input_checkpoint, - output_node_names, - restore_op_name, - filename_tensor_name, - output_graph, - clear_devices, - initializer_nodes, - variable_names_whitelist="", - variable_names_blacklist="", - input_meta_graph=None, - input_saved_model_dir=None, - saved_model_tags=tag_constants.SERVING, - checkpoint_version=saver_pb2.SaverDef.V2): - """Converts all variables in a graph and checkpoint into constants.""" - input_graph_def = None - if input_saved_model_dir: - input_graph_def = saved_model_utils.get_meta_graph_def( - input_saved_model_dir, saved_model_tags).graph_def - elif input_graph: - input_graph_def = _parse_input_graph_proto(input_graph, input_binary) - input_meta_graph_def = None - if input_meta_graph: - input_meta_graph_def = _parse_input_meta_graph_proto( - input_meta_graph, input_binary) - input_saver_def = None - if input_saver: - input_saver_def = _parse_input_saver_proto(input_saver, input_binary) - freeze_graph_with_def_protos( - input_graph_def, - input_saver_def, - input_checkpoint, - output_node_names, - restore_op_name, - filename_tensor_name, - output_graph, - clear_devices, - initializer_nodes, - variable_names_whitelist, - variable_names_blacklist, - input_meta_graph_def, - input_saved_model_dir, - saved_model_tags.replace(" ", "").split(","), - checkpoint_version=checkpoint_version) - - -def main(unused_args, flags): - if flags.checkpoint_version == 1: - checkpoint_version = saver_pb2.SaverDef.V1 - elif flags.checkpoint_version == 2: - checkpoint_version = saver_pb2.SaverDef.V2 - else: - print("Invalid checkpoint version (must be '1' or '2'): %d" % - flags.checkpoint_version) - return -1 - freeze_graph(flags.input_graph, flags.input_saver, flags.input_binary, - flags.input_checkpoint, flags.output_node_names, - flags.restore_op_name, flags.filename_tensor_name, - flags.output_graph, flags.clear_devices, flags.initializer_nodes, - flags.variable_names_whitelist, flags.variable_names_blacklist, - flags.input_meta_graph, flags.input_saved_model_dir, - flags.saved_model_tags, checkpoint_version) - -def run_main(): - parser = argparse.ArgumentParser() - parser.register("type", "bool", lambda v: v.lower() == "true") - parser.add_argument( - "--input_graph", - type=str, - default="", - help="TensorFlow \'GraphDef\' file to load.") - parser.add_argument( - "--input_saver", - type=str, - default="", - help="TensorFlow saver file to load.") - parser.add_argument( - "--input_checkpoint", - type=str, - default="", - help="TensorFlow variables file to load.") - parser.add_argument( - "--checkpoint_version", - type=int, - default=2, - help="Tensorflow variable file format") - parser.add_argument( - "--output_graph", - type=str, - default="", - help="Output \'GraphDef\' file name.") - parser.add_argument( - "--input_binary", - nargs="?", - const=True, - type="bool", - default=False, - help="Whether the input files are in binary format.") - parser.add_argument( - "--output_node_names", - type=str, - default="", - help="The name of the output nodes, comma separated.") - parser.add_argument( - "--restore_op_name", - type=str, - default="save/restore_all", - help="""\ - The name of the master restore operator. Deprecated, unused by updated \ - loading code. - """) - parser.add_argument( - "--filename_tensor_name", - type=str, - default="save/Const:0", - help="""\ - The name of the tensor holding the save path. Deprecated, unused by \ - updated loading code. - """) - parser.add_argument( - "--clear_devices", - nargs="?", - const=True, - type="bool", - default=True, - help="Whether to remove device specifications.") - parser.add_argument( - "--initializer_nodes", - type=str, - default="", - help="Comma separated list of initializer nodes to run before freezing.") - parser.add_argument( - "--variable_names_whitelist", - type=str, - default="", - help="""\ - Comma separated list of variables to convert to constants. If specified, \ - only those variables will be converted to constants.\ - """) - parser.add_argument( - "--variable_names_blacklist", - type=str, - default="", - help="""\ - Comma separated list of variables to skip converting to constants.\ - """) - parser.add_argument( - "--input_meta_graph", - type=str, - default="", - help="TensorFlow \'MetaGraphDef\' file to load.") - parser.add_argument( - "--input_saved_model_dir", - type=str, - default="", - help="Path to the dir with TensorFlow \'SavedModel\' file and variables.") - parser.add_argument( - "--saved_model_tags", - type=str, - default="serve", - help="""\ - Group of tag(s) of the MetaGraphDef to load, in string format,\ - separated by \',\'. For tag-set contains multiple tags, all tags \ - must be passed in.\ - """) - flags, unparsed = parser.parse_known_args() - - my_main = lambda unused_args: main(unused_args, flags) - app.run(main=my_main, argv=[sys.argv[0]] + unparsed) - -if __name__ == '__main__': - run_main() diff --git a/tools/external_converter_v2/parser/kill_tf/get_empt_infer_pb.py b/tools/external_converter_v2/parser/kill_tf/get_empt_infer_pb.py deleted file mode 100644 index 16b9b0f06..000000000 --- a/tools/external_converter_v2/parser/kill_tf/get_empt_infer_pb.py +++ /dev/null @@ -1,39 +0,0 @@ -import tensorflow as tf -from tensorflow.python.framework import graph_util -import numpy as np -from tensorflow.python.platform import gfile -from google.protobuf import text_format - -graph_path='./inception_model/inception_v2_inf_graph.pb' -output_node_names='InceptionV2/Predictions/Reshape_1' -output_graph='./inception_model/inception_v2_inf_graph_empty.pb' - -sess=tf.Session() -if graph_path.endswith('.pbtxt'): - input_binary = False -else: - input_binary = True - -graph = tf.get_default_graph() -graph_def = graph.as_graph_def() -if graph_path.endswith('.pb') or graph_path.endswith('.pbtxt'): - mode = "rb" if input_binary else "r" - with gfile.FastGFile(graph_path, mode) as f: - if input_binary: - graph_def.ParseFromString(f.read()) - else: - text_format.Merge(f.read(), graph_def) -else: - tf.train.import_meta_graph(graph_path, clear_devices=True) - -tf.import_graph_def(graph_def, name='graph') - -output_graph_def = graph_util.convert_variables_to_constants( - sess, - graph_def, - output_node_names.split(",") # We split on comma for convenience - ) -# Finally we serialize and dump the output graph to the filesystem -with tf.gfile.GFile(output_graph, "wb") as f: - f.write(output_graph_def.SerializeToString()) -print("%d ops in the final graph." % len(output_graph_def.node)) \ No newline at end of file diff --git a/tools/external_converter_v2/parser/kill_tf/med_graph.py b/tools/external_converter_v2/parser/kill_tf/med_graph.py deleted file mode 100644 index aacbc5e15..000000000 --- a/tools/external_converter_v2/parser/kill_tf/med_graph.py +++ /dev/null @@ -1,154 +0,0 @@ -import numpy as np - - - -class MedNodeUtil: - - @staticmethod - def new_med_node(): - return {'name':None,'ak_type': None, 'input': [], 'output': [], 'ak_attr': {},'type':None,'med_visted':False} - - @staticmethod - def replace_name_with_list(origin_list, name, replace_list): - new_list = [] - for index, ori_object in enumerate(origin_list): - if ori_object['name'] == name: - new_list = new_list + replace_list + origin_list[index + 1:] - break - else: - new_list.append(ori_object) - if name in new_list: - raise Exception('circle error') - return new_list - - @staticmethod - def retain_input(node, input_list): - new_input = [] - for index, node_object in enumerate(node['input']): - if node_object in input_list: - input_list.remove(node_object) - new_input.append(node_object) - node['input'] = new_input - - @staticmethod - def redirecto_outputs_input_to_this(node,graph,this_name,this_shape): - for i in node['output']: - tar_node=graph[i['name']] - tar_node['input']=MedNodeUtil.replace_name_with_list(tar_node['input'],node['name'],[{'name':this_name,'shape':this_shape}]) - - - -MedGraph_Input_Cnt=0 -class MedGraphUtil: - @staticmethod - def append_node(father_node, son_node, graph): - output = father_node['output'] - son_shape = father_node['output'][0]['shape'] - son_node['input'] = [{'name': father_node['name'], 'shape': son_shape}] - son_node['output'] = output - father_node['output'] = [{'name': son_node['name'], 'shape': son_shape}] - for i in output: - out_node = graph[i['name']] - out_node['input'] = MedNodeUtil.replace_name_with_list(out_node['input'], father_node['name'], - [{'name': son_node['name'], 'shape': son_shape}]) - graph[son_node['name']] = son_node - - @staticmethod - def check_one_of_input_is_const(node,graph): - for i in node['input']: - if graph[i['name']]['type'] == 'Const': - return True - return False - - @staticmethod - def _auto_split(med_node, med_graph): - output = med_node['output'] - if len(output) > 1: - split_node = MedNodeUtil.new_med_node() - split_node['name']=med_node['name']+'_split#' - split_node['ak_type']='Split' - split_node['ak_attr']['split_num'] =len(output) - MedGraphUtil.append_node(med_node,split_node,graph=med_graph) - pass - - @staticmethod - def _auto_input_name(med_node, med_graph): - assert med_node['ak_type']=='Input' - old_name=med_node['name'] - med_node['name']='input_'+str(MedGraph_Input_Cnt) - for i in med_node['output']: - out_node=med_graph[i['name']] - out_node['input']=MedNodeUtil.replace_name_with_list(out_node['input'],old_name,[{'name':med_node['name'],'shape':i['shape']}]) - - @staticmethod - def _fusionScale(med_node, med_graph): - if len(med_node['input']) == 1: - input_node = med_graph[med_node['input'][0]['name']] - med_ak_attr = med_node['ak_attr'] - if input_node['ak_type'] == 'Convolution': - input_attr = input_node['ak_attr'] - conv_weights = input_attr['weights'] - scale_weights = med_ak_attr['scale_weights'] - - assert conv_weights.shape[0] == scale_weights.shape[-1] - new_conv_weights = np.zeros(conv_weights.shape) - for i in range(conv_weights.shape[0]): - new_conv_weights[i] = conv_weights[i] * scale_weights[i] - input_attr['weights'] = new_conv_weights.astype('float32') - if input_attr.get('bias_weights') is not None: - input_attr['bias_weights'] = input_attr['bias_weights'] + med_ak_attr['bias_weights'] - else: - input_attr['bias_weights'] = med_ak_attr['bias_weights'] - med_node['ak_type'] = None - input_node['output'] = MedNodeUtil.replace_name_with_list(input_node['output'], med_node['name'], med_node['output']) - MedNodeUtil.redirecto_outputs_input_to_this(med_node,med_graph,input_node['name'],med_node['input'][0]['shape']) - input_node['fusion_out_name']=med_node['name'] - - pass - - @staticmethod - def _all_search_table(graph, table): - for tf_node in graph.values(): - if tf_node['med_visted']: - continue - type_name = tf_node['ak_type'] - if table.get(type_name) is not None: - table[type_name](tf_node, graph) - - @staticmethod - def _all_search_fusion(graph, fusion_func): - for tf_node in graph.values(): - if tf_node['med_visted']: - continue - if tf_node['ak_type'] is not None: - fusion_func(tf_node, graph) - - @staticmethod - def solve(med_graph): - for node in med_graph.values(): - node['med_visted'] = False - MedGraphUtil._all_search_table(med_graph, {'Scale': MedGraphUtil._fusionScale}) - MedGraphUtil._all_search_fusion(med_graph, MedGraphUtil._auto_split) - MedGraphUtil._all_search_table(med_graph, {'Input':MedGraphUtil._auto_input_name}) - - @staticmethod - def search_output_list(graph): - output_list = set() - graph_cp = graph.copy() - - def recursive_search(node): - if node.get('out_search_flag') is not None: - return set() - node['out_search_flag'] = True - outputs = node['output'] - result = set() - if len(outputs) == 0: - result.add(node['name']) - else: - for i in outputs: - result |= recursive_search(graph[i['name']]) - return result - - for i in graph_cp.values(): - output_list |= recursive_search(i) - return list(output_list) diff --git a/tools/external_converter_v2/parser/kill_tf/parse_med_2_ak.py b/tools/external_converter_v2/parser/kill_tf/parse_med_2_ak.py deleted file mode 100644 index fa0df3c7a..000000000 --- a/tools/external_converter_v2/parser/kill_tf/parse_med_2_ak.py +++ /dev/null @@ -1,149 +0,0 @@ -import numpy as np -from ..graph_io import TensorProtoIO, OpsProtoIO -from ..operations import OpsParam - - -def shape_2_ak_shape(shape): - mini_shape = [i for i in shape if (i != None and i > 0)] - return map(int, [1] * (4 - len(mini_shape)) + list(mini_shape)) - - -def np_2_ak_tensor(np_tensor): - data_type_map = { - np.dtype('float32'): 'float', - np.dtype('int32'): 'int', - np.dtype('bool'): 'bool' - } - - type_str = data_type_map.get(np_tensor.dtype) - # print(np_tensor.dtype) - assert type_str != None - ak_tensor = TensorProtoIO() - ak_tensor.set_shape(shape_2_ak_shape(np_tensor.shape)) - ak_tensor.set_data(np_tensor.flatten(), type_str) - return ak_tensor - - -class MedTransAK: - def __init__(self): - self.input_count = 0 - - def Convolution(self, med_attr, param): - np_filters = med_attr['weights'] - param.weight_1 = np_2_ak_tensor(np_filters) - param.filter_num = np_filters.shape[0] - param.kernel_size = list(np_filters.shape[-2:]) - param.strides = med_attr['strides'] - param.padding = med_attr['padding'] - param.dilation_rate = med_attr['dilations'] - param.group = med_attr['group'] - param.axis = 1 - if med_attr.get('bias_weights') is not None: - param.bias_term = True - bias_tensor = med_attr['bias_weights'] - bias_tensor = bias_tensor.reshape(1, 1, 1, len(bias_tensor.flatten())) - param.weight_2 = np_2_ak_tensor(bias_tensor) - else: - param.bias_term = False - pass - - def Dense(self, med_attr, param): - param.weight_1 = np_2_ak_tensor(med_attr['weights']) - param.axis = 1 - if med_attr.get('bias_weights') is not None: - param.bias_term = True - param.weight_2 = np_2_ak_tensor(med_attr['bias_weights']) - else: - param.bias_term = False - pass - - def Relu(self, med_attr, param): - if med_attr.get('alpha') is None: - param.alpha = 0.0 - else: - param.alpha = med_attr['type'] - - def Activation(self, med_attr, param): - param.type = med_attr['type'] - if med_attr['type']=='ClippedRelu': - param.clip_relu_num=med_attr['clip_relu_num'] - - - def Softmax(self, med_attr, param): - if med_attr.get('axis') is None: - param.axis = 3 - else: - param.axis = med_attr['axis'] - pass - - def Concat(self, med_attr, param): - param.axis = med_attr['axis'] - - def Split(self, med_attr, param): - param.split_num = med_attr['split_num'] - - def Eltwise(self, med_attr, param): - assert med_attr['type'] == 'Add' - param.type = med_attr['type'] - param.coeff = [1.0, 1.0] - - def Scale(self, med_attr, param): - param.weight_1 = np_2_ak_tensor(med_attr['scale_weights']) - if med_attr.get('bias_weights') is not None: - param.weight_2 = np_2_ak_tensor(med_attr['bias_weights']) - param.bias_term = True - else: - param.bias_term = False - param.axis = 1 - param.num_axes = 1 - - def Reshape(self, med_attr, param): - shape = med_attr['shape'] - if isinstance(shape, type(np.array([]))): - shape = [int(i) for i in shape] - param.dims = shape_2_ak_shape(shape) - pass - - def Pooling(self, med_attr, param): - param.method = med_attr['type'] - param.pool_size = med_attr['window'] - param.strides = med_attr['strides'] - param.padding = med_attr['padding'] - if med_attr.get('global_pooling') is None: - param.global_pooling = False - else: - param.global_pooling = med_attr['global_pooling'] - - if med_attr.get('cmp_out_shape_floor_as_conv') is None: - param.cmp_out_shape_floor_as_conv = False - else: - param.cmp_out_shape_floor_as_conv = med_attr['cmp_out_shape_floor_as_conv'] - - pass - - - def Pad(self, med_attr, param): - param.pad_c=med_attr['pad_c'] - param.pad_h = med_attr['pad_h'] - param.pad_w = med_attr['pad_w'] - - - def Input(self, med_attr, param): - param.input_shape = shape_2_ak_shape(med_attr['shape']) - if med_attr.get('alias') is not None: - param.alias = med_attr['alias'] - - def map_med_2_ak(self, ak_node, med_node): - type_name = med_node['ak_type'] - func = getattr(self, type_name, None) - param = OpsParam() - ak_op = OpsProtoIO() - med_attr = med_node['ak_attr'] - # print('nodename = ', med_node['name']) - func(med_attr, param) - - param.feed_node_attr(ak_node) - ak_op.set_name(med_node['ak_type']) - ak_node.set_op(ak_op()) - [ak_node.add_in(i['name']) for i in med_node['input']] - [ak_node.add_out(i['name']) for i in med_node['output']] diff --git a/tools/external_converter_v2/parser/kill_tf/parse_tf_2_med.py b/tools/external_converter_v2/parser/kill_tf/parse_tf_2_med.py deleted file mode 100644 index 14705878b..000000000 --- a/tools/external_converter_v2/parser/kill_tf/parse_tf_2_med.py +++ /dev/null @@ -1,181 +0,0 @@ -import tensorflow as tf -import numpy as np -from tensorflow.core.framework import types_pb2, tensor_pb2 -import logging as log -import collections -from tf_trans_util import * -class ParseTF2Med: - def __init__(self,tf_forzen_pb_path): - self.model_path=tf_forzen_pb_path - - def _debug_nodes(self,nodes): - for i in nodes.values(): - print(i['name'],i['input'],i['output'],i['out_shape']) - print('debug end') - exit() - - - def _parse_tf_node(self,tf_graph,shape_override): - - - """ - Load tensorflow graph into an onnx graph with minimal rewrites so - we can use the onnx graph as intermediate graph. - """ - - # ignore the following attributes - ignored_attr = ["unknown_rank", "_class", "Tidx", "Tshape", "use_cudnn_on_gpu", "Index", - "Tpaddings", "TI", "Tparams", "Tindices", "Tlen", "Tdim", "dynamic_size", "element_shape", - "Tmultiples", "output_dtype", "Tblock_shape", "Tcrops", "index_type", "Taxis", "U", - "maxval", "Tout"] - # some stats - op_cnt = collections.Counter() - attr_cnt = collections.Counter() - anakin_nodes = {} - dtypes = {} - - # find outputs - ops = tf_graph.get_operations() - - tensor_shape={} - for node in ops: - for out in node.outputs: - tensor_shape[out.name]=out.get_shape().as_list() - - - # minimal conversion of attributes - for node in ops: - attr = {} - takeit = True - op_cnt[node.type] += 1 - - for a in node.node_def.attr: - a=str(a) - attr_cnt[a] += 1 - if a == "dtype": - attr[a] = map_tf_dtype(node.get_attr("dtype")) - elif a == "T": - dtype = node.get_attr("T") - if dtype: - if not isinstance(dtype, list): - dtypes[node.name] = map_tf_dtype(dtype) - elif a in ["output_type", "output_dtype", "out_type"]: - attr[a] = map_tf_dtype(node.get_attr(a)) - elif a == "shape": - attr[a] = get_shape(node) - elif a == "Tperm": - pass - elif a == "_output_shapes": - attr[a] = get_shape(node) - elif a == "value": - anakin_tensor = tf_to_anakin_tensor(node.get_attr(a)) - attr[a] = anakin_tensor - elif a == "DstT": - attr["to"] = map_tf_dtype(node.get_attr("DstT")) - elif a == "SrcT": - continue - elif a in ignored_attr: - continue - else: - attr[a] = node.get_attr(a) - - if takeit: - try: - input_names = [i.name for i in node.inputs] - output_names = [i.name for i in node.outputs] - anakin_nodes[node.name] = {'name': node.name, 'type': node.type, - 'input': input_names, - 'output': output_names, - 'tf_attr': attr, 'visted': False, - 'ak_type': None, 'ak_attr': {}} - except Exception as ex: - log.error("pass1 convert failed for %s, ex=%s", node, ex) - raise - - self._fix_self_output(anakin_nodes,tensor_shape) - - return anakin_nodes - - def _fix_self_output(self, nodes, tensor_shape_dict): - out2nodename = {} - for node in nodes.values(): - for out_name in node['output']: - if out2nodename.get(out_name) is None: - out2nodename[out_name] = [node['name']] - else: - out2nodename[out_name].append(node['name']) - - in2nodename = {} - for node in nodes.values(): - for in_name in node['input']: - if in2nodename.get(in_name) is None: - in2nodename[in_name] = [node['name']] - else: - in2nodename[in_name].append(node['name']) - - for node in nodes.values(): - new_output=[] - new_input=[] - - for tensor_name in node['output']: - if in2nodename.get(tensor_name) is not None: - new_output+=[{'name':op_name,'shape':tensor_shape_dict[tensor_name]} for op_name in in2nodename[tensor_name]] - - for tensor_name in node['input']: - if out2nodename.get(tensor_name) is not None: - new_input+=[{'name':op_name,'shape':tensor_shape_dict[tensor_name]} for op_name in out2nodename[tensor_name]] - - node['output']=new_output - node['input']=new_input - - - - def _parse_tf_graph(self,nodes): - - def all_search(graph, table): - for tf_node in graph.values(): - if tf_node['visted']: - continue - type_name = tf_node['type'] - if table.get(type_name) != None: - table[type_name](tf_node, graph) - - all_search(nodes, {'Identity': parse_Identity, - 'Placeholder': parse_Placeholder, - 'Shape': parse_Shape - }) - - all_search(nodes, {'Reshape': parse_fusionReshape,}) - - all_search(nodes, {'MatMul': parse_MatMul, - 'Conv2D': parse_Conv2D, - 'DepthwiseConv2dNative': parse_Conv2D, - 'FusedBatchNorm':parse_BatchNorm, - 'Rsqrt': parse_CustmerBatchNorm,}) - - all_search(nodes, {'Add':parse_Add, - 'AvgPool': parse_Pooling, - 'ConcatV2': parse_Concat, - 'MaxPool': parse_Pooling, - 'Mean':parse_Mean, - 'Pad': parse_Pad, - 'Relu': parse_Act, - 'Relu6': parse_Act, - 'Reshape': parse_Reshape, - 'Squeeze': parse_Squeeze, - 'Softmax': parse_Softmax, - - }) - - return nodes - - def parse(self): - tf_graph = load_graph(self.model_path) - nodes = self._parse_tf_node(tf_graph, {}) - - med_graph=self._parse_tf_graph(nodes) - filter_graph={i:med_graph[i] for i in med_graph.keys() if med_graph[i]['ak_type'] is not None} - for node in filter_graph.values(): - node['input']=[i for i in node['input'] if filter_graph.get(i['name']) is not None] - node['output'] = [i for i in node['output'] if filter_graph.get(i['name']) is not None] - return filter_graph \ No newline at end of file diff --git a/tools/external_converter_v2/parser/kill_tf/parser_tf.py b/tools/external_converter_v2/parser/kill_tf/parser_tf.py deleted file mode 100644 index a62684340..000000000 --- a/tools/external_converter_v2/parser/kill_tf/parser_tf.py +++ /dev/null @@ -1,57 +0,0 @@ -import numpy as np -import os -from ..graph_io import * -from ..logger import * -from ..proto import * -import tensorflow as tf -from parse_tf_2_med import ParseTF2Med -from parse_med_2_ak import MedTransAK -from med_graph import MedGraphUtil,MedNodeUtil - - -class TFParser: - - def __init__(self, fluid_config_dict): - # anakin graph model io - # config info - self.ProtoPaths = fluid_config_dict['ProtoPaths'] - - self.OutPuts = fluid_config_dict['OutPuts'] - if self.OutPuts is not None: - self.OutPuts=[i for i in fluid_config_dict['OutPuts'].split(',')] - - self.med_trans_tool = MedTransAK() - self.input_count=0 - - def __call__(self): - med_graph = self._conver_tf_2_med() - if self.OutPuts is None: - self.OutPuts=MedGraphUtil.search_output_list(med_graph) - - MedGraphUtil.solve(med_graph) - anakin_graph = self._conver_med_2_anakin(med_graph) - return anakin_graph - - def _conver_tf_2_med(self): - parser = ParseTF2Med(self.ProtoPaths) - return parser.parse() - - def _add_protonode(self, ak_graph,med_node): - ak_type = med_node['ak_type'] - if ak_type is None: - return - nodeIO = NodeProtoIO() - nodeIO.set_name(med_node['name']) - self.med_trans_tool.map_med_2_ak(nodeIO,med_node) - ak_graph.add_node(nodeIO()) - if nodeIO().Op.name=='Input': - ak_graph.add_in(nodeIO().name) - - def _conver_med_2_anakin(self, med_graph): - anakin_graph = GraphProtoIO() - for node in med_graph.values(): - self._add_protonode(anakin_graph,node) - anakin_graph.format_edge_from_nodes() - for out_node_name in self.OutPuts: - anakin_graph.add_out('output_'+out_node_name,out_node_name) - return anakin_graph diff --git a/tools/external_converter_v2/parser/kill_tf/run_pb.py b/tools/external_converter_v2/parser/kill_tf/run_pb.py deleted file mode 100644 index 2b6d3a254..000000000 --- a/tools/external_converter_v2/parser/kill_tf/run_pb.py +++ /dev/null @@ -1,74 +0,0 @@ -import numpy as np -from tf_util import TfUtil - -def convert_name_tf2ak(tf_name,perfix='record_'): - ak_name=tf_name[:] - for index,x in enumerate(tf_name): - if x=='/': - ak_name=ak_name[:index]+'_'+ak_name[index+1:] - return perfix+ak_name -ak_work_space='/home/ljj/docker_mount_dev2/anakin2_developing_parser/build/' -# ak_work_space='/your/anakin/workspace' -output_compare_op=None - - -# graph_path='./vgg_model/frozen_vgg_16_i.pb' -# input_name='graph/input:0' -# output_op='graph/vgg_16/fc8/BiasAdd' -# output_compare_op='graph/vgg_16/fc8/convolution' - -graph_path='./resnet_model/frozen_resnet_v1_50.pb' -input_name='graph/input:0' -output_op='graph/resnet_v1_50/predictions/Reshape_1' - -# graph_path='./mobilnetv2/frozen_mobilnet_v2.pb' -# input_name='graph/input:0' -# output_op='graph/MobilenetV2/Predictions/Reshape_1' - -# graph_path='./inception_model/frozen_inception_v2.pb' -# input_name='graph/input:0' -# output_op='graph/InceptionV2/Predictions/Reshape_1' - - -is_compared=True -output_name=output_op+':0' -if output_compare_op is None: - compare_path=ak_work_space+convert_name_tf2ak(output_op) -else: - compare_path=ak_work_space+convert_name_tf2ak(output_compare_op) - -np.random.seed(1234567) -x_location=ak_work_space+'input_x' -x_value=np.random.randn(1,224,224,3) -outs=TfUtil.tf_run_model(graph_path,{input_name:x_value},[output_name]) - -import struct -with open(x_location, "wb") as file: - x_value_new=x_value.transpose((0,3,1,2)) - for value in x_value_new.flatten(): - file.write(struct.pack('f', value)) - -if is_compared: - out=outs[0] - if len(out.shape)==4: - out=out.transpose((0,3,1,2)) - else: - print('out shape :',out.shape) - print(out.flatten()[:10]) - try: - with open(compare_path,'r')as file: - ans=[] - for value_str in file.readlines(): - ans.append(float(value_str.split(' ')[1])) - correct=out.flatten() - assert len(correct)==len(ans) - for i in range(len(ans)): - if abs(ans[i]-correct[i])>0.0001 and abs(ans[i]-correct[i])/abs(correct[i])>0.0001: - print(i,'=',ans[i],'correct = ',correct[i]) - exit() - print('passed') - except Exception,e: - print(out) - print('can`t find file : '+compare_path) - - diff --git a/tools/external_converter_v2/parser/kill_tf/run_pb_get_ckp.py b/tools/external_converter_v2/parser/kill_tf/run_pb_get_ckp.py deleted file mode 100644 index 38ca29178..000000000 --- a/tools/external_converter_v2/parser/kill_tf/run_pb_get_ckp.py +++ /dev/null @@ -1,51 +0,0 @@ -import tensorflow as tf -from tensorflow.python.platform import gfile -from google.protobuf import text_format -import numpy as np -from tensorflow.python.platform import gfile - -# graph_path = '/tmp/pycharm_project_635/external_converter_v2/parser/kill_tf/mnist_model/graph.pbtxt' -# graph_path = './resnet_v1_50_graph.pb' -# graph_path = './frozen_graph.pb' -# graph_path='./ease_model/model.cpkt.meta' -# graph_path='./ease_model/graph.pb' -# graph_path='./ease_model/frozen_mnist.pb' -# graph_path='./vgg_model/frozen_vgg_16_i.pb' -graph_path='./inception_model/inception_v2_inf_graph.pb' -cpkt_path='./inception_model/' -# graph_path='./resnet_model/frozen_resnet_v1_50.pb' - - -sess=tf.Session() -if graph_path.endswith('.pbtxt'): - input_binary = False -else: - input_binary = True - -graph = tf.get_default_graph() -graph_def = graph.as_graph_def() -if graph_path.endswith('.pb') or graph_path.endswith('.pbtxt'): - mode = "rb" if input_binary else "r" - with gfile.FastGFile(graph_path, mode) as f: - if input_binary: - graph_def.ParseFromString(f.read()) - else: - text_format.Merge(f.read(), graph_def) -else: - tf.train.import_meta_graph(graph_path, clear_devices=True) - -tf.import_graph_def(graph_def, name='graph') -sess=tf.Session(graph=graph) -x = graph.get_tensor_by_name('graph/input:0') -y = graph.get_tensor_by_name('graph/InceptionV2/Predictions/Reshape_1:0') - -for var in tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES): - print(var.name) -init_table=tf.tables_initializer() -sess.run(init_table) -init=tf.global_variables_initializer() -sess.run(init) -out=sess.run(y,{x:np.ones((1,224,224,3))}) - -saver = tf.train.Saver() -saver.save(sess, cpkt_path+'/model.cpkt') \ No newline at end of file diff --git a/tools/external_converter_v2/parser/kill_tf/summary.py b/tools/external_converter_v2/parser/kill_tf/summary.py deleted file mode 100644 index 5edcb8358..000000000 --- a/tools/external_converter_v2/parser/kill_tf/summary.py +++ /dev/null @@ -1,45 +0,0 @@ -import tensorflow as tf -from tensorflow.python.platform import gfile -from google.protobuf import text_format - -# import tensorflow as tf -# with tf.Session() as sess: -# with open('./resnet_v1_50_graph.pb', 'rb') as f: -# graph_def = tf.GraphDef() -# graph_def.ParseFromString(f.read()) -# print(graph_def) - - -from tensorflow.python.platform import gfile - - -# graph_path = './resnet_v1_50_graph.pb' -# graph_path = './frozen_graph.pb' -# graph_path='./vgg_model/frozen_vgg_16_i.pb' -# graph_path='./inception_model/frozen_inception_v2.pb' -graph_path='./resnet_model/frozen_resnet_v1_50.pb' -# graph_path='./mobilnetv2/frozen_mobilnet_v2.pb' - -def get_graph(graph_path): - if graph_path.endswith('.pbtxt'): - input_binary = False - else: - input_binary = True - - graph = tf.get_default_graph() - graph_def = graph.as_graph_def() - if graph_path.endswith('.pb') or graph_path.endswith('.pbtxt'): - mode = "rb" if input_binary else "r" - with gfile.FastGFile(graph_path, mode) as f: - if input_binary: - graph_def.ParseFromString(f.read()) - else: - text_format.Merge(f.read(), graph_def) - else: - tf.train.import_meta_graph(graph_path, clear_devices=True) - tf.import_graph_def(graph_def, name='graph') - return graph - - -graph=get_graph(graph_path) -summaryWriter = tf.summary.FileWriter('log/', graph) \ No newline at end of file diff --git a/tools/external_converter_v2/parser/kill_tf/tf_trans_util.py b/tools/external_converter_v2/parser/kill_tf/tf_trans_util.py deleted file mode 100644 index cc8a48823..000000000 --- a/tools/external_converter_v2/parser/kill_tf/tf_trans_util.py +++ /dev/null @@ -1,559 +0,0 @@ -import tensorflow as tf -import numpy as np -from tensorflow.core.framework import types_pb2, tensor_pb2 -from google.protobuf import text_format -from med_graph import MedNodeUtil,MedGraphUtil - -TF_TO_ANAKIN_DTYPE = { - types_pb2.DT_FLOAT: np.float32, - types_pb2.DT_HALF: np.float16, - types_pb2.DT_DOUBLE: np.float64, - types_pb2.DT_INT32: np.int32, - types_pb2.DT_INT16: np.int16, - types_pb2.DT_INT8: np.int8, - types_pb2.DT_UINT8: np.uint8, - types_pb2.DT_UINT16: np.uint16, - types_pb2.DT_INT64: np.int64, - # types_pb2.DT_STRING: onnx_pb.TensorProto.STRING, - # types_pb2.DT_COMPLEX64: onnx_pb.TensorProto.COMPLEX64, - # types_pb2.DT_COMPLEX128: onnx_pb.TensorProto.COMPLEX128, - types_pb2.DT_BOOL: np.bool, -} - -ANAKIN_VALID_ATTRIBUTES = { - 'p', 'bias', 'axes', 'pads', 'mean', 'activation_beta', 'spatial_scale', 'broadcast', 'pooled_shape', 'high', - 'activation_alpha', 'is_test', 'hidden_size', 'activations', 'beta', 'input_as_shape', 'drop_states', 'alpha', - 'momentum', 'scale', 'axis', 'dilations', 'transB', 'axis_w', 'blocksize', 'output_sequence', 'mode', 'perm', - 'min', 'seed', 'ends', 'paddings', 'to', 'gamma', 'width_scale', 'normalize_variance', 'group', 'ratio', - 'values', - 'dtype', 'output_shape', 'spatial', 'split', 'input_forget', 'keepdims', 'transA', 'auto_pad', 'border', 'low', - 'linear_before_reset', 'height_scale', 'output_padding', 'shape', 'kernel_shape', 'epsilon', 'size', 'starts', - 'direction', 'max', 'clip', 'across_channels', 'value', 'strides', 'extra_shape', 'scales', 'k', 'sample_size', - 'blocksize', 'epsilon', 'momentum' -} - - -def get_tf_tensor_data(tensor): - """Get data from tensor.""" - assert isinstance(tensor, tensor_pb2.TensorProto) - is_raw = False - if tensor.tensor_content: - data = tensor.tensor_content - is_raw = True - elif tensor.float_val: - data = tensor.float_val - elif tensor.dcomplex_val: - data = tensor.dcomplex_val - elif tensor.int_val: - data = tensor.int_val - elif tensor.bool_val: - data = tensor.bool_val - elif tensor.dtype == tf.int32: - data = [0] - elif tensor.dtype == tf.int64: - data = [0] - elif tensor.dtype == tf.float32: - data = [0.] - elif tensor.string_val: - data = tensor.string_val - else: - raise ValueError('tensor data not supported') - return [is_raw, data] - - -def map_tf_dtype(dtype): - return TF_TO_ANAKIN_DTYPE.get(dtype) - - -def get_shape(node): - """Get shape from tensorflow node.""" - # FIXME: do we use this? - dims = None - try: - if node.type == "Const": - shape = node.get_attr("value").tensor_shape - dims = [int(d.size) for d in shape.dim] - else: - shape = node.get_attr("shape") - dims = [d.size for d in shape.dim] - if shape[0] is not None or shape[0] == -1: - shape[0] = 1 - except Exception as ex: - pass - return dims - - -def tf_to_anakin_tensor(tensor): - """Convert tensorflow tensor to anakin med tensor.""" - new_type = TF_TO_ANAKIN_DTYPE[tensor.dtype] - tdim = tensor.tensor_shape.dim - dims = [d.size for d in tdim] - # FIXME: something is fishy here - if dims == [0]: - dims = [1] - is_raw, data = get_tf_tensor_data(tensor) - dim_size=1 - for i in dims: - dim_size*=i - # print(type(data),data,tensor.dtype,is_raw) - if is_raw: - if len(dims) > 0: - anakin_tensor = np.frombuffer(data, map_tf_dtype(tensor.dtype)) - anakin_tensor = anakin_tensor.reshape(dims) - else: - anakin_tensor = np.zeros(0) - return anakin_tensor - elif dim_size >1 and len(data)==1: - - return np.array([data]*dim_size).reshape(dims) - else: - return data - - -def load_graph(graph_path): - if graph_path.endswith('.pbtxt'): - input_binary = False - else: - input_binary = True - - graph = tf.get_default_graph() - graph_def = graph.as_graph_def() - if graph_path.endswith('.pb') or graph_path.endswith('.pbtxt'): - mode = "rb" if input_binary else "r" - with tf.gfile.FastGFile(graph_path, mode) as f: - if input_binary: - graph_def.ParseFromString(f.read()) - else: - text_format.Merge(f.read(), graph_def) - else: - tf.train.import_meta_graph(graph_path, clear_devices=True) - tf.import_graph_def(graph_def, name='graph') - return graph - - -NCHW_TO_NHWC = [0, 2, 3, 1] -NHWC_TO_NCHW = [0, 3, 1, 2] -HWCN_TO_NCHW = [3, 2, 0, 1] -NCHW_TO_HWCN = [2, 3, 1, 0] - - -def spatial_map(shape, perm): - # print('HI ',type(shape),shape) - new_shape = shape[:] - for i in perm: - new_shape[i] = shape[perm[i]] - return new_shape - - -def trans_move_attr(attr, format): - if attr is None: - return attr - if len(attr) == 2: - return attr - if format == 'NHWC': - n, h, w, c = attr - elif format == 'NCHW': - n, c, h, w = attr - else: - raise Exception('not support format ' + format) - return [h, w] - -def add_special_pad(padding,tf_node,graph): - # print(tf_node['name']) - assert len(tf_node['input'])<=2 - now_shape=tf_node['input'][0]['shape'] - tar_shape =now_shape[:] - tar_shape[1]=now_shape[1]+padding[0]+padding[1] - tar_shape[2] = now_shape[2] + padding[2] + padding[3] - tf_name = tf_node['name'] - padding_node={'name':tf_node['name']+'_pad','ak_type':'Pad','type':None,'visted':True, - 'ak_attr':{'pad_c':[0,0],'pad_h':[padding[0],padding[1]],'pad_w':[padding[2],padding[3]]}, - 'input':[tf_node['input'][0]],'output':[{'name':tf_name,'shape':tar_shape}]} - - input_0=graph[tf_node['input'][0]['name']] - input_0['output']=MedNodeUtil.replace_name_with_list(input_0['output'],tf_name,[{'name':padding_node['name'],'shape':now_shape}]) - tf_node['input'][0]={'name':padding_node['name'],'shape':tar_shape} - graph[padding_node['name']]=padding_node - -def parse_Identity(tf_node, graph): - tf_node['visted'] = True - outputs = tf_node['output'] - input_0 = tf_node['input'][0] - in_node = graph[input_0['name']] - - for next in outputs: - next_name = next['name'] - next_node = graph[next_name] - next_node['input'] = [input_0 if i['name'] == tf_node['name'] else i for i in next_node['input']] - in_node['output'] = MedNodeUtil.replace_name_with_list(in_node['output'], tf_node['name'], outputs) - - -def parse_Shape(tf_node, graph): - assert len(tf_node['input']) == 1 - tf_node['type'] = 'Const' - tf_node['tf_attr']['value'] = tf_node['input'][0]['shape'] - tf_node['tf_attr']['dtype'] = np.int32 - - -def parse_Squeeze(tf_node, graph): - tf_node['visted'] = True - tf_node['ak_type'] = 'Reshape' - tf_node['ak_attr']['shape'] = tf_node['output'][0]['shape'] - tf_node['output'] = [i for i in tf_node['output'] if graph[i['name']]['type'] != 'Const'] - - -def parse_Placeholder(tf_node, graph): - tf_node['visted'] = True - tf_node['ak_type'] = 'Input' - tf_node['ak_attr']['shape'] = spatial_map(tf_node['output'][0]['shape'], NHWC_TO_NCHW) - - -def parse_Pad(tf_node, graph): - tf_node['visted'] = True - tf_node['ak_type'] = 'Pad' - pad_shape_node = graph[tf_node['input'][1]['name']] - assert pad_shape_node['type'] == 'Const' - pad_shape=pad_shape_node['tf_attr']['value'] - ak_attr=tf_node['ak_attr'] - ak_attr['pad_c'] = pad_shape[3].flatten().tolist() - ak_attr['pad_h'] = pad_shape[1].flatten().tolist() - ak_attr['pad_w'] = pad_shape[2].flatten().tolist() - - -def parse_Softmax(tf_node, graph): - tf_node['visted'] = True - tf_node['ak_type'] = 'Softmax' - tf_node['ak_attr']['axis']=3 - - -def parse_Reshape(tf_node, graph): - tf_node['visted'] = True - tf_node['ak_type'] = 'Reshape' - shape = graph[tf_node['input'][1]['name']] - assert shape['type'] == 'Const' - assert shape['tf_attr']['dtype'] == np.int32 - tf_node['ak_attr']['shape'] = shape['tf_attr']['value'] - tf_node['input'] = tf_node['input'][:1] - MedNodeUtil.retain_input(tf_node, [tf_node['input'][0]]) - - -def parse_Act(tf_node, graph): - tf_node['visted'] = True - tf_node['ak_type'] = 'Activation' - if tf_node['type'] == 'Relu' : - tf_node['ak_type'] = 'Relu' - tf_node['ak_attr']['type'] = 'Relu' - elif tf_node['type'] == 'Relu6': - tf_node['ak_type'] = 'Activation' - tf_node['ak_attr']['type'] = 'ClippedRelu' - tf_node['ak_attr']['clip_relu_num'] = 6 - else: - raise Exception('un handel activation ' + str(tf_node['type'])) - - -def parse_Concat(tf_node, graph): - tf_node['visted'] = True - tf_node['ak_type'] = 'Concat' - N = tf_node['tf_attr']['N'] - axis_node = graph[tf_node['input'][N]['name']] - assert axis_node['type'] == 'Const' - nhwc2hchw={0:0,1:2,2:3,3:1} - tf_node['ak_attr']['axis'] = nhwc2hchw[axis_node['tf_attr']['value'][0]] - - -def parse_Add(tf_node, graph): - tf_node['visted'] = True - assert len(tf_node['input']) == 2 - input_0 = graph[tf_node['input'][0]['name']] - input_1 = graph[tf_node['input'][1]['name']] - ak_attr = tf_node['ak_attr'] - - if input_0['type'] == 'Const' and input_1['type'] == 'Const': - assert False, 'have not handle' - elif input_0['type'] == 'Const' and input_1['type'] != 'Const': - assert False, 'not support' - elif input_0['type'] != 'Const' and input_1['type'] == 'Const': - assert False, 'not support' - else: - tf_node['ak_type'] = 'Eltwise' - ak_attr['type'] = 'Add' - -def parse_Mean(tf_node, graph): - tf_node['visted'] = True - tf_node['ak_type'] = 'Pooling' - ak_attr = tf_node['ak_attr'] - tf_attr = tf_node['tf_attr'] - ak_attr['type']='AVG' - reduction_shape=None - keep_dims=tf_attr['keep_dims'] - - if len(tf_node['input'])>1: - reduction_shape_node=graph[tf_node['input'][1]['name']] - assert reduction_shape_node['type']=='Const' - reduction_shape=reduction_shape_node['tf_attr']['value'].flatten().tolist() - assert reduction_shape is not None - assert keep_dims is True - assert reduction_shape == [1,2] - ak_attr['strides'] = [1,1] - ak_attr['window'] = [tf_node['input'][0]['shape'][reduction_shape[0]],tf_node['input'][0]['shape'][reduction_shape[1]]] - ak_attr['padding'] = [0,0] - - -def parse_Pooling(tf_node, graph): - tf_node['visted'] = True - tf_node['ak_type'] = 'Pooling' - ak_attr = tf_node['ak_attr'] - tf_attr = tf_node['tf_attr'] - #TODO TF default pad is exclusive method - map_tf_pool = {'MaxPool': 'MAX', - 'AvgPool': 'AVGEXC'} - - ak_attr['type'] = map_tf_pool[tf_node['type']] - - strides = tf_attr['strides'] - ksizes = tf_attr['ksize'] - padding = tf_attr['padding'] - dilations = tf_attr.get('dilations') - data_format = tf_attr['data_format'].decode() - - kernel_shape = trans_move_attr(ksizes, data_format) - strides = trans_move_attr(strides, data_format) - - padding = cal_padding(padding, kernel_shape, strides, dilations, data_format, - tf_node['input'][0]['shape'], tf_node['output'][0]['shape']) - - if padding[0]!=padding[1] or padding[2]!=padding[3]: - add_special_pad(padding,tf_node,graph) - padding=[0,0] - else: - padding=[padding[0],padding[2]] - - ak_attr['window'] = kernel_shape - ak_attr['padding'] = padding - ak_attr['strides'] = strides - ak_attr['cmp_out_shape_floor_as_conv']=True - - -def cal_padding(padding, kernel_shape, strides, dilations, data_format, input_shape, output_shape, spatial=2): - pads = [0] * spatial*2 - if type(padding) == bytes: - padding = padding.decode() - if dilations is None: - dilations = [1] * spatial * 2 - if padding == 'SAME': - pads = [0] * spatial*2 - if data_format == 'NHWC': - # print('in out shape = ',input_shape,output_shape) - input_shape = spatial_map(input_shape, NHWC_TO_NCHW) - output_shape = spatial_map(output_shape, NHWC_TO_NCHW) - elif data_format != 'NCHW': - raise Exception('not suppor format ' + data_format) - for i in range(spatial): - pad = (output_shape[i + 2] - 1) * strides[i] + dilations[i] * kernel_shape[i] - input_shape[i + 2] - pad = max(pad, 0) - pads1 = pad // 2 - pads2 = pad - pad // 2 - pads[i*2+0]=pads1 - pads[i * 2 + 1] = pads2 - return pads - elif padding == 'VALID': - return pads - else: - raise ValueError("invalid padding value: " + padding) - - -def get_const_from_biinput(inputs, graph): - assert len(inputs) <= 2 - input_0 = graph[inputs[0]['name']] - input_1 = graph[inputs[1]['name']] - if input_0['type'] == 'Const': - return input_0['tf_attr']['value'] - elif len(inputs) == 2 and input_1['type'] == 'Const': - return input_1['tf_attr']['value'] - return None - - -def get_bias(tf_node, graph): - bias_weight = None - output = tf_node['output'] - output_0 = graph[output[0]['name']] - if len(output) == 1 and (output_0['type'] == 'Add' or output_0['type'] == 'BiasAdd'): - bias_weight = get_const_from_biinput(output_0['input'], graph) - - if bias_weight is not None: - output_0['visted'] = True - tf_node['output'] = output_0['output'] - MedNodeUtil.redirecto_outputs_input_to_this(output_0,graph,tf_node['name'],output[0]['shape']) - - return bias_weight - - -def parse_Conv2D(tf_node, graph): - tf_node['visted'] = True - tf_node['ak_type'] = 'Convolution' - weights_node = graph[tf_node['input'][1]['name']] - - assert weights_node['type'] == 'Const' - weights = weights_node['tf_attr']['value'] - weights = weights.transpose((3, 2, 0, 1)) - - tf_attr = tf_node['tf_attr'] - data_format = tf_attr['data_format'].decode() - - padding = tf_attr['padding'] - dilations = trans_move_attr(tf_attr['dilations'], data_format) - strides = trans_move_attr(tf_attr['strides'], data_format) - kernel_shape = weights_node['output'][0]['shape'][:2] - # print('name ',tf_node['name'],input_node['name'],input_node['out_shape']) - padding = cal_padding(padding, kernel_shape, strides, dilations, data_format, tf_node['input'][0]['shape'], - tf_node['output'][0]['shape']) - if padding[0]!=padding[1] or padding[2]!=padding[3]: - add_special_pad(padding,tf_node,graph) - padding=[0,0] - else: - padding=[padding[0],padding[2]] - - group = 1 - if tf_node['type'] == 'DepthwiseConv2dNative': - weights = weights.transpose((1, 0, 2, 3)) - group = weights.shape[0] - out_c=weights.shape[0]*weights.shape[1] - weights=weights.reshape(out_c,1,weights.shape[2],weights.shape[3]) - - ak_attr = tf_node['ak_attr'] - ak_attr['weights'] = weights - ak_attr['padding'] = padding - ak_attr['dilations'] = dilations - ak_attr['strides'] = strides - ak_attr['bias_weights'] = get_bias(tf_node, graph) - ak_attr['group'] = group - MedNodeUtil.retain_input(tf_node, [tf_node['input'][0]]) - - -def parse_MatMul(tf_node, graph): - tf_node['visted'] = True - tf_node['ak_type'] = 'Dense' - in_name_0 = tf_node['input'][0]['name'] - in_name_1 = tf_node['input'][1]['name'] - in_type_0 = graph[in_name_0]['type'] - in_type_1 = graph[in_name_1]['type'] - if in_type_0 == 'Const' and in_type_1 == 'Const': - raise Exception('Whate hannpend both const') - elif in_type_1 == 'Const' and tf_node['tf_attr']['transpose_a'] != True: - weights = graph[in_name_1]['tf_attr']['value'] - if tf_node['tf_attr']['transpose_b']: - weights = weights.T - tf_node['ak_attr']['weights'] = weights - MedNodeUtil.retain_input(tf_node, [tf_node['input'][0]]) - elif in_type_0 == 'Const' and tf_node['tf_attr']['transpose_b'] != True: - weights = graph[in_name_1]['tf_attr']['value'].T - if tf_node['tf_attr']['transpose_a']: - weights = weights.T - tf_node['ak_attr']['weights'] = weights - MedNodeUtil.retain_input(tf_node, [tf_node['input'][1]]) - else: - raise Exception('can`t parse ' + str(tf_node)) - tf_node['ak_attr']['bias_weights'] = get_bias(tf_node, graph) - - -def parse_fusionReshape(tf_node, graph): - assert tf_node['type'] == 'Reshape' - input_0 = graph[tf_node['input'][0]['name']] - input_1 = graph[tf_node['input'][1]['name']] - - if not (input_0['type'] == 'Const' and input_1['type'] == 'Const'): return - - tf_node['type'] = 'Const' - const_value = input_0['tf_attr']['value'] - shape = input_1['tf_attr']['value'] - new_const_value = const_value.reshape(shape) - tf_node['tf_attr'] = {'value': new_const_value} - tf_node['input'] = [] - - -def parse_CustmerBatchNorm(tf_node, graph): - assert tf_node['type'] == 'Rsqrt' - assert len(tf_node['input']) == 1 and len(tf_node['output']) == 1 - rsqrt_mul_node = graph[tf_node['output'][0]['name']] - add_rsqrt_node = graph[tf_node['input'][0]['name']] - assert len(add_rsqrt_node['input']) == 2 and len(add_rsqrt_node['output']) == 1 - eps_node = graph[add_rsqrt_node['input'][1]['name']] - var_node = graph[add_rsqrt_node['input'][0]['name']] - - assert eps_node['type'] == 'Const' and var_node['type'] == 'Const' - epse_value = eps_node['tf_attr']['value'] - var_value = var_node['tf_attr']['value'].flatten() - assert rsqrt_mul_node['type'] == 'Mul' and len(rsqrt_mul_node['input']) == 2 and len(rsqrt_mul_node['output']) == 2 - const_mul_node_input_1 = graph[rsqrt_mul_node['input'][1]['name']] - if MedGraphUtil.check_one_of_input_is_const(graph[rsqrt_mul_node['output'][0]['name']],graph): - mul_mul_1_node = graph[rsqrt_mul_node['output'][1]['name']] - mul_mul_2_node = graph[rsqrt_mul_node['output'][0]['name']] - else: - mul_mul_1_node = graph[rsqrt_mul_node['output'][0]['name']] - mul_mul_2_node = graph[rsqrt_mul_node['output'][1]['name']] - - assert mul_mul_1_node['type'] == 'Mul' and mul_mul_2_node['type'] == 'Mul' and const_mul_node_input_1[ - 'type'] == 'Const' - assert len(mul_mul_1_node['output']) == 1 and len(mul_mul_2_node['output']) == 1 - alpha_value = const_mul_node_input_1['tf_attr']['value'].flatten() - mul_add_node = graph[mul_mul_1_node['output'][0]['name']] - mul2_sub_node = graph[mul_mul_2_node['output'][0]['name']] - mean_node = graph[mul_mul_2_node['input'][0]['name']] - - assert mul_add_node['type'] == 'Add' and mul2_sub_node['type'] == 'Sub' and mean_node['type'] == 'Const' - beta_node = graph[mul2_sub_node['input'][0]['name']] - - assert beta_node['type']=='Const' - beta_value = beta_node['tf_attr']['value'].flatten() - mean_value = mean_node['tf_attr']['value'].flatten() - assert mul_add_node['input'][1]['name'] == mul2_sub_node['name'] - - mul_mul_1_node['visted'] = True - mul_mul_2_node['visted'] = True - rsqrt_mul_node['visted'] = True - mul_add_node['visted'] = True - add_rsqrt_node['visted'] = True - mul2_sub_node['visted'] = True - tf_node['visted'] = True - - var = np.sqrt(var_value + epse_value) - np_scale = alpha_value / var - np_bias = beta_value -np_scale * mean_value - mul_mul_1_node['output'] = mul_add_node['output'] - mul_mul_1_node['type'] = 'CustomerBN' - mul_mul_1_node['ak_type'] = 'Scale' - - MedNodeUtil.retain_input(mul_mul_1_node, [mul_mul_1_node['input'][0]]) - MedNodeUtil.redirecto_outputs_input_to_this(mul_add_node,graph,mul_mul_1_node['name'],mul_mul_1_node['output'][0]['shape']) - ak_attr = mul_mul_1_node['ak_attr'] - ak_attr['scale_weights'] = np_scale.astype('float32') - ak_attr['bias_weights'] = np_bias.astype('float32') - pass - - -def parse_BatchNorm(tf_node, graph): - tf_node['visted'] = True - tf_node['ak_type'] = 'Scale' - assert len(tf_node['input']) == 5 - alpha_node = graph[tf_node['input'][1]['name']] - beta_node = graph[tf_node['input'][2]['name']] - mean_node = graph[tf_node['input'][3]['name']] - var_node = graph[tf_node['input'][4]['name']] - assert beta_node['type'] == 'Const' and mean_node['type'] == 'Const' and var_node['type'] == 'Const' and alpha_node[ - 'type'] == 'Const' - tf_attr = tf_node['tf_attr'] - eps = tf_attr['epsilon'] - var_value = var_node['tf_attr']['value'].flatten() - - alpha_value = alpha_node['tf_attr']['value'].flatten() - mean_value = mean_node['tf_attr']['value'].flatten() - beta_value = beta_node['tf_attr']['value'].flatten() - - var = np.sqrt(var_value + eps) - np_scale = alpha_value / var - np_bias = beta_value - (alpha_value * mean_value / var) - ak_attr = tf_node['ak_attr'] - ak_attr['scale_weights'] = np_scale.astype('float32') - ak_attr['bias_weights'] = np_bias.astype('float32') - - MedNodeUtil.retain_input(tf_node, [tf_node['input'][0]]) \ No newline at end of file diff --git a/tools/external_converter_v2/parser/kill_tf/tf_util.py b/tools/external_converter_v2/parser/kill_tf/tf_util.py deleted file mode 100644 index 8baed082d..000000000 --- a/tools/external_converter_v2/parser/kill_tf/tf_util.py +++ /dev/null @@ -1,33 +0,0 @@ -import tensorflow as tf -from tensorflow.python.platform import gfile -from google.protobuf import text_format -import numpy as np - -class TfUtil: - @staticmethod - def tf_run_model(graph_path, inputs, output_tensor_list): - sess = tf.Session() - if graph_path.endswith('.pbtxt'): - input_binary = False - else: - input_binary = True - - graph = tf.get_default_graph() - graph_def = graph.as_graph_def() - if graph_path.endswith('.pb') or graph_path.endswith('.pbtxt'): - mode = "rb" if input_binary else "r" - with gfile.FastGFile(graph_path, mode) as f: - if input_binary: - graph_def.ParseFromString(f.read()) - else: - text_format.Merge(f.read(), graph_def) - else: - tf.train.import_meta_graph(graph_path, clear_devices=True) - - tf.import_graph_def(graph_def, name='graph') - - inputs_dict = {graph.get_tensor_by_name(i): inputs[i] for i in inputs} - output_list = [graph.get_tensor_by_name(i) for i in output_tensor_list] - print(output_list) - out = sess.run(output_list, inputs_dict) - return out \ No newline at end of file diff --git a/tools/external_converter_v2/parser/pbs/__init__.py b/tools/external_converter_v2/parser/pbs/__init__.py index f79d97d1c..9e1c738fc 100644 --- a/tools/external_converter_v2/parser/pbs/__init__.py +++ b/tools/external_converter_v2/parser/pbs/__init__.py @@ -2,9 +2,10 @@ # Copyright (c) 2017, Cuichaowen. All rights reserved. # -*- coding: utf-8 -*- import os -from ..logger import * - -#import caffe_pb2 +from ..logger import verbose +from ..logger import shellcolors +from ..logger import with_color +from ..logger import logger for module in os.listdir(os.path.dirname(__file__)): if module == '__init__.py' or module[-3:] != '.py': From d503eaaa8f5c45f6219280ecaa9d2bea17479dda Mon Sep 17 00:00:00 2001 From: liujunjie Date: Tue, 4 Sep 2018 11:57:59 +0800 Subject: [PATCH 14/51] Merge branch 'developing' of https://github.com/PaddlePaddle/Anakin into developing # Conflicts: # tools/external_converter_v2/parser/kill_fluid/parser_fluid.py --- tools/external_converter_v2/config.yaml | 3 +- .../parser/kill_tf/auto_debug.py | 132 ++-- .../parser/kill_tf/freeze.py | 9 +- .../parser/kill_tf/freeze_graph.py | 564 +++++++++--------- .../parser/kill_tf/get_empt_infer_pb.py | 18 +- .../parser/kill_tf/med_graph.py | 124 +++- .../parser/kill_tf/parse_med_2_ak.py | 103 +++- .../parser/kill_tf/parse_tf_2_med.py | 85 +-- .../parser/kill_tf/parser_tf.py | 105 ++-- .../parser/kill_tf/run_pb.py | 75 +-- .../parser/kill_tf/run_pb_get_ckp.py | 18 +- .../parser/kill_tf/summary.py | 14 +- .../parser/kill_tf/tf_trans_util.py | 266 +++++++-- .../parser/kill_tf/tf_util.py | 10 +- 14 files changed, 981 insertions(+), 545 deletions(-) diff --git a/tools/external_converter_v2/config.yaml b/tools/external_converter_v2/config.yaml index 2c00def1d..dba869455 100644 --- a/tools/external_converter_v2/config.yaml +++ b/tools/external_converter_v2/config.yaml @@ -40,7 +40,7 @@ ##-------------------------------------------------------------- # OPTIONS: - Framework: TENSORFLOW + Framework: FLUID SavePath: /ak_model/save/path ResultName: resnet50_v1 @@ -66,6 +66,7 @@ TARGET: FLUID: # path of fluid inference model + ProtoPaths: / Debug: NULL # Generally no need to modify. ModelPath: /path/to/your/model/ # The upper path of a fluid inference model. NetType: # Generally no need to modify. diff --git a/tools/external_converter_v2/parser/kill_tf/auto_debug.py b/tools/external_converter_v2/parser/kill_tf/auto_debug.py index ffa2c16a5..af970bcd6 100644 --- a/tools/external_converter_v2/parser/kill_tf/auto_debug.py +++ b/tools/external_converter_v2/parser/kill_tf/auto_debug.py @@ -6,12 +6,14 @@ from med_graph import MedGraphUtil from tf_trans_util import load_graph from tf_util import TfUtil + + class AutoDebug: - def __init__(self,tf_model_path,ak_output_dir,workspace=None): - self.ak_perfix='record_' - self.tf_model_path=tf_model_path - self.ak_output_dir=os.path.dirname(ak_output_dir) + def __init__(self, tf_model_path, ak_output_dir, workspace=None): + self.ak_perfix = 'record_' + self.tf_model_path = tf_model_path + self.ak_output_dir = os.path.dirname(ak_output_dir) med_graph = ParseTF2Med(self.tf_model_path).parse() MedGraphUtil.solve(med_graph) self.med_graph = med_graph @@ -21,13 +23,22 @@ def __init__(self,tf_model_path,ak_output_dir,workspace=None): # self.workspace = workspace # print('workspace is ', self.workspace) - - def _debug_graph(self,graph): + def _debug_graph(self, graph): + ''' + print debug info + :param graph: + :return: + ''' for i in graph.values(): print(i) exit() - def _convert_name_tf2ak(self,tf_name): + def _convert_name_tf2ak(self, tf_name): + ''' + conver name from tf 2 ak + :param tf_name: + :return: + ''' ak_name = tf_name[:] for index, x in enumerate(tf_name): if x == '/': @@ -35,14 +46,23 @@ def _convert_name_tf2ak(self,tf_name): return self.ak_perfix + ak_name def _find_ak_output(self): + ''' + find output name in graph + :return: + ''' result = {} for file_name in os.listdir(self.ak_output_dir): - real_path=os.path.join(self.ak_output_dir,file_name) - if not os.path.isdir(real_path) and file_name.startswith(self.ak_perfix) and not file_name.startswith(self.ak_perfix+'_'): - result[file_name]=[float(i.split(' ')[1]) for i in open(real_path,'r').readlines()] + real_path = os.path.join(self.ak_output_dir, file_name) + if not os.path.isdir(real_path) and file_name.startswith(self.ak_perfix) and not file_name.startswith( + self.ak_perfix + '_'): + result[file_name] = [float(i.split(' ')[1]) for i in open(real_path, 'r').readlines()] return result def _creat_and_clear_workspace(self): + ''' + remove temp workspace + :return: + ''' if os.path.exists(self.workspace): assert os.path.isdir(self.workspace) ls = os.listdir(self.workspace) @@ -52,60 +72,73 @@ def _creat_and_clear_workspace(self): else: os.mkdir(self.workspace) - def _prepare_data(self,med_graph): - input_cnt=0 - inputs={} + def _prepare_data(self, med_graph): + ''' + gen input data + :param med_graph: + :return: + ''' + input_cnt = 0 + inputs = {} result = {} np.random.seed(1234567) for i in med_graph.values(): if i['ak_type'] == 'Input': - shape=i['output'][0]['shape'] - size=1 + shape = i['output'][0]['shape'] + size = 1 for k in shape: - size*=k - tensor=np.random.randn(size).reshape(shape) - inputs['input_'+str(input_cnt)]=tensor - result[i['name']+':0']=tensor - input_cnt+=1 + size *= k + tensor = np.random.randn(size).reshape(shape) + inputs['input_' + str(input_cnt)] = tensor + result[i['name'] + ':0'] = tensor + input_cnt += 1 for i in inputs.keys(): import struct - with open(os.path.join(self.ak_output_dir,i), "wb") as file: + with open(os.path.join(self.ak_output_dir, i), "wb") as file: x_value_new = inputs[i].transpose((0, 3, 1, 2)) for value in x_value_new.flatten(): file.write(struct.pack('f', value)) return result - def run_ak(self): + ''' + run ak mode + :return: + ''' self._prepare_data(self.med_graph) def run(self): - inputs = self._prepare_data(self.med_graph) - akopname2ak_out=self._find_ak_output() - for i in akopname2ak_out: - print(i) - compare_dic={} - for node in self.med_graph.values(): - print(node['name'], node['ak_type']) - if node['ak_type'] is not None and node['type'] is not None: - - name=node['name'] - if node.get('fusion_out_name') is not None: - name=node['fusion_out_name'] - ak_name=self._convert_name_tf2ak(name) - print('key ',ak_name) - if akopname2ak_out.get(ak_name) is not None: - compare_dic[name+':0']=akopname2ak_out[ak_name] - outlist=compare_dic.keys() - out=TfUtil.tf_run_model(self.tf_model_path,inputs,outlist) - for index,name in enumerate(outlist): - correct=out[index].transpose() - ak_result=akopname2ak_out[name] - assert len() - for i in range(len(ak_result)): - if abs() + ''' + run debug mode + :return: + ''' + pass + # inputs = self._prepare_data(self.med_graph) + # akopname2ak_out=self._find_ak_output() + # for i in akopname2ak_out: + # print(i) + # compare_dic={} + # for node in self.med_graph.values(): + # print(node['name'], node['ak_type']) + # if node['ak_type'] is not None and node['type'] is not None: + # + # name=node['name'] + # if node.get('fusion_out_name') is not None: + # name=node['fusion_out_name'] + # ak_name=self._convert_name_tf2ak(name) + # print('key ',ak_name) + # if akopname2ak_out.get(ak_name) is not None: + # compare_dic[name+':0']=akopname2ak_out[ak_name] + # outlist=compare_dic.keys() + # out=TfUtil.tf_run_model(self.tf_model_path,inputs,outlist) + # for index,name in enumerate(outlist): + # correct=out[index].transpose() + # ak_result=akopname2ak_out[name] + # assert len() + # for i in range(len(ak_result)): + # if abs() # tensor_shape = {} # graph={} # for node in tf_ops: @@ -116,9 +149,10 @@ def run(self): # graph[node.name]={'name':node.name,'input':input_names,'output':output_names} # self._fix_self_output(graph,tensor_shape) # self._debug_graph(graph) -ak_work_space='/home/ljj/docker_mount_dev2/anakin2_developing_parser/build/' -debug=AutoDebug('./resnet_model/frozen_resnet_v1_50.pb',ak_work_space) + +ak_work_space = '/home/ljj/docker_mount_dev2/anakin2_developing_parser/build/' + +debug = AutoDebug('./resnet_model/frozen_resnet_v1_50.pb', ak_work_space) debug.run_ak() debug.run() - diff --git a/tools/external_converter_v2/parser/kill_tf/freeze.py b/tools/external_converter_v2/parser/kill_tf/freeze.py index bc5b77631..c45ccba51 100644 --- a/tools/external_converter_v2/parser/kill_tf/freeze.py +++ b/tools/external_converter_v2/parser/kill_tf/freeze.py @@ -6,7 +6,13 @@ dir = os.path.dirname(os.path.realpath(__file__)) -def freeze_graph(model_folder,output_name): +def freeze_graph(model_folder, output_name): + ''' + freeze graph from meta input + :param model_folder: + :param output_name: + :return: + ''' # We retrieve our checkpoint fullpath checkpoint = tf.train.get_checkpoint_state(model_folder) input_checkpoint = checkpoint.model_checkpoint_path @@ -59,4 +65,3 @@ def freeze_graph(model_folder,output_name): # freeze_graph('/tmp/pycharm_project_635/tensorflow/RNN/model/language_model_tf','Softmax') freeze_graph('./ease_model/', 'add_2') - diff --git a/tools/external_converter_v2/parser/kill_tf/freeze_graph.py b/tools/external_converter_v2/parser/kill_tf/freeze_graph.py index 73a430866..d6e369f4d 100644 --- a/tools/external_converter_v2/parser/kill_tf/freeze_graph.py +++ b/tools/external_converter_v2/parser/kill_tf/freeze_graph.py @@ -73,159 +73,159 @@ def freeze_graph_with_def_protos(input_graph_def, input_saved_model_dir=None, saved_model_tags=None, checkpoint_version=saver_pb2.SaverDef.V2): - """Converts all variables in a graph and checkpoint into constants.""" - del restore_op_name, filename_tensor_name # Unused by updated loading code. - - if not output_node_names: - print("You need to supply the name of a node to --output_node_names.") - return -1 - - # Remove all the explicit device specifications for this node. This helps to - # make the graph more portable. - if clear_devices: - if input_meta_graph_def: - for node in input_meta_graph_def.graph_def.node: - node.device = "" - elif input_graph_def: - for node in input_graph_def.node: - node.device = "" - - if input_graph_def: - _ = importer.import_graph_def(input_graph_def, name="") - with session.Session() as sess: - if input_saver_def: - saver = saver_lib.Saver( - saver_def=input_saver_def, write_version=checkpoint_version) - saver.restore(sess, input_checkpoint) - elif input_meta_graph_def: - restorer = saver_lib.import_meta_graph( - input_meta_graph_def, clear_devices=True) - restorer.restore(sess, input_checkpoint) - if initializer_nodes: - sess.run(initializer_nodes.replace(" ", "").split(",")) - elif input_saved_model_dir: - if saved_model_tags is None: - saved_model_tags = [] - loader.load(sess, saved_model_tags, input_saved_model_dir) - else: - var_list = {} - reader = pywrap_tensorflow.NewCheckpointReader(input_checkpoint) - var_to_shape_map = reader.get_variable_to_shape_map() - - # List of all partition variables. Because the condition is heuristic - # based, the list could include false positives. - all_parition_variable_names = [ - tensor.name.split(":")[0] - for op in sess.graph.get_operations() - for tensor in op.values() - if re.search(r"/part_\d+/", tensor.name) - ] - has_partition_var = False - - for key in var_to_shape_map: - try: - tensor = sess.graph.get_tensor_by_name(key + ":0") - if any(key in name for name in all_parition_variable_names): - has_partition_var = True - except KeyError: - # This tensor doesn't exist in the graph (for example it's - # 'global_step' or a similar housekeeping element) so skip it. - continue - var_list[key] = tensor - - try: - saver = saver_lib.Saver( - var_list=var_list, write_version=checkpoint_version) - except TypeError as e: - # `var_list` is required to be a map of variable names to Variable - # tensors. Partition variables are Identity tensors that cannot be - # handled by Saver. - if has_partition_var: - print("Models containing partition variables cannot be converted " - "from checkpoint files. Please pass in a SavedModel using " - "the flag --input_saved_model_dir.") - return -1 + """Converts all variables in a graph and checkpoint into constants.""" + del restore_op_name, filename_tensor_name # Unused by updated loading code. + + if not output_node_names: + print("You need to supply the name of a node to --output_node_names.") + return -1 + + # Remove all the explicit device specifications for this node. This helps to + # make the graph more portable. + if clear_devices: + if input_meta_graph_def: + for node in input_meta_graph_def.graph_def.node: + node.device = "" + elif input_graph_def: + for node in input_graph_def.node: + node.device = "" + + if input_graph_def: + _ = importer.import_graph_def(input_graph_def, name="") + with session.Session() as sess: + if input_saver_def: + saver = saver_lib.Saver( + saver_def=input_saver_def, write_version=checkpoint_version) + saver.restore(sess, input_checkpoint) + elif input_meta_graph_def: + restorer = saver_lib.import_meta_graph( + input_meta_graph_def, clear_devices=True) + restorer.restore(sess, input_checkpoint) + if initializer_nodes: + sess.run(initializer_nodes.replace(" ", "").split(",")) + elif input_saved_model_dir: + if saved_model_tags is None: + saved_model_tags = [] + loader.load(sess, saved_model_tags, input_saved_model_dir) else: - raise e - - saver.restore(sess, input_checkpoint) - if initializer_nodes: - sess.run(initializer_nodes.replace(" ", "").split(",")) - - variable_names_whitelist = ( - variable_names_whitelist.replace(" ", "").split(",") - if variable_names_whitelist else None) - variable_names_blacklist = ( - variable_names_blacklist.replace(" ", "").split(",") - if variable_names_blacklist else None) - - if input_meta_graph_def: - output_graph_def = graph_util.convert_variables_to_constants( - sess, - input_meta_graph_def.graph_def, - output_node_names.replace(" ", "").split(","), - variable_names_whitelist=variable_names_whitelist, - variable_names_blacklist=variable_names_blacklist) - else: - output_graph_def = graph_util.convert_variables_to_constants( - sess, - input_graph_def, - output_node_names.replace(" ", "").split(","), - variable_names_whitelist=variable_names_whitelist, - variable_names_blacklist=variable_names_blacklist) + var_list = {} + reader = pywrap_tensorflow.NewCheckpointReader(input_checkpoint) + var_to_shape_map = reader.get_variable_to_shape_map() + + # List of all partition variables. Because the condition is heuristic + # based, the list could include false positives. + all_parition_variable_names = [ + tensor.name.split(":")[0] + for op in sess.graph.get_operations() + for tensor in op.values() + if re.search(r"/part_\d+/", tensor.name) + ] + has_partition_var = False + + for key in var_to_shape_map: + try: + tensor = sess.graph.get_tensor_by_name(key + ":0") + if any(key in name for name in all_parition_variable_names): + has_partition_var = True + except KeyError: + # This tensor doesn't exist in the graph (for example it's + # 'global_step' or a similar housekeeping element) so skip it. + continue + var_list[key] = tensor + + try: + saver = saver_lib.Saver( + var_list=var_list, write_version=checkpoint_version) + except TypeError as e: + # `var_list` is required to be a map of variable names to Variable + # tensors. Partition variables are Identity tensors that cannot be + # handled by Saver. + if has_partition_var: + print("Models containing partition variables cannot be converted " + "from checkpoint files. Please pass in a SavedModel using " + "the flag --input_saved_model_dir.") + return -1 + else: + raise e + + saver.restore(sess, input_checkpoint) + if initializer_nodes: + sess.run(initializer_nodes.replace(" ", "").split(",")) + + variable_names_whitelist = ( + variable_names_whitelist.replace(" ", "").split(",") + if variable_names_whitelist else None) + variable_names_blacklist = ( + variable_names_blacklist.replace(" ", "").split(",") + if variable_names_blacklist else None) + + if input_meta_graph_def: + output_graph_def = graph_util.convert_variables_to_constants( + sess, + input_meta_graph_def.graph_def, + output_node_names.replace(" ", "").split(","), + variable_names_whitelist=variable_names_whitelist, + variable_names_blacklist=variable_names_blacklist) + else: + output_graph_def = graph_util.convert_variables_to_constants( + sess, + input_graph_def, + output_node_names.replace(" ", "").split(","), + variable_names_whitelist=variable_names_whitelist, + variable_names_blacklist=variable_names_blacklist) - # Write GraphDef to file if output path has been given. - if output_graph: - with gfile.GFile(output_graph, "wb") as f: - f.write(output_graph_def.SerializeToString()) + # Write GraphDef to file if output path has been given. + if output_graph: + with gfile.GFile(output_graph, "wb") as f: + f.write(output_graph_def.SerializeToString()) - return output_graph_def + return output_graph_def def _parse_input_graph_proto(input_graph, input_binary): - """Parser input tensorflow graph into GraphDef proto.""" - if not gfile.Exists(input_graph): - print("Input graph file '" + input_graph + "' does not exist!") - return -1 - input_graph_def = graph_pb2.GraphDef() - mode = "rb" if input_binary else "r" - with gfile.FastGFile(input_graph, mode) as f: - if input_binary: - input_graph_def.ParseFromString(f.read()) - else: - text_format.Merge(f.read(), input_graph_def) - return input_graph_def + """Parser input tensorflow graph into GraphDef proto.""" + if not gfile.Exists(input_graph): + print("Input graph file '" + input_graph + "' does not exist!") + return -1 + input_graph_def = graph_pb2.GraphDef() + mode = "rb" if input_binary else "r" + with gfile.FastGFile(input_graph, mode) as f: + if input_binary: + input_graph_def.ParseFromString(f.read()) + else: + text_format.Merge(f.read(), input_graph_def) + return input_graph_def def _parse_input_meta_graph_proto(input_graph, input_binary): - """Parser input tensorflow graph into MetaGraphDef proto.""" - if not gfile.Exists(input_graph): - print("Input meta graph file '" + input_graph + "' does not exist!") - return -1 - input_meta_graph_def = MetaGraphDef() - mode = "rb" if input_binary else "r" - with gfile.FastGFile(input_graph, mode) as f: - if input_binary: - input_meta_graph_def.ParseFromString(f.read()) - else: - text_format.Merge(f.read(), input_meta_graph_def) - print("Loaded meta graph file '" + input_graph) - return input_meta_graph_def + """Parser input tensorflow graph into MetaGraphDef proto.""" + if not gfile.Exists(input_graph): + print("Input meta graph file '" + input_graph + "' does not exist!") + return -1 + input_meta_graph_def = MetaGraphDef() + mode = "rb" if input_binary else "r" + with gfile.FastGFile(input_graph, mode) as f: + if input_binary: + input_meta_graph_def.ParseFromString(f.read()) + else: + text_format.Merge(f.read(), input_meta_graph_def) + print("Loaded meta graph file '" + input_graph) + return input_meta_graph_def def _parse_input_saver_proto(input_saver, input_binary): - """Parser input tensorflow Saver into SaverDef proto.""" - if not gfile.Exists(input_saver): - print("Input saver file '" + input_saver + "' does not exist!") - return -1 - mode = "rb" if input_binary else "r" - with gfile.FastGFile(input_saver, mode) as f: - saver_def = saver_pb2.SaverDef() - if input_binary: - saver_def.ParseFromString(f.read()) - else: - text_format.Merge(f.read(), saver_def) - return saver_def + """Parser input tensorflow Saver into SaverDef proto.""" + if not gfile.Exists(input_saver): + print("Input saver file '" + input_saver + "' does not exist!") + return -1 + mode = "rb" if input_binary else "r" + with gfile.FastGFile(input_saver, mode) as f: + saver_def = saver_pb2.SaverDef() + if input_binary: + saver_def.ParseFromString(f.read()) + else: + text_format.Merge(f.read(), saver_def) + return saver_def def freeze_graph(input_graph, @@ -244,161 +244,173 @@ def freeze_graph(input_graph, input_saved_model_dir=None, saved_model_tags=tag_constants.SERVING, checkpoint_version=saver_pb2.SaverDef.V2): - """Converts all variables in a graph and checkpoint into constants.""" - input_graph_def = None - if input_saved_model_dir: - input_graph_def = saved_model_utils.get_meta_graph_def( - input_saved_model_dir, saved_model_tags).graph_def - elif input_graph: - input_graph_def = _parse_input_graph_proto(input_graph, input_binary) - input_meta_graph_def = None - if input_meta_graph: - input_meta_graph_def = _parse_input_meta_graph_proto( - input_meta_graph, input_binary) - input_saver_def = None - if input_saver: - input_saver_def = _parse_input_saver_proto(input_saver, input_binary) - freeze_graph_with_def_protos( - input_graph_def, - input_saver_def, - input_checkpoint, - output_node_names, - restore_op_name, - filename_tensor_name, - output_graph, - clear_devices, - initializer_nodes, - variable_names_whitelist, - variable_names_blacklist, - input_meta_graph_def, - input_saved_model_dir, - saved_model_tags.replace(" ", "").split(","), - checkpoint_version=checkpoint_version) + """Converts all variables in a graph and checkpoint into constants.""" + input_graph_def = None + if input_saved_model_dir: + input_graph_def = saved_model_utils.get_meta_graph_def( + input_saved_model_dir, saved_model_tags).graph_def + elif input_graph: + input_graph_def = _parse_input_graph_proto(input_graph, input_binary) + input_meta_graph_def = None + if input_meta_graph: + input_meta_graph_def = _parse_input_meta_graph_proto( + input_meta_graph, input_binary) + input_saver_def = None + if input_saver: + input_saver_def = _parse_input_saver_proto(input_saver, input_binary) + freeze_graph_with_def_protos( + input_graph_def, + input_saver_def, + input_checkpoint, + output_node_names, + restore_op_name, + filename_tensor_name, + output_graph, + clear_devices, + initializer_nodes, + variable_names_whitelist, + variable_names_blacklist, + input_meta_graph_def, + input_saved_model_dir, + saved_model_tags.replace(" ", "").split(","), + checkpoint_version=checkpoint_version) def main(unused_args, flags): - if flags.checkpoint_version == 1: - checkpoint_version = saver_pb2.SaverDef.V1 - elif flags.checkpoint_version == 2: - checkpoint_version = saver_pb2.SaverDef.V2 - else: - print("Invalid checkpoint version (must be '1' or '2'): %d" % - flags.checkpoint_version) - return -1 - freeze_graph(flags.input_graph, flags.input_saver, flags.input_binary, - flags.input_checkpoint, flags.output_node_names, - flags.restore_op_name, flags.filename_tensor_name, - flags.output_graph, flags.clear_devices, flags.initializer_nodes, - flags.variable_names_whitelist, flags.variable_names_blacklist, - flags.input_meta_graph, flags.input_saved_model_dir, - flags.saved_model_tags, checkpoint_version) + ''' + main function + :param unused_args: + :param flags: + :return: + ''' + if flags.checkpoint_version == 1: + checkpoint_version = saver_pb2.SaverDef.V1 + elif flags.checkpoint_version == 2: + checkpoint_version = saver_pb2.SaverDef.V2 + else: + print("Invalid checkpoint version (must be '1' or '2'): %d" % + flags.checkpoint_version) + return -1 + freeze_graph(flags.input_graph, flags.input_saver, flags.input_binary, + flags.input_checkpoint, flags.output_node_names, + flags.restore_op_name, flags.filename_tensor_name, + flags.output_graph, flags.clear_devices, flags.initializer_nodes, + flags.variable_names_whitelist, flags.variable_names_blacklist, + flags.input_meta_graph, flags.input_saved_model_dir, + flags.saved_model_tags, checkpoint_version) + def run_main(): - parser = argparse.ArgumentParser() - parser.register("type", "bool", lambda v: v.lower() == "true") - parser.add_argument( - "--input_graph", - type=str, - default="", - help="TensorFlow \'GraphDef\' file to load.") - parser.add_argument( - "--input_saver", - type=str, - default="", - help="TensorFlow saver file to load.") - parser.add_argument( - "--input_checkpoint", - type=str, - default="", - help="TensorFlow variables file to load.") - parser.add_argument( - "--checkpoint_version", - type=int, - default=2, - help="Tensorflow variable file format") - parser.add_argument( - "--output_graph", - type=str, - default="", - help="Output \'GraphDef\' file name.") - parser.add_argument( - "--input_binary", - nargs="?", - const=True, - type="bool", - default=False, - help="Whether the input files are in binary format.") - parser.add_argument( - "--output_node_names", - type=str, - default="", - help="The name of the output nodes, comma separated.") - parser.add_argument( - "--restore_op_name", - type=str, - default="save/restore_all", - help="""\ + ''' + excution entry + :return: + ''' + parser = argparse.ArgumentParser() + parser.register("type", "bool", lambda v: v.lower() == "true") + parser.add_argument( + "--input_graph", + type=str, + default="", + help="TensorFlow \'GraphDef\' file to load.") + parser.add_argument( + "--input_saver", + type=str, + default="", + help="TensorFlow saver file to load.") + parser.add_argument( + "--input_checkpoint", + type=str, + default="", + help="TensorFlow variables file to load.") + parser.add_argument( + "--checkpoint_version", + type=int, + default=2, + help="Tensorflow variable file format") + parser.add_argument( + "--output_graph", + type=str, + default="", + help="Output \'GraphDef\' file name.") + parser.add_argument( + "--input_binary", + nargs="?", + const=True, + type="bool", + default=False, + help="Whether the input files are in binary format.") + parser.add_argument( + "--output_node_names", + type=str, + default="", + help="The name of the output nodes, comma separated.") + parser.add_argument( + "--restore_op_name", + type=str, + default="save/restore_all", + help="""\ The name of the master restore operator. Deprecated, unused by updated \ loading code. """) - parser.add_argument( - "--filename_tensor_name", - type=str, - default="save/Const:0", - help="""\ + parser.add_argument( + "--filename_tensor_name", + type=str, + default="save/Const:0", + help="""\ The name of the tensor holding the save path. Deprecated, unused by \ updated loading code. """) - parser.add_argument( - "--clear_devices", - nargs="?", - const=True, - type="bool", - default=True, - help="Whether to remove device specifications.") - parser.add_argument( - "--initializer_nodes", - type=str, - default="", - help="Comma separated list of initializer nodes to run before freezing.") - parser.add_argument( - "--variable_names_whitelist", - type=str, - default="", - help="""\ + parser.add_argument( + "--clear_devices", + nargs="?", + const=True, + type="bool", + default=True, + help="Whether to remove device specifications.") + parser.add_argument( + "--initializer_nodes", + type=str, + default="", + help="Comma separated list of initializer nodes to run before freezing.") + parser.add_argument( + "--variable_names_whitelist", + type=str, + default="", + help="""\ Comma separated list of variables to convert to constants. If specified, \ only those variables will be converted to constants.\ """) - parser.add_argument( - "--variable_names_blacklist", - type=str, - default="", - help="""\ + parser.add_argument( + "--variable_names_blacklist", + type=str, + default="", + help="""\ Comma separated list of variables to skip converting to constants.\ """) - parser.add_argument( - "--input_meta_graph", - type=str, - default="", - help="TensorFlow \'MetaGraphDef\' file to load.") - parser.add_argument( - "--input_saved_model_dir", - type=str, - default="", - help="Path to the dir with TensorFlow \'SavedModel\' file and variables.") - parser.add_argument( - "--saved_model_tags", - type=str, - default="serve", - help="""\ + parser.add_argument( + "--input_meta_graph", + type=str, + default="", + help="TensorFlow \'MetaGraphDef\' file to load.") + parser.add_argument( + "--input_saved_model_dir", + type=str, + default="", + help="Path to the dir with TensorFlow \'SavedModel\' file and variables.") + parser.add_argument( + "--saved_model_tags", + type=str, + default="serve", + help="""\ Group of tag(s) of the MetaGraphDef to load, in string format,\ separated by \',\'. For tag-set contains multiple tags, all tags \ must be passed in.\ """) - flags, unparsed = parser.parse_known_args() + flags, unparsed = parser.parse_known_args() + + my_main = lambda unused_args: main(unused_args, flags) + app.run(main=my_main, argv=[sys.argv[0]] + unparsed) - my_main = lambda unused_args: main(unused_args, flags) - app.run(main=my_main, argv=[sys.argv[0]] + unparsed) if __name__ == '__main__': - run_main() + run_main() diff --git a/tools/external_converter_v2/parser/kill_tf/get_empt_infer_pb.py b/tools/external_converter_v2/parser/kill_tf/get_empt_infer_pb.py index 16b9b0f06..11be45be9 100644 --- a/tools/external_converter_v2/parser/kill_tf/get_empt_infer_pb.py +++ b/tools/external_converter_v2/parser/kill_tf/get_empt_infer_pb.py @@ -4,11 +4,11 @@ from tensorflow.python.platform import gfile from google.protobuf import text_format -graph_path='./inception_model/inception_v2_inf_graph.pb' -output_node_names='InceptionV2/Predictions/Reshape_1' -output_graph='./inception_model/inception_v2_inf_graph_empty.pb' +graph_path = './inception_model/inception_v2_inf_graph.pb' +output_node_names = 'InceptionV2/Predictions/Reshape_1' +output_graph = './inception_model/inception_v2_inf_graph_empty.pb' -sess=tf.Session() +sess = tf.Session() if graph_path.endswith('.pbtxt'): input_binary = False else: @@ -29,11 +29,11 @@ tf.import_graph_def(graph_def, name='graph') output_graph_def = graph_util.convert_variables_to_constants( - sess, - graph_def, - output_node_names.split(",") # We split on comma for convenience - ) + sess, + graph_def, + output_node_names.split(",") # We split on comma for convenience +) # Finally we serialize and dump the output graph to the filesystem with tf.gfile.GFile(output_graph, "wb") as f: f.write(output_graph_def.SerializeToString()) -print("%d ops in the final graph." % len(output_graph_def.node)) \ No newline at end of file +print("%d ops in the final graph." % len(output_graph_def.node)) diff --git a/tools/external_converter_v2/parser/kill_tf/med_graph.py b/tools/external_converter_v2/parser/kill_tf/med_graph.py index aacbc5e15..d17cc8702 100644 --- a/tools/external_converter_v2/parser/kill_tf/med_graph.py +++ b/tools/external_converter_v2/parser/kill_tf/med_graph.py @@ -1,15 +1,26 @@ import numpy as np - class MedNodeUtil: @staticmethod def new_med_node(): - return {'name':None,'ak_type': None, 'input': [], 'output': [], 'ak_attr': {},'type':None,'med_visted':False} + ''' + return instance of empty standard med graph node + :return: + ''' + return {'name': None, 'ak_type': None, 'input': [], 'output': [], 'ak_attr': {}, 'type': None, + 'med_visted': False} @staticmethod def replace_name_with_list(origin_list, name, replace_list): + ''' + replace name in input or output with replace_list + :param origin_list: + :param name: + :param replace_list: + :return: + ''' new_list = [] for index, ori_object in enumerate(origin_list): if ori_object['name'] == name: @@ -23,6 +34,12 @@ def replace_name_with_list(origin_list, name, replace_list): @staticmethod def retain_input(node, input_list): + ''' + remove node input except element in input_list + :param node: + :param input_list: + :return: + ''' new_input = [] for index, node_object in enumerate(node['input']): if node_object in input_list: @@ -31,17 +48,35 @@ def retain_input(node, input_list): node['input'] = new_input @staticmethod - def redirecto_outputs_input_to_this(node,graph,this_name,this_shape): + def redirecto_outputs_input_to_this(node, graph, this_name, this_shape): + ''' + get node_x in node`s outputs + make node_x`s inputs reference to node + :param node: + :param graph: + :param this_name: + :param this_shape: + :return: + ''' for i in node['output']: - tar_node=graph[i['name']] - tar_node['input']=MedNodeUtil.replace_name_with_list(tar_node['input'],node['name'],[{'name':this_name,'shape':this_shape}]) + tar_node = graph[i['name']] + tar_node['input'] = MedNodeUtil.replace_name_with_list(tar_node['input'], node['name'], + [{'name': this_name, 'shape': this_shape}]) + +MedGraph_Input_Cnt = 0 -MedGraph_Input_Cnt=0 class MedGraphUtil: @staticmethod def append_node(father_node, son_node, graph): + ''' + add the son_node after father_node in graph + :param father_node: + :param son_node: + :param graph: + :return: + ''' output = father_node['output'] son_shape = father_node['output'][0]['shape'] son_node['input'] = [{'name': father_node['name'], 'shape': son_shape}] @@ -54,7 +89,13 @@ def append_node(father_node, son_node, graph): graph[son_node['name']] = son_node @staticmethod - def check_one_of_input_is_const(node,graph): + def check_one_of_input_is_const(node, graph): + ''' + check one of input is const + :param node: + :param graph: + :return: + ''' for i in node['input']: if graph[i['name']]['type'] == 'Const': return True @@ -62,26 +103,45 @@ def check_one_of_input_is_const(node,graph): @staticmethod def _auto_split(med_node, med_graph): + ''' + add split to node which output size >=2 + :param med_node: + :param med_graph: + :return: + ''' output = med_node['output'] if len(output) > 1: split_node = MedNodeUtil.new_med_node() - split_node['name']=med_node['name']+'_split#' - split_node['ak_type']='Split' - split_node['ak_attr']['split_num'] =len(output) - MedGraphUtil.append_node(med_node,split_node,graph=med_graph) + split_node['name'] = med_node['name'] + '_split#' + split_node['ak_type'] = 'Split' + split_node['ak_attr']['split_num'] = len(output) + MedGraphUtil.append_node(med_node, split_node, graph=med_graph) pass @staticmethod def _auto_input_name(med_node, med_graph): - assert med_node['ak_type']=='Input' - old_name=med_node['name'] - med_node['name']='input_'+str(MedGraph_Input_Cnt) + ''' + gen input name + :param med_node: + :param med_graph: + :return: + ''' + assert med_node['ak_type'] == 'Input' + old_name = med_node['name'] + med_node['name'] = 'input_' + str(MedGraph_Input_Cnt) for i in med_node['output']: - out_node=med_graph[i['name']] - out_node['input']=MedNodeUtil.replace_name_with_list(out_node['input'],old_name,[{'name':med_node['name'],'shape':i['shape']}]) + out_node = med_graph[i['name']] + out_node['input'] = MedNodeUtil.replace_name_with_list(out_node['input'], old_name, + [{'name': med_node['name'], 'shape': i['shape']}]) @staticmethod def _fusionScale(med_node, med_graph): + ''' + fusion scale node after convolution node + :param med_node: + :param med_graph: + :return: + ''' if len(med_node['input']) == 1: input_node = med_graph[med_node['input'][0]['name']] med_ak_attr = med_node['ak_attr'] @@ -100,14 +160,22 @@ def _fusionScale(med_node, med_graph): else: input_attr['bias_weights'] = med_ak_attr['bias_weights'] med_node['ak_type'] = None - input_node['output'] = MedNodeUtil.replace_name_with_list(input_node['output'], med_node['name'], med_node['output']) - MedNodeUtil.redirecto_outputs_input_to_this(med_node,med_graph,input_node['name'],med_node['input'][0]['shape']) - input_node['fusion_out_name']=med_node['name'] + input_node['output'] = MedNodeUtil.replace_name_with_list(input_node['output'], med_node['name'], + med_node['output']) + MedNodeUtil.redirecto_outputs_input_to_this(med_node, med_graph, input_node['name'], + med_node['input'][0]['shape']) + input_node['fusion_out_name'] = med_node['name'] pass @staticmethod def _all_search_table(graph, table): + ''' + search template for dict + :param graph: + :param table: + :return: + ''' for tf_node in graph.values(): if tf_node['med_visted']: continue @@ -117,6 +185,12 @@ def _all_search_table(graph, table): @staticmethod def _all_search_fusion(graph, fusion_func): + ''' + search template for func + :param graph: + :param fusion_func: + :return: + ''' for tf_node in graph.values(): if tf_node['med_visted']: continue @@ -125,14 +199,24 @@ def _all_search_fusion(graph, fusion_func): @staticmethod def solve(med_graph): + ''' + do fusion and adjust for med graph that we can convert med graph to ak graph + :param med_graph: + :return: + ''' for node in med_graph.values(): node['med_visted'] = False MedGraphUtil._all_search_table(med_graph, {'Scale': MedGraphUtil._fusionScale}) MedGraphUtil._all_search_fusion(med_graph, MedGraphUtil._auto_split) - MedGraphUtil._all_search_table(med_graph, {'Input':MedGraphUtil._auto_input_name}) + MedGraphUtil._all_search_table(med_graph, {'Input': MedGraphUtil._auto_input_name}) @staticmethod def search_output_list(graph): + ''' + search output list in recursive method + :param graph: + :return: + ''' output_list = set() graph_cp = graph.copy() diff --git a/tools/external_converter_v2/parser/kill_tf/parse_med_2_ak.py b/tools/external_converter_v2/parser/kill_tf/parse_med_2_ak.py index fa0df3c7a..2cc53107e 100644 --- a/tools/external_converter_v2/parser/kill_tf/parse_med_2_ak.py +++ b/tools/external_converter_v2/parser/kill_tf/parse_med_2_ak.py @@ -4,11 +4,21 @@ def shape_2_ak_shape(shape): + ''' + convert med shape to ak shape + :param shape: + :return: + ''' mini_shape = [i for i in shape if (i != None and i > 0)] return map(int, [1] * (4 - len(mini_shape)) + list(mini_shape)) def np_2_ak_tensor(np_tensor): + ''' + conver med tensor to ak tensor + :param np_tensor: + :return: + ''' data_type_map = { np.dtype('float32'): 'float', np.dtype('int32'): 'int', @@ -29,6 +39,12 @@ def __init__(self): self.input_count = 0 def Convolution(self, med_attr, param): + ''' + fill convlution param in ak graph + :param med_attr: + :param param: + :return: + ''' np_filters = med_attr['weights'] param.weight_1 = np_2_ak_tensor(np_filters) param.filter_num = np_filters.shape[0] @@ -48,6 +64,12 @@ def Convolution(self, med_attr, param): pass def Dense(self, med_attr, param): + ''' + fill Dense param in ak graph + :param med_attr: + :param param: + :return: + ''' param.weight_1 = np_2_ak_tensor(med_attr['weights']) param.axis = 1 if med_attr.get('bias_weights') is not None: @@ -58,18 +80,35 @@ def Dense(self, med_attr, param): pass def Relu(self, med_attr, param): + ''' + fill Relu param in ak graph + :param med_attr: + :param param: + :return: + ''' if med_attr.get('alpha') is None: param.alpha = 0.0 else: param.alpha = med_attr['type'] def Activation(self, med_attr, param): + ''' + fill Activation param in ak graph + :param med_attr: + :param param: + :return: + ''' param.type = med_attr['type'] - if med_attr['type']=='ClippedRelu': - param.clip_relu_num=med_attr['clip_relu_num'] - + if med_attr['type'] == 'ClippedRelu': + param.clip_relu_num = med_attr['clip_relu_num'] def Softmax(self, med_attr, param): + ''' + fill Softmax param in ak graph + :param med_attr: + :param param: + :return: + ''' if med_attr.get('axis') is None: param.axis = 3 else: @@ -77,17 +116,41 @@ def Softmax(self, med_attr, param): pass def Concat(self, med_attr, param): + ''' + fill Concat param in ak graph + :param med_attr: + :param param: + :return: + ''' param.axis = med_attr['axis'] def Split(self, med_attr, param): + ''' + fill Split param in ak graph + :param med_attr: + :param param: + :return: + ''' param.split_num = med_attr['split_num'] def Eltwise(self, med_attr, param): + ''' + fill Eltwise param in ak graph + :param med_attr: + :param param: + :return: + ''' assert med_attr['type'] == 'Add' param.type = med_attr['type'] param.coeff = [1.0, 1.0] def Scale(self, med_attr, param): + ''' + fill Scale param in ak graph + :param med_attr: + :param param: + :return: + ''' param.weight_1 = np_2_ak_tensor(med_attr['scale_weights']) if med_attr.get('bias_weights') is not None: param.weight_2 = np_2_ak_tensor(med_attr['bias_weights']) @@ -98,6 +161,12 @@ def Scale(self, med_attr, param): param.num_axes = 1 def Reshape(self, med_attr, param): + ''' + fill Reshape param in ak graph + :param med_attr: + :param param: + :return: + ''' shape = med_attr['shape'] if isinstance(shape, type(np.array([]))): shape = [int(i) for i in shape] @@ -105,6 +174,12 @@ def Reshape(self, med_attr, param): pass def Pooling(self, med_attr, param): + ''' + fill Pooling param in ak graph + :param med_attr: + :param param: + :return: + ''' param.method = med_attr['type'] param.pool_size = med_attr['window'] param.strides = med_attr['strides'] @@ -121,19 +196,35 @@ def Pooling(self, med_attr, param): pass - def Pad(self, med_attr, param): - param.pad_c=med_attr['pad_c'] + ''' + fill Pad param in ak graph + :param med_attr: + :param param: + :return: + ''' + param.pad_c = med_attr['pad_c'] param.pad_h = med_attr['pad_h'] param.pad_w = med_attr['pad_w'] - def Input(self, med_attr, param): + ''' + fill Input param in ak graph + :param med_attr: + :param param: + :return: + ''' param.input_shape = shape_2_ak_shape(med_attr['shape']) if med_attr.get('alias') is not None: param.alias = med_attr['alias'] def map_med_2_ak(self, ak_node, med_node): + ''' + entrance for trans med graph 2 ak graph + :param ak_node: + :param med_node: + :return: + ''' type_name = med_node['ak_type'] func = getattr(self, type_name, None) param = OpsParam() diff --git a/tools/external_converter_v2/parser/kill_tf/parse_tf_2_med.py b/tools/external_converter_v2/parser/kill_tf/parse_tf_2_med.py index 14705878b..6f26d8a55 100644 --- a/tools/external_converter_v2/parser/kill_tf/parse_tf_2_med.py +++ b/tools/external_converter_v2/parser/kill_tf/parse_tf_2_med.py @@ -4,23 +4,26 @@ import logging as log import collections from tf_trans_util import * -class ParseTF2Med: - def __init__(self,tf_forzen_pb_path): - self.model_path=tf_forzen_pb_path - def _debug_nodes(self,nodes): + +class ParseTF2Med: + def __init__(self, tf_forzen_pb_path): + self.model_path = tf_forzen_pb_path + + def _debug_nodes(self, nodes): + ''' + print debug info and exit + :param nodes: + :return: + ''' for i in nodes.values(): - print(i['name'],i['input'],i['output'],i['out_shape']) + print(i['name'], i['input'], i['output'], i['out_shape']) print('debug end') exit() - - def _parse_tf_node(self,tf_graph,shape_override): - - + def _parse_tf_node(self, tf_graph, shape_override): """ - Load tensorflow graph into an onnx graph with minimal rewrites so - we can use the onnx graph as intermediate graph. + Load tensorflow graph into an raw med graph """ # ignore the following attributes @@ -37,11 +40,10 @@ def _parse_tf_node(self,tf_graph,shape_override): # find outputs ops = tf_graph.get_operations() - tensor_shape={} + tensor_shape = {} for node in ops: for out in node.outputs: - tensor_shape[out.name]=out.get_shape().as_list() - + tensor_shape[out.name] = out.get_shape().as_list() # minimal conversion of attributes for node in ops: @@ -50,7 +52,7 @@ def _parse_tf_node(self,tf_graph,shape_override): op_cnt[node.type] += 1 for a in node.node_def.attr: - a=str(a) + a = str(a) attr_cnt[a] += 1 if a == "dtype": attr[a] = map_tf_dtype(node.get_attr("dtype")) @@ -92,11 +94,17 @@ def _parse_tf_node(self,tf_graph,shape_override): log.error("pass1 convert failed for %s, ex=%s", node, ex) raise - self._fix_self_output(anakin_nodes,tensor_shape) + self._fix_self_output(anakin_nodes, tensor_shape) return anakin_nodes def _fix_self_output(self, nodes, tensor_shape_dict): + ''' + convert tensor connection to op connection + :param nodes: + :param tensor_shape_dict: + :return: + ''' out2nodename = {} for node in nodes.values(): for out_name in node['output']: @@ -114,23 +122,28 @@ def _fix_self_output(self, nodes, tensor_shape_dict): in2nodename[in_name].append(node['name']) for node in nodes.values(): - new_output=[] - new_input=[] + new_output = [] + new_input = [] for tensor_name in node['output']: if in2nodename.get(tensor_name) is not None: - new_output+=[{'name':op_name,'shape':tensor_shape_dict[tensor_name]} for op_name in in2nodename[tensor_name]] + new_output += [{'name': op_name, 'shape': tensor_shape_dict[tensor_name]} for op_name in + in2nodename[tensor_name]] for tensor_name in node['input']: if out2nodename.get(tensor_name) is not None: - new_input+=[{'name':op_name,'shape':tensor_shape_dict[tensor_name]} for op_name in out2nodename[tensor_name]] - - node['output']=new_output - node['input']=new_input - + new_input += [{'name': op_name, 'shape': tensor_shape_dict[tensor_name]} for op_name in + out2nodename[tensor_name]] + node['output'] = new_output + node['input'] = new_input - def _parse_tf_graph(self,nodes): + def _parse_tf_graph(self, nodes): + ''' + conver op in tf graph to med graph + :param nodes: + :return: + ''' def all_search(graph, table): for tf_node in graph.values(): @@ -145,19 +158,19 @@ def all_search(graph, table): 'Shape': parse_Shape }) - all_search(nodes, {'Reshape': parse_fusionReshape,}) + all_search(nodes, {'Reshape': parse_fusionReshape, }) all_search(nodes, {'MatMul': parse_MatMul, 'Conv2D': parse_Conv2D, 'DepthwiseConv2dNative': parse_Conv2D, - 'FusedBatchNorm':parse_BatchNorm, - 'Rsqrt': parse_CustmerBatchNorm,}) + 'FusedBatchNorm': parse_BatchNorm, + 'Rsqrt': parse_CustmerBatchNorm, }) - all_search(nodes, {'Add':parse_Add, + all_search(nodes, {'Add': parse_Add, 'AvgPool': parse_Pooling, 'ConcatV2': parse_Concat, 'MaxPool': parse_Pooling, - 'Mean':parse_Mean, + 'Mean': parse_Mean, 'Pad': parse_Pad, 'Relu': parse_Act, 'Relu6': parse_Act, @@ -170,12 +183,16 @@ def all_search(graph, table): return nodes def parse(self): + ''' + entrance to load tf graph and convert it to med graph + :return: + ''' tf_graph = load_graph(self.model_path) nodes = self._parse_tf_node(tf_graph, {}) - med_graph=self._parse_tf_graph(nodes) - filter_graph={i:med_graph[i] for i in med_graph.keys() if med_graph[i]['ak_type'] is not None} + med_graph = self._parse_tf_graph(nodes) + filter_graph = {i: med_graph[i] for i in med_graph.keys() if med_graph[i]['ak_type'] is not None} for node in filter_graph.values(): - node['input']=[i for i in node['input'] if filter_graph.get(i['name']) is not None] + node['input'] = [i for i in node['input'] if filter_graph.get(i['name']) is not None] node['output'] = [i for i in node['output'] if filter_graph.get(i['name']) is not None] - return filter_graph \ No newline at end of file + return filter_graph diff --git a/tools/external_converter_v2/parser/kill_tf/parser_tf.py b/tools/external_converter_v2/parser/kill_tf/parser_tf.py index a62684340..7e800f2a3 100644 --- a/tools/external_converter_v2/parser/kill_tf/parser_tf.py +++ b/tools/external_converter_v2/parser/kill_tf/parser_tf.py @@ -6,52 +6,67 @@ import tensorflow as tf from parse_tf_2_med import ParseTF2Med from parse_med_2_ak import MedTransAK -from med_graph import MedGraphUtil,MedNodeUtil +from med_graph import MedGraphUtil, MedNodeUtil class TFParser: - def __init__(self, fluid_config_dict): - # anakin graph model io - # config info - self.ProtoPaths = fluid_config_dict['ProtoPaths'] - - self.OutPuts = fluid_config_dict['OutPuts'] - if self.OutPuts is not None: - self.OutPuts=[i for i in fluid_config_dict['OutPuts'].split(',')] - - self.med_trans_tool = MedTransAK() - self.input_count=0 - - def __call__(self): - med_graph = self._conver_tf_2_med() - if self.OutPuts is None: - self.OutPuts=MedGraphUtil.search_output_list(med_graph) - - MedGraphUtil.solve(med_graph) - anakin_graph = self._conver_med_2_anakin(med_graph) - return anakin_graph - - def _conver_tf_2_med(self): - parser = ParseTF2Med(self.ProtoPaths) - return parser.parse() - - def _add_protonode(self, ak_graph,med_node): - ak_type = med_node['ak_type'] - if ak_type is None: - return - nodeIO = NodeProtoIO() - nodeIO.set_name(med_node['name']) - self.med_trans_tool.map_med_2_ak(nodeIO,med_node) - ak_graph.add_node(nodeIO()) - if nodeIO().Op.name=='Input': - ak_graph.add_in(nodeIO().name) - - def _conver_med_2_anakin(self, med_graph): - anakin_graph = GraphProtoIO() - for node in med_graph.values(): - self._add_protonode(anakin_graph,node) - anakin_graph.format_edge_from_nodes() - for out_node_name in self.OutPuts: - anakin_graph.add_out('output_'+out_node_name,out_node_name) - return anakin_graph + def __init__(self, fluid_config_dict): + # anakin graph model io + # config info + self.ProtoPaths = fluid_config_dict['ProtoPaths'] + + self.OutPuts = fluid_config_dict['OutPuts'] + if self.OutPuts is not None: + self.OutPuts = [i for i in fluid_config_dict['OutPuts'].split(',')] + + self.med_trans_tool = MedTransAK() + self.input_count = 0 + + def __call__(self): + med_graph = self._conver_tf_2_med() + if self.OutPuts is None: + self.OutPuts = MedGraphUtil.search_output_list(med_graph) + + MedGraphUtil.solve(med_graph) + anakin_graph = self._conver_med_2_anakin(med_graph) + return anakin_graph + + def _conver_tf_2_med(self): + ''' + convert tf graph to med graph + :return: + ''' + parser = ParseTF2Med(self.ProtoPaths) + return parser.parse() + + def _add_protonode(self, ak_graph, med_node): + ''' + add protobuf node in ak graph + :param ak_graph: + :param med_node: + :return: + ''' + ak_type = med_node['ak_type'] + if ak_type is None: + return + nodeIO = NodeProtoIO() + nodeIO.set_name(med_node['name']) + self.med_trans_tool.map_med_2_ak(nodeIO, med_node) + ak_graph.add_node(nodeIO()) + if nodeIO().Op.name == 'Input': + ak_graph.add_in(nodeIO().name) + + def _conver_med_2_anakin(self, med_graph): + ''' + convert med graph to ak graph + :param med_graph: + :return: + ''' + anakin_graph = GraphProtoIO() + for node in med_graph.values(): + self._add_protonode(anakin_graph, node) + anakin_graph.format_edge_from_nodes() + for out_node_name in self.OutPuts: + anakin_graph.add_out('output_' + out_node_name, out_node_name) + return anakin_graph diff --git a/tools/external_converter_v2/parser/kill_tf/run_pb.py b/tools/external_converter_v2/parser/kill_tf/run_pb.py index 2b6d3a254..3dcaf77d6 100644 --- a/tools/external_converter_v2/parser/kill_tf/run_pb.py +++ b/tools/external_converter_v2/parser/kill_tf/run_pb.py @@ -1,25 +1,33 @@ import numpy as np from tf_util import TfUtil -def convert_name_tf2ak(tf_name,perfix='record_'): - ak_name=tf_name[:] - for index,x in enumerate(tf_name): - if x=='/': - ak_name=ak_name[:index]+'_'+ak_name[index+1:] - return perfix+ak_name -ak_work_space='/home/ljj/docker_mount_dev2/anakin2_developing_parser/build/' -# ak_work_space='/your/anakin/workspace' -output_compare_op=None +def convert_name_tf2ak(tf_name, perfix='record_'): + ''' + conver tf name to ak name + :param tf_name: + :param perfix: + :return: + ''' + ak_name = tf_name[:] + for index, x in enumerate(tf_name): + if x == '/': + ak_name = ak_name[:index] + '_' + ak_name[index + 1:] + return perfix + ak_name + + +ak_work_space = '/home/ljj/docker_mount_dev2/anakin2_developing_parser/build/' +# ak_work_space='/your/anakin/workspace' +output_compare_op = None # graph_path='./vgg_model/frozen_vgg_16_i.pb' # input_name='graph/input:0' # output_op='graph/vgg_16/fc8/BiasAdd' # output_compare_op='graph/vgg_16/fc8/convolution' -graph_path='./resnet_model/frozen_resnet_v1_50.pb' -input_name='graph/input:0' -output_op='graph/resnet_v1_50/predictions/Reshape_1' +graph_path = './resnet_model/frozen_resnet_v1_50.pb' +input_name = 'graph/input:0' +output_op = 'graph/resnet_v1_50/predictions/Reshape_1' # graph_path='./mobilnetv2/frozen_mobilnet_v2.pb' # input_name='graph/input:0' @@ -30,45 +38,44 @@ def convert_name_tf2ak(tf_name,perfix='record_'): # output_op='graph/InceptionV2/Predictions/Reshape_1' -is_compared=True -output_name=output_op+':0' +is_compared = True +output_name = output_op + ':0' if output_compare_op is None: - compare_path=ak_work_space+convert_name_tf2ak(output_op) + compare_path = ak_work_space + convert_name_tf2ak(output_op) else: - compare_path=ak_work_space+convert_name_tf2ak(output_compare_op) + compare_path = ak_work_space + convert_name_tf2ak(output_compare_op) np.random.seed(1234567) -x_location=ak_work_space+'input_x' -x_value=np.random.randn(1,224,224,3) -outs=TfUtil.tf_run_model(graph_path,{input_name:x_value},[output_name]) +x_location = ak_work_space + 'input_x' +x_value = np.random.randn(1, 224, 224, 3) +outs = TfUtil.tf_run_model(graph_path, {input_name: x_value}, [output_name]) import struct + with open(x_location, "wb") as file: - x_value_new=x_value.transpose((0,3,1,2)) + x_value_new = x_value.transpose((0, 3, 1, 2)) for value in x_value_new.flatten(): file.write(struct.pack('f', value)) if is_compared: - out=outs[0] - if len(out.shape)==4: - out=out.transpose((0,3,1,2)) + out = outs[0] + if len(out.shape) == 4: + out = out.transpose((0, 3, 1, 2)) else: - print('out shape :',out.shape) + print('out shape :', out.shape) print(out.flatten()[:10]) try: - with open(compare_path,'r')as file: - ans=[] + with open(compare_path, 'r')as file: + ans = [] for value_str in file.readlines(): ans.append(float(value_str.split(' ')[1])) - correct=out.flatten() - assert len(correct)==len(ans) + correct = out.flatten() + assert len(correct) == len(ans) for i in range(len(ans)): - if abs(ans[i]-correct[i])>0.0001 and abs(ans[i]-correct[i])/abs(correct[i])>0.0001: - print(i,'=',ans[i],'correct = ',correct[i]) + if abs(ans[i] - correct[i]) > 0.0001 and abs(ans[i] - correct[i]) / abs(correct[i]) > 0.0001: + print(i, '=', ans[i], 'correct = ', correct[i]) exit() print('passed') - except Exception,e: + except Exception, e: print(out) - print('can`t find file : '+compare_path) - - + print('can`t find file : ' + compare_path) diff --git a/tools/external_converter_v2/parser/kill_tf/run_pb_get_ckp.py b/tools/external_converter_v2/parser/kill_tf/run_pb_get_ckp.py index 38ca29178..d9816c8f8 100644 --- a/tools/external_converter_v2/parser/kill_tf/run_pb_get_ckp.py +++ b/tools/external_converter_v2/parser/kill_tf/run_pb_get_ckp.py @@ -11,12 +11,12 @@ # graph_path='./ease_model/graph.pb' # graph_path='./ease_model/frozen_mnist.pb' # graph_path='./vgg_model/frozen_vgg_16_i.pb' -graph_path='./inception_model/inception_v2_inf_graph.pb' -cpkt_path='./inception_model/' +graph_path = './inception_model/inception_v2_inf_graph.pb' +cpkt_path = './inception_model/' # graph_path='./resnet_model/frozen_resnet_v1_50.pb' -sess=tf.Session() +sess = tf.Session() if graph_path.endswith('.pbtxt'): input_binary = False else: @@ -35,17 +35,17 @@ tf.train.import_meta_graph(graph_path, clear_devices=True) tf.import_graph_def(graph_def, name='graph') -sess=tf.Session(graph=graph) +sess = tf.Session(graph=graph) x = graph.get_tensor_by_name('graph/input:0') y = graph.get_tensor_by_name('graph/InceptionV2/Predictions/Reshape_1:0') for var in tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES): - print(var.name) -init_table=tf.tables_initializer() + print(var.name) +init_table = tf.tables_initializer() sess.run(init_table) -init=tf.global_variables_initializer() +init = tf.global_variables_initializer() sess.run(init) -out=sess.run(y,{x:np.ones((1,224,224,3))}) +out = sess.run(y, {x: np.ones((1, 224, 224, 3))}) saver = tf.train.Saver() -saver.save(sess, cpkt_path+'/model.cpkt') \ No newline at end of file +saver.save(sess, cpkt_path + '/model.cpkt') diff --git a/tools/external_converter_v2/parser/kill_tf/summary.py b/tools/external_converter_v2/parser/kill_tf/summary.py index 5edcb8358..cc1eac454 100644 --- a/tools/external_converter_v2/parser/kill_tf/summary.py +++ b/tools/external_converter_v2/parser/kill_tf/summary.py @@ -12,15 +12,21 @@ from tensorflow.python.platform import gfile - # graph_path = './resnet_v1_50_graph.pb' # graph_path = './frozen_graph.pb' # graph_path='./vgg_model/frozen_vgg_16_i.pb' # graph_path='./inception_model/frozen_inception_v2.pb' -graph_path='./resnet_model/frozen_resnet_v1_50.pb' +graph_path = './resnet_model/frozen_resnet_v1_50.pb' + + # graph_path='./mobilnetv2/frozen_mobilnet_v2.pb' def get_graph(graph_path): + ''' + get tensor board graph from pb file or meta file + :param graph_path: + :return: + ''' if graph_path.endswith('.pbtxt'): input_binary = False else: @@ -41,5 +47,5 @@ def get_graph(graph_path): return graph -graph=get_graph(graph_path) -summaryWriter = tf.summary.FileWriter('log/', graph) \ No newline at end of file +graph = get_graph(graph_path) +summaryWriter = tf.summary.FileWriter('log/', graph) diff --git a/tools/external_converter_v2/parser/kill_tf/tf_trans_util.py b/tools/external_converter_v2/parser/kill_tf/tf_trans_util.py index cc8a48823..581a313bc 100644 --- a/tools/external_converter_v2/parser/kill_tf/tf_trans_util.py +++ b/tools/external_converter_v2/parser/kill_tf/tf_trans_util.py @@ -2,7 +2,7 @@ import numpy as np from tensorflow.core.framework import types_pb2, tensor_pb2 from google.protobuf import text_format -from med_graph import MedNodeUtil,MedGraphUtil +from med_graph import MedNodeUtil, MedGraphUtil TF_TO_ANAKIN_DTYPE = { types_pb2.DT_FLOAT: np.float32, @@ -62,6 +62,11 @@ def get_tf_tensor_data(tensor): def map_tf_dtype(dtype): + ''' + wraper for TF_TO_ANAKIN_DTYPE + :param dtype: + :return: + ''' return TF_TO_ANAKIN_DTYPE.get(dtype) @@ -92,9 +97,9 @@ def tf_to_anakin_tensor(tensor): if dims == [0]: dims = [1] is_raw, data = get_tf_tensor_data(tensor) - dim_size=1 + dim_size = 1 for i in dims: - dim_size*=i + dim_size *= i # print(type(data),data,tensor.dtype,is_raw) if is_raw: if len(dims) > 0: @@ -103,14 +108,19 @@ def tf_to_anakin_tensor(tensor): else: anakin_tensor = np.zeros(0) return anakin_tensor - elif dim_size >1 and len(data)==1: + elif dim_size > 1 and len(data) == 1: - return np.array([data]*dim_size).reshape(dims) + return np.array([data] * dim_size).reshape(dims) else: return data def load_graph(graph_path): + ''' + load tensorflow graph + :param graph_path: + :return: + ''' if graph_path.endswith('.pbtxt'): input_binary = False else: @@ -138,6 +148,12 @@ def load_graph(graph_path): def spatial_map(shape, perm): + ''' + convert shape in different layout + :param shape: + :param perm: + :return: + ''' # print('HI ',type(shape),shape) new_shape = shape[:] for i in perm: @@ -146,6 +162,12 @@ def spatial_map(shape, perm): def trans_move_attr(attr, format): + ''' + get h,w shape from attr + :param attr: + :param format: + :return: + ''' if attr is None: return attr if len(attr) == 2: @@ -158,24 +180,40 @@ def trans_move_attr(attr, format): raise Exception('not support format ' + format) return [h, w] -def add_special_pad(padding,tf_node,graph): + +def add_special_pad(padding, tf_node, graph): + ''' + add pad op to solve different pad method in caffe and tensorflow + :param padding: + :param tf_node: + :param graph: + :return: + ''' # print(tf_node['name']) - assert len(tf_node['input'])<=2 - now_shape=tf_node['input'][0]['shape'] - tar_shape =now_shape[:] - tar_shape[1]=now_shape[1]+padding[0]+padding[1] + assert len(tf_node['input']) <= 2 + now_shape = tf_node['input'][0]['shape'] + tar_shape = now_shape[:] + tar_shape[1] = now_shape[1] + padding[0] + padding[1] tar_shape[2] = now_shape[2] + padding[2] + padding[3] tf_name = tf_node['name'] - padding_node={'name':tf_node['name']+'_pad','ak_type':'Pad','type':None,'visted':True, - 'ak_attr':{'pad_c':[0,0],'pad_h':[padding[0],padding[1]],'pad_w':[padding[2],padding[3]]}, - 'input':[tf_node['input'][0]],'output':[{'name':tf_name,'shape':tar_shape}]} + padding_node = {'name': tf_node['name'] + '_pad', 'ak_type': 'Pad', 'type': None, 'visted': True, + 'ak_attr': {'pad_c': [0, 0], 'pad_h': [padding[0], padding[1]], 'pad_w': [padding[2], padding[3]]}, + 'input': [tf_node['input'][0]], 'output': [{'name': tf_name, 'shape': tar_shape}]} + + input_0 = graph[tf_node['input'][0]['name']] + input_0['output'] = MedNodeUtil.replace_name_with_list(input_0['output'], tf_name, + [{'name': padding_node['name'], 'shape': now_shape}]) + tf_node['input'][0] = {'name': padding_node['name'], 'shape': tar_shape} + graph[padding_node['name']] = padding_node - input_0=graph[tf_node['input'][0]['name']] - input_0['output']=MedNodeUtil.replace_name_with_list(input_0['output'],tf_name,[{'name':padding_node['name'],'shape':now_shape}]) - tf_node['input'][0]={'name':padding_node['name'],'shape':tar_shape} - graph[padding_node['name']]=padding_node def parse_Identity(tf_node, graph): + ''' + remove identity in tensorflow graph + :param tf_node: + :param graph: + :return: + ''' tf_node['visted'] = True outputs = tf_node['output'] input_0 = tf_node['input'][0] @@ -189,6 +227,12 @@ def parse_Identity(tf_node, graph): def parse_Shape(tf_node, graph): + ''' + parse shape for tensorflow graph + :param tf_node: + :param graph: + :return: + ''' assert len(tf_node['input']) == 1 tf_node['type'] = 'Const' tf_node['tf_attr']['value'] = tf_node['input'][0]['shape'] @@ -196,6 +240,12 @@ def parse_Shape(tf_node, graph): def parse_Squeeze(tf_node, graph): + ''' + convert squeeze to reshape + :param tf_node: + :param graph: + :return: + ''' tf_node['visted'] = True tf_node['ak_type'] = 'Reshape' tf_node['ak_attr']['shape'] = tf_node['output'][0]['shape'] @@ -203,30 +253,54 @@ def parse_Squeeze(tf_node, graph): def parse_Placeholder(tf_node, graph): + ''' + conver placeholder to input op + :param tf_node: + :param graph: + :return: + ''' tf_node['visted'] = True tf_node['ak_type'] = 'Input' tf_node['ak_attr']['shape'] = spatial_map(tf_node['output'][0]['shape'], NHWC_TO_NCHW) def parse_Pad(tf_node, graph): + ''' + convert pad op + :param tf_node: + :param graph: + :return: + ''' tf_node['visted'] = True tf_node['ak_type'] = 'Pad' pad_shape_node = graph[tf_node['input'][1]['name']] assert pad_shape_node['type'] == 'Const' - pad_shape=pad_shape_node['tf_attr']['value'] - ak_attr=tf_node['ak_attr'] + pad_shape = pad_shape_node['tf_attr']['value'] + ak_attr = tf_node['ak_attr'] ak_attr['pad_c'] = pad_shape[3].flatten().tolist() ak_attr['pad_h'] = pad_shape[1].flatten().tolist() ak_attr['pad_w'] = pad_shape[2].flatten().tolist() def parse_Softmax(tf_node, graph): + ''' + convert softmax op, default axis is 3 + :param tf_node: + :param graph: + :return: + ''' tf_node['visted'] = True tf_node['ak_type'] = 'Softmax' - tf_node['ak_attr']['axis']=3 + tf_node['ak_attr']['axis'] = 3 def parse_Reshape(tf_node, graph): + ''' + convert reshape op + :param tf_node: + :param graph: + :return: + ''' tf_node['visted'] = True tf_node['ak_type'] = 'Reshape' shape = graph[tf_node['input'][1]['name']] @@ -238,9 +312,15 @@ def parse_Reshape(tf_node, graph): def parse_Act(tf_node, graph): + ''' + convert activate op + :param tf_node: + :param graph: + :return: + ''' tf_node['visted'] = True tf_node['ak_type'] = 'Activation' - if tf_node['type'] == 'Relu' : + if tf_node['type'] == 'Relu': tf_node['ak_type'] = 'Relu' tf_node['ak_attr']['type'] = 'Relu' elif tf_node['type'] == 'Relu6': @@ -252,16 +332,28 @@ def parse_Act(tf_node, graph): def parse_Concat(tf_node, graph): + ''' + convert concat op + :param tf_node: + :param graph: + :return: + ''' tf_node['visted'] = True tf_node['ak_type'] = 'Concat' N = tf_node['tf_attr']['N'] axis_node = graph[tf_node['input'][N]['name']] assert axis_node['type'] == 'Const' - nhwc2hchw={0:0,1:2,2:3,3:1} + nhwc2hchw = {0: 0, 1: 2, 2: 3, 3: 1} tf_node['ak_attr']['axis'] = nhwc2hchw[axis_node['tf_attr']['value'][0]] def parse_Add(tf_node, graph): + ''' + convert add op + :param tf_node: + :param graph: + :return: + ''' tf_node['visted'] = True assert len(tf_node['input']) == 2 input_0 = graph[tf_node['input'][0]['name']] @@ -278,33 +370,47 @@ def parse_Add(tf_node, graph): tf_node['ak_type'] = 'Eltwise' ak_attr['type'] = 'Add' + def parse_Mean(tf_node, graph): + ''' + convert mean op to pooling op + :param tf_node: + :param graph: + :return: + ''' tf_node['visted'] = True tf_node['ak_type'] = 'Pooling' ak_attr = tf_node['ak_attr'] tf_attr = tf_node['tf_attr'] - ak_attr['type']='AVG' - reduction_shape=None - keep_dims=tf_attr['keep_dims'] - - if len(tf_node['input'])>1: - reduction_shape_node=graph[tf_node['input'][1]['name']] - assert reduction_shape_node['type']=='Const' - reduction_shape=reduction_shape_node['tf_attr']['value'].flatten().tolist() + ak_attr['type'] = 'AVG' + reduction_shape = None + keep_dims = tf_attr['keep_dims'] + + if len(tf_node['input']) > 1: + reduction_shape_node = graph[tf_node['input'][1]['name']] + assert reduction_shape_node['type'] == 'Const' + reduction_shape = reduction_shape_node['tf_attr']['value'].flatten().tolist() assert reduction_shape is not None assert keep_dims is True - assert reduction_shape == [1,2] - ak_attr['strides'] = [1,1] - ak_attr['window'] = [tf_node['input'][0]['shape'][reduction_shape[0]],tf_node['input'][0]['shape'][reduction_shape[1]]] - ak_attr['padding'] = [0,0] + assert reduction_shape == [1, 2] + ak_attr['strides'] = [1, 1] + ak_attr['window'] = [tf_node['input'][0]['shape'][reduction_shape[0]], + tf_node['input'][0]['shape'][reduction_shape[1]]] + ak_attr['padding'] = [0, 0] def parse_Pooling(tf_node, graph): + ''' + convert pooling op + :param tf_node: + :param graph: + :return: + ''' tf_node['visted'] = True tf_node['ak_type'] = 'Pooling' ak_attr = tf_node['ak_attr'] tf_attr = tf_node['tf_attr'] - #TODO TF default pad is exclusive method + # TODO TF default pad is exclusive method map_tf_pool = {'MaxPool': 'MAX', 'AvgPool': 'AVGEXC'} @@ -322,26 +428,38 @@ def parse_Pooling(tf_node, graph): padding = cal_padding(padding, kernel_shape, strides, dilations, data_format, tf_node['input'][0]['shape'], tf_node['output'][0]['shape']) - if padding[0]!=padding[1] or padding[2]!=padding[3]: - add_special_pad(padding,tf_node,graph) - padding=[0,0] + if padding[0] != padding[1] or padding[2] != padding[3]: + add_special_pad(padding, tf_node, graph) + padding = [0, 0] else: - padding=[padding[0],padding[2]] + padding = [padding[0], padding[2]] ak_attr['window'] = kernel_shape ak_attr['padding'] = padding ak_attr['strides'] = strides - ak_attr['cmp_out_shape_floor_as_conv']=True + ak_attr['cmp_out_shape_floor_as_conv'] = True def cal_padding(padding, kernel_shape, strides, dilations, data_format, input_shape, output_shape, spatial=2): - pads = [0] * spatial*2 + ''' + convert pad string to pad list + :param padding: + :param kernel_shape: + :param strides: + :param dilations: + :param data_format: + :param input_shape: + :param output_shape: + :param spatial: + :return: + ''' + pads = [0] * spatial * 2 if type(padding) == bytes: padding = padding.decode() if dilations is None: dilations = [1] * spatial * 2 if padding == 'SAME': - pads = [0] * spatial*2 + pads = [0] * spatial * 2 if data_format == 'NHWC': # print('in out shape = ',input_shape,output_shape) input_shape = spatial_map(input_shape, NHWC_TO_NCHW) @@ -353,7 +471,7 @@ def cal_padding(padding, kernel_shape, strides, dilations, data_format, input_sh pad = max(pad, 0) pads1 = pad // 2 pads2 = pad - pad // 2 - pads[i*2+0]=pads1 + pads[i * 2 + 0] = pads1 pads[i * 2 + 1] = pads2 return pads elif padding == 'VALID': @@ -363,6 +481,12 @@ def cal_padding(padding, kernel_shape, strides, dilations, data_format, input_sh def get_const_from_biinput(inputs, graph): + ''' + search const input of node`s input + :param inputs: + :param graph: + :return: + ''' assert len(inputs) <= 2 input_0 = graph[inputs[0]['name']] input_1 = graph[inputs[1]['name']] @@ -374,6 +498,12 @@ def get_const_from_biinput(inputs, graph): def get_bias(tf_node, graph): + ''' + try to fetch const value form node + :param tf_node: + :param graph: + :return: + ''' bias_weight = None output = tf_node['output'] output_0 = graph[output[0]['name']] @@ -383,12 +513,18 @@ def get_bias(tf_node, graph): if bias_weight is not None: output_0['visted'] = True tf_node['output'] = output_0['output'] - MedNodeUtil.redirecto_outputs_input_to_this(output_0,graph,tf_node['name'],output[0]['shape']) + MedNodeUtil.redirecto_outputs_input_to_this(output_0, graph, tf_node['name'], output[0]['shape']) return bias_weight def parse_Conv2D(tf_node, graph): + ''' + convert conv2D to convolution + :param tf_node: + :param graph: + :return: + ''' tf_node['visted'] = True tf_node['ak_type'] = 'Convolution' weights_node = graph[tf_node['input'][1]['name']] @@ -407,18 +543,18 @@ def parse_Conv2D(tf_node, graph): # print('name ',tf_node['name'],input_node['name'],input_node['out_shape']) padding = cal_padding(padding, kernel_shape, strides, dilations, data_format, tf_node['input'][0]['shape'], tf_node['output'][0]['shape']) - if padding[0]!=padding[1] or padding[2]!=padding[3]: - add_special_pad(padding,tf_node,graph) - padding=[0,0] + if padding[0] != padding[1] or padding[2] != padding[3]: + add_special_pad(padding, tf_node, graph) + padding = [0, 0] else: - padding=[padding[0],padding[2]] + padding = [padding[0], padding[2]] group = 1 if tf_node['type'] == 'DepthwiseConv2dNative': weights = weights.transpose((1, 0, 2, 3)) group = weights.shape[0] - out_c=weights.shape[0]*weights.shape[1] - weights=weights.reshape(out_c,1,weights.shape[2],weights.shape[3]) + out_c = weights.shape[0] * weights.shape[1] + weights = weights.reshape(out_c, 1, weights.shape[2], weights.shape[3]) ak_attr = tf_node['ak_attr'] ak_attr['weights'] = weights @@ -431,6 +567,12 @@ def parse_Conv2D(tf_node, graph): def parse_MatMul(tf_node, graph): + ''' + convert matmul to dense + :param tf_node: + :param graph: + :return: + ''' tf_node['visted'] = True tf_node['ak_type'] = 'Dense' in_name_0 = tf_node['input'][0]['name'] @@ -457,6 +599,12 @@ def parse_MatMul(tf_node, graph): def parse_fusionReshape(tf_node, graph): + ''' + convert reshape + :param tf_node: + :param graph: + :return: + ''' assert tf_node['type'] == 'Reshape' input_0 = graph[tf_node['input'][0]['name']] input_1 = graph[tf_node['input'][1]['name']] @@ -472,6 +620,7 @@ def parse_fusionReshape(tf_node, graph): def parse_CustmerBatchNorm(tf_node, graph): + '''convert user custmer batchnorm to scale''' assert tf_node['type'] == 'Rsqrt' assert len(tf_node['input']) == 1 and len(tf_node['output']) == 1 rsqrt_mul_node = graph[tf_node['output'][0]['name']] @@ -485,7 +634,7 @@ def parse_CustmerBatchNorm(tf_node, graph): var_value = var_node['tf_attr']['value'].flatten() assert rsqrt_mul_node['type'] == 'Mul' and len(rsqrt_mul_node['input']) == 2 and len(rsqrt_mul_node['output']) == 2 const_mul_node_input_1 = graph[rsqrt_mul_node['input'][1]['name']] - if MedGraphUtil.check_one_of_input_is_const(graph[rsqrt_mul_node['output'][0]['name']],graph): + if MedGraphUtil.check_one_of_input_is_const(graph[rsqrt_mul_node['output'][0]['name']], graph): mul_mul_1_node = graph[rsqrt_mul_node['output'][1]['name']] mul_mul_2_node = graph[rsqrt_mul_node['output'][0]['name']] else: @@ -503,7 +652,7 @@ def parse_CustmerBatchNorm(tf_node, graph): assert mul_add_node['type'] == 'Add' and mul2_sub_node['type'] == 'Sub' and mean_node['type'] == 'Const' beta_node = graph[mul2_sub_node['input'][0]['name']] - assert beta_node['type']=='Const' + assert beta_node['type'] == 'Const' beta_value = beta_node['tf_attr']['value'].flatten() mean_value = mean_node['tf_attr']['value'].flatten() assert mul_add_node['input'][1]['name'] == mul2_sub_node['name'] @@ -518,13 +667,14 @@ def parse_CustmerBatchNorm(tf_node, graph): var = np.sqrt(var_value + epse_value) np_scale = alpha_value / var - np_bias = beta_value -np_scale * mean_value + np_bias = beta_value - np_scale * mean_value mul_mul_1_node['output'] = mul_add_node['output'] mul_mul_1_node['type'] = 'CustomerBN' mul_mul_1_node['ak_type'] = 'Scale' MedNodeUtil.retain_input(mul_mul_1_node, [mul_mul_1_node['input'][0]]) - MedNodeUtil.redirecto_outputs_input_to_this(mul_add_node,graph,mul_mul_1_node['name'],mul_mul_1_node['output'][0]['shape']) + MedNodeUtil.redirecto_outputs_input_to_this(mul_add_node, graph, mul_mul_1_node['name'], + mul_mul_1_node['output'][0]['shape']) ak_attr = mul_mul_1_node['ak_attr'] ak_attr['scale_weights'] = np_scale.astype('float32') ak_attr['bias_weights'] = np_bias.astype('float32') @@ -532,6 +682,12 @@ def parse_CustmerBatchNorm(tf_node, graph): def parse_BatchNorm(tf_node, graph): + ''' + convert fused batchnorm to scale + :param tf_node: + :param graph: + :return: + ''' tf_node['visted'] = True tf_node['ak_type'] = 'Scale' assert len(tf_node['input']) == 5 @@ -556,4 +712,4 @@ def parse_BatchNorm(tf_node, graph): ak_attr['scale_weights'] = np_scale.astype('float32') ak_attr['bias_weights'] = np_bias.astype('float32') - MedNodeUtil.retain_input(tf_node, [tf_node['input'][0]]) \ No newline at end of file + MedNodeUtil.retain_input(tf_node, [tf_node['input'][0]]) diff --git a/tools/external_converter_v2/parser/kill_tf/tf_util.py b/tools/external_converter_v2/parser/kill_tf/tf_util.py index 8baed082d..b8dfe78d9 100644 --- a/tools/external_converter_v2/parser/kill_tf/tf_util.py +++ b/tools/external_converter_v2/parser/kill_tf/tf_util.py @@ -3,9 +3,17 @@ from google.protobuf import text_format import numpy as np + class TfUtil: @staticmethod def tf_run_model(graph_path, inputs, output_tensor_list): + ''' + fill inputs, run tensorflow mode and fetch output in output_tensor_list + :param graph_path: + :param inputs: + :param output_tensor_list: + :return: + ''' sess = tf.Session() if graph_path.endswith('.pbtxt'): input_binary = False @@ -30,4 +38,4 @@ def tf_run_model(graph_path, inputs, output_tensor_list): output_list = [graph.get_tensor_by_name(i) for i in output_tensor_list] print(output_list) out = sess.run(output_list, inputs_dict) - return out \ No newline at end of file + return out From 9654a5fbe1e3bcaef691e397d1cd20b002c3d220 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Tue, 4 Sep 2018 19:49:24 +0800 Subject: [PATCH 15/51] add norm op --- .../parser/kill_caffe/caffe_layer_param_transmit.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/external_converter_v2/parser/kill_caffe/caffe_layer_param_transmit.py b/tools/external_converter_v2/parser/kill_caffe/caffe_layer_param_transmit.py index 7ebacc803..f0f4983fe 100755 --- a/tools/external_converter_v2/parser/kill_caffe/caffe_layer_param_transmit.py +++ b/tools/external_converter_v2/parser/kill_caffe/caffe_layer_param_transmit.py @@ -1218,5 +1218,6 @@ def Parser_relu6(args): "Normalize": OpsParam().set_parser(Parser_normalize), "Resize": OpsParam().set_parser(Parser_resize), "ReLU6": OpsParam().set_parser(Parser_relu6), + "Normalization": OpsParam().set_parser(Parser_normalize), "ShuffleChannel": OpsParam().set_parser(Parser_ShuffleChannel) } From be97324ab51fea3682ef0bd90fdb2a0f9d2b673e Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Wed, 5 Sep 2018 13:42:41 +0800 Subject: [PATCH 16/51] add split_inception --- .../parser/kill_caffe/parser_caffe.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py index f91103958..f8e5bb397 100644 --- a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py +++ b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py @@ -40,13 +40,13 @@ def _DetectionArch(self): self._ParserPrototxt() self._UpgradeNetAsNeeded() self._FilterNet() - #self._SplitInception(False) + self._SplitInception(False) self._InsertSplits() self._ScatterInputLayer() # create input node #self._CreateInputNode() maybe not need - ''' + def _SplitInception(self, is_weight): print is_weight net = self.net_parameter @@ -181,7 +181,7 @@ def _SplitInception(self, is_weight): if self.net_parameter.layer: del self.net_parameter.layer[:] self.net_parameter.layer.extend(new_layers) - ''' + def _ParserPrototxt(self): """ @@ -486,7 +486,7 @@ def _Parsing_new(self): # parsing model logger(verbose.ERROR).feed(" [CAFFE] Model Parameter Parsing ...") self._ParserModel() - self._SplitInception(True) + #self._SplitInception(True) model_layers = self.net_param_weights.layers or self.net_param_weights.layer # we must setting graph edge first @@ -607,7 +607,7 @@ def _Parsing(self): # parsing model logger(verbose.ERROR).feed(" [CAFFE] Model Parameter Parsing ...") self._ParserModel() - #self._SplitInception(True) + self._SplitInception(True) model_layers = self.net_param_weights.layers or self.net_param_weights.layer for idx, rlayer in enumerate(real_layers): source_layer_name = rlayer.name From 01eab8b2234c91520cb7be71154057550eb32ca3 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Wed, 5 Sep 2018 13:45:21 +0800 Subject: [PATCH 17/51] add parse_inceptrion --- tools/external_converter_v2/parser/kill_caffe/parser_caffe.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py index f8e5bb397..bc406e920 100644 --- a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py +++ b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py @@ -486,7 +486,7 @@ def _Parsing_new(self): # parsing model logger(verbose.ERROR).feed(" [CAFFE] Model Parameter Parsing ...") self._ParserModel() - #self._SplitInception(True) + self._SplitInception(True) model_layers = self.net_param_weights.layers or self.net_param_weights.layer # we must setting graph edge first @@ -607,7 +607,7 @@ def _Parsing(self): # parsing model logger(verbose.ERROR).feed(" [CAFFE] Model Parameter Parsing ...") self._ParserModel() - self._SplitInception(True) + #self._SplitInception(True) model_layers = self.net_param_weights.layers or self.net_param_weights.layer for idx, rlayer in enumerate(real_layers): source_layer_name = rlayer.name From d5f400c25f85c3b252e37e3ff55281785ccf5d00 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Wed, 5 Sep 2018 14:42:36 +0800 Subject: [PATCH 18/51] update parser --- tools/external_converter_v2/parser/kill_caffe/parser_caffe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py index bc406e920..21f802426 100644 --- a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py +++ b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py @@ -36,11 +36,11 @@ def __call__(self): def _DetectionArch(self): """ """ - self._InsSplitBtwSliceConcat() self._ParserPrototxt() self._UpgradeNetAsNeeded() self._FilterNet() self._SplitInception(False) + self._InsSplitBtwSliceConcat() self._InsertSplits() self._ScatterInputLayer() # create input node From cff87b4ef208b1f8737137fc02979ed0b4f88d9a Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Wed, 5 Sep 2018 15:23:33 +0800 Subject: [PATCH 19/51] update parser --- tools/external_converter_v2/parser/kill_caffe/parser_caffe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py index 21f802426..8080ed50c 100644 --- a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py +++ b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py @@ -40,7 +40,7 @@ def _DetectionArch(self): self._UpgradeNetAsNeeded() self._FilterNet() self._SplitInception(False) - self._InsSplitBtwSliceConcat() + self._InsSplitBtwSliceConcat() self._InsertSplits() self._ScatterInputLayer() # create input node From a9d626e16ddcfe15403fbdca7951553eda6ac548 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Wed, 5 Sep 2018 15:23:42 +0800 Subject: [PATCH 20/51] update parser --- tools/external_converter_v2/parser/kill_caffe/parser_caffe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py index 8080ed50c..21f802426 100644 --- a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py +++ b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py @@ -40,7 +40,7 @@ def _DetectionArch(self): self._UpgradeNetAsNeeded() self._FilterNet() self._SplitInception(False) - self._InsSplitBtwSliceConcat() + self._InsSplitBtwSliceConcat() self._InsertSplits() self._ScatterInputLayer() # create input node From 46261a2639bf430febee03c8129ac6b9c6e74de7 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Wed, 5 Sep 2018 23:07:18 +0800 Subject: [PATCH 21/51] update caffe parser --- .../parser/kill_caffe/parser_caffe.py | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py index 21f802426..9258ed04b 100644 --- a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py +++ b/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py @@ -227,7 +227,7 @@ def _UpgradeNetAsNeeded(self): logger(verbose.FATAL).feed("[ Upgrade Level 3 ] Details: need to upgrade from V1 to V2 [ FAILED ]") exit() if NetNeedsInputUpgrade(self.net_parameter): - logger(verbose.INFO).feed("[ Upgrade Level 4 ] Details: need Input upgrade [ ... ]") + logger(verbose.INFO).feed("[ Upgrade Level 4 ] Details: need Input upgrade [ ... ]") UpgradeNetInput(self.net_parameter) logger(verbose.WARNING).feed("[ Upgrade Level 4 ] Details: need Input upgrade [ SUC ]") if NetNeedsBatchNormUpgrade(self.net_parameter): @@ -239,26 +239,34 @@ def _InsSplitBtwSliceConcat(self): ''' Currently, the connection between Slice and Concat must be implemented via Split. ''' - param_split = NetParameter() layers = self.net_parameter.layer or self.net_parameter.layers top_blobs_of_slices = list() btm_blobs_of_concats = list() - for idx, layer in enumerate(layers): + for layer in layers: if layer.type == 'Slice': - top_blobs_of_slices.extend(layer.top) + top_blobs_of_slices.extend(layer.top) elif layer.type == 'Concat': btm_blobs_of_concats.extend(layer.bottom) intersection_blobs = list(set(top_blobs_of_slices).intersection(set(btm_blobs_of_concats))) - for blob in intersection_blobs: - layer_param = param_split.layer.add() - layer_param.bottom.append(blob) - layer_param.top.append(blob) - layer_param.name = 'Split_' + blob - layer_param.type = 'Split' + new_param = NetParameter() + for layer in layers: + new_layer = new_param.layer.add() + new_layer.CopyFrom(layer) + if layer.type == 'Slice': + for top_blob in layer.top: + if top_blob in intersection_blobs: + split_param = new_param.layer.add() + split_param.bottom.append(top_blob) + split_param.top.append(top_blob) + split_param.name = 'Split_' + top_blob + split_param.type = 'Split' if self.net_parameter.layer: - self.net_parameter.layer.extend(param_split.layer) + del self.net_parameter.layer[:] + self.net_parameter.layer.extend(new_param.layer) else: - self.net_parameter.layers.extend(param_split.layer) + del self.net_parameter.layers[:] + self.net_parameter.layers.extend(new_param.layer) + def _InsertSplits(self): """ @@ -283,7 +291,7 @@ def _InsertSplits(self): layer_idx_to_name[idx] = layer.name for j, btm in enumerate(layer.bottom): if btm not in self.blob_name_to_last_top_idx.keys(): - logger(verbose.FATAL).feed("Unknown bottom (blob: %s) in (layer: '%s')" % (btm, layer.name)) + logger(verbose.FATAL).feed("Unknown bottom (blob: %s) in (layer: '%s')" % (btm, layer.name)) exit() bottom_idx = (idx, j) top_idx = self.blob_name_to_last_top_idx[btm] From 4a13b9dd19226fe41196a2fc6eb442e107f74e48 Mon Sep 17 00:00:00 2001 From: luotao1 Date: Thu, 6 Sep 2018 14:03:23 +0800 Subject: [PATCH 22/51] remove a lot of warning --- cmake/compiler_options.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/compiler_options.cmake b/cmake/compiler_options.cmake index 6d0881545..835b7d884 100644 --- a/cmake/compiler_options.cmake +++ b/cmake/compiler_options.cmake @@ -41,6 +41,8 @@ anakin_add_compile_option(-Wshadow) anakin_add_compile_option(-fpermissive) anakin_add_compile_option(-Wsign-promo) anakin_add_compile_option(-fdiagnostics-show-option) +anakin_add_compile_option(-Wno-missing-field-initializers) +anakin_add_compile_option(-Wno-extra) if(ENABLE_NOISY_WARNINGS) anakin_add_compile_option(-Wcast-align) From 6470a5ecaf492cb6143959bac66139879eba0d63 Mon Sep 17 00:00:00 2001 From: liujunjie Date: Thu, 6 Sep 2018 15:38:48 +0800 Subject: [PATCH 23/51] add converter design doc --- docs/Manual/DesignConverter_ch.md | 56 +++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 docs/Manual/DesignConverter_ch.md diff --git a/docs/Manual/DesignConverter_ch.md b/docs/Manual/DesignConverter_ch.md new file mode 100644 index 000000000..139f46c2a --- /dev/null +++ b/docs/Manual/DesignConverter_ch.md @@ -0,0 +1,56 @@ +# Parser的编写指南 +下文称Anakin为AK,运算操作为OP,本文参考Tensorflow的Parser编写,参考代码目录为tools/external_converter_v2/parser/kill_tf +## Parser的功能和执行流程 +功能是将其他深度学习框架(如CAFFE,FLUID,TENSORFLOW,ONNEX)的模型转换为AK的模型.对AK的作用是屏蔽不同框架间的差异,这种差异包括模型存储、OP的定义、图差异 +因此Parser的执行流程是: +1. 将源框架的模型载入Parser +2. 将原框架的图解析为AK中的OP节点和OP节点的连接关系 +3. 进行OP定义的转换和图优化 +4. 将符合AK标准的图写入protobuf +## Parser的目录结构 +Parser工具在tools/external_converter_v2/parser目录下 +Parser的目录主要包含3部分: +1. Parser的运行配置文件包括 config.py, config.yaml, converter.py, 用户只用执行converter.py,Parser就会按照config.yaml中的声明去解析模型 +2. Parser的公共定义,包括operations,pbs,proto三个目录. Parser的公共工具函数 graph*.py logger.py utils.py +3. 各个框架对应的Parser,其目录的命名方式为kill_*,如kill_caffe +## Parser的编写流程 +### 1、声明你的Parser +1. 在config.yaml中填写你的Parser运行的必要信息,包括ProtoPath和SavePath等.OPTIONS/Framework改为你的Parser的类型,TARGET下填写对应的参数列表 +2. 添加你的Parser目录,如kill_tf,导出你的Parser符号.注意,Parser的框架默认调用你的Parser类中的__call__方法来执行解析,这个方法需要返回填写完毕的GraphProtoIO对象 +3. 在config.py中Configuration下__init__函数中增加对你的Parser的调用,将yaml中读取的配置信息传给你的Parser,此处调用你的Parser中的__init__方法 +### 2、添加你的Parser主体 +可以参考parser_tf.py +1. 你需要在Parser主体构造时获取模型路径,input,ouput名字等解析必须的信息, +2. 在__call__中返回填写好的GraphProtoIO对象,该对象为填写protobuf的辅助工具 +3. 建议Parser的解析过程分成三部分,先将原框架的模型载入并转换为一种便于修改的中间的图形式;对中间图修改使得图满足AK的要求;将满足要求的中间图利用NodeProtoIO和GraphProtoIO这两个辅助类填入protobuf.具体细节可以参考parser_tf +### 3、读取原始模型,并将模型转换为中间类型 +可以参考parse_tf_2_med.py +1. 这一步与原始框架结合紧密,你可能需要import原始框架的工具函数来完成模型的裁剪、固定、加载等操作 +2. 大部分的框架都是使用tensor来连接OP的,但AK中是OP直接相连,这点需要注意 +3. AK的shape默认是4维的,有的参数的shape不足4维,需要Parser补全 +### 4、对中间类型的图进行优化 +可以参考med_graph.py +1. 由于AK不支持普通OP多输出的情况,需要在多输出的OP后面补上Splite类型的OP节点 +2. 对于Convlution后接Batchnorm这种可以合并又不会导致OP定义改变的情况,需要Parser在这一步做掉 +3. AK规定所有的输入类型OP的名字必须是input_x这种命名方式,其中x为从0开始的数字 +### 5、将中间类型的图以GraphProtoIO的方式保存 +可以参考parse_med_2_ak.py 和 parser_tf.py +1. 你首先需要构造Node节点,Node节点的名字是OP的名字(如conv2d_1_a_0),Node节点中OP成员变量的名字是Node节点的类型(如Convlution) +2. Node节点需要按照输入的顺序用Node的add_in方法填写输入Node的名字,add_out方法按顺序填写输出Node的名字 +3. 通过调用GraphProtoIO的add_node方法将构造好的Node的__call__方法的返回值作为参数,将Node节点加入AK的graph中 +4. 调用GraphProtoIO的add_in_edge和add_out_edge完成AK图中OP间关系的构建. 如果Node中的in和out填写正确,你也可以通过调用GraphProtoIO的format_edge_from_nodes方法完成这个工作 +5. AK的模型需要Parser给出输出Node的名字,使用GraphProtoIO的add_out方法填写输出Node的名字 +### 6、检查模型解析的正确性 +1. 默认的config.yaml配置会在解析结束后启动一个web服务器展示解析后的AK模型图,你需要对比原框架的模型图进行验证.这里最容易出现的错误是边关系的错误,表现为图非常乱,你需要逐条边地检查错误.第二个容易出错的地方是参数漏填,需要你检查OP中的属性 +2. 将解析后的模型放入AK中执行,使用相同的输入,原框架与AK有相同的输出.若果输出不一致可以开启AK的DEBUG模式,在net.cpp中将没层的输出打印.如果AK在解析阶段陷入死循环,大概率是边的关系出错. +## 如何添加新OP +1. 需要在AK代码中加入该OP的实现,包括对应设备Saber的OP,Saber单测和Framework中的OP +2. 根据Framework的OP在ops.py中添加Parser公共的OP定义 +3. 从原框架的模型中解析出该OP的节点,并在AK的graph中填入该OP节点 +## AK模型与其他框架模型的不同之处 ++ AK模型与CAFFE的模型相似,因此与其他模型有很多不同的地方,需要Parser在解析过程中处理掉. ++ 最大的不同是与FLUID或TENSORFLOW这种OP粒度很细的框架,AK的模型中OP的粒度很粗,这是为了节省访存开销.这会导致解析这些框架的模型时存在大量的合并操作. ++ 其次是OP的行为不同,如TENSORFLOW中Pooling默认都是exclusive的,而AK中是inclusive的.TENSORFLOW的Padding如果是奇数pad则在右方和下方多pad,AK是在左方和上方多Pad ++ AK默认的布局是NCHW,如果其他框架的OP是其他形式的,需要在Parser中做weights的布局转换,并处理reshape的问题. ++ AK中有的weights是需要预先做布局转换的(如GRU,LSTM).AK中也支持同一OP的不同算法,如(GRU,Pooling). + From 3b0fda43089060a88889a697b5ef121c989f1bfd Mon Sep 17 00:00:00 2001 From: liujunjie Date: Thu, 6 Sep 2018 16:02:01 +0800 Subject: [PATCH 24/51] add init --- tools/external_converter_v2/parser/kill_tf/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/external_converter_v2/parser/kill_tf/__init__.py b/tools/external_converter_v2/parser/kill_tf/__init__.py index e69de29bb..5a19cdd07 100644 --- a/tools/external_converter_v2/parser/kill_tf/__init__.py +++ b/tools/external_converter_v2/parser/kill_tf/__init__.py @@ -0,0 +1,5 @@ +#! /usr/bin/env python +# Copyright (c) 2017, Cuichaowen. All rights reserved. +# -*- coding: utf-8 -*- + +from parser_tf import TFParser From c4ac0bf65241bad25e4662e29f83f7bb02e5d559 Mon Sep 17 00:00:00 2001 From: liujunjie Date: Thu, 6 Sep 2018 16:31:49 +0800 Subject: [PATCH 25/51] rm abs path --- tools/external_converter_v2/config.yaml | 6 +++--- tools/external_converter_v2/parser/kill_tf/auto_debug.py | 2 +- tools/external_converter_v2/parser/kill_tf/run_pb.py | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tools/external_converter_v2/config.yaml b/tools/external_converter_v2/config.yaml index 676ff7c04..674774563 100644 --- a/tools/external_converter_v2/config.yaml +++ b/tools/external_converter_v2/config.yaml @@ -76,9 +76,9 @@ TARGET: ModelPath: TENSORFLOW: - ProtoPaths: /path/to/your/model/ - PrototxtPath: - ModelPath: + ProtoPaths: / + PrototxtPath: / + ModelPath: / OutPuts: ONNX: diff --git a/tools/external_converter_v2/parser/kill_tf/auto_debug.py b/tools/external_converter_v2/parser/kill_tf/auto_debug.py index af970bcd6..3865666a4 100644 --- a/tools/external_converter_v2/parser/kill_tf/auto_debug.py +++ b/tools/external_converter_v2/parser/kill_tf/auto_debug.py @@ -151,7 +151,7 @@ def run(self): # self._debug_graph(graph) -ak_work_space = '/home/ljj/docker_mount_dev2/anakin2_developing_parser/build/' +ak_work_space = '' debug = AutoDebug('./resnet_model/frozen_resnet_v1_50.pb', ak_work_space) debug.run_ak() diff --git a/tools/external_converter_v2/parser/kill_tf/run_pb.py b/tools/external_converter_v2/parser/kill_tf/run_pb.py index 3dcaf77d6..5b44bc23e 100644 --- a/tools/external_converter_v2/parser/kill_tf/run_pb.py +++ b/tools/external_converter_v2/parser/kill_tf/run_pb.py @@ -16,7 +16,6 @@ def convert_name_tf2ak(tf_name, perfix='record_'): return perfix + ak_name -ak_work_space = '/home/ljj/docker_mount_dev2/anakin2_developing_parser/build/' # ak_work_space='/your/anakin/workspace' output_compare_op = None From cf1665a4a1ad421bb472b10dca5c5c364fee22ef Mon Sep 17 00:00:00 2001 From: chengyujuan Date: Fri, 7 Sep 2018 17:11:16 +0800 Subject: [PATCH 26/51] fix resize bug --- .../impl/cuda/base/cuda_c/saber_resize.cu | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/saber/funcs/impl/cuda/base/cuda_c/saber_resize.cu b/saber/funcs/impl/cuda/base/cuda_c/saber_resize.cu index 5c2f4cbe1..6760c7f54 100644 --- a/saber/funcs/impl/cuda/base/cuda_c/saber_resize.cu +++ b/saber/funcs/impl/cuda/base/cuda_c/saber_resize.cu @@ -73,9 +73,9 @@ __global__ void resize_bilinear_2d_kernel(const int wout, const int hout, dtype br = (w > win || h > hin)? 0 : src[src_indexBR]; #else dtype tl = src[src_indexTL]; - dtype tr = w > win? 0 : src[src_indexTR];//w > win? 0 : - dtype bl = h > hin? 0 : src[src_indexBL];//h > hin? 0 : - dtype br = (w > win || h > hin)? 0 : src[src_indexBR];//(w > win || h > hin)? 0 : + dtype tr = w < win? src[src_indexTR]:0;//w > win? 0 : + dtype bl = h < hin? src[src_indexBL]:0;//h > hin? 0 : + dtype br = (w < win && h < hin) ? src[src_indexBR]: 0;//(w > win || h > hin)? 0 : #endif dst[dst_index] = static_cast(w_00 * tl + w_01 * tr + w_10 * bl + w_11 * br); src_indexBR += src_stride_c; @@ -152,19 +152,13 @@ SaberStatus SaberResizecount(height_idx + 1, dims); int dst_stride_channel = dst_real_shape.count(channel_idx + 1);//outputs[0]->count(channel_idx + 1, dims); int dst_stride_batch = dst_real_shape.count(num_idx + 1);//outputs[0]->count(num_idx + 1, dims); - const InDataType* in_data_batch = in_data; - OutDataType* out_data_batch = out_data; - for (int i = 0; i < n_out; ++i) { - resize_bilinear_2d_kernel<<>>( - w_out, h_out, n_out, c_out, - dst_stride_w, dst_stride_h, dst_stride_channel, dst_stride_batch, - w_in, h_in, - src_stride_w, src_stride_h, src_stride_channel, src_stride_batch, - 1 / param.width_scale, 1 / param.height_scale, - in_data, out_data); - in_data_batch += src_stride_batch; - out_data_batch += dst_stride_batch; - } + resize_bilinear_2d_kernel<<>>( + w_out, h_out, n_out, c_out, + dst_stride_w, dst_stride_h, dst_stride_channel, dst_stride_batch, + w_in, h_in, + src_stride_w, src_stride_h, src_stride_channel, src_stride_batch, + 1 / param.width_scale, 1 / param.height_scale, + in_data, out_data); //outputs[0]->record_event(stream); return SaberSuccess; } From 1ae3bd5c92c4c86346df16f399fe47ce87410b6b Mon Sep 17 00:00:00 2001 From: chengyujuan Date: Fri, 7 Sep 2018 17:26:45 +0800 Subject: [PATCH 27/51] fix resize bug --- framework/core/net/net.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/framework/core/net/net.cpp b/framework/core/net/net.cpp index c972c0c26..c39fb8938 100755 --- a/framework/core/net/net.cpp +++ b/framework/core/net/net.cpp @@ -393,9 +393,11 @@ void Net::prediction() { #define RECORD_INNER #if defined(RECORD_INNER) && defined(USE_X86_PLACE) record_tensor_to_file(*out,("record_"+executer.name).c_str()); - if(executer.name=="") #endif LOG(INFO) <data(); +#ifdef USE_CUDA + record_tensor_to_file(*out,("record_"+executer.name).c_str()); +#endif #ifdef USE_X86_PLACE // for (int i = 0; i < 10; ++i) { // std::cout << out->data()[i]<<" "; From 36b7fb6ef10929ad6b98d19458e6437504fdd28e Mon Sep 17 00:00:00 2001 From: yma-admin <40477813+yma-admin@users.noreply.github.com> Date: Mon, 10 Sep 2018 09:49:49 +0800 Subject: [PATCH 28/51] Update README_CPU.md --- benchmark/README_CPU.md | 68 ----------------------------------------- 1 file changed, 68 deletions(-) diff --git a/benchmark/README_CPU.md b/benchmark/README_CPU.md index 6113e2e2c..0f847ce85 100644 --- a/benchmark/README_CPU.md +++ b/benchmark/README_CPU.md @@ -205,74 +205,6 @@ We tested them on single-CPU with different thread numbers. 4 | 18074 | 118696 6 | 26607 | 102044 -2. **`Anakin`** VS **`PaddlePaddle/Fluid`** -We use private dataset and different QPS index in this benchmark. -### language model in E5-2650 v4 - -- Latency (`ms`) of one batch - - ThreadNum | Fluid | Anakin - :---: | :---: | :---: | - 1 | 42.7418 | 1.93589 - 2 | 42.7418 | 2.49537 - 6 | 42.7734 | 3.14332 - 10 | 43.0721 | 4.55329 - 12 | 42.8501 | 5.09893 - -- Throughput (`sentence/s`) - - ThreadNum | Fluid | Anakin - :---: | :---: | :---: | - 1 | 23 | 504 - 2 | 46 | 762 - 6 | 134 | 1393 - 10 | 218 | 1556 - 12 | 260 | 1541 - -### Chinese_ner model in E5-2650 v4 - -- Latency (`ms`) of one batch - - ThreadNum | Fluid | Anakin - :---: | :---: | :---: | - 1 | 0.380475 | 0.17034 - 4 | 0.380475 | 0.171143 - 6 | 0.380475 | 0.172688 - 10 | 0.380475 | 0.173269 - 12 | 0.380475 | 0.17668 - -- Throughput (`sentence/s`) - - ThreadNum | Fluid | Anakin - :---: | :---: | :---: | - 1 | 7844 | 5822 - 4 | 7844 | 11377 - 6 | 7844 | 29725 - 10 | 7844 | 41238 - 12 | 7844 | 42790 - -### text_classfication model in E5-2650 v4 - -- Latency (`ms`) of one batch - - ThreadNum | Fluid | Anakin - :---: | :---: | :---: | - 1 | 1.48578 | 1.10088 - 4 | 1.54025 | 1.11258 - 6 | 1.68529 | 1.1257 - 10 | 1.9817 | 1.13267 - 12 | 2.21864 | 1.1429 - -- Throughput (`sentence/s`) - - ThreadNum | Fluid | Anakin - :---: | :---: | :---: | - 1 | 673 | 901 - 4 | 1289 | 1665 - 6 | 3458 | 4449 - 10 | 4875 | 6183 - 12 | 5265 | 6188 - ## How to run those Benchmark models? > 1. You can just run `sh benchmark_tensorflow.sh` and `sh benchmark_anakin.sh` From e7d7258a5e18707036567163669e4f78680ced84 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Mon, 10 Sep 2018 14:51:25 +0800 Subject: [PATCH 29/51] update names --- .../parser/{kill_caffe => caffe}/.gitignore | 0 .../parser/{kill_caffe => caffe}/__init__.py | 0 .../parser/{kill_caffe => caffe}/caffe_helper.py | 0 .../{kill_caffe => caffe}/caffe_layer_param_transmit.py | 0 .../parser/{kill_caffe => caffe}/parser_caffe.py | 0 .../parser/{kill_fluid => fluid}/__init__.py | 0 .../parser/{kill_fluid => fluid}/fluid_debugger.py | 0 .../parser/{kill_fluid => fluid}/fluid_helper.py | 0 .../{kill_fluid => fluid}/fluid_layer_param_transmit.py | 0 .../parser/{kill_fluid => fluid}/parser_fluid.py | 0 tools/external_converter_v2/parser/graph.py | 6 +++--- 11 files changed, 3 insertions(+), 3 deletions(-) rename tools/external_converter_v2/parser/{kill_caffe => caffe}/.gitignore (100%) rename tools/external_converter_v2/parser/{kill_caffe => caffe}/__init__.py (100%) rename tools/external_converter_v2/parser/{kill_caffe => caffe}/caffe_helper.py (100%) rename tools/external_converter_v2/parser/{kill_caffe => caffe}/caffe_layer_param_transmit.py (100%) rename tools/external_converter_v2/parser/{kill_caffe => caffe}/parser_caffe.py (100%) rename tools/external_converter_v2/parser/{kill_fluid => fluid}/__init__.py (100%) rename tools/external_converter_v2/parser/{kill_fluid => fluid}/fluid_debugger.py (100%) rename tools/external_converter_v2/parser/{kill_fluid => fluid}/fluid_helper.py (100%) rename tools/external_converter_v2/parser/{kill_fluid => fluid}/fluid_layer_param_transmit.py (100%) rename tools/external_converter_v2/parser/{kill_fluid => fluid}/parser_fluid.py (100%) diff --git a/tools/external_converter_v2/parser/kill_caffe/.gitignore b/tools/external_converter_v2/parser/caffe/.gitignore similarity index 100% rename from tools/external_converter_v2/parser/kill_caffe/.gitignore rename to tools/external_converter_v2/parser/caffe/.gitignore diff --git a/tools/external_converter_v2/parser/kill_caffe/__init__.py b/tools/external_converter_v2/parser/caffe/__init__.py similarity index 100% rename from tools/external_converter_v2/parser/kill_caffe/__init__.py rename to tools/external_converter_v2/parser/caffe/__init__.py diff --git a/tools/external_converter_v2/parser/kill_caffe/caffe_helper.py b/tools/external_converter_v2/parser/caffe/caffe_helper.py similarity index 100% rename from tools/external_converter_v2/parser/kill_caffe/caffe_helper.py rename to tools/external_converter_v2/parser/caffe/caffe_helper.py diff --git a/tools/external_converter_v2/parser/kill_caffe/caffe_layer_param_transmit.py b/tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py similarity index 100% rename from tools/external_converter_v2/parser/kill_caffe/caffe_layer_param_transmit.py rename to tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py diff --git a/tools/external_converter_v2/parser/kill_caffe/parser_caffe.py b/tools/external_converter_v2/parser/caffe/parser_caffe.py similarity index 100% rename from tools/external_converter_v2/parser/kill_caffe/parser_caffe.py rename to tools/external_converter_v2/parser/caffe/parser_caffe.py diff --git a/tools/external_converter_v2/parser/kill_fluid/__init__.py b/tools/external_converter_v2/parser/fluid/__init__.py similarity index 100% rename from tools/external_converter_v2/parser/kill_fluid/__init__.py rename to tools/external_converter_v2/parser/fluid/__init__.py diff --git a/tools/external_converter_v2/parser/kill_fluid/fluid_debugger.py b/tools/external_converter_v2/parser/fluid/fluid_debugger.py similarity index 100% rename from tools/external_converter_v2/parser/kill_fluid/fluid_debugger.py rename to tools/external_converter_v2/parser/fluid/fluid_debugger.py diff --git a/tools/external_converter_v2/parser/kill_fluid/fluid_helper.py b/tools/external_converter_v2/parser/fluid/fluid_helper.py similarity index 100% rename from tools/external_converter_v2/parser/kill_fluid/fluid_helper.py rename to tools/external_converter_v2/parser/fluid/fluid_helper.py diff --git a/tools/external_converter_v2/parser/kill_fluid/fluid_layer_param_transmit.py b/tools/external_converter_v2/parser/fluid/fluid_layer_param_transmit.py similarity index 100% rename from tools/external_converter_v2/parser/kill_fluid/fluid_layer_param_transmit.py rename to tools/external_converter_v2/parser/fluid/fluid_layer_param_transmit.py diff --git a/tools/external_converter_v2/parser/kill_fluid/parser_fluid.py b/tools/external_converter_v2/parser/fluid/parser_fluid.py similarity index 100% rename from tools/external_converter_v2/parser/kill_fluid/parser_fluid.py rename to tools/external_converter_v2/parser/fluid/parser_fluid.py diff --git a/tools/external_converter_v2/parser/graph.py b/tools/external_converter_v2/parser/graph.py index e3fa90c4b..9d94a6900 100644 --- a/tools/external_converter_v2/parser/graph.py +++ b/tools/external_converter_v2/parser/graph.py @@ -20,19 +20,19 @@ def __init__(self, config): """ self.save_file_path = config.SavePath + config.ResultName + ".anakin.bin" if config.framework == 'CAFFE': - from kill_caffe import CaffeParser + from caffe import CaffeParser self.parser = CaffeParser(config.framework_config_dict) elif config.framework == 'PADDLE': pass elif config.framework == 'LEGO': pass elif config.framework == 'TENSORFLOW': - from kill_tf import TFParser + from tensorflow import TFParser self.parser=TFParser(config.framework_config_dict) elif config.framework == 'MXNET': pass elif config.framework == 'FLUID': - from kill_fluid import FluidParser + from fluid import FluidParser self.parser = FluidParser(config.framework_config_dict) else: raise NameError('ERROR: GrapProtoIO not support %s model.' % (config.framework)) From 8180eb73be92bc899c4d96e4eb762ae79beadc1a Mon Sep 17 00:00:00 2001 From: liujunjie Date: Mon, 10 Sep 2018 14:55:15 +0800 Subject: [PATCH 30/51] update name --- tools/external_converter_v2/parser/graph.py | 2 +- .../parser/{kill_tf => tensorflow}/__init__.py | 0 .../parser/{kill_tf => tensorflow}/auto_debug.py | 0 .../parser/{kill_tf => tensorflow}/freeze.py | 0 .../parser/{kill_tf => tensorflow}/freeze_graph.py | 0 .../parser/{kill_tf => tensorflow}/get_empt_infer_pb.py | 0 .../parser/{kill_tf => tensorflow}/med_graph.py | 0 .../parser/{kill_tf => tensorflow}/parse_med_2_ak.py | 0 .../parser/{kill_tf => tensorflow}/parse_tf_2_med.py | 0 .../parser/{kill_tf => tensorflow}/parser_tf.py | 0 .../parser/{kill_tf => tensorflow}/run_pb.py | 0 .../parser/{kill_tf => tensorflow}/run_pb_get_ckp.py | 0 .../parser/{kill_tf => tensorflow}/summary.py | 0 .../parser/{kill_tf => tensorflow}/tf_trans_util.py | 0 .../parser/{kill_tf => tensorflow}/tf_util.py | 0 15 files changed, 1 insertion(+), 1 deletion(-) rename tools/external_converter_v2/parser/{kill_tf => tensorflow}/__init__.py (100%) rename tools/external_converter_v2/parser/{kill_tf => tensorflow}/auto_debug.py (100%) rename tools/external_converter_v2/parser/{kill_tf => tensorflow}/freeze.py (100%) rename tools/external_converter_v2/parser/{kill_tf => tensorflow}/freeze_graph.py (100%) rename tools/external_converter_v2/parser/{kill_tf => tensorflow}/get_empt_infer_pb.py (100%) rename tools/external_converter_v2/parser/{kill_tf => tensorflow}/med_graph.py (100%) rename tools/external_converter_v2/parser/{kill_tf => tensorflow}/parse_med_2_ak.py (100%) rename tools/external_converter_v2/parser/{kill_tf => tensorflow}/parse_tf_2_med.py (100%) rename tools/external_converter_v2/parser/{kill_tf => tensorflow}/parser_tf.py (100%) rename tools/external_converter_v2/parser/{kill_tf => tensorflow}/run_pb.py (100%) rename tools/external_converter_v2/parser/{kill_tf => tensorflow}/run_pb_get_ckp.py (100%) rename tools/external_converter_v2/parser/{kill_tf => tensorflow}/summary.py (100%) rename tools/external_converter_v2/parser/{kill_tf => tensorflow}/tf_trans_util.py (100%) rename tools/external_converter_v2/parser/{kill_tf => tensorflow}/tf_util.py (100%) diff --git a/tools/external_converter_v2/parser/graph.py b/tools/external_converter_v2/parser/graph.py index e3fa90c4b..af9a6908d 100644 --- a/tools/external_converter_v2/parser/graph.py +++ b/tools/external_converter_v2/parser/graph.py @@ -27,7 +27,7 @@ def __init__(self, config): elif config.framework == 'LEGO': pass elif config.framework == 'TENSORFLOW': - from kill_tf import TFParser + from tensorflow import TFParser self.parser=TFParser(config.framework_config_dict) elif config.framework == 'MXNET': pass diff --git a/tools/external_converter_v2/parser/kill_tf/__init__.py b/tools/external_converter_v2/parser/tensorflow/__init__.py similarity index 100% rename from tools/external_converter_v2/parser/kill_tf/__init__.py rename to tools/external_converter_v2/parser/tensorflow/__init__.py diff --git a/tools/external_converter_v2/parser/kill_tf/auto_debug.py b/tools/external_converter_v2/parser/tensorflow/auto_debug.py similarity index 100% rename from tools/external_converter_v2/parser/kill_tf/auto_debug.py rename to tools/external_converter_v2/parser/tensorflow/auto_debug.py diff --git a/tools/external_converter_v2/parser/kill_tf/freeze.py b/tools/external_converter_v2/parser/tensorflow/freeze.py similarity index 100% rename from tools/external_converter_v2/parser/kill_tf/freeze.py rename to tools/external_converter_v2/parser/tensorflow/freeze.py diff --git a/tools/external_converter_v2/parser/kill_tf/freeze_graph.py b/tools/external_converter_v2/parser/tensorflow/freeze_graph.py similarity index 100% rename from tools/external_converter_v2/parser/kill_tf/freeze_graph.py rename to tools/external_converter_v2/parser/tensorflow/freeze_graph.py diff --git a/tools/external_converter_v2/parser/kill_tf/get_empt_infer_pb.py b/tools/external_converter_v2/parser/tensorflow/get_empt_infer_pb.py similarity index 100% rename from tools/external_converter_v2/parser/kill_tf/get_empt_infer_pb.py rename to tools/external_converter_v2/parser/tensorflow/get_empt_infer_pb.py diff --git a/tools/external_converter_v2/parser/kill_tf/med_graph.py b/tools/external_converter_v2/parser/tensorflow/med_graph.py similarity index 100% rename from tools/external_converter_v2/parser/kill_tf/med_graph.py rename to tools/external_converter_v2/parser/tensorflow/med_graph.py diff --git a/tools/external_converter_v2/parser/kill_tf/parse_med_2_ak.py b/tools/external_converter_v2/parser/tensorflow/parse_med_2_ak.py similarity index 100% rename from tools/external_converter_v2/parser/kill_tf/parse_med_2_ak.py rename to tools/external_converter_v2/parser/tensorflow/parse_med_2_ak.py diff --git a/tools/external_converter_v2/parser/kill_tf/parse_tf_2_med.py b/tools/external_converter_v2/parser/tensorflow/parse_tf_2_med.py similarity index 100% rename from tools/external_converter_v2/parser/kill_tf/parse_tf_2_med.py rename to tools/external_converter_v2/parser/tensorflow/parse_tf_2_med.py diff --git a/tools/external_converter_v2/parser/kill_tf/parser_tf.py b/tools/external_converter_v2/parser/tensorflow/parser_tf.py similarity index 100% rename from tools/external_converter_v2/parser/kill_tf/parser_tf.py rename to tools/external_converter_v2/parser/tensorflow/parser_tf.py diff --git a/tools/external_converter_v2/parser/kill_tf/run_pb.py b/tools/external_converter_v2/parser/tensorflow/run_pb.py similarity index 100% rename from tools/external_converter_v2/parser/kill_tf/run_pb.py rename to tools/external_converter_v2/parser/tensorflow/run_pb.py diff --git a/tools/external_converter_v2/parser/kill_tf/run_pb_get_ckp.py b/tools/external_converter_v2/parser/tensorflow/run_pb_get_ckp.py similarity index 100% rename from tools/external_converter_v2/parser/kill_tf/run_pb_get_ckp.py rename to tools/external_converter_v2/parser/tensorflow/run_pb_get_ckp.py diff --git a/tools/external_converter_v2/parser/kill_tf/summary.py b/tools/external_converter_v2/parser/tensorflow/summary.py similarity index 100% rename from tools/external_converter_v2/parser/kill_tf/summary.py rename to tools/external_converter_v2/parser/tensorflow/summary.py diff --git a/tools/external_converter_v2/parser/kill_tf/tf_trans_util.py b/tools/external_converter_v2/parser/tensorflow/tf_trans_util.py similarity index 100% rename from tools/external_converter_v2/parser/kill_tf/tf_trans_util.py rename to tools/external_converter_v2/parser/tensorflow/tf_trans_util.py diff --git a/tools/external_converter_v2/parser/kill_tf/tf_util.py b/tools/external_converter_v2/parser/tensorflow/tf_util.py similarity index 100% rename from tools/external_converter_v2/parser/kill_tf/tf_util.py rename to tools/external_converter_v2/parser/tensorflow/tf_util.py From d30da5ed4c0d422979187c4a211b04115c34415c Mon Sep 17 00:00:00 2001 From: liujunjie Date: Mon, 10 Sep 2018 14:57:16 +0800 Subject: [PATCH 31/51] update name --- docs/Manual/DesignConverter_ch.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/Manual/DesignConverter_ch.md b/docs/Manual/DesignConverter_ch.md index 139f46c2a..7031c034e 100644 --- a/docs/Manual/DesignConverter_ch.md +++ b/docs/Manual/DesignConverter_ch.md @@ -1,5 +1,5 @@ # Parser的编写指南 -下文称Anakin为AK,运算操作为OP,本文参考Tensorflow的Parser编写,参考代码目录为tools/external_converter_v2/parser/kill_tf +下文称Anakin为AK,运算操作为OP,本文参考Tensorflow的Parser编写,参考代码目录为tools/external_converter_v2/parser/tensorflow ## Parser的功能和执行流程 功能是将其他深度学习框架(如CAFFE,FLUID,TENSORFLOW,ONNEX)的模型转换为AK的模型.对AK的作用是屏蔽不同框架间的差异,这种差异包括模型存储、OP的定义、图差异 因此Parser的执行流程是: @@ -12,11 +12,11 @@ Parser工具在tools/external_converter_v2/parser目录下 Parser的目录主要包含3部分: 1. Parser的运行配置文件包括 config.py, config.yaml, converter.py, 用户只用执行converter.py,Parser就会按照config.yaml中的声明去解析模型 2. Parser的公共定义,包括operations,pbs,proto三个目录. Parser的公共工具函数 graph*.py logger.py utils.py -3. 各个框架对应的Parser,其目录的命名方式为kill_*,如kill_caffe +3. 各个框架对应的Parser,其目录的命名方式为框架名,如caffe, tensorflow ## Parser的编写流程 ### 1、声明你的Parser 1. 在config.yaml中填写你的Parser运行的必要信息,包括ProtoPath和SavePath等.OPTIONS/Framework改为你的Parser的类型,TARGET下填写对应的参数列表 -2. 添加你的Parser目录,如kill_tf,导出你的Parser符号.注意,Parser的框架默认调用你的Parser类中的__call__方法来执行解析,这个方法需要返回填写完毕的GraphProtoIO对象 +2. 添加你的Parser目录,如tensorflow,导出你的Parser符号.注意,Parser的框架默认调用你的Parser类中的__call__方法来执行解析,这个方法需要返回填写完毕的GraphProtoIO对象 3. 在config.py中Configuration下__init__函数中增加对你的Parser的调用,将yaml中读取的配置信息传给你的Parser,此处调用你的Parser中的__init__方法 ### 2、添加你的Parser主体 可以参考parser_tf.py From decb72c58b1ff847bf22ce64680ef90be90cd9b6 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Mon, 10 Sep 2018 20:10:21 +0800 Subject: [PATCH 32/51] support diepsie --- .../caffe/caffe_layer_param_transmit.py | 34 ++++++++++++++++--- .../parser/operations/op_io.py | 16 +++++---- .../parser/operations/ops.py | 13 +++++++ 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py b/tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py index f0f4983fe..436d3be50 100755 --- a/tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py +++ b/tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py @@ -732,6 +732,7 @@ def Parser_rpn_proposal_ssd(args): OpsRegister()["RPNProposalSSD"].nms_among_classes = nms_param.nms_among_classes OpsRegister()["RPNProposalSSD"].voting = list(nms_param.voting) OpsRegister()["RPNProposalSSD"].vote_iou = list(nms_param.vote_iou) + OpsRegister()["RPNProposalSSD"].nms_gpu_max_n_per_time = nms_param.nms_gpu_max_n_per_time # parsing gen_anchor_param pkg gen_anchor_param = detect_output_ssd.gen_anchor_param OpsRegister()["RPNProposalSSD"].base_size = gen_anchor_param.base_size @@ -836,6 +837,7 @@ def Parser_rcnn_net_output_with_attr(args): OpsRegister()["RCNNDetOutputWithAttr"].nms_among_classes = nms_param.nms_among_classes OpsRegister()["RCNNDetOutputWithAttr"].voting = list(nms_param.voting) OpsRegister()["RCNNDetOutputWithAttr"].vote_iou = list(nms_param.vote_iou) + OpsRegister()["RCNNDetOutputWithAttr"].nms_gpu_max_n_per_time = nms_param.nms_gpu_max_n_per_time # parsing gen_anchor_param pkg gen_anchor_param = detect_output_ssd.gen_anchor_param OpsRegister()["RCNNDetOutputWithAttr"].base_size = gen_anchor_param.base_size @@ -957,6 +959,7 @@ def Parser_rcnn_proposal(args): OpsRegister()["RCNNProposal"].nms_among_classes = nms_param.nms_among_classes OpsRegister()["RCNNProposal"].voting = list(nms_param.voting) OpsRegister()["RCNNProposal"].vote_iou = list(nms_param.vote_iou) + OpsRegister()["RCNNProposal"].nms_gpu_max_n_per_time = nms_param.nms_gpu_max_n_per_time # parsing gen_anchor_param pkg gen_anchor_param = detect_output_ssd.gen_anchor_param OpsRegister()["RCNNProposal"].base_size = gen_anchor_param.base_size @@ -1059,12 +1062,32 @@ def Parser_proposal_img_scale_to_cam_coords(args): OpsRegister()["ProposalImgScaleToCamCoords"].cords_offset_y = proposal_img_scale_to_cam_coords.cords_offset_y OpsRegister()["ProposalImgScaleToCamCoords"].bbox_size_add_one = proposal_img_scale_to_cam_coords.bbox_size_add_one OpsRegister()["ProposalImgScaleToCamCoords"].rotate_coords_by_pitch = proposal_img_scale_to_cam_coords.rotate_coords_by_pitch - OpsRegister()["ProposalImgScaleToCamCoords"].refine_coords_by_bbox = proposal_img_scale_to_cam_coords.refine_coords_by_bbox - OpsRegister()["ProposalImgScaleToCamCoords"].refine_min_dist = proposal_img_scale_to_cam_coords.refine_min_dist - OpsRegister()["ProposalImgScaleToCamCoords"].refine_dist_for_height_ratio_one = proposal_img_scale_to_cam_coords.refine_dist_for_height_ratio_one - OpsRegister()["ProposalImgScaleToCamCoords"].max_3d2d_height_ratio_for_min_dist = proposal_img_scale_to_cam_coords.max_3d2d_height_ratio_for_min_dist + #OpsRegister()["ProposalImgScaleToCamCoords"].refine_coords_by_bbox = proposal_img_scale_to_cam_coords.refine_coords_by_bbox + #OpsRegister()["ProposalImgScaleToCamCoords"].refine_min_dist = proposal_img_scale_to_cam_coords.refine_min_dist + #OpsRegister()["ProposalImgScaleToCamCoords"].refine_dist_for_height_ratio_one = proposal_img_scale_to_cam_coords.refine_dist_for_height_ratio_one + #OpsRegister()["ProposalImgScaleToCamCoords"].max_3d2d_height_ratio_for_min_dist = proposal_img_scale_to_cam_coords.max_3d2d_height_ratio_for_min_dist OpsRegister()["ProposalImgScaleToCamCoords"].with_trunc_ratio = proposal_img_scale_to_cam_coords.with_trunc_ratio + OpsRegister()["ProposalImgScaleToCamCoords"].regress_ph_rh_as_whole = proposal_img_scale_to_cam_coords.regress_ph_rh_as_whole + OpsRegister()["ProposalImgScaleToCamCoords"].real_h_means_as_whole = list(proposal_img_scale_to_cam_coords.real_h_means_as_whole) + OpsRegister()["ProposalImgScaleToCamCoords"].real_h_stds_as_whole = list(proposal_img_scale_to_cam_coords.real_h_stds_as_whole) +@ParserFeedDecorator("RoisAnchorFeature") +def Parser_rois_anchor_feature(args): + layer = args[1] + # parser caffe parameter + rois_anchor_feature_param = layer.rois_anchor_feature_param + OpsRegister()["RoisAnchorFeature"].min_anchor_size = rois_anchor_feature_param.min_anchor_size + OpsRegister()["RoisAnchorFeature"].num_anchor_scales = rois_anchor_feature_param.num_anchor_scales + OpsRegister()["RoisAnchorFeature"].anchor_scale_pow_base = rois_anchor_feature_param.anchor_scale_pow_base + OpsRegister()["RoisAnchorFeature"].anchor_wph_ratios = list(rois_anchor_feature_param.anchor_wph_ratios) + OpsRegister()["RoisAnchorFeature"].num_top_iou_anchor = rois_anchor_feature_param.num_top_iou_anchor + OpsRegister()["RoisAnchorFeature"].min_num_top_iou_anchor = rois_anchor_feature_param.min_num_top_iou_anchor + OpsRegister()["RoisAnchorFeature"].iou_thr = rois_anchor_feature_param.iou_thr + OpsRegister()["RoisAnchorFeature"].ft_ratio_h = rois_anchor_feature_param.ft_ratio_h + OpsRegister()["RoisAnchorFeature"].ft_ratio_w = rois_anchor_feature_param.ft_ratio_w + OpsRegister()["RoisAnchorFeature"].ft_log_ratio_h = rois_anchor_feature_param.ft_log_ratio_h + OpsRegister()["RoisAnchorFeature"].ft_log_ratio_w = rois_anchor_feature_param.ft_log_ratio_w + OpsRegister()["RoisAnchorFeature"].bbox_size_add_one = rois_anchor_feature_param.bbox_size_add_one @ParserFeedDecorator("Axpy") def Parser_axpy(args): @@ -1219,5 +1242,6 @@ def Parser_relu6(args): "Resize": OpsParam().set_parser(Parser_resize), "ReLU6": OpsParam().set_parser(Parser_relu6), "Normalization": OpsParam().set_parser(Parser_normalize), - "ShuffleChannel": OpsParam().set_parser(Parser_ShuffleChannel) + "ShuffleChannel": OpsParam().set_parser(Parser_ShuffleChannel), + "RoisAnchorFeature": OpsParam().set_parser(Parser_rois_anchor_feature) } diff --git a/tools/external_converter_v2/parser/operations/op_io.py b/tools/external_converter_v2/parser/operations/op_io.py index 11539f38e..d7c647bb1 100644 --- a/tools/external_converter_v2/parser/operations/op_io.py +++ b/tools/external_converter_v2/parser/operations/op_io.py @@ -41,7 +41,8 @@ def __call__(self): use_soft_nms=list(), nms_among_classes=bool(), voting=list(), - vote_iou=list()) + vote_iou=list(), + nms_gpu_max_n_per_time=int()) # BBoxRegParameter bbox_reg_param = Dictionary().set_attr(bbox_mean=list(), @@ -189,11 +190,14 @@ def __call__(self): cords_offset_y=float(), bbox_size_add_one=bool(), rotate_coords_by_pitch=bool(), - refine_coords_by_bbox=bool(), - refine_min_dist=float(), - refine_dist_for_height_ratio_one=float(), - max_3d2d_height_ratio_for_min_dist=float(), - with_trunc_ratio=bool()) + #refine_coords_by_bbox=bool(), + #refine_min_dist=float(), + #refine_dist_for_height_ratio_one=float(), + #max_3d2d_height_ratio_for_min_dist=float(), + with_trunc_ratio=bool(), + regress_ph_rh_as_whole=bool(), + real_h_means_as_whole=list(), + real_h_stds_as_whole=list()) # RPNProposalSSD parameter RPNProposalSSD_param = Dictionary().set_attr(detection_output_ssd=detection_output_ssd_param(), bbox_reg=bbox_reg_param()) diff --git a/tools/external_converter_v2/parser/operations/ops.py b/tools/external_converter_v2/parser/operations/ops.py index 1656bdba5..697501492 100755 --- a/tools/external_converter_v2/parser/operations/ops.py +++ b/tools/external_converter_v2/parser/operations/ops.py @@ -370,3 +370,16 @@ OpsRegister.Register("ShuffleChannel").set_attr(group=int()) + +OpsRegister.Register("RoisAnchorFeature").set_attr(min_anchor_size=float(), + num_anchor_scales=int(), + anchor_scale_pow_base=float(), + anchor_wph_ratios=list(), + num_top_iou_anchor=int(), + min_num_top_iou_anchor=int(), + iou_thr=float(), + ft_ratio_h=bool(), + ft_ratio_w=bool(), + ft_log_ratio_h=bool(), + ft_log_ratio_w=bool(), + bbox_size_add_one=bool()) From 3e057ce3c15ba99e211cd108b013273193ba3b1e Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Tue, 11 Sep 2018 16:42:50 +0800 Subject: [PATCH 33/51] add fluid tool --- .../parser/fluid/tools/all_ones.py | 136 +++++++++++++ .../parser/fluid/tools/all_txt.py | 178 ++++++++++++++++++ 2 files changed, 314 insertions(+) create mode 100644 tools/external_converter_v2/parser/fluid/tools/all_ones.py create mode 100644 tools/external_converter_v2/parser/fluid/tools/all_txt.py diff --git a/tools/external_converter_v2/parser/fluid/tools/all_ones.py b/tools/external_converter_v2/parser/fluid/tools/all_ones.py new file mode 100644 index 000000000..6b7d5721a --- /dev/null +++ b/tools/external_converter_v2/parser/fluid/tools/all_ones.py @@ -0,0 +1,136 @@ +import sys +import numpy as np +import os +import paddle.fluid as fluid +from paddle.fluid import debugger +from paddle.fluid import core +import subprocess + +GLB_model_path = '' +GLB_arg_name = '' +GLB_batch_size = 1 + +def load_inference_model(model_path, exe): + model_abs_path = os.path.join(model_path, 'model') + param_abs_path = os.path.join(model_path, 'params') + if os.path.exists(model_abs_path) and os.path.exists(param_abs_path): + return fluid.io.load_inference_model(model_path, exe, 'model', 'params') + else: + return fluid.io.load_inference_model(model_path, exe) + +def feed_ones(block, feed_target_names, batch_size = 1): + feed_dict = dict() + + def set_batch_size(shape, batch_size): + if shape[0] == -1: + shape[0] = batch_size + return shape + + def fill_ones(var_name, batch_size): + var = block.var(var_name) + np_shape = set_batch_size(list(var.shape), 1) + var_np = { + core.VarDesc.VarType.BOOL: np.bool_, + core.VarDesc.VarType.INT32: np.int32, + core.VarDesc.VarType.INT64: np.int64, + core.VarDesc.VarType.FP16: np.float16, + core.VarDesc.VarType.FP32: np.float32, + core.VarDesc.VarType.FP64: np.float64, + } + np_dtype = var_np[var.dtype] + return np.ones(np_shape, dtype=np_dtype) + + for feed_target_name in feed_target_names: + feed_dict[feed_target_name] = fill_ones(feed_target_name, batch_size) + return feed_dict + + +def draw(block, filename='debug'): + dot_path = './' + filename + '.dot' + pdf_path = './' + filename + '.pdf' + debugger.draw_block_graphviz(block, path=dot_path) + cmd = ["dot", "-Tpdf", dot_path, "-o", pdf_path] + subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + +def fetch_tmp_vars(block, fetch_targets, var_names_list = None): + + def var_names_of_fetch(fetch_targets): + var_names_list = [] + for var in fetch_targets: + var_names_list.append(var.name) + return var_names_list + + fetch_var = block.var('fetch') + old_fetch_names = var_names_of_fetch(fetch_targets) + new_fetch_vars = [] + for var_name in old_fetch_names: + var = block.var(var_name) + new_fetch_vars.append(var) + i = len(new_fetch_vars) + if var_names_list is None: + var_names_list = block.vars.keys() + for var_name in var_names_list: + if '.tmp_' in var_name and var_name not in old_fetch_names: + var = block.var(var_name) + new_fetch_vars.append(var) + block.append_op( + type='fetch', + inputs={'X': [var_name]}, + outputs={'Out': [fetch_var]}, + attrs={'col': i}) + i = i + 1 + return new_fetch_vars + + +def print_results(results, fetch_targets, need_save = True): + for result in results: + idx = results.index(result) + print fetch_targets[idx] + print np.array(result) + if need_save is True: + fluid_fetch_list = list(np.array(result).flatten()) + fetch_txt_fp = open('result_' + fetch_targets[idx].name + '.txt', 'w') + for num in fluid_fetch_list: + fetch_txt_fp.write(str(num) + '\n') + fetch_txt_fp.close() + + +def fluid_inference_test(model_path): + place = fluid.CPUPlace() + exe = fluid.Executor(place) + scope = fluid.core.Scope() + + with fluid.scope_guard(scope): + [net_program, + feed_target_names, + fetch_targets] = load_inference_model(model_path, exe) + + global_block = net_program.global_block() + draw(global_block) + + feed_list = feed_ones(global_block, feed_target_names) + fetch_targets = fetch_tmp_vars(global_block, fetch_targets, [GLB_arg_name]) + + results = exe.run(program=net_program, + feed=feed_list, + fetch_list=fetch_targets, + return_numpy=False) + + print_results(results, fetch_targets) + + + +if __name__ == "__main__": + + if len(sys.argv) == 1: + raise NameError('Usage: python ./all_ones.py path/to/model arg_name batch_size') + if len(sys.argv) > 1: + GLB_model_path = sys.argv[1] + if len(sys.argv) > 2: + GLB_arg_name = sys.argv[2] + if len(sys.argv) > 3: + GLB_batch_size = sys.argv[3] + + fluid_inference_test(GLB_model_path) + diff --git a/tools/external_converter_v2/parser/fluid/tools/all_txt.py b/tools/external_converter_v2/parser/fluid/tools/all_txt.py new file mode 100644 index 000000000..8fcfafcfa --- /dev/null +++ b/tools/external_converter_v2/parser/fluid/tools/all_txt.py @@ -0,0 +1,178 @@ +import sys +import numpy as np +import os +import paddle.fluid as fluid +from paddle.fluid import debugger +from paddle.fluid import core +from prettytable import PrettyTable +from operator import mul +import subprocess + +GLB_model_path = '/path/to/fluid/inference/model/' +GLB_feed_example = { + 'var_name': 'data', + 'tensor_shape': [n, c, h, w], + 'txt_path': '/path/to/input/txt/', +} +GLB_feed_list = [GLB_feed_example] + +# Do not modify +GLB_arg_name = '' +GLB_batch_size = 1 + + +def load_inference_model(model_path, exe): + model_abs_path = os.path.join(model_path, 'model') + param_abs_path = os.path.join(model_path, 'params') + if os.path.exists(model_abs_path) and os.path.exists(param_abs_path): + return fluid.io.load_inference_model(model_path, exe, 'model', 'params') + else: + return fluid.io.load_inference_model(model_path, exe) + + +def print_feed_fetch(block, feed_target_names, fetch_targets): + tag_list = ["Index", "Name", "Shape", "Data Type", "Tensor Type"] + def add_var_table(table, var, idx): + table.add_row([idx, var.name, var.shape, str(var.dtype), str(var.type)]) + def feed_table(block, var_name_list): + table = PrettyTable(tag_list) + for var_name in var_name_list: + idx = var_name_list.index(var_name) + var = block.var(var_name) + add_var_table(table, var, idx) + return table + def fetch_table(var_list): + idx = 0 + table = PrettyTable(tag_list) + for var in var_list: + add_var_table(table, var, idx) + idx = idx + 1 + return table + print "\n", "=========== FEED TABLE ===========" + print feed_table(block, feed_target_names) + print "\n", "=========== FETCH TABLE ===========" + print fetch_table(fetch_targets), "\n" + + +def add_feed_list(feed_list, fluid_feed_dict=dict()): + + def numpy_from_txt(txt_path, + tensor_shape=list(), + dtype=np.float32, + delimiter=None, + comments='#'): + data = np.loadtxt(txt_path, dtype, comments, delimiter) + data_size = np.size(data) + tensor_size = reduce(mul, tensor_shape) + assert (data_size == tensor_size), \ + "data size of txt (%d) must be equal to shape size (%d)." % (data_size, tensor_size) + return np.reshape(data, tensor_shape) + + def add_feed_var(input_dict, fluid_feed_dict): + var_name = input_dict['var_name'] + tensor_shape = input_dict['tensor_shape'] + txt_path = input_dict['txt_path'] + if 'data_type' in input_dict.keys(): + dtype = input_dict['data_type'] + else: + dtype = np.float32 + if 'delimiter' in input_dict.keys(): + delim = input_dict['delimiter'] + else: + delim = None + fluid_feed_dict[var_name] = numpy_from_txt(txt_path, tensor_shape, dtype, delim) + return fluid_feed_dict + + for input_dict in feed_list: + add_feed_var(input_dict, fluid_feed_dict) + return fluid_feed_dict + + +def draw(block, filename='debug'): + dot_path = './' + filename + '.dot' + pdf_path = './' + filename + '.pdf' + debugger.draw_block_graphviz(block, path=dot_path) + cmd = ["dot", "-Tpdf", dot_path, "-o", pdf_path] + subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + +def fetch_tmp_vars(block, fetch_targets, var_names_list = None): + def var_names_of_fetch(fetch_targets): + var_names_list = [] + for var in fetch_targets: + var_names_list.append(var.name) + return var_names_list + + fetch_var = block.var('fetch') + old_fetch_names = var_names_of_fetch(fetch_targets) + new_fetch_vars = [] + for var_name in old_fetch_names: + var = block.var(var_name) + new_fetch_vars.append(var) + i = len(new_fetch_vars) + if var_names_list is None: + var_names_list = block.vars.keys() + for var_name in var_names_list: + if '.tmp_' in var_name and var_name not in old_fetch_names: + var = block.var(var_name) + new_fetch_vars.append(var) + block.append_op( + type='fetch', + inputs={'X': [var_name]}, + outputs={'Out': [fetch_var]}, + attrs={'col': i}) + i = i + 1 + return new_fetch_vars + + +def print_results(results, fetch_targets, need_save = True): + for result in results: + idx = results.index(result) + print fetch_targets[idx] + print np.array(result) + if need_save is True: + fluid_fetch_list = list(np.array(result).flatten()) + fetch_txt_fp = open('result_' + fetch_targets[idx].name + '.txt', 'w') + for num in fluid_fetch_list: + fetch_txt_fp.write(str(num) + '\n') + fetch_txt_fp.close() + + +def fluid_inference_test(model_path, feed_list): + place = fluid.CPUPlace() + exe = fluid.Executor(place) + scope = fluid.core.Scope() + + with fluid.scope_guard(scope): + [net_program, + feed_target_names, + fetch_targets] = load_inference_model(model_path, exe) + + global_block = net_program.global_block() + print_feed_fetch(global_block, feed_target_names, fetch_targets) + draw(global_block) + + feed_list = add_feed_list(feed_list) + fetch_targets = fetch_tmp_vars(global_block, fetch_targets, [GLB_arg_name]) + + results = exe.run(program=net_program, + feed=feed_list, + fetch_list=fetch_targets, + return_numpy=False) + + print_results(results, fetch_targets) + + +if __name__ == "__main__": + + if len(sys.argv) == 1 and GLB_model_path == '': + raise NameError('Usage: python ./all_ones.py path/to/model arg_name batch_size') + if len(sys.argv) > 1 and GLB_model_path == '': + GLB_model_path = sys.argv[1] + if len(sys.argv) > 2: + GLB_arg_name = sys.argv[2] + if len(sys.argv) > 3: + GLB_batch_size = sys.argv[3] + + fluid_inference_test(GLB_model_path, GLB_feed_list) + From cf6b426156f0886684c5bf9c002fb0c64ed0d617 Mon Sep 17 00:00:00 2001 From: zhangshuai20 Date: Wed, 12 Sep 2018 21:05:44 +0800 Subject: [PATCH 34/51] update conv + prelu fusion --- .../conv_3x3_batchnorm_scale_relu.cpp | 26 +++++++--- .../fusion_ops/conv_batchnorm_scale_relu.cpp | 19 +++++-- framework/operators/fusion_ops/conv_relu.cpp | 14 ++++-- .../impl/cuda/base/cuda_c/saber_activation.cu | 49 ++++++++++++++++--- saber/funcs/impl/cuda/saber_activation.h | 2 +- saber/funcs/impl/cuda/vender_conv_act.cpp | 12 +++-- saber/funcs/impl/cuda/vender_conv_act.h | 10 +++- 7 files changed, 104 insertions(+), 28 deletions(-) diff --git a/framework/operators/fusion_ops/conv_3x3_batchnorm_scale_relu.cpp b/framework/operators/fusion_ops/conv_3x3_batchnorm_scale_relu.cpp index 0d6d6ee8a..0094f46fe 100644 --- a/framework/operators/fusion_ops/conv_3x3_batchnorm_scale_relu.cpp +++ b/framework/operators/fusion_ops/conv_3x3_batchnorm_scale_relu.cpp @@ -88,12 +88,17 @@ Status SassConvBatchnormScaleReluHelper::InitParam() { // get relu param auto alpha = GET_PARAMETER(float, relu_0_alpha); - ActivationParam> active_param(Active_relu);//, alpha); // TEMP - - - ConvActiveParam> conv_act_param(_conv_param, active_param, batchnorm_param, - scale_param); - _param_conv_batchnorm_scale_relu = conv_act_param; + if (alpha != 0) { + ActivationParam> active_param(Active_prelu, alpha); // TEMP + ConvActiveParam> conv_act_param(_conv_param, active_param, batchnorm_param, + scale_param); + _param_conv_batchnorm_scale_relu = conv_act_param; + } else { + ActivationParam> active_param(Active_relu); // TEMP + ConvActiveParam> conv_act_param(_conv_param, active_param, batchnorm_param, + scale_param); + _param_conv_batchnorm_scale_relu = conv_act_param; + } return Status::OK(); } @@ -102,8 +107,13 @@ template Status SassConvBatchnormScaleReluHelper::Init(OpContext& ctx, const std::vector >& ins, std::vector >& outs) { - _funcs_conv_batchnorm_scale_relu.init(ins, outs, _param_conv_batchnorm_scale_relu, SPECIFY, - SABER_IMPL, ctx); + if (_param_conv_batchnorm_scale_relu.activation_param.active == Active_relu) { + _funcs_conv_batchnorm_scale_relu.init(ins, outs, _param_conv_batchnorm_scale_relu, SPECIFY, + SABER_IMPL, ctx); + } else { + _funcs_conv_batchnorm_scale_relu.init(ins, outs, _param_conv_batchnorm_scale_relu, SPECIFY, + VENDER_IMPL, ctx); + } return Status::OK(); } diff --git a/framework/operators/fusion_ops/conv_batchnorm_scale_relu.cpp b/framework/operators/fusion_ops/conv_batchnorm_scale_relu.cpp index b8a83269d..f8ffe978e 100644 --- a/framework/operators/fusion_ops/conv_batchnorm_scale_relu.cpp +++ b/framework/operators/fusion_ops/conv_batchnorm_scale_relu.cpp @@ -83,12 +83,19 @@ Status ConvBatchnormScaleReluHelper::InitParam() { // get relu param auto alpha = GET_PARAMETER(float, relu_0_alpha); - ActivationParam> active_param(Active_relu);//, alpha); // TEMP + if (alpha != 0) { + ActivationParam> active_param(Active_prelu, alpha); // TEMP + ConvActiveParam> conv_act_param(_conv_param, active_param, batchnorm_param, + scale_param); + _param_conv_batchnorm_scale_relu = conv_act_param; + } else { + ActivationParam> active_param(Active_relu); // TEMP + ConvActiveParam> conv_act_param(_conv_param, active_param, batchnorm_param, + scale_param); + _param_conv_batchnorm_scale_relu = conv_act_param; + } - ConvActiveParam> conv_act_param(_conv_param, active_param, batchnorm_param, - scale_param); - _param_conv_batchnorm_scale_relu = conv_act_param; return Status::OK(); } @@ -115,7 +122,9 @@ Status ConvBatchnormScaleReluHelper::InferShape(const template <> Status ConvBatchnormScaleReluHelper::Init(OpContext &ctx, \ const std::vector >& ins, std::vector >& outs) { - if (_param_conv_batchnorm_scale_relu.conv_param.group == ins[0]->channel() && \ + bool use_saber = true; + use_saber = use_saber && (_param_conv_batchnorm_scale_relu.activation_param.active == Active_relu); + if (use_saber && _param_conv_batchnorm_scale_relu.conv_param.group == ins[0]->channel() && \ _param_conv_batchnorm_scale_relu.conv_param.group == outs[0]->channel()) { _funcs_conv_batchnorm_scale_relu.init(ins, outs, _param_conv_batchnorm_scale_relu, SPECIFY, SABER_IMPL, ctx); diff --git a/framework/operators/fusion_ops/conv_relu.cpp b/framework/operators/fusion_ops/conv_relu.cpp index da44143f4..757d9f901 100644 --- a/framework/operators/fusion_ops/conv_relu.cpp +++ b/framework/operators/fusion_ops/conv_relu.cpp @@ -62,11 +62,16 @@ Status ConvReluHelper::InitParam() { // get relu param auto alpha = GET_PARAMETER(float, relu_0_alpha); - ActivationParam> active_param(Active_relu);//, alpha); // TEMP - + if (alpha != 0) { + ActivationParam> active_param(Active_prelu, alpha); // TEMP + ConvActiveParam> conv_act_param(_conv_param, active_param); + _param_conv_relu = conv_act_param; + } else { + ActivationParam> active_param(Active_relu); // TEMP + ConvActiveParam> conv_act_param(_conv_param, active_param); + _param_conv_relu = conv_act_param; + } - ConvActiveParam> conv_act_param(_conv_param, active_param); - _param_conv_relu = conv_act_param; return Status::OK(); @@ -100,6 +105,7 @@ Status ConvReluHelper::Init(OpContext& ctx, \ use_saber = use_saber && (_param_conv_relu.conv_param.weight()->width()==3); use_saber = use_saber && (_param_conv_relu.conv_param.dilation_h == 1); use_saber = use_saber && (_param_conv_relu.conv_param.dilation_w == 1); + use_saber = use_saber && (_param_conv_relu.activation_param.active == Active_relu); if (((_param_conv_relu.conv_param.group == 1) && use_saber)|| (_param_conv_relu.conv_param.group == ins[0]->channel() && \ _param_conv_relu.conv_param.group == outs[0]->channel())) { _funcs_conv_relu.init(ins, outs, _param_conv_relu, SPECIFY, SABER_IMPL, ctx); diff --git a/saber/funcs/impl/cuda/base/cuda_c/saber_activation.cu b/saber/funcs/impl/cuda/base/cuda_c/saber_activation.cu index 9f2c42b92..229e7802d 100644 --- a/saber/funcs/impl/cuda/base/cuda_c/saber_activation.cu +++ b/saber/funcs/impl/cuda/base/cuda_c/saber_activation.cu @@ -175,6 +175,34 @@ __global__ void ker_prelu_fwd(Dtype * out_data, } } +template +__global__ void ker_prelu_fwd(Dtype * out_data, + const Dtype* in_data, const int count, + const Dtype slope, bool is_channel_shared, + int in_n, int in_c, int in_h, int in_w, + int in_n_stride, int in_c_stride, int in_h_stride, int in_w_stride, + int out_n_stride, int out_c_stride, int out_h_stride, int out_w_stride) { + CUDA_KERNEL_LOOP(tid, count){ + int w = tid % in_w; + int h = (tid / (in_w)) % in_h; + int c = (tid / (in_h * in_w)) % in_c; + int n = (tid / (in_c * in_h * in_w)) % in_n; + + int in_idx = n * in_n_stride + + c * in_c_stride + + h * in_h_stride + + w * in_w_stride; + + int out_idx = n * out_n_stride + + c * out_c_stride + + h * out_h_stride + + w * out_w_stride; + + Dtype in_var = in_data[in_idx]; + out_data[out_idx] = in_var > 0 ? in_var : slope * in_var; + } +} + template <> SaberStatus SaberActivation::dispatch( \ @@ -248,12 +276,21 @@ SaberStatus SaberActivation - <<>>( - out_data, in_data, count, prelu_param.slope->data(), prelu_param.channel_shared, - in_shape[0], in_shape[1], in_shape[2], in_shape[3], - stride_in[0], stride_in[1], stride_in[2], stride_in[3], - stride_out[0], stride_out[1], stride_out[2], stride_out[3]); + if (param.prelu_param.slope == nullptr) { + ker_prelu_fwd + << < CUDA_GET_BLOCKS(count), CUDA_NUM_THREADS, 0, cuda_stream >> > ( + out_data, in_data, count, param.negative_slope, prelu_param.channel_shared, + in_shape[0], in_shape[1], in_shape[2], in_shape[3], + stride_in[0], stride_in[1], stride_in[2], stride_in[3], + stride_out[0], stride_out[1], stride_out[2], stride_out[3]); + } else { + ker_prelu_fwd + << < CUDA_GET_BLOCKS(count), CUDA_NUM_THREADS, 0, cuda_stream >> > ( + out_data, in_data, count, prelu_param.slope->data(), prelu_param.channel_shared, + in_shape[0], in_shape[1], in_shape[2], in_shape[3], + stride_in[0], stride_in[1], stride_in[2], stride_in[3], + stride_out[0], stride_out[1], stride_out[2], stride_out[3]); + } break; } diff --git a/saber/funcs/impl/cuda/saber_activation.h b/saber/funcs/impl/cuda/saber_activation.h index a39004469..b799dec7b 100644 --- a/saber/funcs/impl/cuda/saber_activation.h +++ b/saber/funcs/impl/cuda/saber_activation.h @@ -65,7 +65,7 @@ class SaberActivation& inputs, std::vector& outputs, ActivationParam& param); - + OpTensor _slope; }; //template class SaberActivation; diff --git a/saber/funcs/impl/cuda/vender_conv_act.cpp b/saber/funcs/impl/cuda/vender_conv_act.cpp index 88bddf9ca..c7b3e3192 100644 --- a/saber/funcs/impl/cuda/vender_conv_act.cpp +++ b/saber/funcs/impl/cuda/vender_conv_act.cpp @@ -1,4 +1,5 @@ #include "saber/funcs/impl/cuda/vender_conv_act.h" +#include "saber/funcs/impl/cuda/saber_activation.h" #include "cuda_fp16.h" namespace anakin { @@ -10,6 +11,9 @@ SaberStatus VenderConv2DAct: std::vector& outputs, ConvActiveParam& param, Context& ctx) { + if (_use_saber_act) { + _saber_act.create(inputs, outputs, param.activation_param, ctx); + } if (!(&ctx == this->_ctx)) { if (_handle != NULL) { CUDNN_CHECK(cudnnDestroy(_handle)); @@ -65,7 +69,7 @@ SaberStatus VenderConv2DAct: inputs[0]->dims() - 2, pad_a, filter_stride_a, dilation_a); // set activation descriptor - if(param.has_active) { + if(param.has_active && !_use_saber_act) { cudnn::set_activation_des(&_active_descs, param.activation_param.active); } @@ -113,12 +117,11 @@ SaberStatus VenderConv2DAct: dispatch(const std::vector& inputs, std::vector& outputs, ConvActiveParam& param) { - const InDataType *in_data = (const InDataType*)inputs[0]->data(); InDataType *out_data = (InDataType*)outputs[0]->mutable_data(); const float *weight_data = (const float *) param.conv_param.weight()->data(); - if (param.has_active == false) { + if (_use_saber_act || param.has_active == false) { CUDNN_CHECK(cudnnConvolutionForward(_handle, cudnn::cudnnTypeWrapper::kOne(), _input_descs, in_data, @@ -140,6 +143,9 @@ SaberStatus VenderConv2DAct: _output_descs, out_data)); } + if (_use_saber_act) { + _saber_act.dispatch(inputs, outputs, param.activation_param); + } return SaberSuccess; } diff --git a/saber/funcs/impl/cuda/vender_conv_act.h b/saber/funcs/impl/cuda/vender_conv_act.h index ec72de353..965e6a5e5 100644 --- a/saber/funcs/impl/cuda/vender_conv_act.h +++ b/saber/funcs/impl/cuda/vender_conv_act.h @@ -17,7 +17,8 @@ #define ANAKIN_SABER_FUNCS_IMPL_CUDA_CUDNN_CONV_ACT_H #include "saber/funcs/impl/impl_conv_act.h" -#include "saber/funcs/impl/cuda/cudnn_helper.h" +#include "saber/funcs/impl/cuda/cudnn_helper.h" +#include "saber/funcs/impl/cuda/saber_activation.h" #include namespace anakin{ @@ -119,6 +120,10 @@ class VenderConv2DAct& outputs, ConvActiveParam& param, Context& ctx) { // ---- init cudnn resources ---- + if (param.activation_param.active!= Active_relu) { + _use_saber_act = true; + _saber_act.init(inputs, outputs, param.activation_param, ctx); + } _workspaceSizeInBytes = 0; _workspaceData = NULL; @@ -192,6 +197,9 @@ class VenderConv2DAct _saber_act; void *x8_data; void *y8_data; From 67f08f1b65dbd6f80cefb3181f7a991b5e781a42 Mon Sep 17 00:00:00 2001 From: throneclay Date: Thu, 13 Sep 2018 02:01:49 -0400 Subject: [PATCH 35/51] fix conv act bug --- saber/funcs/impl/cuda/vender_conv_act.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/saber/funcs/impl/cuda/vender_conv_act.cpp b/saber/funcs/impl/cuda/vender_conv_act.cpp index c7b3e3192..d973daef0 100644 --- a/saber/funcs/impl/cuda/vender_conv_act.cpp +++ b/saber/funcs/impl/cuda/vender_conv_act.cpp @@ -144,7 +144,7 @@ SaberStatus VenderConv2DAct: } if (_use_saber_act) { - _saber_act.dispatch(inputs, outputs, param.activation_param); + _saber_act.dispatch(outputs, outputs, param.activation_param); } return SaberSuccess; } From db7411a4c452cd354f6016d507d502aa48a9ffa6 Mon Sep 17 00:00:00 2001 From: shixiaowei02 Date: Sat, 15 Sep 2018 19:26:42 +0800 Subject: [PATCH 36/51] fix prior_box bug --- .../parser/caffe/caffe_layer_param_transmit.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py b/tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py index 436d3be50..59ddcc6fc 100755 --- a/tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py +++ b/tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py @@ -1098,13 +1098,14 @@ def Parser_axpy(args): def Parser_priorbox(args): layer = args[1] prior_box_param = layer.prior_box_param - OpsRegister()["PriorBox"].min_size = list(prior_box_param.min_size) - OpsRegister()["PriorBox"].max_size = list(prior_box_param.max_size) - OpsRegister()["PriorBox"].aspect_ratio = list(prior_box_param.aspect_ratio) - OpsRegister()["PriorBox"].fixed_size = list(prior_box_param.fixed_size) - OpsRegister()["PriorBox"].fixed_ratio = list(prior_box_param.fixed_ratio) - OpsRegister()["PriorBox"].density = list(prior_box_param.density) - OpsRegister()["PriorBox"].aspect_ratio = list(prior_box_param.aspect_ratio) + if prior_box_param.HasField('aspect_ratio'): + OpsRegister()["PriorBox"].min_size = list(prior_box_param.min_size) + OpsRegister()["PriorBox"].max_size = list(prior_box_param.max_size) + OpsRegister()["PriorBox"].aspect_ratio = list(prior_box_param.aspect_ratio) + if prior_box_param.HasField('density'): + OpsRegister()["PriorBox"].fixed_size = list(prior_box_param.fixed_size) + OpsRegister()["PriorBox"].fixed_ratio = list(prior_box_param.fixed_ratio) + OpsRegister()["PriorBox"].density = list(prior_box_param.density) OpsRegister()["PriorBox"].is_flip = prior_box_param.flip OpsRegister()["PriorBox"].is_clip = prior_box_param.clip OpsRegister()["PriorBox"].variance = list(prior_box_param.variance) From 0426146d59d63cee0a93acf493537d936b89e014 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Mon, 17 Sep 2018 17:16:07 +0800 Subject: [PATCH 37/51] add slice eltwise --- .../parser/caffe/parser_caffe.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tools/external_converter_v2/parser/caffe/parser_caffe.py b/tools/external_converter_v2/parser/caffe/parser_caffe.py index 9258ed04b..336fed4a0 100644 --- a/tools/external_converter_v2/parser/caffe/parser_caffe.py +++ b/tools/external_converter_v2/parser/caffe/parser_caffe.py @@ -41,6 +41,7 @@ def _DetectionArch(self): self._FilterNet() self._SplitInception(False) self._InsSplitBtwSliceConcat() + self._InsSplitBtwSliceEltwise() self._InsertSplits() self._ScatterInputLayer() # create input node @@ -267,6 +268,37 @@ def _InsSplitBtwSliceConcat(self): del self.net_parameter.layers[:] self.net_parameter.layers.extend(new_param.layer) + def _InsSplitBtwSliceEltwise(self): + ''' + Currently, the connection between Slice and Concat must be implemented via Split. + ''' + layers = self.net_parameter.layer or self.net_parameter.layers + top_blobs_of_slices = list() + btm_blobs_of_concats = list() + for layer in layers: + if layer.type == 'Slice': + top_blobs_of_slices.extend(layer.top) + elif layer.type == 'Eltwise': + btm_blobs_of_concats.extend(layer.bottom) + intersection_blobs = list(set(top_blobs_of_slices).intersection(set(btm_blobs_of_concats))) + new_param = NetParameter() + for layer in layers: + new_layer = new_param.layer.add() + new_layer.CopyFrom(layer) + if layer.type == 'Slice': + for top_blob in layer.top: + if top_blob in intersection_blobs: + split_param = new_param.layer.add() + split_param.bottom.append(top_blob) + split_param.top.append(top_blob) + split_param.name = 'Split_' + top_blob + split_param.type = 'Split' + if self.net_parameter.layer: + del self.net_parameter.layer[:] + self.net_parameter.layer.extend(new_param.layer) + else: + del self.net_parameter.layers[:] + self.net_parameter.layers.extend(new_param.layer) def _InsertSplits(self): """ @@ -579,6 +611,7 @@ def _Parsing_new(self): # add node to graph io self.graphIO.add_node(nodeIO()) + #print self.graphIO() return self.graphIO def _Parsing(self): From 04e3a797ef40c614ff07615b392c3f4268da5a1f Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Mon, 17 Sep 2018 17:18:42 +0800 Subject: [PATCH 38/51] update --- tools/external_converter_v2/parser/caffe/parser_caffe.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/external_converter_v2/parser/caffe/parser_caffe.py b/tools/external_converter_v2/parser/caffe/parser_caffe.py index 336fed4a0..43a6d8fe9 100644 --- a/tools/external_converter_v2/parser/caffe/parser_caffe.py +++ b/tools/external_converter_v2/parser/caffe/parser_caffe.py @@ -611,7 +611,6 @@ def _Parsing_new(self): # add node to graph io self.graphIO.add_node(nodeIO()) - #print self.graphIO() return self.graphIO def _Parsing(self): From a379ab7f3c8dfcd5ede68048cad40e0ce8fc4e86 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Mon, 17 Sep 2018 17:51:48 +0800 Subject: [PATCH 39/51] judge proto repeated field --- .../parser/caffe/caffe_layer_param_transmit.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py b/tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py index 59ddcc6fc..7fd1f9acb 100755 --- a/tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py +++ b/tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py @@ -1098,11 +1098,11 @@ def Parser_axpy(args): def Parser_priorbox(args): layer = args[1] prior_box_param = layer.prior_box_param - if prior_box_param.HasField('aspect_ratio'): + if len(prior_box_param.aspect_ratio) > 0: OpsRegister()["PriorBox"].min_size = list(prior_box_param.min_size) OpsRegister()["PriorBox"].max_size = list(prior_box_param.max_size) OpsRegister()["PriorBox"].aspect_ratio = list(prior_box_param.aspect_ratio) - if prior_box_param.HasField('density'): + if len(prior_box_param.density) > 0: OpsRegister()["PriorBox"].fixed_size = list(prior_box_param.fixed_size) OpsRegister()["PriorBox"].fixed_ratio = list(prior_box_param.fixed_ratio) OpsRegister()["PriorBox"].density = list(prior_box_param.density) From 216bf8772892575bb41e181d637f853c0a01e34d Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Mon, 17 Sep 2018 19:51:43 +0800 Subject: [PATCH 40/51] fix style --- .../parser/fluid/__init__.py | 1 - .../fluid/tools/{all_ones.py => feed_ones.py} | 42 ++++++++-------- .../fluid/tools/{all_txt.py => feed_txt.py} | 48 ++++++++++--------- 3 files changed, 48 insertions(+), 43 deletions(-) rename tools/external_converter_v2/parser/fluid/tools/{all_ones.py => feed_ones.py} (91%) rename tools/external_converter_v2/parser/fluid/tools/{all_txt.py => feed_txt.py} (92%) diff --git a/tools/external_converter_v2/parser/fluid/__init__.py b/tools/external_converter_v2/parser/fluid/__init__.py index 4d8ee7a14..4d195813c 100644 --- a/tools/external_converter_v2/parser/fluid/__init__.py +++ b/tools/external_converter_v2/parser/fluid/__init__.py @@ -1,5 +1,4 @@ #! /usr/bin/env python -# Copyright (c) 2017, Cuichaowen. All rights reserved. # -*- coding: utf-8 -*- from parser_fluid import * diff --git a/tools/external_converter_v2/parser/fluid/tools/all_ones.py b/tools/external_converter_v2/parser/fluid/tools/feed_ones.py similarity index 91% rename from tools/external_converter_v2/parser/fluid/tools/all_ones.py rename to tools/external_converter_v2/parser/fluid/tools/feed_ones.py index 6b7d5721a..06238f598 100644 --- a/tools/external_converter_v2/parser/fluid/tools/all_ones.py +++ b/tools/external_converter_v2/parser/fluid/tools/feed_ones.py @@ -1,3 +1,10 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +''' +A separate Fluid test file for feeding specific data. +''' + import sys import numpy as np import os @@ -11,6 +18,8 @@ GLB_batch_size = 1 def load_inference_model(model_path, exe): + ''' + ''' model_abs_path = os.path.join(model_path, 'model') param_abs_path = os.path.join(model_path, 'params') if os.path.exists(model_abs_path) and os.path.exists(param_abs_path): @@ -18,14 +27,14 @@ def load_inference_model(model_path, exe): else: return fluid.io.load_inference_model(model_path, exe) -def feed_ones(block, feed_target_names, batch_size = 1): +def feed_ones(block, feed_target_names, batch_size=1): + """ + """ feed_dict = dict() - def set_batch_size(shape, batch_size): if shape[0] == -1: shape[0] = batch_size return shape - def fill_ones(var_name, batch_size): var = block.var(var_name) np_shape = set_batch_size(list(var.shape), 1) @@ -39,22 +48,22 @@ def fill_ones(var_name, batch_size): } np_dtype = var_np[var.dtype] return np.ones(np_shape, dtype=np_dtype) - for feed_target_name in feed_target_names: feed_dict[feed_target_name] = fill_ones(feed_target_name, batch_size) return feed_dict - def draw(block, filename='debug'): + """ + """ dot_path = './' + filename + '.dot' pdf_path = './' + filename + '.pdf' debugger.draw_block_graphviz(block, path=dot_path) cmd = ["dot", "-Tpdf", dot_path, "-o", pdf_path] subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - -def fetch_tmp_vars(block, fetch_targets, var_names_list = None): - +def fetch_tmp_vars(block, fetch_targets, var_names_list=None): + """ + """ def var_names_of_fetch(fetch_targets): var_names_list = [] for var in fetch_targets: @@ -82,8 +91,9 @@ def var_names_of_fetch(fetch_targets): i = i + 1 return new_fetch_vars - -def print_results(results, fetch_targets, need_save = True): +def print_results(results, fetch_targets, need_save=True): + """ + """ for result in results: idx = results.index(result) print fetch_targets[idx] @@ -95,34 +105,27 @@ def print_results(results, fetch_targets, need_save = True): fetch_txt_fp.write(str(num) + '\n') fetch_txt_fp.close() - def fluid_inference_test(model_path): + """ + """ place = fluid.CPUPlace() exe = fluid.Executor(place) scope = fluid.core.Scope() - with fluid.scope_guard(scope): [net_program, feed_target_names, fetch_targets] = load_inference_model(model_path, exe) - global_block = net_program.global_block() draw(global_block) - feed_list = feed_ones(global_block, feed_target_names) fetch_targets = fetch_tmp_vars(global_block, fetch_targets, [GLB_arg_name]) - results = exe.run(program=net_program, feed=feed_list, fetch_list=fetch_targets, return_numpy=False) - print_results(results, fetch_targets) - - if __name__ == "__main__": - if len(sys.argv) == 1: raise NameError('Usage: python ./all_ones.py path/to/model arg_name batch_size') if len(sys.argv) > 1: @@ -131,6 +134,5 @@ def fluid_inference_test(model_path): GLB_arg_name = sys.argv[2] if len(sys.argv) > 3: GLB_batch_size = sys.argv[3] - fluid_inference_test(GLB_model_path) diff --git a/tools/external_converter_v2/parser/fluid/tools/all_txt.py b/tools/external_converter_v2/parser/fluid/tools/feed_txt.py similarity index 92% rename from tools/external_converter_v2/parser/fluid/tools/all_txt.py rename to tools/external_converter_v2/parser/fluid/tools/feed_txt.py index 8fcfafcfa..03ef81104 100644 --- a/tools/external_converter_v2/parser/fluid/tools/all_txt.py +++ b/tools/external_converter_v2/parser/fluid/tools/feed_txt.py @@ -1,3 +1,10 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- + +""" +A separate Fluid test file for feeding specific data. +""" + import sys import numpy as np import os @@ -20,8 +27,9 @@ GLB_arg_name = '' GLB_batch_size = 1 - def load_inference_model(model_path, exe): + """ + """ model_abs_path = os.path.join(model_path, 'model') param_abs_path = os.path.join(model_path, 'params') if os.path.exists(model_abs_path) and os.path.exists(param_abs_path): @@ -29,8 +37,9 @@ def load_inference_model(model_path, exe): else: return fluid.io.load_inference_model(model_path, exe) - def print_feed_fetch(block, feed_target_names, fetch_targets): + """ + """ tag_list = ["Index", "Name", "Shape", "Data Type", "Tensor Type"] def add_var_table(table, var, idx): table.add_row([idx, var.name, var.shape, str(var.dtype), str(var.type)]) @@ -53,9 +62,11 @@ def fetch_table(var_list): print "\n", "=========== FETCH TABLE ===========" print fetch_table(fetch_targets), "\n" - -def add_feed_list(feed_list, fluid_feed_dict=dict()): - +def add_feed_list(feed_list, fluid_feed_dict=None): + """ + """ + if fluid_feed_dict is None: + fluid_feed_dict = dict() def numpy_from_txt(txt_path, tensor_shape=list(), dtype=np.float32, @@ -82,27 +93,27 @@ def add_feed_var(input_dict, fluid_feed_dict): delim = None fluid_feed_dict[var_name] = numpy_from_txt(txt_path, tensor_shape, dtype, delim) return fluid_feed_dict - for input_dict in feed_list: add_feed_var(input_dict, fluid_feed_dict) return fluid_feed_dict - def draw(block, filename='debug'): + """ + """ dot_path = './' + filename + '.dot' pdf_path = './' + filename + '.pdf' debugger.draw_block_graphviz(block, path=dot_path) cmd = ["dot", "-Tpdf", dot_path, "-o", pdf_path] subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - -def fetch_tmp_vars(block, fetch_targets, var_names_list = None): +def fetch_tmp_vars(block, fetch_targets, var_names_list=None): + """ + """ def var_names_of_fetch(fetch_targets): var_names_list = [] for var in fetch_targets: var_names_list.append(var.name) return var_names_list - fetch_var = block.var('fetch') old_fetch_names = var_names_of_fetch(fetch_targets) new_fetch_vars = [] @@ -124,8 +135,9 @@ def var_names_of_fetch(fetch_targets): i = i + 1 return new_fetch_vars - -def print_results(results, fetch_targets, need_save = True): +def print_results(results, fetch_targets, need_save=True): + """ + """ for result in results: idx = results.index(result) print fetch_targets[idx] @@ -137,34 +149,28 @@ def print_results(results, fetch_targets, need_save = True): fetch_txt_fp.write(str(num) + '\n') fetch_txt_fp.close() - def fluid_inference_test(model_path, feed_list): + """ + """ place = fluid.CPUPlace() exe = fluid.Executor(place) scope = fluid.core.Scope() - with fluid.scope_guard(scope): [net_program, feed_target_names, fetch_targets] = load_inference_model(model_path, exe) - global_block = net_program.global_block() print_feed_fetch(global_block, feed_target_names, fetch_targets) draw(global_block) - feed_list = add_feed_list(feed_list) fetch_targets = fetch_tmp_vars(global_block, fetch_targets, [GLB_arg_name]) - results = exe.run(program=net_program, feed=feed_list, fetch_list=fetch_targets, return_numpy=False) - print_results(results, fetch_targets) - if __name__ == "__main__": - if len(sys.argv) == 1 and GLB_model_path == '': raise NameError('Usage: python ./all_ones.py path/to/model arg_name batch_size') if len(sys.argv) > 1 and GLB_model_path == '': @@ -173,6 +179,4 @@ def fluid_inference_test(model_path, feed_list): GLB_arg_name = sys.argv[2] if len(sys.argv) > 3: GLB_batch_size = sys.argv[3] - fluid_inference_test(GLB_model_path, GLB_feed_list) - From 4df42abf5d5b664cab1d6731efc6cdc9b17e06e3 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Wed, 19 Sep 2018 16:04:28 +0800 Subject: [PATCH 41/51] update normalize --- framework/operators/normalize.cpp | 16 ++++++++++------ saber/saber_funcs_param.h | 10 ++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/framework/operators/normalize.cpp b/framework/operators/normalize.cpp index 56cfa921c..db8ba69de 100644 --- a/framework/operators/normalize.cpp +++ b/framework/operators/normalize.cpp @@ -32,12 +32,16 @@ Status NormalizeHelper::InitParam() { auto eps = GET_PARAMETER(float, eps); auto p = GET_PARAMETER(int, p); - using pblock_type = PBlock::type, Ttype>; - auto input_scale = GET_PARAMETER(pblock_type, weight_1); - - saber::NormalizeParam> normalize_param(is_across_spatial, is_shared_channel, \ - &(input_scale.d_tensor()), eps, p); - _param_normalize = normalize_param; + if (FIND_PARAMETER(weight_1)) { + using pblock_type = PBlock::type, Ttype>; + auto input_scale = GET_PARAMETER(pblock_type, weight_1); + saber::NormalizeParam> normalize_param(is_across_spatial, is_shared_channel, \ + &(input_scale.d_tensor()), eps, p); + _param_normalize = normalize_param; + } else { + saber::NormalizeParam> normalize_param(is_across_spatial, is_shared_channel, eps, p); + _param_normalize = normalize_param; + } return Status::OK(); } diff --git a/saber/saber_funcs_param.h b/saber/saber_funcs_param.h index c2c045cff..260caf1a8 100644 --- a/saber/saber_funcs_param.h +++ b/saber/saber_funcs_param.h @@ -1515,7 +1515,17 @@ struct NormalizeParam { eps = eps_in; CHECK_EQ(p == 2 || p == 1, true) << "only support L1 and L2 norm"; } + NormalizeParam(bool is_across_spatial, bool is_shared_channel, \ + float eps_in = 1e-6f, int pin = 2) { + across_spatial = is_across_spatial; + channel_shared = is_shared_channel; + p = pin; + has_scale = false; + scale = nullptr; + eps = eps_in; + CHECK_EQ(p == 2 || p == 1, true) << "only support L1 and L2 norm"; + } NormalizeParam(const NormalizeParam& right) { channel_shared = right.channel_shared; across_spatial = right.across_spatial; From 1189a2ecaf6ce7d5c1069a06cf33400e39ddda39 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Thu, 20 Sep 2018 13:46:28 +0800 Subject: [PATCH 42/51] update interp --- .../caffe/caffe_layer_param_transmit.py | 13 +- .../parser/fluid/tools/debug.dot | 5104 +++++++++++++++++ .../parser/fluid/tools/debug.pdf | Bin 0 -> 152185 bytes .../tools/result_detection_output_0.tmp_0.txt | 552 ++ .../parser/fluid/tools/xcam_fluid.txt | 198 + .../parser/operations/ops.py | 7 + 6 files changed, 5873 insertions(+), 1 deletion(-) create mode 100644 tools/external_converter_v2/parser/fluid/tools/debug.dot create mode 100644 tools/external_converter_v2/parser/fluid/tools/debug.pdf create mode 100644 tools/external_converter_v2/parser/fluid/tools/result_detection_output_0.tmp_0.txt create mode 100644 tools/external_converter_v2/parser/fluid/tools/xcam_fluid.txt diff --git a/tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py b/tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py index 7fd1f9acb..f6a2a258e 100755 --- a/tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py +++ b/tools/external_converter_v2/parser/caffe/caffe_layer_param_transmit.py @@ -1174,6 +1174,16 @@ def Parser_relu6(args): OpsRegister()["Activation"].type = "ClippedRelu" OpsRegister()["Activation"].clip_relu_num = 6 +@ParserFeedDecorator("Interp") +def Parser_interp(args): + layer = args[1] + interp_param = layer.interp_param + OpsRegister()["Interp"].height = interp_param.height + OpsRegister()["Interp"].width = interp_param.width + OpsRegister()["Interp"].zoom_factor = interp_param.zoom_factor + OpsRegister()["Interp"].shrink_factor = interp_param.shrink_factor + OpsRegister()["Interp"].pad_beg = interp_param.pad_beg + OpsRegister()["Interp"].pad_end = interp_param.pad_end # caffe layer parameter parser map CAFFE_LAYER_PARSER = { @@ -1244,5 +1254,6 @@ def Parser_relu6(args): "ReLU6": OpsParam().set_parser(Parser_relu6), "Normalization": OpsParam().set_parser(Parser_normalize), "ShuffleChannel": OpsParam().set_parser(Parser_ShuffleChannel), - "RoisAnchorFeature": OpsParam().set_parser(Parser_rois_anchor_feature) + "RoisAnchorFeature": OpsParam().set_parser(Parser_rois_anchor_feature), + "Interp": OpsParam().set_parser(Parser_interp) } diff --git a/tools/external_converter_v2/parser/fluid/tools/debug.dot b/tools/external_converter_v2/parser/fluid/tools/debug.dot new file mode 100644 index 000000000..f350cddf2 --- /dev/null +++ b/tools/external_converter_v2/parser/fluid/tools/debug.dot @@ -0,0 +1,5104 @@ +digraph G { +title = "some graph" +rankdir="TB"; +concentrate="true"; +layout="dot"; + + + + +arg_168 [label="batch_norm_13.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_142 [label=< + + + + + +
+ +batch_norm_12.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_220 [label=< + + + + + +
+ +batch_norm_4.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_401 [label=< + + + + + +
+ +batch_norm_18.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_242 [label=< + + + + + +
+ +batch_norm_2.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 16 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_485 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_525 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_447 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_14 [label="transpose_7.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_515 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_471 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_368 [label="batch_norm_18.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_72 [label=< + + + + + +
+ +batch_norm_3.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 16 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_125 [label="batch_norm_33.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_210 [label=< + + + + + +
+ +batch_norm_22.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_342 [label="prior_box_0.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_226 [label="batch_norm_32.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_51 [label=< + + + + + +
+ +conv2d_32.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 24 + dims: 32 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_393 [label=< + + + + + +
+ +depthwise_conv2d_4.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + dims: 1 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_405 [label=< + + + + + +
+ +depthwise_conv2d_3.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + dims: 1 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_434 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_309 [label="concat_2.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_566 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_365 [label=< + + + + + +
+ +conv2d_17.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + dims: 32 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_385 [label=< + + + + + +
+ +conv2d_33.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 36 + dims: 32 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_272 [label=< + + + + + +
+ +conv2d_14.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + dims: 256 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_354 [label=< + + + + + +
+ +batch_norm_19.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_340 [label="batch_norm_19.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_92 [label=< + + + + + +
+ +batch_norm_29.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_602 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_493 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_381 [label="transpose_3.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_538 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_464 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_406 [label="conv2d_21.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_132 [label=< + + + + + +
+ +batch_norm_17.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_331 [label="conv2d_2.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_470 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_288 [label="batch_norm_17.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_206 [label="transpose_10.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_238 [label="batch_norm_10.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_71 [label="batch_norm_14.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_2 [label=< + + + + + +
+ +feed + +
+type: FEED_MINIBATCH
+
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_545 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_261 [label=< + + + + + +
+ +batch_norm_4.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_216 [label=< + + + + + +
+ +batch_norm_34.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_380 [label="prior_box_3.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_136 [label="prior_box_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_27 [label="batch_norm_14.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_117 [label="transpose_12.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_519 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_233 [label=< + + + + + +
+ +batch_norm_17.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_75 [label="batch_norm_10.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_376 [label=< + + + + + +
+ +conv2d_30.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 24 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_57 [label=< + + + + + +
+ +batch_norm_23.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_256 [label="batch_norm_4.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_308 [label="batch_norm_4.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_392 [label="conv2d_7.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_433 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_187 [label=< + + + + + +
+ +batch_norm_34.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_211 [label=< + + + + + +
+ +batch_norm_31.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_230 [label="batch_norm_8.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_33 [label="conv2d_16.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_171 [label=< + + + + + +
+ +batch_norm_11.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_567 [label=<prior_box> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_137 [label=< + + + + + +
+ +batch_norm_3.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 16 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_512 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_469 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_320 [label="conv2d_11.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_425 [label=<feed> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_409 [label="depthwise_conv2d_6.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_93 [label=< + + + + + +
+ +batch_norm_3.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 16 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_213 [label=< + + + + + +
+ +batch_norm_14.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_64 [label="batch_norm_13.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_473 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_350 [label="conv2d_25.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_184 [label="batch_norm_8.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_306 [label="transpose_2.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_63 [label="batch_norm_11.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_424 [label="prior_box_2.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_571 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_444 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_575 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_337 [label="reshape_5.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_273 [label="batch_norm_6.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_529 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_26 [label="batch_norm_0.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_176 [label="batch_norm_16.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_16 [label="reshape_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_122 [label=< + + + + + +
+ +batch_norm_29.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_329 [label="reshape_23.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_499 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_116 [label=< + + + + + +
+ +conv2d_23.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 18 + dims: 128 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_453 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_403 [label="batch_norm_9.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_84 [label=< + + + + + +
+ +batch_norm_20.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_255 [label="softmax_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_42 [label=< + + + + + +
+ +batch_norm_30.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_540 [label=<prior_box> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_441 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_326 [label="batch_norm_30.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_450 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_161 [label="batch_norm_11.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_572 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_430 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_506 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_455 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_222 [label=< + + + + + +
+ +batch_norm_26.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 256 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_266 [label=< + + + + + +
+ +conv2d_8.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + dims: 128 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_276 [label=< + + + + + +
+ +batch_norm_6.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_399 [label="depthwise_conv2d_12.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_449 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_40 [label=< + + + + + +
+ +batch_norm_1.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 8 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_45 [label="batch_norm_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_333 [label=< + + + + + +
+ +conv2d_2.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + dims: 16 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_18 [label=< + + + + + +
+ +batch_norm_18.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_270 [label=< + + + + + +
+ +conv2d_10.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + dims: 128 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_443 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_456 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_533 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_484 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_299 [label=< + + + + + +
+ +batch_norm_7.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_139 [label=< + + + + + +
+ +batch_norm_13.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_165 [label=< + + + + + +
+ +batch_norm_26.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 256 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_516 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_37 [label=< + + + + + +
+ +batch_norm_1.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 8 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_353 [label="depthwise_conv2d_4.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_358 [label=< + + + + + +
+ +conv2d_27.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 36 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_364 [label="conv2d_28.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_135 [label=< + + + + + +
+ +batch_norm_33.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 16 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_362 [label="conv2d_27.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_215 [label=< + + + + + +
+ +batch_norm_10.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_494 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_153 [label=< + + + + + +
+ +batch_norm_0.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 8 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_148 [label="batch_norm_1.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_404 [label="conv2d_18.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_17 [label=< + + + + + +
+ +batch_norm_28.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_39 [label="batch_norm_14.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_49 [label=< + + + + + +
+ +batch_norm_16.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_517 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_29 [label="batch_norm_3.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_589 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_336 [label="conv2d_22.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_124 [label="batch_norm_29.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_174 [label="conv2d_13.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_532 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_417 [label=< + + + + + +
+ +conv2d_32.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 24 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_289 [label=< + + + + + +
+ +batch_norm_8.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_157 [label=< + + + + + +
+ +batch_norm_22.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_396 [label=< + + + + + +
+ +depthwise_conv2d_0.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 8 + dims: 1 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_23 [label="batch_norm_6.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_311 [label="batch_norm_22.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_121 [label=< + + + + + +
+ +batch_norm_0.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 8 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_239 [label="depthwise_conv2d_10.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_73 [label="batch_norm_2.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_369 [label="conv2d_12.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_235 [label="batch_norm_9.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_163 [label="batch_norm_28.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_367 [label=< + + + + + +
+ +batch_norm_25.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 256 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_585 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_291 [label="conv2d_17.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_384 [label="prior_box_5.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_375 [label="conv2d_33.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_558 [label=<prior_box> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_293 [label="reshape_9.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_96 [label="reshape_1.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_129 [label="batch_norm_26.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_207 [label=< + + + + + +
+ +batch_norm_28.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_103 [label=< + + + + + +
+ +batch_norm_26.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 256 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_70 [label="depthwise_conv2d_11.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_20 [label=< + + + + + +
+ +batch_norm_6.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_477 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_598 [label=<concat> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_35 [label=< + + + + + +
+ +batch_norm_28.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_581 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_549 [label=<prior_box> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_167 [label=< + + + + + +
+ +depthwise_conv2d_9.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + dims: 1 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_81 [label="conv2d_28.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_553 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_402 [label="depthwise_conv2d_3.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_164 [label=< + + + + + +
+ +batch_norm_30.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_439 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_327 [label="batch_norm_26.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_144 [label="transpose_6.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_319 [label="conv2d_10.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_389 [label="conv2d_5.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_475 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_264 [label=< + + + + + +
+ +batch_norm_11.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_568 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_138 [label="conv2d_32.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_607 [label=<fetch> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_397 [label=< + + + + + +
+ +depthwise_conv2d_1.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 16 + dims: 1 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_382 [label=< + + + + + +
+ +batch_norm_25.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 256 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_271 [label="batch_norm_20.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_305 [label=< + + + + + +
+ +conv2d_3.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + dims: 32 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_201 [label=< + + + + + +
+ +batch_norm_23.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_159 [label="batch_norm_8.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_490 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_415 [label=< + + + + + +
+ +depthwise_conv2d_7.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + dims: 1 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_374 [label=< + + + + + +
+ +batch_norm_33.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 16 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_591 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_287 [label=< + + + + + +
+ +batch_norm_8.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_240 [label="batch_norm_19.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_596 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_339 [label="conv2d_22.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_420 [label="detection_output_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_197 [label=< + + + + + +
+ +batch_norm_19.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_312 [label=< + + + + + +
+ +conv2d_25.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 36 + dims: 256 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_505 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_244 [label=< + + + + + +
+ +batch_norm_21.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_155 [label="batch_norm_29.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_587 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_295 [label=< + + + + + +
+ +conv2d_21.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + dims: 16 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_298 [label="reshape_19.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_111 [label=< + + + + + +
+ +batch_norm_26.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 256 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_36 [label="batch_norm_25.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_217 [label=< + + + + + +
+ +batch_norm_15.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_56 [label=< + + + + + +
+ +batch_norm_0.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 8 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_263 [label=< + + + + + +
+ +depthwise_conv2d_11.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + dims: 1 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_101 [label="conv2d_30.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_411 [label=< + + + + + +
+ +batch_norm_5.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_594 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_314 [label="concat_3.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_323 [label="conv2d_15.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_318 [label="batch_norm_27.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_126 [label=< + + + + + +
+ +batch_norm_10.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_422 [label="reshape_24.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_146 [label=< + + + + + +
+ +batch_norm_25.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 256 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_193 [label=< + + + + + +
+ +batch_norm_27.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_543 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_579 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_219 [label="batch_norm_15.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_85 [label="batch_norm_2.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_182 [label="reshape_21.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_531 [label=<prior_box> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_9 [label="conv2d_29.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_218 [label="reshape_20.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_550 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_231 [label="batch_norm_15.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_360 [label="conv2d_27.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_188 [label=< + + + + + +
+ +batch_norm_18.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_76 [label=< + + + + + +
+ +batch_norm_29.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_310 [label="conv2d_1.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_59 [label="batch_norm_1.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_466 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_74 [label="batch_norm_13.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_100 [label=< + + + + + +
+ +batch_norm_7.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_190 [label="reshape_15.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_606 [label=<multiclass_nms> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_166 [label="conv2d_31.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_134 [label=< + + + + + +
+ +batch_norm_3.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 16 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_565 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_479 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_416 [label="depthwise_conv2d_8.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_212 [label=< + + + + + +
+ +batch_norm_23.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_379 [label="image" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_245 [label="prior_box_2.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_286 [label=< + + + + + +
+ +batch_norm_8.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_488 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_243 [label="batch_norm_20.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_6 [label="reshape_2.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_282 [label="batch_norm_7.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_348 [label="conv2d_24.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_300 [label="reshape_8.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_151 [label="batch_norm_3.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_324 [label=< + + + + + +
+ +conv2d_15.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + dims: 64 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_483 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_225 [label=< + + + + + +
+ +conv2d_7.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + dims: 128 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_315 [label="conv2d_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_259 [label=< + + + + + +
+ +batch_norm_9.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_301 [label="box_coder_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_551 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_555 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_257 [label=< + + + + + +
+ +batch_norm_22.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_413 [label=< + + + + + +
+ +batch_norm_21.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_185 [label="batch_norm_25.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_513 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_34 [label="conv2d_19.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_317 [label=< + + + + + +
+ +batch_norm_30.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_590 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_200 [label="batch_norm_31.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_32 [label="conv2d_26.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_412 [label=< + + + + + +
+ +depthwise_conv2d_6.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + dims: 1 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_603 [label=<softmax> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_357 [label="batch_norm_5.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_202 [label=< + + + + + +
+ +batch_norm_27.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_410 [label="depthwise_conv2d_1.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_541 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_437 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_521 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_534 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_414 [label=< + + + + + +
+ +conv2d_19.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + dims: 32 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_110 [label="batch_norm_24.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_522 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_8 [label="reshape_18.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_277 [label=< + + + + + +
+ +batch_norm_6.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_65 [label="conv2d_8.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_344 [label="conv2d_23.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_335 [label="conv2d_3.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_489 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_569 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_361 [label="transpose_11.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_278 [label="batch_norm_7.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_131 [label=< + + + + + +
+ +batch_norm_21.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_552 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_294 [label=< + + + + + +
+ +batch_norm_9.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_498 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_107 [label=< + + + + + +
+ +batch_norm_29.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_31 [label=< + + + + + +
+ +batch_norm_13.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_274 [label="batch_norm_6.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_584 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_332 [label="batch_norm_17.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_341 [label="batch_norm_4.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_232 [label="batch_norm_32.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_597 [label=<concat> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_109 [label=< + + + + + +
+ +conv2d_12.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 256 + dims: 128 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_510 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_467 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_192 [label=< + + + + + +
+ +batch_norm_17.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_25 [label=< + + + + + +
+ +batch_norm_32.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_275 [label="prior_box_3.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_504 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_102 [label="batch_norm_34.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_511 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_588 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_82 [label=< + + + + + +
+ +batch_norm_6.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_322 [label=< + + + + + +
+ +conv2d_11.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + dims: 128 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_419 [label="reshape_13.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_442 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_547 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_386 [label="batch_norm_19.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_169 [label="reshape_12.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_366 [label="conv2d_4.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_407 [label=< + + + + + +
+ +depthwise_conv2d_5.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + dims: 1 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_160 [label=< + + + + + +
+ +batch_norm_32.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_457 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_94 [label="batch_norm_16.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_604 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_559 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_52 [label=< + + + + + +
+ +batch_norm_5.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_43 [label=< + + + + + +
+ +batch_norm_10.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_133 [label="batch_norm_0.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_542 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_478 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_158 [label="transpose_8.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_156 [label="reshape_4.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_104 [label=< + + + + + +
+ +batch_norm_31.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_15 [label="reshape_10.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_189 [label=< + + + + + +
+ +conv2d_28.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 24 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_80 [label="batch_norm_12.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_253 [label="conv2d_30.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_562 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_267 [label="batch_norm_5.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_180 [label=< + + + + + +
+ +batch_norm_0.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 8 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_66 [label="batch_norm_10.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_118 [label=< + + + + + +
+ +batch_norm_20.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_601 [label=<box_coder> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_325 [label="depthwise_conv2d_9.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_520 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_98 [label="batch_norm_25.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_78 [label=< + + + + + +
+ +batch_norm_31.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_108 [label=< + + + + + +
+ +batch_norm_32.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_141 [label=< + + + + + +
+ +batch_norm_12.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_140 [label="batch_norm_30.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_13 [label=< + + + + + +
+ +batch_norm_14.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_83 [label=< + + + + + +
+ +conv2d_33.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 36 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_546 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_481 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_120 [label="prior_box_1.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_10 [label="reshape_16.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_537 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_438 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_527 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_501 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_461 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_307 [label=< + + + + + +
+ +batch_norm_14.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_536 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_130 [label=< + + + + + +
+ +batch_norm_34.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_436 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_191 [label=< + + + + + +
+ +batch_norm_24.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 256 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_462 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_359 [label=< + + + + + +
+ +conv2d_31.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 36 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_395 [label="conv2d_9.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_119 [label="transpose_9.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_451 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_173 [label="batch_norm_3.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_343 [label=< + + + + + +
+ +conv2d_24.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 24 + dims: 256 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_539 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_480 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_58 [label="batch_norm_12.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_145 [label="transpose_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_328 [label=< + + + + + +
+ +conv2d_18.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + dims: 64 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_421 [label="prior_box_1.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_172 [label="depthwise_conv2d_2.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_53 [label=< + + + + + +
+ +batch_norm_10.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_492 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_592 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_463 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_248 [label="batch_norm_12.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_24 [label="conv2d_14.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_292 [label=< + + + + + +
+ +batch_norm_8.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_246 [label=< + + + + + +
+ +batch_norm_5.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_241 [label=< + + + + + +
+ +batch_norm_19.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_371 [label="conv2d_31.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_582 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_560 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_181 [label="batch_norm_21.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_507 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_55 [label="transpose_4.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_19 [label="batch_norm_18.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_196 [label="batch_norm_24.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_363 [label=< + + + + + +
+ +conv2d_27.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 36 + dims: 128 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_175 [label="batch_norm_21.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_285 [label="batch_norm_7.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_580 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_372 [label=< + + + + + +
+ +conv2d_31.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 36 + dims: 64 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_114 [label=< + + + + + +
+ +batch_norm_20.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_432 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_68 [label=< + + + + + +
+ +batch_norm_2.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 16 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_482 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_269 [label=< + + + + + +
+ +batch_norm_5.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_321 [label="batch_norm_22.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_345 [label="conv2d_23.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_194 [label=< + + + + + +
+ +batch_norm_24.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 256 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_61 [label=< + + + + + +
+ +batch_norm_24.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 256 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_435 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_209 [label="batch_norm_31.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_123 [label="prior_box_4.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_302 [label="batch_norm_30.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_400 [label=< + + + + + +
+ +depthwise_conv2d_12.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 256 + dims: 1 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_503 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_459 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_557 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_21 [label=< + + + + + +
+ +batch_norm_19.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_224 [label=< + + + + + +
+ +batch_norm_16.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_445 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_593 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_112 [label="concat_1.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_370 [label=< + + + + + +
+ +conv2d_30.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 24 + dims: 64 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_595 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_99 [label=< + + + + + +
+ +batch_norm_32.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_502 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_5 [label="conv2d_24.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_237 [label=< + + + + + +
+ +conv2d_20.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 16 + dims: 64 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_251 [label=< + + + + + +
+ +conv2d_29.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 36 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_152 [label=< + + + + + +
+ +batch_norm_1.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 8 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_30 [label=< + + + + + +
+ +batch_norm_22.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_162 [label="batch_norm_15.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_564 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_228 [label="batch_norm_34.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_523 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_265 [label=< + + + + + +
+ +batch_norm_4.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_426 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_97 [label="batch_norm_28.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_347 [label=< + + + + + +
+ +conv2d_24.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 24 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_418 [label=< + + + + + +
+ +depthwise_conv2d_8.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + dims: 1 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_62 [label="batch_norm_27.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_204 [label="batch_norm_21.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_47 [label=< + + + + + +
+ +depthwise_conv2d_2.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + dims: 1 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_458 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_378 [label=< + + + + + +
+ +batch_norm_2.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 16 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_214 [label=< + + + + + +
+ +batch_norm_2.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 16 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_429 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_544 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_423 [label=< + + + + + +
+ +batch_norm_24.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 256 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_60 [label="batch_norm_1.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_460 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_387 [label=< + + + + + +
+ +conv2d_4.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + dims: 32 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_427 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_154 [label=< + + + + + +
+ +batch_norm_23.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_528 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_304 [label=< + + + + + +
+ +conv2d_22.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 12 + dims: 128 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_91 [label="batch_norm_26.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_398 [label=< + + + + + +
+ +depthwise_conv2d_10.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + dims: 1 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_454 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_199 [label=< + + + + + +
+ +batch_norm_28.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_79 [label="batch_norm_23.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_229 [label="batch_norm_31.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_1 [label=< + + + + + +
+ +fetch + +
+type: FETCH_LIST
+
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_179 [label="transpose_5.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_446 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_115 [label=< + + + + + +
+ +batch_norm_7.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_198 [label=< + + + + + +
+ +batch_norm_27.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_600 [label=<concat> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_183 [label="batch_norm_11.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_28 [label=< + + + + + +
+ +batch_norm_16.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_54 [label=< + + + + + +
+ +batch_norm_33.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 16 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_149 [label=< + + + + + +
+ +conv2d_23.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 18 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_373 [label="conv2d_32.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_514 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_95 [label=< + + + + + +
+ +batch_norm_11.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_177 [label=< + + + + + +
+ +batch_norm_9.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_205 [label=< + + + + + +
+ +batch_norm_31.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_283 [label="reshape_17.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_334 [label=< + + + + + +
+ +conv2d_22.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 12 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_147 [label=< + + + + + +
+ +batch_norm_14.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_86 [label="conv2d_26.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_497 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_316 [label=< + + + + + +
+ +conv2d_1.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 16 + dims: 8 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_518 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_330 [label="batch_norm_22.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_227 [label="batch_norm_20.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_50 [label="depthwise_conv2d_5.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_128 [label=< + + + + + +
+ +batch_norm_12.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_474 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_605 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_377 [label="conv2d_33.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_524 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_203 [label="batch_norm_33.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_89 [label=< + + + + + +
+ +conv2d_13.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 256 + dims: 256 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_252 [label="batch_norm_34.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_247 [label=< + + + + + +
+ +batch_norm_27.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_383 [label="batch_norm_17.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_391 [label="batch_norm_27.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_69 [label="conv2d_20.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_452 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_394 [label="batch_norm_28.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_509 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_351 [label="batch_norm_23.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_495 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_11 [label="reshape_14.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_563 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_4 [label="reshape_25.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_577 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_556 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_250 [label="depthwise_conv2d_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_548 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_491 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_268 [label="batch_norm_5.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_313 [label="transpose_1.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_486 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_349 [label=< + + + + + +
+ +conv2d_25.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 36 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_303 [label="concat_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_281 [label="prior_box_4.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_87 [label=< + + + + + +
+ +batch_norm_17.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_186 [label=< + + + + + +
+ +batch_norm_21.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_258 [label="batch_norm_9.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_260 [label="conv2d_6.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_440 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_508 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_352 [label="conv2d_25.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_290 [label=< + + + + + +
+ +batch_norm_13.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_573 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_90 [label=< + + + + + +
+ +batch_norm_12.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_576 [label=<prior_box> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_143 [label=< + + + + + +
+ +conv2d_5.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + dims: 64 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_280 [label=< + + + + + +
+ +conv2d_0.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 8 + dims: 3 + dims: 3 + dims: 3 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_223 [label="batch_norm_2.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_38 [label="reshape_6.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_46 [label=< + + + + + +
+ +batch_norm_11.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_254 [label="reshape_22.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_106 [label="reshape_7.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_41 [label=< + + + + + +
+ +batch_norm_16.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_178 [label="batch_norm_23.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_472 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_356 [label=< + + + + + +
+ +conv2d_26.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 24 + dims: 128 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_195 [label="batch_norm_24.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_583 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_338 [label=< + + + + + +
+ +batch_norm_33.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 16 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_530 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_150 [label="batch_norm_33.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_3 [label="reshape_3.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_448 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_127 [label=< + + + + + +
+ +batch_norm_4.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_77 [label=< + + + + + +
+ +batch_norm_7.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_262 [label=< + + + + + +
+ +batch_norm_13.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_44 [label=< + + + + + +
+ +batch_norm_15.w_2 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_67 [label=< + + + + + +
+ +conv2d_29.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 36 + dims: 64 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_236 [label="batch_norm_32.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_221 [label="batch_norm_16.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_408 [label=< + + + + + +
+ +conv2d_16.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + dims: 128 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_468 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_88 [label="prior_box_5.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_22 [label=< + + + + + +
+ +batch_norm_1.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 8 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_428 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_570 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_586 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_431 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_500 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_355 [label=< + + + + + +
+ +conv2d_26.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 24 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_113 [label=< + + + + + +
+ +batch_norm_20.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_476 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_578 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_170 [label=< + + + + + +
+ +batch_norm_15.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_208 [label=< + + + + + +
+ +batch_norm_25.b_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 256 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_496 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_574 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_388 [label=< + + + + + +
+ +batch_norm_34.w_1 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 32 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_297 [label=< + + + + + +
+ +batch_norm_9.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_284 [label=< + + + + + +
+ +batch_norm_15.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_561 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_487 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +arg_296 [label="depthwise_conv2d_7.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_48 [label="batch_norm_29.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +param_249 [label=< + + + + + +
+ +conv2d_28.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 24 + dims: 64 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_7 [label="conv2d_29.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +arg_12 [label="reshape_11.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_465 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_346 [label=< + + + + + +
+ +conv2d_9.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + dims: 128 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +arg_234 [label="batch_norm_18.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; +op_535 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +op_526 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_390 [label=< + + + + + +
+ +conv2d_6.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + dims: 64 + dims: 1 + dims: 1 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_554 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_279 [label=< + + + + + +
+ +batch_norm_30.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 64 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +op_599 [label=<concat> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; +param_105 [label=< + + + + + +
+ +batch_norm_18.w_0 + +
+type: LOD_TENSOR
lod_tensor { + tensor { + data_type: FP32 + dims: 128 + } +} + +
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; +param_2 -> op_425 [color="#00000"] +op_425 -> arg_379 [color="#00000"] +param_280 -> op_426 [color="#00000"] +arg_379 -> op_426 [color="#00000"] +op_426 -> arg_315 [color="#00000"] +param_180 -> op_427 [color="#00000"] +param_153 -> op_427 [color="#00000"] +param_121 -> op_427 [color="#00000"] +param_56 -> op_427 [color="#00000"] +arg_315 -> op_427 [color="#00000"] +op_427 -> param_153 [color="#00000"] +op_427 -> arg_45 [color="#00000"] +op_427 -> arg_133 [color="#00000"] +op_427 -> param_56 [color="#00000"] +op_427 -> arg_26 [color="#00000"] +arg_26 -> op_428 [color="#00000"] +op_428 -> arg_26 [color="#00000"] +param_396 -> op_429 [color="#00000"] +arg_26 -> op_429 [color="#00000"] +op_429 -> arg_250 [color="#00000"] +param_37 -> op_430 [color="#00000"] +param_22 -> op_430 [color="#00000"] +param_152 -> op_430 [color="#00000"] +param_40 -> op_430 [color="#00000"] +arg_250 -> op_430 [color="#00000"] +op_430 -> param_22 [color="#00000"] +op_430 -> arg_59 [color="#00000"] +op_430 -> arg_60 [color="#00000"] +op_430 -> param_40 [color="#00000"] +op_430 -> arg_148 [color="#00000"] +arg_148 -> op_431 [color="#00000"] +op_431 -> arg_148 [color="#00000"] +param_316 -> op_432 [color="#00000"] +arg_148 -> op_432 [color="#00000"] +op_432 -> arg_310 [color="#00000"] +param_378 -> op_433 [color="#00000"] +param_242 -> op_433 [color="#00000"] +param_68 -> op_433 [color="#00000"] +param_214 -> op_433 [color="#00000"] +arg_310 -> op_433 [color="#00000"] +op_433 -> param_242 [color="#00000"] +op_433 -> arg_73 [color="#00000"] +op_433 -> arg_223 [color="#00000"] +op_433 -> param_214 [color="#00000"] +op_433 -> arg_85 [color="#00000"] +arg_85 -> op_434 [color="#00000"] +op_434 -> arg_85 [color="#00000"] +param_397 -> op_435 [color="#00000"] +arg_85 -> op_435 [color="#00000"] +op_435 -> arg_410 [color="#00000"] +param_134 -> op_436 [color="#00000"] +param_72 -> op_436 [color="#00000"] +param_93 -> op_436 [color="#00000"] +param_137 -> op_436 [color="#00000"] +arg_410 -> op_436 [color="#00000"] +op_436 -> param_72 [color="#00000"] +op_436 -> arg_151 [color="#00000"] +op_436 -> arg_173 [color="#00000"] +op_436 -> param_137 [color="#00000"] +op_436 -> arg_29 [color="#00000"] +arg_29 -> op_437 [color="#00000"] +op_437 -> arg_29 [color="#00000"] +param_333 -> op_438 [color="#00000"] +arg_29 -> op_438 [color="#00000"] +op_438 -> arg_331 [color="#00000"] +param_127 -> op_439 [color="#00000"] +param_220 -> op_439 [color="#00000"] +param_261 -> op_439 [color="#00000"] +param_265 -> op_439 [color="#00000"] +arg_331 -> op_439 [color="#00000"] +op_439 -> param_220 [color="#00000"] +op_439 -> arg_341 [color="#00000"] +op_439 -> arg_256 [color="#00000"] +op_439 -> param_265 [color="#00000"] +op_439 -> arg_308 [color="#00000"] +arg_308 -> op_440 [color="#00000"] +op_440 -> arg_308 [color="#00000"] +param_47 -> op_441 [color="#00000"] +arg_308 -> op_441 [color="#00000"] +op_441 -> arg_172 [color="#00000"] +param_246 -> op_442 [color="#00000"] +param_52 -> op_442 [color="#00000"] +param_411 -> op_442 [color="#00000"] +param_269 -> op_442 [color="#00000"] +arg_172 -> op_442 [color="#00000"] +op_442 -> param_52 [color="#00000"] +op_442 -> arg_267 [color="#00000"] +op_442 -> arg_357 [color="#00000"] +op_442 -> param_269 [color="#00000"] +op_442 -> arg_268 [color="#00000"] +arg_268 -> op_443 [color="#00000"] +op_443 -> arg_268 [color="#00000"] +param_305 -> op_444 [color="#00000"] +arg_268 -> op_444 [color="#00000"] +op_444 -> arg_335 [color="#00000"] +param_82 -> op_445 [color="#00000"] +param_277 -> op_445 [color="#00000"] +param_276 -> op_445 [color="#00000"] +param_20 -> op_445 [color="#00000"] +arg_335 -> op_445 [color="#00000"] +op_445 -> param_277 [color="#00000"] +op_445 -> arg_273 [color="#00000"] +op_445 -> arg_23 [color="#00000"] +op_445 -> param_20 [color="#00000"] +op_445 -> arg_274 [color="#00000"] +arg_274 -> op_446 [color="#00000"] +op_446 -> arg_274 [color="#00000"] +param_405 -> op_447 [color="#00000"] +arg_274 -> op_447 [color="#00000"] +op_447 -> arg_402 [color="#00000"] +param_299 -> op_448 [color="#00000"] +param_77 -> op_448 [color="#00000"] +param_115 -> op_448 [color="#00000"] +param_100 -> op_448 [color="#00000"] +arg_402 -> op_448 [color="#00000"] +op_448 -> param_77 [color="#00000"] +op_448 -> arg_278 [color="#00000"] +op_448 -> arg_282 [color="#00000"] +op_448 -> param_100 [color="#00000"] +op_448 -> arg_285 [color="#00000"] +arg_285 -> op_449 [color="#00000"] +op_449 -> arg_285 [color="#00000"] +param_387 -> op_450 [color="#00000"] +arg_285 -> op_450 [color="#00000"] +op_450 -> arg_366 [color="#00000"] +param_286 -> op_451 [color="#00000"] +param_289 -> op_451 [color="#00000"] +param_287 -> op_451 [color="#00000"] +param_292 -> op_451 [color="#00000"] +arg_366 -> op_451 [color="#00000"] +op_451 -> param_289 [color="#00000"] +op_451 -> arg_230 [color="#00000"] +op_451 -> arg_159 [color="#00000"] +op_451 -> param_292 [color="#00000"] +op_451 -> arg_184 [color="#00000"] +arg_184 -> op_452 [color="#00000"] +op_452 -> arg_184 [color="#00000"] +param_393 -> op_453 [color="#00000"] +arg_184 -> op_453 [color="#00000"] +op_453 -> arg_353 [color="#00000"] +param_294 -> op_454 [color="#00000"] +param_259 -> op_454 [color="#00000"] +param_297 -> op_454 [color="#00000"] +param_177 -> op_454 [color="#00000"] +arg_353 -> op_454 [color="#00000"] +op_454 -> param_259 [color="#00000"] +op_454 -> arg_235 [color="#00000"] +op_454 -> arg_258 [color="#00000"] +op_454 -> param_177 [color="#00000"] +op_454 -> arg_403 [color="#00000"] +arg_403 -> op_455 [color="#00000"] +op_455 -> arg_403 [color="#00000"] +param_143 -> op_456 [color="#00000"] +arg_403 -> op_456 [color="#00000"] +op_456 -> arg_389 [color="#00000"] +param_53 -> op_457 [color="#00000"] +param_126 -> op_457 [color="#00000"] +param_215 -> op_457 [color="#00000"] +param_43 -> op_457 [color="#00000"] +arg_389 -> op_457 [color="#00000"] +op_457 -> param_126 [color="#00000"] +op_457 -> arg_66 [color="#00000"] +op_457 -> arg_238 [color="#00000"] +op_457 -> param_43 [color="#00000"] +op_457 -> arg_75 [color="#00000"] +arg_75 -> op_458 [color="#00000"] +op_458 -> arg_75 [color="#00000"] +param_407 -> op_459 [color="#00000"] +arg_75 -> op_459 [color="#00000"] +op_459 -> arg_50 [color="#00000"] +param_46 -> op_460 [color="#00000"] +param_264 -> op_460 [color="#00000"] +param_171 -> op_460 [color="#00000"] +param_95 -> op_460 [color="#00000"] +arg_50 -> op_460 [color="#00000"] +op_460 -> param_264 [color="#00000"] +op_460 -> arg_183 [color="#00000"] +op_460 -> arg_161 [color="#00000"] +op_460 -> param_95 [color="#00000"] +op_460 -> arg_63 [color="#00000"] +arg_63 -> op_461 [color="#00000"] +op_461 -> arg_63 [color="#00000"] +param_390 -> op_462 [color="#00000"] +arg_63 -> op_462 [color="#00000"] +op_462 -> arg_260 [color="#00000"] +param_128 -> op_463 [color="#00000"] +param_142 -> op_463 [color="#00000"] +param_141 -> op_463 [color="#00000"] +param_90 -> op_463 [color="#00000"] +arg_260 -> op_463 [color="#00000"] +op_463 -> param_142 [color="#00000"] +op_463 -> arg_248 [color="#00000"] +op_463 -> arg_58 [color="#00000"] +op_463 -> param_90 [color="#00000"] +op_463 -> arg_80 [color="#00000"] +arg_80 -> op_464 [color="#00000"] +op_464 -> arg_80 [color="#00000"] +param_412 -> op_465 [color="#00000"] +arg_80 -> op_465 [color="#00000"] +op_465 -> arg_409 [color="#00000"] +param_290 -> op_466 [color="#00000"] +param_139 -> op_466 [color="#00000"] +param_262 -> op_466 [color="#00000"] +param_31 -> op_466 [color="#00000"] +arg_409 -> op_466 [color="#00000"] +op_466 -> param_139 [color="#00000"] +op_466 -> arg_64 [color="#00000"] +op_466 -> arg_168 [color="#00000"] +op_466 -> param_31 [color="#00000"] +op_466 -> arg_74 [color="#00000"] +arg_74 -> op_467 [color="#00000"] +op_467 -> arg_74 [color="#00000"] +param_225 -> op_468 [color="#00000"] +arg_74 -> op_468 [color="#00000"] +op_468 -> arg_392 [color="#00000"] +param_213 -> op_469 [color="#00000"] +param_147 -> op_469 [color="#00000"] +param_13 -> op_469 [color="#00000"] +param_307 -> op_469 [color="#00000"] +arg_392 -> op_469 [color="#00000"] +op_469 -> param_147 [color="#00000"] +op_469 -> arg_71 [color="#00000"] +op_469 -> arg_39 [color="#00000"] +op_469 -> param_307 [color="#00000"] +op_469 -> arg_27 [color="#00000"] +arg_27 -> op_470 [color="#00000"] +op_470 -> arg_27 [color="#00000"] +param_415 -> op_471 [color="#00000"] +arg_27 -> op_471 [color="#00000"] +op_471 -> arg_296 [color="#00000"] +param_217 -> op_472 [color="#00000"] +param_170 -> op_472 [color="#00000"] +param_284 -> op_472 [color="#00000"] +param_44 -> op_472 [color="#00000"] +arg_296 -> op_472 [color="#00000"] +op_472 -> param_170 [color="#00000"] +op_472 -> arg_231 [color="#00000"] +op_472 -> arg_219 [color="#00000"] +op_472 -> param_44 [color="#00000"] +op_472 -> arg_162 [color="#00000"] +arg_162 -> op_473 [color="#00000"] +op_473 -> arg_162 [color="#00000"] +param_266 -> op_474 [color="#00000"] +arg_162 -> op_474 [color="#00000"] +op_474 -> arg_65 [color="#00000"] +param_49 -> op_475 [color="#00000"] +param_41 -> op_475 [color="#00000"] +param_28 -> op_475 [color="#00000"] +param_224 -> op_475 [color="#00000"] +arg_65 -> op_475 [color="#00000"] +op_475 -> param_41 [color="#00000"] +op_475 -> arg_221 [color="#00000"] +op_475 -> arg_176 [color="#00000"] +op_475 -> param_224 [color="#00000"] +op_475 -> arg_94 [color="#00000"] +arg_94 -> op_476 [color="#00000"] +op_476 -> arg_94 [color="#00000"] +param_418 -> op_477 [color="#00000"] +arg_94 -> op_477 [color="#00000"] +op_477 -> arg_416 [color="#00000"] +param_192 -> op_478 [color="#00000"] +param_233 -> op_478 [color="#00000"] +param_132 -> op_478 [color="#00000"] +param_87 -> op_478 [color="#00000"] +arg_416 -> op_478 [color="#00000"] +op_478 -> param_233 [color="#00000"] +op_478 -> arg_332 [color="#00000"] +op_478 -> arg_383 [color="#00000"] +op_478 -> param_87 [color="#00000"] +op_478 -> arg_288 [color="#00000"] +arg_288 -> op_479 [color="#00000"] +op_479 -> arg_288 [color="#00000"] +param_346 -> op_480 [color="#00000"] +arg_288 -> op_480 [color="#00000"] +op_480 -> arg_395 [color="#00000"] +param_18 -> op_481 [color="#00000"] +param_188 -> op_481 [color="#00000"] +param_105 -> op_481 [color="#00000"] +param_401 -> op_481 [color="#00000"] +arg_395 -> op_481 [color="#00000"] +op_481 -> param_188 [color="#00000"] +op_481 -> arg_234 [color="#00000"] +op_481 -> arg_368 [color="#00000"] +op_481 -> param_401 [color="#00000"] +op_481 -> arg_19 [color="#00000"] +arg_19 -> op_482 [color="#00000"] +op_482 -> arg_19 [color="#00000"] +param_167 -> op_483 [color="#00000"] +arg_19 -> op_483 [color="#00000"] +op_483 -> arg_325 [color="#00000"] +param_354 -> op_484 [color="#00000"] +param_241 -> op_484 [color="#00000"] +param_197 -> op_484 [color="#00000"] +param_21 -> op_484 [color="#00000"] +arg_325 -> op_484 [color="#00000"] +op_484 -> param_241 [color="#00000"] +op_484 -> arg_386 [color="#00000"] +op_484 -> arg_240 [color="#00000"] +op_484 -> param_21 [color="#00000"] +op_484 -> arg_340 [color="#00000"] +arg_340 -> op_485 [color="#00000"] +op_485 -> arg_340 [color="#00000"] +param_270 -> op_486 [color="#00000"] +arg_340 -> op_486 [color="#00000"] +op_486 -> arg_319 [color="#00000"] +param_84 -> op_487 [color="#00000"] +param_114 -> op_487 [color="#00000"] +param_113 -> op_487 [color="#00000"] +param_118 -> op_487 [color="#00000"] +arg_319 -> op_487 [color="#00000"] +op_487 -> param_114 [color="#00000"] +op_487 -> arg_243 [color="#00000"] +op_487 -> arg_227 [color="#00000"] +op_487 -> param_118 [color="#00000"] +op_487 -> arg_271 [color="#00000"] +arg_271 -> op_488 [color="#00000"] +op_488 -> arg_271 [color="#00000"] +param_398 -> op_489 [color="#00000"] +arg_271 -> op_489 [color="#00000"] +op_489 -> arg_239 [color="#00000"] +param_131 -> op_490 [color="#00000"] +param_244 -> op_490 [color="#00000"] +param_186 -> op_490 [color="#00000"] +param_413 -> op_490 [color="#00000"] +arg_239 -> op_490 [color="#00000"] +op_490 -> param_244 [color="#00000"] +op_490 -> arg_175 [color="#00000"] +op_490 -> arg_204 [color="#00000"] +op_490 -> param_413 [color="#00000"] +op_490 -> arg_181 [color="#00000"] +arg_181 -> op_491 [color="#00000"] +op_491 -> arg_181 [color="#00000"] +param_322 -> op_492 [color="#00000"] +arg_181 -> op_492 [color="#00000"] +op_492 -> arg_320 [color="#00000"] +param_30 -> op_493 [color="#00000"] +param_257 -> op_493 [color="#00000"] +param_210 -> op_493 [color="#00000"] +param_157 -> op_493 [color="#00000"] +arg_320 -> op_493 [color="#00000"] +op_493 -> param_257 [color="#00000"] +op_493 -> arg_311 [color="#00000"] +op_493 -> arg_330 [color="#00000"] +op_493 -> param_157 [color="#00000"] +op_493 -> arg_321 [color="#00000"] +arg_321 -> op_494 [color="#00000"] +op_494 -> arg_321 [color="#00000"] +param_263 -> op_495 [color="#00000"] +arg_321 -> op_495 [color="#00000"] +op_495 -> arg_70 [color="#00000"] +param_212 -> op_496 [color="#00000"] +param_57 -> op_496 [color="#00000"] +param_201 -> op_496 [color="#00000"] +param_154 -> op_496 [color="#00000"] +arg_70 -> op_496 [color="#00000"] +op_496 -> param_57 [color="#00000"] +op_496 -> arg_79 [color="#00000"] +op_496 -> arg_351 [color="#00000"] +op_496 -> param_154 [color="#00000"] +op_496 -> arg_178 [color="#00000"] +arg_178 -> op_497 [color="#00000"] +op_497 -> arg_178 [color="#00000"] +param_109 -> op_498 [color="#00000"] +arg_178 -> op_498 [color="#00000"] +op_498 -> arg_369 [color="#00000"] +param_194 -> op_499 [color="#00000"] +param_61 -> op_499 [color="#00000"] +param_423 -> op_499 [color="#00000"] +param_191 -> op_499 [color="#00000"] +arg_369 -> op_499 [color="#00000"] +op_499 -> param_61 [color="#00000"] +op_499 -> arg_196 [color="#00000"] +op_499 -> arg_110 [color="#00000"] +op_499 -> param_191 [color="#00000"] +op_499 -> arg_195 [color="#00000"] +arg_195 -> op_500 [color="#00000"] +op_500 -> arg_195 [color="#00000"] +param_400 -> op_501 [color="#00000"] +arg_195 -> op_501 [color="#00000"] +op_501 -> arg_399 [color="#00000"] +param_208 -> op_502 [color="#00000"] +param_367 -> op_502 [color="#00000"] +param_382 -> op_502 [color="#00000"] +param_146 -> op_502 [color="#00000"] +arg_399 -> op_502 [color="#00000"] +op_502 -> param_367 [color="#00000"] +op_502 -> arg_98 [color="#00000"] +op_502 -> arg_185 [color="#00000"] +op_502 -> param_146 [color="#00000"] +op_502 -> arg_36 [color="#00000"] +arg_36 -> op_503 [color="#00000"] +op_503 -> arg_36 [color="#00000"] +param_89 -> op_504 [color="#00000"] +arg_36 -> op_504 [color="#00000"] +op_504 -> arg_174 [color="#00000"] +param_222 -> op_505 [color="#00000"] +param_111 -> op_505 [color="#00000"] +param_103 -> op_505 [color="#00000"] +param_165 -> op_505 [color="#00000"] +arg_174 -> op_505 [color="#00000"] +op_505 -> param_111 [color="#00000"] +op_505 -> arg_327 [color="#00000"] +op_505 -> arg_91 [color="#00000"] +op_505 -> param_165 [color="#00000"] +op_505 -> arg_129 [color="#00000"] +arg_129 -> op_506 [color="#00000"] +op_506 -> arg_129 [color="#00000"] +param_272 -> op_507 [color="#00000"] +arg_129 -> op_507 [color="#00000"] +op_507 -> arg_24 [color="#00000"] +param_247 -> op_508 [color="#00000"] +param_202 -> op_508 [color="#00000"] +param_198 -> op_508 [color="#00000"] +param_193 -> op_508 [color="#00000"] +arg_24 -> op_508 [color="#00000"] +op_508 -> param_202 [color="#00000"] +op_508 -> arg_62 [color="#00000"] +op_508 -> arg_391 [color="#00000"] +op_508 -> param_193 [color="#00000"] +op_508 -> arg_318 [color="#00000"] +arg_318 -> op_509 [color="#00000"] +op_509 -> arg_318 [color="#00000"] +param_324 -> op_510 [color="#00000"] +arg_318 -> op_510 [color="#00000"] +op_510 -> arg_323 [color="#00000"] +param_207 -> op_511 [color="#00000"] +param_35 -> op_511 [color="#00000"] +param_17 -> op_511 [color="#00000"] +param_199 -> op_511 [color="#00000"] +arg_323 -> op_511 [color="#00000"] +op_511 -> param_35 [color="#00000"] +op_511 -> arg_394 [color="#00000"] +op_511 -> arg_163 [color="#00000"] +op_511 -> param_199 [color="#00000"] +op_511 -> arg_97 [color="#00000"] +arg_97 -> op_512 [color="#00000"] +op_512 -> arg_97 [color="#00000"] +param_408 -> op_513 [color="#00000"] +arg_97 -> op_513 [color="#00000"] +op_513 -> arg_33 [color="#00000"] +param_107 -> op_514 [color="#00000"] +param_122 -> op_514 [color="#00000"] +param_76 -> op_514 [color="#00000"] +param_92 -> op_514 [color="#00000"] +arg_33 -> op_514 [color="#00000"] +op_514 -> param_122 [color="#00000"] +op_514 -> arg_155 [color="#00000"] +op_514 -> arg_48 [color="#00000"] +op_514 -> param_92 [color="#00000"] +op_514 -> arg_124 [color="#00000"] +arg_124 -> op_515 [color="#00000"] +op_515 -> arg_124 [color="#00000"] +param_365 -> op_516 [color="#00000"] +arg_124 -> op_516 [color="#00000"] +op_516 -> arg_291 [color="#00000"] +param_42 -> op_517 [color="#00000"] +param_317 -> op_517 [color="#00000"] +param_279 -> op_517 [color="#00000"] +param_164 -> op_517 [color="#00000"] +arg_291 -> op_517 [color="#00000"] +op_517 -> param_317 [color="#00000"] +op_517 -> arg_302 [color="#00000"] +op_517 -> arg_140 [color="#00000"] +op_517 -> param_164 [color="#00000"] +op_517 -> arg_326 [color="#00000"] +arg_326 -> op_518 [color="#00000"] +op_518 -> arg_326 [color="#00000"] +param_328 -> op_519 [color="#00000"] +arg_326 -> op_519 [color="#00000"] +op_519 -> arg_404 [color="#00000"] +param_205 -> op_520 [color="#00000"] +param_104 -> op_520 [color="#00000"] +param_211 -> op_520 [color="#00000"] +param_78 -> op_520 [color="#00000"] +arg_404 -> op_520 [color="#00000"] +op_520 -> param_104 [color="#00000"] +op_520 -> arg_229 [color="#00000"] +op_520 -> arg_209 [color="#00000"] +op_520 -> param_78 [color="#00000"] +op_520 -> arg_200 [color="#00000"] +arg_200 -> op_521 [color="#00000"] +op_521 -> arg_200 [color="#00000"] +param_414 -> op_522 [color="#00000"] +arg_200 -> op_522 [color="#00000"] +op_522 -> arg_34 [color="#00000"] +param_99 -> op_523 [color="#00000"] +param_108 -> op_523 [color="#00000"] +param_25 -> op_523 [color="#00000"] +param_160 -> op_523 [color="#00000"] +arg_34 -> op_523 [color="#00000"] +op_523 -> param_108 [color="#00000"] +op_523 -> arg_236 [color="#00000"] +op_523 -> arg_232 [color="#00000"] +op_523 -> param_160 [color="#00000"] +op_523 -> arg_226 [color="#00000"] +arg_226 -> op_524 [color="#00000"] +op_524 -> arg_226 [color="#00000"] +param_237 -> op_525 [color="#00000"] +arg_226 -> op_525 [color="#00000"] +op_525 -> arg_69 [color="#00000"] +param_54 -> op_526 [color="#00000"] +param_135 -> op_526 [color="#00000"] +param_338 -> op_526 [color="#00000"] +param_374 -> op_526 [color="#00000"] +arg_69 -> op_526 [color="#00000"] +op_526 -> param_135 [color="#00000"] +op_526 -> arg_125 [color="#00000"] +op_526 -> arg_203 [color="#00000"] +op_526 -> param_374 [color="#00000"] +op_526 -> arg_150 [color="#00000"] +arg_150 -> op_527 [color="#00000"] +op_527 -> arg_150 [color="#00000"] +param_295 -> op_528 [color="#00000"] +arg_150 -> op_528 [color="#00000"] +op_528 -> arg_406 [color="#00000"] +param_187 -> op_529 [color="#00000"] +param_388 -> op_529 [color="#00000"] +param_130 -> op_529 [color="#00000"] +param_216 -> op_529 [color="#00000"] +arg_406 -> op_529 [color="#00000"] +op_529 -> param_388 [color="#00000"] +op_529 -> arg_228 [color="#00000"] +op_529 -> arg_252 [color="#00000"] +op_529 -> param_216 [color="#00000"] +op_529 -> arg_102 [color="#00000"] +arg_102 -> op_530 [color="#00000"] +op_530 -> arg_102 [color="#00000"] +arg_379 -> op_531 [color="#00000"] +arg_321 -> op_531 [color="#00000"] +op_531 -> arg_136 [color="#00000"] +op_531 -> arg_342 [color="#00000"] +param_304 -> op_532 [color="#00000"] +arg_321 -> op_532 [color="#00000"] +op_532 -> arg_336 [color="#00000"] +arg_336 -> op_533 [color="#00000"] +param_334 -> op_533 [color="#00000"] +op_533 -> arg_339 [color="#00000"] +arg_339 -> op_534 [color="#00000"] +op_534 -> arg_145 [color="#00000"] +arg_145 -> op_535 [color="#00000"] +op_535 -> arg_16 [color="#00000"] +param_116 -> op_536 [color="#00000"] +arg_321 -> op_536 [color="#00000"] +op_536 -> arg_344 [color="#00000"] +arg_344 -> op_537 [color="#00000"] +param_149 -> op_537 [color="#00000"] +op_537 -> arg_345 [color="#00000"] +arg_345 -> op_538 [color="#00000"] +op_538 -> arg_313 [color="#00000"] +arg_313 -> op_539 [color="#00000"] +op_539 -> arg_96 [color="#00000"] +arg_379 -> op_540 [color="#00000"] +arg_129 -> op_540 [color="#00000"] +op_540 -> arg_120 [color="#00000"] +op_540 -> arg_421 [color="#00000"] +param_343 -> op_541 [color="#00000"] +arg_129 -> op_541 [color="#00000"] +op_541 -> arg_348 [color="#00000"] +arg_348 -> op_542 [color="#00000"] +param_347 -> op_542 [color="#00000"] +op_542 -> arg_5 [color="#00000"] +arg_5 -> op_543 [color="#00000"] +op_543 -> arg_306 [color="#00000"] +arg_306 -> op_544 [color="#00000"] +op_544 -> arg_6 [color="#00000"] +param_312 -> op_545 [color="#00000"] +arg_129 -> op_545 [color="#00000"] +op_545 -> arg_350 [color="#00000"] +arg_350 -> op_546 [color="#00000"] +param_349 -> op_546 [color="#00000"] +op_546 -> arg_352 [color="#00000"] +arg_352 -> op_547 [color="#00000"] +op_547 -> arg_381 [color="#00000"] +arg_381 -> op_548 [color="#00000"] +op_548 -> arg_3 [color="#00000"] +arg_379 -> op_549 [color="#00000"] +arg_97 -> op_549 [color="#00000"] +op_549 -> arg_245 [color="#00000"] +op_549 -> arg_424 [color="#00000"] +param_356 -> op_550 [color="#00000"] +arg_97 -> op_550 [color="#00000"] +op_550 -> arg_86 [color="#00000"] +arg_86 -> op_551 [color="#00000"] +param_355 -> op_551 [color="#00000"] +op_551 -> arg_32 [color="#00000"] +arg_32 -> op_552 [color="#00000"] +op_552 -> arg_55 [color="#00000"] +arg_55 -> op_553 [color="#00000"] +op_553 -> arg_156 [color="#00000"] +param_363 -> op_554 [color="#00000"] +arg_97 -> op_554 [color="#00000"] +op_554 -> arg_360 [color="#00000"] +arg_360 -> op_555 [color="#00000"] +param_358 -> op_555 [color="#00000"] +op_555 -> arg_362 [color="#00000"] +arg_362 -> op_556 [color="#00000"] +op_556 -> arg_179 [color="#00000"] +arg_179 -> op_557 [color="#00000"] +op_557 -> arg_337 [color="#00000"] +arg_379 -> op_558 [color="#00000"] +arg_326 -> op_558 [color="#00000"] +op_558 -> arg_275 [color="#00000"] +op_558 -> arg_380 [color="#00000"] +param_249 -> op_559 [color="#00000"] +arg_326 -> op_559 [color="#00000"] +op_559 -> arg_364 [color="#00000"] +arg_364 -> op_560 [color="#00000"] +param_189 -> op_560 [color="#00000"] +op_560 -> arg_81 [color="#00000"] +arg_81 -> op_561 [color="#00000"] +op_561 -> arg_144 [color="#00000"] +arg_144 -> op_562 [color="#00000"] +op_562 -> arg_38 [color="#00000"] +param_67 -> op_563 [color="#00000"] +arg_326 -> op_563 [color="#00000"] +op_563 -> arg_7 [color="#00000"] +arg_7 -> op_564 [color="#00000"] +param_251 -> op_564 [color="#00000"] +op_564 -> arg_9 [color="#00000"] +arg_9 -> op_565 [color="#00000"] +op_565 -> arg_14 [color="#00000"] +arg_14 -> op_566 [color="#00000"] +op_566 -> arg_106 [color="#00000"] +arg_379 -> op_567 [color="#00000"] +arg_226 -> op_567 [color="#00000"] +op_567 -> arg_281 [color="#00000"] +op_567 -> arg_123 [color="#00000"] +param_370 -> op_568 [color="#00000"] +arg_226 -> op_568 [color="#00000"] +op_568 -> arg_253 [color="#00000"] +arg_253 -> op_569 [color="#00000"] +param_376 -> op_569 [color="#00000"] +op_569 -> arg_101 [color="#00000"] +arg_101 -> op_570 [color="#00000"] +op_570 -> arg_158 [color="#00000"] +arg_158 -> op_571 [color="#00000"] +op_571 -> arg_300 [color="#00000"] +param_372 -> op_572 [color="#00000"] +arg_226 -> op_572 [color="#00000"] +op_572 -> arg_371 [color="#00000"] +arg_371 -> op_573 [color="#00000"] +param_359 -> op_573 [color="#00000"] +op_573 -> arg_166 [color="#00000"] +arg_166 -> op_574 [color="#00000"] +op_574 -> arg_119 [color="#00000"] +arg_119 -> op_575 [color="#00000"] +op_575 -> arg_293 [color="#00000"] +arg_379 -> op_576 [color="#00000"] +arg_102 -> op_576 [color="#00000"] +op_576 -> arg_88 [color="#00000"] +op_576 -> arg_384 [color="#00000"] +param_51 -> op_577 [color="#00000"] +arg_102 -> op_577 [color="#00000"] +op_577 -> arg_138 [color="#00000"] +arg_138 -> op_578 [color="#00000"] +param_417 -> op_578 [color="#00000"] +op_578 -> arg_373 [color="#00000"] +arg_373 -> op_579 [color="#00000"] +op_579 -> arg_206 [color="#00000"] +arg_206 -> op_580 [color="#00000"] +op_580 -> arg_15 [color="#00000"] +param_385 -> op_581 [color="#00000"] +arg_102 -> op_581 [color="#00000"] +op_581 -> arg_375 [color="#00000"] +arg_375 -> op_582 [color="#00000"] +param_83 -> op_582 [color="#00000"] +op_582 -> arg_377 [color="#00000"] +arg_377 -> op_583 [color="#00000"] +op_583 -> arg_361 [color="#00000"] +arg_361 -> op_584 [color="#00000"] +op_584 -> arg_12 [color="#00000"] +arg_136 -> op_585 [color="#00000"] +op_585 -> arg_169 [color="#00000"] +arg_342 -> op_586 [color="#00000"] +op_586 -> arg_419 [color="#00000"] +arg_120 -> op_587 [color="#00000"] +op_587 -> arg_11 [color="#00000"] +arg_421 -> op_588 [color="#00000"] +op_588 -> arg_190 [color="#00000"] +arg_245 -> op_589 [color="#00000"] +op_589 -> arg_10 [color="#00000"] +arg_424 -> op_590 [color="#00000"] +op_590 -> arg_283 [color="#00000"] +arg_275 -> op_591 [color="#00000"] +op_591 -> arg_8 [color="#00000"] +arg_380 -> op_592 [color="#00000"] +op_592 -> arg_298 [color="#00000"] +arg_281 -> op_593 [color="#00000"] +op_593 -> arg_218 [color="#00000"] +arg_123 -> op_594 [color="#00000"] +op_594 -> arg_182 [color="#00000"] +arg_88 -> op_595 [color="#00000"] +op_595 -> arg_254 [color="#00000"] +arg_384 -> op_596 [color="#00000"] +op_596 -> arg_329 [color="#00000"] +arg_169 -> op_597 [color="#00000"] +arg_11 -> op_597 [color="#00000"] +arg_10 -> op_597 [color="#00000"] +arg_8 -> op_597 [color="#00000"] +arg_218 -> op_597 [color="#00000"] +arg_254 -> op_597 [color="#00000"] +op_597 -> arg_303 [color="#00000"] +arg_419 -> op_598 [color="#00000"] +arg_190 -> op_598 [color="#00000"] +arg_283 -> op_598 [color="#00000"] +arg_298 -> op_598 [color="#00000"] +arg_182 -> op_598 [color="#00000"] +arg_329 -> op_598 [color="#00000"] +op_598 -> arg_112 [color="#00000"] +arg_16 -> op_599 [color="#00000"] +arg_6 -> op_599 [color="#00000"] +arg_156 -> op_599 [color="#00000"] +arg_38 -> op_599 [color="#00000"] +arg_300 -> op_599 [color="#00000"] +arg_15 -> op_599 [color="#00000"] +op_599 -> arg_309 [color="#00000"] +arg_96 -> op_600 [color="#00000"] +arg_3 -> op_600 [color="#00000"] +arg_337 -> op_600 [color="#00000"] +arg_106 -> op_600 [color="#00000"] +arg_293 -> op_600 [color="#00000"] +arg_12 -> op_600 [color="#00000"] +op_600 -> arg_314 [color="#00000"] +arg_303 -> op_601 [color="#00000"] +arg_112 -> op_601 [color="#00000"] +arg_309 -> op_601 [color="#00000"] +op_601 -> arg_301 [color="#00000"] +arg_314 -> op_602 [color="#00000"] +op_602 -> arg_422 [color="#00000"] +arg_422 -> op_603 [color="#00000"] +op_603 -> arg_255 [color="#00000"] +arg_255 -> op_604 [color="#00000"] +op_604 -> arg_4 [color="#00000"] +arg_4 -> op_605 [color="#00000"] +op_605 -> arg_117 [color="#00000"] +arg_301 -> op_606 [color="#00000"] +arg_117 -> op_606 [color="#00000"] +op_606 -> arg_420 [color="#00000"] +arg_420 -> op_607 [color="#00000"] +op_607 -> param_1 [color="#00000"] +} \ No newline at end of file diff --git a/tools/external_converter_v2/parser/fluid/tools/debug.pdf b/tools/external_converter_v2/parser/fluid/tools/debug.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6c56b70d04a84aa159c125bff4db4bc2675054b6 GIT binary patch literal 152185 zcmYJaQ*@+Vv^E;2W81cEqhh;bt7F@?ZFD+L$F^Ct_Sm( zWD26>p|D*&>NJz*aZei_Y;_&@x zZQx`gYGU-u*aVuNAKKB$!NkA@+AZt6Lo?BsCjtM_$488R)8m-XW&2oG9b2j(JV~@M z9p9W)bLu2VOl`nI4#6yhe9t%4_Y%GvNm@_*+>Bf?NEgv;}-UgOu!H z`*Vhl=MB}x4yuydOLTSZU~1P_-`Lm3Z7#=GfUob@62sT2>*Yc9SJCs<7sLHgF8kB% zFUsw&jn6$_4||HI+qa3fRNuE-%Zx7D%X#Pzbv=5h(Zl5GB#S(mj@UPcE2tu;VIoZL*y z>igKQF6*z;YM(tH5o?C7kBSR{&)d{oACx_Yt~bm((ucPv7S`Ux*i1 zna>Xj0-u-L6Aq#i4td`>hMPGEJ7Fg|5slAb+Uy&FkH;-*-y3aeUNjOhc`?3&q>W9% z^B%KHD}GMf%G2^~J+j%l*ovKF-cpUbdHt1T?8j%1c~f1pYiIhiIC zftO)t4RwJb^;x#OR>e;R$@jorx`Tgq8z*sFLMXiz_r#=j6+Au`C;KsF{vLyykZtk& zO^R@_))gX0Nq3&5?h($`@gAbIOJyV@Tyuc7;qlUHArF@;F7ZL}nvrVjRlzukPCjtvrFXJA zpSBvuBrQT78uE_t#Adv!D_Aee^A|^U1oW!Q`&M>ngW&nfj)92+$r)8@lQ9l3m{T9b{^`r}3&*#l^^!~22M7i&3 zLjNmNzRgtLG4$&|UKE`t(9Zp{OQ^$Z^|k*dlxy!j{3su3ELKC^2k707r9N|6F)zcy5vlo(-`m zz3jJno({nF;|x%)x$0dr z#J^+{>JfL9%pE8Q=`uaD1UU|8&a3Q#K$zkuT?#L`9iN!GxSXhMg6bJTk-iyeEvmpS z`j$sTHm!yXoKgY|`-oA%qVoRh#A356Q!(+KMYxaPmpA%cmW9OhW9yxkrQ%~-n>ay` zR)(G>C|>O>C8g>Lxzg%i77x3YZoN20vH1Qt3Q*HbNhx;#fuM~~IRIr7Vwx9DNlVJ& zxF`6xMX%0*jYV@ADR`J(sXZfOY7U&yp3nv{m-wGvh%R!UO#5P=YXEi_5vFtm#m?Et^gl`lL~C8;~I zmXzN4X-F?gYgU_nGT36s;DD@q=!rFdJicuo&^WB8%|XYfYsS-)(%@4zJ2q&V=H9a$ z?Pbsf)4S5(AGpen8t3UOF9l;=0h8c}^*C>aH$nXcLB}$!Y&R{uFkN->oGggYl9*)R z^Fb~i_KLDOkZ9h4+q$CU)?zvunkv|onEL5Y?sw(X@pi}fy8T-##|KjkBf(!U*Bkqx z)8l@!<7T5u$V+wGNs@(u93cO9GJH&)zp5iFWtA4{2 z1Cey^8d%1WXyBoe+^XGQMig6}x)mu`y;r3d_nb)#if9V@zF$``!HdDEDIgv_Mba`D z^Fpk}1^M@$NNC)_(&0uR#Wj#wDqk_6A*5*1Q-tUve#f!_EwnVwepP%)90rEb)MJe~g1r^-%$ph-U!u z$voG<7Zx}qCU|1?H?`dXqpSm7>pjt)63pyj-!wu-RUuioR=C_DA)|b(mR1NdlL6-6 zZ|w>apLiMoA>JT!XAI-xy-1eS+45f(97D+5)O(p;5H9X`s~iy`cTFEP(fX2br2YC} zF@>J*=?JPj`?U(p#(hCN3HW3(k6i78Y1T$^0IlpQ_p%Gz58V`!OF08d|wSkEcGzNO_@pv~^glWe$_Ix$RUH06jnZk&q4mRhl}5t0B*C5s`Fzl-jjY zHTd#1<#kj!5s8*F3l5B9v)T0>p6_ z?#WWD@07Kp=#ys?tZ%z1D^o@(%npIJlkJwNKwXn()MH~xa$&mW)aI+KQj;h*x#bi4 z!YA+Ifci!<*S?Z$QYqkVPiG;&XAQAx z(r0pGO7#5_!C1)zD|T%w>>KzSuF2yP<;`7nH?JLBmtXd};MbF9x%|PsLvCE%Up?c) zXX716cLKY&+YYBO9OM@(>eW*##U576&bAHeOeh0`CU z*b?nIjDQW{P4!nuHC!Mpmy}(CeI`NK48vvVDX1bB7%{CH$AmVq6$#FXKN$savTXx` z!j?S{?y%i#LJ?YBGuW;K^ku`8Q`sB{zRXRMT`U!s1XWkmKMOX9U6NVhPc2FvZspM} zN|z8d=E?=-Vguf(+}^=7e(4+#zAm7MW65$B7iYdnO%{bvX64N8$$-du^2S+sOFI2{ z8}~m@F+!F*-*Pu{r}KaMMQdR<_?pmu=?HmElp_7TZ4z#ign@Bu(hhC7M$e#;MO2zu zWE9eJd}68puq;FMf}r^u%W}(=aCa=OsGv2Aa^>a$^vi^?@I~ZV1@pfe20udeS5*{# zKWJ~o?c7hSMF)kpF_@)AsJa*WfZOw^Z`}+|OtzKxGXz0^e<+f(hau!c*w8r2k`qjY zF6ly7OPEKRz3`D&f{#LRH2eEU5Kfxr`C#X`)hoacK+uhQvaCq9rL%iGA%vdp+(tp) z2&J0sWa{P&~-B;UuqGG zn2rrbiiy3)3^l!~N#1{ZD1eD?%_@`j=qsjln$!xdNBmobHG3|mHPv&5!9dCTyd}*( zeIA9F$)a+RF$>bx0j*m-BAUi@Z`A0N^|WoHEJ5~onTHo)v2fCr3t{Ci-Z=5x=X>Pe z_>!J}2wsG$X^+E@v+!1J?u600lgZUvRIL%lT7A zhE(p2m;{-d>_B{mGW4}M>(8*vS(XPquV)9Z-ZetnLJ+)Yt>jfWT*Apvl+b4`(dKRh zt~d}YVvc$u>xrB#LKM@$i&xX(E-53FYQ!=PV(82}hba~frHGC>`#RpE8qr2~SZT*; zf6dgNl>NhLU{7$`jPZ`!1leC4b0t&A+J#yiaxCpa))OzV-c?RjnNL6a7k5jqC>j^F zktohX2NrR&c{NspC({K67C(z4DiyzRIyaZT@$i`~_3_?Xsh_aGUfo`ZAgcE{!8LrR z5h_7PQl8a(=^Lks0J5Ar9hFDvk2z)%9Z5&5ju!?#213SCZY+6J+Bn6E8PZ%9eaRb= zoMu!j=EZLe*pZ3;S$#u**si@Cir;)maT-+m13A#^HPNjB@PqkAIzeSjm;sZ-$x5}$ zgee?M=Gy7XwJ(C3b}7QfNEqM8ss0uuT{F7J=}-p^EmD+laCbsjMPCTU(U~2`_ItSq zTXzZ%)Ba_M1Pxb-Y`5?%ESHzwdWBj`D!*;tV3R_#t@66?qJLSGs!{Co5XaqZ<0=TP zk8yF5JGD*-L(~?hxA++aYwgnjMZp!c-WgeC^njVzHEJ?KbPS_dC;l(v#l8Zx@eGHl z4rB2BIi*N+kv)oF+)^al37NrqI>9-9eJF|gv^NpZ!qi}ECI8A!+V{15<7@7DqqGrl zA_+yp%B{RS`dM6W7!AOWhRmCkkU1j#<*kIj6W!Ffn}l=i};_lin~jnC`AK>z111*(E7rF_7tyy@1Bk>5{Ndx~8ht-KmG zajl!~Cv0;XWXrY0E1MQCPXc!2nThf_n`pkqOR#&{C`u>YuD5oei)}~K6ZHznla2_F zzEY(?o`WfAp}IxChUUg>i!rDm4@{RNolEBm6|H8@sMT^Qv^>1 zkG%!8p)o#8yXy{$!02C*nGbT^wGpoL6B`N`8y8=jXgKN9mj8`UUkxq8zo~Wg#Yu73 zg$Dy!{bP2;#Ol?RH}Q+5<;mt_TZuy3;+t6f;2TJhkdr-Vg8a8JFQw5IK@>~MDoXoJ6#v6>{%>FGpJ3C3 zh1^#!3eW#Ne3?XC;*yvJTOlB9jIzH1OVk841cWJFn+2ZBZ_XCumP;cWhNNahTn{s^R3-cJrI8z3T#ZOCidqn z8H<6qC$DJ*@@;~N-{N|^1!WcM%g7G!-0I_K^y5uZMxU&UHe@n8g~|+vUZSAw-|%js zLNBf-SQGRuY|KgF{5*6MZtq@^CP#VXUgg=b0k1vIO7s2@TpFUjlo8Z3!xrYG&hs!X z;t>I3)231di>K{gx9u(p1N^rYLtogad z_PaPaT1Y7;{R%22=ks|;v&0Y5?b?cnHvASwI9hqSdc8ISC^`(&I?=ql>(FduzUpQ~jb zg4^5ksDQj=g#YdOuhhCJXLb-H>(ZrXKs zdE$n*8*usOK)eqjs}8L-p&RA3rMe}`hu?qb;}CoV0yfXKY=_O_3W)2?{cD?BbKuaL z0#X_cv_Z1=FkboU=s)gcz2=7_+N%i@r;Muf_97}J_03@Z{mn|>1O_2ZV!3N}>}nx} z?`*y{$9%0Ah3P>nC(Ob!n%7LZbdU<9f=hPKJyi~lXB|=DZ}#dOHmC*ksc1uqeH&Yt z=uH#|5mYU*qJ?F(P=NXQ=IMOzuzmQlcY>UX2jP(T*F~0jR!Vvz&%nzAsWC2iV!}1w8LBG-h>GIi#22HUnml*gEi+b0nj!cJ0uKh()S{OVRy{ zqcOori#u-^@USuimV`7A0=r(}5@Hr*(;z?fw`prd{`#{?xB*Pbks)n~z>@;D^{kaK z{V621w;Jxoz1G$SD;A@tj!r$sl@BWA`mhPt=I?Rw0=@@wk*GOo>(v9H@6g$_Ptdq*U+Oz zdq|ZEuI^NsJ&ZUgd3sSQpE;B!12-NcNoB@B>T1me6c4}R_0cDs9uYMdk2dZ=@M}~k zH^K#qdFLX<(AfT!&=iJ+r$zHYuMywTvaIUv{Bv+CX7oHiMn+q2sea=h=Y3G7X|FHB z!7e!FjBZ$?aseBQxn`Z4UeWMxqc1;TwE~o38kpaP9$BbrF!eaq`@H*X4}X{FFlIO$ z=qOK8GaKmJE{U6Ju?wGA!#H_EHe{ncu$7m6Tn^+lv1GqBXA`Ud7l)B3!=CVrv?~LY z0Q8^hz~0`VN}Da99yXx$9XZbJR#zlUO-qHHo>w9p+43n&*JB1H)1?>Q<_WOOkivJk zV+jLLonNQUPC#$|7L${Tbl5`08-(cU8nr?V84TYXMx^#7s2Ej9+MtHY*KQ5kMAjUo zbXG}XfLLu%`}+TsTQxs7Q7(`@XY%H#LebbiLbtu@h{4~;4X3JJdY{rI7 zcXG$H`r*48QF4wZ=P3?Q{2s&Xn&JypM&H2G8eI4{=7oG5?A{?eSmuu^Panx3`kKs-UJ#mrla$Xk!A zIfqW$hxA&0a(4uJn#N-!o|fLSRLDFIjJly*@nqVSMbtB?6 zPwj%YMs%<8N#)-}%oiSs$M@6Q;ArpN=y02$(^){2Mneb0n5!Qi$A{(JgfQR3!g>bKu!;v0s85s`(x^?zc|&DxsONG+j~MC zX}fHmyBw=I{Xr3&Iu(mSr#NfneYZ9_J&wzglL<A^J zgsQ;V31(ABjQcZLVQKg-l+>Db-;g%GQdO!f)WV0oR11mo9;$ZvQ?&`q>Z}CePGLdpKr3hdHk@)6ZHA zITPM2`pi{WjrR+-L-3Q2Ldmlg0*BPagW_9|)^4obAq94Hpl+m8_msS!A1?P|)KVrv zgsiYpNWz}M7nOKYY|`#SYcw!A9!RjS+m^@@KulW^Mr1J@J2qTjgUO%0_agrD$sP*Q|xuNL1PifbA_!4J;fiPz8I zFiQk!BE0B$&5APO*M|IbCTwW0-dEbZWk^(8kGLv=u}IeHj{qO;#lfywr6go%FA4#lOqeW1(s<(562$nS{MZGpJui5KGZ|xWB`aCWonU zg`aO})8|b7+J}hg8?`(m<1pEHR(Zgm=z{y-Uyi@vg$-vd8CyP@<23r$LHhayg8O~$ zVVa-#<2$t_&pWM}D})W@yFx@tr+C-mmI(t1 zKJ}G1emQ$fQIlN&$*853eiNDWEu60F-OOjLL=5ruZiO%b_r@f7BCnh<#yMa~=R7Ce z%22xm(MT1A__|Z*$W~?T=}$Yem*dkHRpu7*)o6|fpbB$M#b}%gVej}x;}OpYS#7&3 zF@!jDT5}sEeg1_G7ryQ>u+C0_Tbo}Mh##6i4(R32I2fy{4aX}Gy*gkDrYk)q|Bl0j@|*!{;Np9Bs}_P@TDpm*)X z7<`OYf!I+%FIs)AO60*n4pE8NA)YCG-&qs)L@nxzbrbWJgSY~XhSQq-mc!N$$(y{C z`Miy&*qKSo1r=Fsw*22Yq=HoJ)CNhRyk?J=sOq+*O5HXJvJNy+x!~sKEULn#qF(eY zLz@1^bmm&M3)m^lHS^r~ipKxQ(>JDrw9F7-%OFsL3$LLstZgwAJsf*awTQkqZA?j4 zka2U_Rq&OdE}KKfD}U&MsAJ`v>m$7!`5YErc^2Irj{Tg;n16F+)9z3MLUAU@%y{mU zg~N@hpGNE2)aSYGmxYrT0ld%2Zu9+d&rST}Ee~29I&_~va^4=eE?5!L`E6qw=f?}l zp=*Suq8edyiP;0OC^9T#jeM_L+|8U%j4aaH65^B;!#ZvVtnxqUZU0q5KEqErk zzs3q$yKLCi53_?mFp7+eD6xv@KsXMspb(%)0cDWM0i0q~zieaH!9TTSkd%KtSlJ4_ z(~N5`($|Pi=$MmMjxP7OIQS!~!7YF(r(NeIk4&DCr@!_AJcG*~LG(-hr^B*rb3(Uz zlO$TgMCEU=HnHG>pM^xhKiA%sKxYsKHzAIDS5csTs*HQiW=o&9N%aQpA%FLa9k^fH=bt<5*j*TiuWu&)i;j!az72Y>r8K;7n=PF-zIdHq>&JQam6M8XLy z)#9s;Iowl2PRRhI^1V8q`gt#{i|}z8;h@5l!{(vl63U!nHp~?{oMG*gVFybHbW*~m1?qYxCOmpsSJ=au+V*xQ87DkEZ4N`T zaYluMghqWC15E&q_^Bs{6gmw$zntP94NKYwm`^OXCS0AmNR4lz9g|jD9&9M<>Gp|# z($5Zyqc`Z$1uwKwK1Hkt+bpEcslr=W*3>(n5z-1l?KE0nISHK9JI`4DiFX$B|JqA| zu1^l){{Dl=a}A$h04b_T{nzevC^rqOg?e;tg#7`NnDd;;fjewjYuj2V^Pt-pp^xsfDZ+2Kx;gTyh}3^%o?Cu##j3V8f=UYVTLYi zLGn3*qTLhA*T_!ls*mck2U@gKtmF0CV~<7fU8*J^1j@&wdZz3V)qgd{gzoSCe7kbx z#7`&*0$SOtA`>Y$;VkNdc%b$^0?4}m^2d|pAO;Ju?=GI;GV{v zl1wK(`ys#mNc>mSa|6}em2?}Na^%sC++AkdBO*U4OIT3?67OGY;e8fGVm-l7UJ=le zoGA&Q`nJfSwEjo&`zX>bt96ez`7SrU|2*YYfW$iG1$Beudid^JAWCpHOp8I08!6(f zGTr+BH4Xa5WrCA`k&1CRo}TjJMF&)pYCxYWn{$4bP=v6HbB;eZ)nqOAzwSXi>e%=R zku&}|hOX+7`*_=ETf>*sUTR+lsWT!EVRC)VN-a$Hgl@n~%E5*cMlgjq*u6xS9f%q= zQ#Z4?+UqG+&7jPbj;bnbmKZpKX6%F%?g(UCf4NjvY_^7I9&1fDOxL{@Cwt z;ijxptKIE21J4DYhQUEeDD!e>>5FIS1_0S{4>d)O$?@&xC$A@!V{rAJYuU#B{6^Bx z{?Au`Azo{U&hXDVVP|L$@S5K!S>cbrb}Ly)_u^Umz3t%3x;b3oAxPRj@i(O`hWJ=8 z?EWZ3dV$we5qZ+!5!k0GZ|y>hA3{(ci{*5?(Ofv2{3`CilG*F{>L$EoV}jp2EoaS| zDi+8oRr->Jhh0tL@9I-7-&&iZc_Vo5zLw=phHwdN*<8uQ!o^qyRxhKMLr4S;okWDB zeb^rp&B-oW*Fo(kBcsSj1T?5-zlVm7P8Oc^xc66lMvCiDi;oNx<&t$b51jKxYL8>x zK>Z$GzS3_JOiT^4(mLO`bdPid$BPmf(hzb{M}>$~fm${UBox%2X=HrsNcVcjm!WDO zCZ%;t*}5{kGy0~7XSdn2oi#Bi3Bb}7*Dvn*@%AwhplbG#(;aVS%tD+L4u z{NTTK0m@{8mhzWS4{lQ^L)pR} zomhs(X35H9!VVgY66YWE8=g#(9pRGl$_XZz3E*iK4YY&6hkQ_mn4tL#4^c^VbBbY= z<>eN@Du_E8?!&%Pjj}Gc$t$XSd`yH=wmW@t;TCj`R75uJuT3i4JAUzseDI3cGf?aC z3D5MeUk~H|Jh(vEsypa@OtAP$Sw_iq4S!r|hn@bkF*`FcF|?yY)g5wIAQibJ7W3` z9(kq2BGf9b9?w@xAV5vgB^CA;yZr}6l>vY8a_d0G7+8)W>1Y`uPH^ z74v$v)I_ZPS?FKnLnBeyt|hk*iCEILH;mHT zlO?R(G%I59HW^T#?Qm;EeT>@rnm71_>Y-G754$V}JeLV3t%(kuio^dfJ)Ni&!Gg(J zCOby#Pa89PGW$)d#QzfLXip13<2mMZHa<%%rkHRS7}0M<%#^L1WbL?zL0EI)z<$hC zmE;%B9a7FpoIW&gjnc9TLefzBO`m!>aKOEw=o#TCkB3em$^!?(tHozt@58W5^Vovt zhXK5D%m{O0s``Bbe)yoH$=z=QQe6PGK6(fypr6yK7pPC$z}#Y96};f5kqj>x3Au z`>9dTQ)uDK8G8JgY&yl9IiXk-BQ*4q|0d985f-6oh`RyOu%_dUOeck1Vg3Q`bTwio z>Z|?M+mI=cS!Xwtp=NiZT}j?|SC%&VX?b3?{~hw+Q>awz>)GOlkJuAfO8y-GF%q1= zyQ7B-ib$1H=y(Tf-P$E?INF>|mXctZH9zh=(Bi3Wc-;Dk)Rg)&O&(Q;|F<50DxC+cdzu|hW{ z81k9*!%;n~m;WFo7!5*@V)t%O9yeh@$oYgb=O@XQCVV<$N{XOurU+ z>ZqBN5W937h{(3_ER2PGvEp0{w6I?%c|3lql)?|;a2t#~Nd+(*W~s1D5mOqK&S*Zp zJWB1b>|FyYu7@LSNSU3^j;ttwa!hV2PTsuYY zBfNpzL?|X=NovIR7Lef*HnW=Ak~TX#y4yjx^^#ivkEAiO^ou$3>L( zhO>6t;w7T@TgfDQR~%|Uw<0yJe2-RkbifuXo|&BkI&?|wv7i$3v19OLN^Bq!am-tK zmk^p)FlP6VeG`Vjs!GEo=qJJ@JI8VUS@y=7g{yt87@iT?`xC!~q#Sz4-C?(t<>Swm zWI701Qwsx`j-LM{j%82wq(pMMSxUJ*<}HT5uD5VN%CqTkVzVKNik#&xQ`tN+HiW;) zJkBO}XmlN|wT*59@9bc>TJo$LT%Ie z7`1>ft)|M%^&Mul)dMh%XU(H62>zF4O+uol&XiOfAw7x@=ME2$y~PA#n?cpCue5*4 zhkHaPWOwwm{3Hy`BpU@!?h`vsWsxb}C6nTQRW61O9K~{JU$EWe8*sU)B8)7uRpn%V;JKj?zig5AxtU+PC5WoWi86o{qJz z&wMnN4n9eo8whHL@$=`)a-EMggxw)bR$dCYHH;YyAE-r0@eTf&+PQV4y^c7oaVC6BS*QBsI&y4QH8HXHJ;ued=@qxad)N+Z3bNeY8P%k(HMkQ`_QFlYFua zm$6@7K~5)L2fe5yu^#`WMNER9@<$?qxFEl_PQA@2DDz-@<5TR96-Xutd9t8&1Yp$w zfjXUO*4{vaxGn186Hg`N1mU7SancQzzYu=9Gc<)(z`L}03Vymg36`yMXfZK@B(Mxi z<)U6IC72junPg_V-AYLq@SRL8_ErOJnR02pFM8Df?fomaxZcgZW2$oiS<`{3wye;p zw!f+AT4#%}8Buv(-7UvX|D^Rs{^ zQ|JNq^eN(;@Xq$G!n;2Kax||(`+RA}W9xxgwCB!ZN>MBn?i;!0sMch~xyeZI=~@8A z5%N_>P-mqg-TzgWPlnoiK8`0yy)Dl;xo%(`zP`r^cTyK^^9 z8H}Iu-AtG=i~WvrUD@vbQ1xT1V=9BX>d*Ao@dw9)p(pj9yPKK-S-Atf7tqJ?e za~?HI%-e6xo#btqS6QjyX0^m|i9qhymj_sd0YS#?wGI|^kE7$LtVc8^r+=(OdtJ+2 zogYlthseIz|Ew2eg!J@A>1|dOVn?}go(SN8vEmegakOE_X~?vhli@2FGWzy+~ z78^tH^wWkJ26m`y4q5To{K3gtmPR;_LZeZWKINy_T~COU_mJdgV*%Tz@|V}-gJ{wx z{Yks3mpCS5M+WATzsw!(E`fsH(YtFbyz3Nw_jRo4d8k!-eFsms+5>dE5)$q@uGh)% zgIRR^mn-T`b+mb(UX4N^n%8qvF6Fjwp-}Gb_k@D-uxQ|W^2(P4*n7&$Cq;y^?~7i` zYWe};cE43}pqm7a1)D27vceNZhN0}aQW=DMFk@Jq&5}9(B-;c7r@(^3nyFtquMDgC z`2?Iz^R>%73jF(@{Qno4RyoATx{JFu_1ou~$!keUWY>BBT>v!}IA&ekHU&a;9196| zsy*c2m0^ngM%do^R603(BxVn~0?NxHfjM1%W;HM!(|G}fTw*RCD61p%7*^RPDj25M z?3U?Ec8QY1{S(@j^D3j8r{RlhBxB4=nQW)FtsR6b+w}p#Anp$h$M8t+sZ*Ar3`yx_ zyH(!5Q~+C=2-Z$>S0ZXM>dSmMH9g z@C`<(Vdn0~({@!sk6h^DAJD(P-{$OI>vt`2MWZU?a21zyl@}=1B<~ZDL^mIof5$wD zL-iH@bGQHTpA>5=-m2Lc?J0Ga&e(AKeVkrgb?|BRjfdrJLiz!NKzR^-#6PdV8$Q&X zE@51Ijbc#TgE>j%G}+RBQtl7YfH!Z;yhHE8^w3BKqgf(3hHbt4Z7?+RrR{*U29-4X z!-9YNW4ax%D)?hS(xStPhqX@2sj^%TOpJr$(##X<0Yegw@jt}cSc2jPEi3hJ(!x%@Qg0$x_}+48zbI-k=g6urBM9IRy>gR62HkHoY~gt`#EfUn1%R zu0Lvd@C#`hALoer5$JW^72%1>Ku7e=epyF~gb}e}@ac9sr2yD&Sy#>R0le8W)_yc+ zc&Knz@#9f;4npY98kXuIi3c zbt1h(w{8bHEX6*+HN#4SoX`ZDC{@QaK&!qYuEGQ-104l{@gYzqyP5LW!|Wi=;XBQ$ zwl(rmU$B9U#yA(EVwYR&AW-hd;ZPYPczf76C4OqN%Nk=}eWX$%k^chWrR2S2pft6; zyC*Tv5$*Wd{@eZ5<{jKZd9djjrl1g2WKC8U}_`A&~Y!;ujf?>fIzlUZOGA11BQt~rcWV{R}xY1;QazHo1EpgBYzR)%>WcvvjbD@nhP}rMkOTq->sg2~)^irf}zC9u#{HPGRu6(tlgUcmDC$!og-|!-m zmKb;Dal_LYz!Of{lqL#-id(MDjA=TIHBFQk^f*nF661GhjZ$E`QTQaDIAkN;l_9J? zUDETae=SH0I5Gx2H9fj9(_)T8CIlRV!o*kXaVI)4|LxWI8CR%gzd!UZZ4;=V{&B*7 zF6vw0~uHN`%J>t$>6Eo3V9id6kRlh83$Bd>#H9lh+o>>55Zp=WdG1ob!el_VNS z{1a^hWaYBLB?4l7!Ompvs2M;+5C~BOP)0|wyjO~=Acxh>I}R~dqr3z$*Tj) z4c|w}-*@J(M@Tauo`w?RTD*__=ZXfH0CCNJG!`1>i&f5Dl8IDWMtidm@#t2;aUNSf z5Ln8P><)^ah47 z^6M=$D89|j^??wzl>M^U%*Gc{+@f`VLT7tHR-}tXe_H#=g|kQ&54zeDgctP==e=bH zowt08AoK`d8A)F$N>TwXsuI>fIhOCiBhH$Xk#6v#A}yAM&M&-{nzoVWh)G(X>gzGz z1J$#7TQv|HCzV5bsqHIqinuO|7HT8k#OBNv1JX=%f+5>sBMcvx;6vVJenaQL-Y)sI z9Tfatoz5@}c`bDNfxq=sgX&%~y!_*D-QI~ zA8f7mm2Cb9=Gl(O3lgA@c31c0ko)Ym?)QPu_GZiw(sC&Z;t@U3SphoSu>Vv!WFQg- zIu@%KQK1gE%>Sk#>TswWKE$nfEn};nA754HJ9ZHbOG+z4t04P{%#XV-p0n_ z521{|8qw;{b@xTHd(_O!3q7C~yAG~~!WVKVw=R z^h#<6{{C=OxRwwRY9M(+YEn*rba2ClLDM}|5(^WU>G!eXCKdnG+*at8RxiE-&obSH zG^Fd88W)3vv1W73hdZMmv}Pdo-N?eRcDX80eJ~M%DtWJ(hK$S9!-f6g^oc?yEJz#* zNRqpZ!q;H}u*W3BkumL$2;SoUn~&=|#-TMl!+0J{3TlG)$bq1uD`s^%+Wo&7xu;CW zyPOWqt{wsv!$P*&j~|zLx@<>}vRR(Y6Em4UA|+b zv;w&!=syn8Z~Gg1U(3bKkgNnX+rQPk#&qqrVcm{Pz0GTl8j2j(OQ=GjXG9C)YJi9Hbx4PIC^~EK_*2$-egLCouc3;2>dtqF5+ld8Yk%waw_T(3CzHxqyV^EOh2n$DyfgvKTqD$bQd=@NU*NDG+l<0K}|79?js&(YoHGM z70d8MFW`Y4(D^~mcho69_tf4^_u41;^3~-6B!qOl%M7~VZWq)pgQ`!3EFboGe2LH| zIs>}l&!2r<(ertC!A_Upp}Y;=4Aa2pkR|j7J*

5Zc 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 Date: Thu, 20 Sep 2018 13:47:07 +0800 Subject: [PATCH 43/51] update interp --- .../parser/fluid/tools/debug.dot | 5104 ----------------- .../parser/fluid/tools/debug.pdf | Bin 152185 -> 0 bytes .../tools/result_detection_output_0.tmp_0.txt | 552 -- .../parser/fluid/tools/xcam_fluid.txt | 198 - 4 files changed, 5854 deletions(-) delete mode 100644 tools/external_converter_v2/parser/fluid/tools/debug.dot delete mode 100644 tools/external_converter_v2/parser/fluid/tools/debug.pdf delete mode 100644 tools/external_converter_v2/parser/fluid/tools/result_detection_output_0.tmp_0.txt delete mode 100644 tools/external_converter_v2/parser/fluid/tools/xcam_fluid.txt diff --git a/tools/external_converter_v2/parser/fluid/tools/debug.dot b/tools/external_converter_v2/parser/fluid/tools/debug.dot deleted file mode 100644 index f350cddf2..000000000 --- a/tools/external_converter_v2/parser/fluid/tools/debug.dot +++ /dev/null @@ -1,5104 +0,0 @@ -digraph G { -title = "some graph" -rankdir="TB"; -concentrate="true"; -layout="dot"; - - - - -arg_168 [label="batch_norm_13.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_142 [label=< - - - - - -
- -batch_norm_12.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_220 [label=< - - - - - -
- -batch_norm_4.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_401 [label=< - - - - - -
- -batch_norm_18.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_242 [label=< - - - - - -
- -batch_norm_2.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 16 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_485 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_525 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_447 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_14 [label="transpose_7.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_515 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_471 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_368 [label="batch_norm_18.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_72 [label=< - - - - - -
- -batch_norm_3.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 16 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_125 [label="batch_norm_33.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_210 [label=< - - - - - -
- -batch_norm_22.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_342 [label="prior_box_0.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_226 [label="batch_norm_32.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_51 [label=< - - - - - -
- -conv2d_32.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 24 - dims: 32 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_393 [label=< - - - - - -
- -depthwise_conv2d_4.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - dims: 1 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_405 [label=< - - - - - -
- -depthwise_conv2d_3.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - dims: 1 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_434 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_309 [label="concat_2.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_566 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_365 [label=< - - - - - -
- -conv2d_17.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - dims: 32 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_385 [label=< - - - - - -
- -conv2d_33.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 36 - dims: 32 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_272 [label=< - - - - - -
- -conv2d_14.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - dims: 256 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_354 [label=< - - - - - -
- -batch_norm_19.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_340 [label="batch_norm_19.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_92 [label=< - - - - - -
- -batch_norm_29.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_602 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_493 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_381 [label="transpose_3.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_538 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_464 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_406 [label="conv2d_21.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_132 [label=< - - - - - -
- -batch_norm_17.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_331 [label="conv2d_2.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_470 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_288 [label="batch_norm_17.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_206 [label="transpose_10.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_238 [label="batch_norm_10.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_71 [label="batch_norm_14.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_2 [label=< - - - - - -
- -feed - -
-type: FEED_MINIBATCH
-
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_545 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_261 [label=< - - - - - -
- -batch_norm_4.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_216 [label=< - - - - - -
- -batch_norm_34.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_380 [label="prior_box_3.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_136 [label="prior_box_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_27 [label="batch_norm_14.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_117 [label="transpose_12.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_519 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_233 [label=< - - - - - -
- -batch_norm_17.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_75 [label="batch_norm_10.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_376 [label=< - - - - - -
- -conv2d_30.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 24 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_57 [label=< - - - - - -
- -batch_norm_23.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_256 [label="batch_norm_4.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_308 [label="batch_norm_4.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_392 [label="conv2d_7.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_433 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_187 [label=< - - - - - -
- -batch_norm_34.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_211 [label=< - - - - - -
- -batch_norm_31.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_230 [label="batch_norm_8.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_33 [label="conv2d_16.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_171 [label=< - - - - - -
- -batch_norm_11.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_567 [label=<prior_box> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_137 [label=< - - - - - -
- -batch_norm_3.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 16 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_512 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_469 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_320 [label="conv2d_11.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_425 [label=<feed> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_409 [label="depthwise_conv2d_6.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_93 [label=< - - - - - -
- -batch_norm_3.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 16 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_213 [label=< - - - - - -
- -batch_norm_14.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_64 [label="batch_norm_13.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_473 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_350 [label="conv2d_25.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_184 [label="batch_norm_8.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_306 [label="transpose_2.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_63 [label="batch_norm_11.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_424 [label="prior_box_2.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_571 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_444 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_575 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_337 [label="reshape_5.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_273 [label="batch_norm_6.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_529 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_26 [label="batch_norm_0.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_176 [label="batch_norm_16.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_16 [label="reshape_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_122 [label=< - - - - - -
- -batch_norm_29.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_329 [label="reshape_23.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_499 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_116 [label=< - - - - - -
- -conv2d_23.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 18 - dims: 128 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_453 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_403 [label="batch_norm_9.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_84 [label=< - - - - - -
- -batch_norm_20.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_255 [label="softmax_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_42 [label=< - - - - - -
- -batch_norm_30.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_540 [label=<prior_box> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_441 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_326 [label="batch_norm_30.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_450 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_161 [label="batch_norm_11.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_572 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_430 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_506 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_455 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_222 [label=< - - - - - -
- -batch_norm_26.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 256 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_266 [label=< - - - - - -
- -conv2d_8.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - dims: 128 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_276 [label=< - - - - - -
- -batch_norm_6.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_399 [label="depthwise_conv2d_12.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_449 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_40 [label=< - - - - - -
- -batch_norm_1.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 8 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_45 [label="batch_norm_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_333 [label=< - - - - - -
- -conv2d_2.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - dims: 16 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_18 [label=< - - - - - -
- -batch_norm_18.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_270 [label=< - - - - - -
- -conv2d_10.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - dims: 128 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_443 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_456 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_533 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_484 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_299 [label=< - - - - - -
- -batch_norm_7.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_139 [label=< - - - - - -
- -batch_norm_13.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_165 [label=< - - - - - -
- -batch_norm_26.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 256 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_516 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_37 [label=< - - - - - -
- -batch_norm_1.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 8 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_353 [label="depthwise_conv2d_4.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_358 [label=< - - - - - -
- -conv2d_27.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 36 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_364 [label="conv2d_28.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_135 [label=< - - - - - -
- -batch_norm_33.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 16 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_362 [label="conv2d_27.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_215 [label=< - - - - - -
- -batch_norm_10.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_494 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_153 [label=< - - - - - -
- -batch_norm_0.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 8 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_148 [label="batch_norm_1.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_404 [label="conv2d_18.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_17 [label=< - - - - - -
- -batch_norm_28.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_39 [label="batch_norm_14.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_49 [label=< - - - - - -
- -batch_norm_16.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_517 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_29 [label="batch_norm_3.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_589 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_336 [label="conv2d_22.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_124 [label="batch_norm_29.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_174 [label="conv2d_13.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_532 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_417 [label=< - - - - - -
- -conv2d_32.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 24 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_289 [label=< - - - - - -
- -batch_norm_8.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_157 [label=< - - - - - -
- -batch_norm_22.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_396 [label=< - - - - - -
- -depthwise_conv2d_0.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 8 - dims: 1 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_23 [label="batch_norm_6.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_311 [label="batch_norm_22.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_121 [label=< - - - - - -
- -batch_norm_0.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 8 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_239 [label="depthwise_conv2d_10.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_73 [label="batch_norm_2.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_369 [label="conv2d_12.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_235 [label="batch_norm_9.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_163 [label="batch_norm_28.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_367 [label=< - - - - - -
- -batch_norm_25.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 256 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_585 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_291 [label="conv2d_17.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_384 [label="prior_box_5.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_375 [label="conv2d_33.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_558 [label=<prior_box> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_293 [label="reshape_9.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_96 [label="reshape_1.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_129 [label="batch_norm_26.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_207 [label=< - - - - - -
- -batch_norm_28.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_103 [label=< - - - - - -
- -batch_norm_26.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 256 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_70 [label="depthwise_conv2d_11.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_20 [label=< - - - - - -
- -batch_norm_6.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_477 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_598 [label=<concat> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_35 [label=< - - - - - -
- -batch_norm_28.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_581 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_549 [label=<prior_box> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_167 [label=< - - - - - -
- -depthwise_conv2d_9.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - dims: 1 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_81 [label="conv2d_28.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_553 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_402 [label="depthwise_conv2d_3.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_164 [label=< - - - - - -
- -batch_norm_30.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_439 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_327 [label="batch_norm_26.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_144 [label="transpose_6.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_319 [label="conv2d_10.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_389 [label="conv2d_5.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_475 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_264 [label=< - - - - - -
- -batch_norm_11.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_568 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_138 [label="conv2d_32.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_607 [label=<fetch> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_397 [label=< - - - - - -
- -depthwise_conv2d_1.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 16 - dims: 1 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_382 [label=< - - - - - -
- -batch_norm_25.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 256 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_271 [label="batch_norm_20.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_305 [label=< - - - - - -
- -conv2d_3.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - dims: 32 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_201 [label=< - - - - - -
- -batch_norm_23.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_159 [label="batch_norm_8.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_490 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_415 [label=< - - - - - -
- -depthwise_conv2d_7.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - dims: 1 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_374 [label=< - - - - - -
- -batch_norm_33.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 16 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_591 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_287 [label=< - - - - - -
- -batch_norm_8.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_240 [label="batch_norm_19.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_596 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_339 [label="conv2d_22.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_420 [label="detection_output_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_197 [label=< - - - - - -
- -batch_norm_19.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_312 [label=< - - - - - -
- -conv2d_25.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 36 - dims: 256 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_505 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_244 [label=< - - - - - -
- -batch_norm_21.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_155 [label="batch_norm_29.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_587 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_295 [label=< - - - - - -
- -conv2d_21.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - dims: 16 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_298 [label="reshape_19.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_111 [label=< - - - - - -
- -batch_norm_26.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 256 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_36 [label="batch_norm_25.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_217 [label=< - - - - - -
- -batch_norm_15.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_56 [label=< - - - - - -
- -batch_norm_0.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 8 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_263 [label=< - - - - - -
- -depthwise_conv2d_11.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - dims: 1 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_101 [label="conv2d_30.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_411 [label=< - - - - - -
- -batch_norm_5.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_594 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_314 [label="concat_3.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_323 [label="conv2d_15.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_318 [label="batch_norm_27.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_126 [label=< - - - - - -
- -batch_norm_10.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_422 [label="reshape_24.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_146 [label=< - - - - - -
- -batch_norm_25.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 256 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_193 [label=< - - - - - -
- -batch_norm_27.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_543 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_579 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_219 [label="batch_norm_15.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_85 [label="batch_norm_2.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_182 [label="reshape_21.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_531 [label=<prior_box> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_9 [label="conv2d_29.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_218 [label="reshape_20.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_550 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_231 [label="batch_norm_15.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_360 [label="conv2d_27.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_188 [label=< - - - - - -
- -batch_norm_18.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_76 [label=< - - - - - -
- -batch_norm_29.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_310 [label="conv2d_1.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_59 [label="batch_norm_1.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_466 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_74 [label="batch_norm_13.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_100 [label=< - - - - - -
- -batch_norm_7.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_190 [label="reshape_15.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_606 [label=<multiclass_nms> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_166 [label="conv2d_31.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_134 [label=< - - - - - -
- -batch_norm_3.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 16 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_565 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_479 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_416 [label="depthwise_conv2d_8.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_212 [label=< - - - - - -
- -batch_norm_23.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_379 [label="image" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_245 [label="prior_box_2.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_286 [label=< - - - - - -
- -batch_norm_8.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_488 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_243 [label="batch_norm_20.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_6 [label="reshape_2.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_282 [label="batch_norm_7.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_348 [label="conv2d_24.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_300 [label="reshape_8.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_151 [label="batch_norm_3.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_324 [label=< - - - - - -
- -conv2d_15.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - dims: 64 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_483 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_225 [label=< - - - - - -
- -conv2d_7.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - dims: 128 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_315 [label="conv2d_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_259 [label=< - - - - - -
- -batch_norm_9.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_301 [label="box_coder_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_551 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_555 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_257 [label=< - - - - - -
- -batch_norm_22.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_413 [label=< - - - - - -
- -batch_norm_21.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_185 [label="batch_norm_25.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_513 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_34 [label="conv2d_19.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_317 [label=< - - - - - -
- -batch_norm_30.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_590 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_200 [label="batch_norm_31.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_32 [label="conv2d_26.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_412 [label=< - - - - - -
- -depthwise_conv2d_6.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - dims: 1 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_603 [label=<softmax> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_357 [label="batch_norm_5.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_202 [label=< - - - - - -
- -batch_norm_27.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_410 [label="depthwise_conv2d_1.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_541 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_437 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_521 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_534 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_414 [label=< - - - - - -
- -conv2d_19.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - dims: 32 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_110 [label="batch_norm_24.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_522 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_8 [label="reshape_18.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_277 [label=< - - - - - -
- -batch_norm_6.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_65 [label="conv2d_8.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_344 [label="conv2d_23.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_335 [label="conv2d_3.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_489 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_569 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_361 [label="transpose_11.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_278 [label="batch_norm_7.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_131 [label=< - - - - - -
- -batch_norm_21.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_552 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_294 [label=< - - - - - -
- -batch_norm_9.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_498 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_107 [label=< - - - - - -
- -batch_norm_29.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_31 [label=< - - - - - -
- -batch_norm_13.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_274 [label="batch_norm_6.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_584 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_332 [label="batch_norm_17.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_341 [label="batch_norm_4.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_232 [label="batch_norm_32.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_597 [label=<concat> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_109 [label=< - - - - - -
- -conv2d_12.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 256 - dims: 128 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_510 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_467 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_192 [label=< - - - - - -
- -batch_norm_17.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_25 [label=< - - - - - -
- -batch_norm_32.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_275 [label="prior_box_3.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_504 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_102 [label="batch_norm_34.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_511 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_588 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_82 [label=< - - - - - -
- -batch_norm_6.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_322 [label=< - - - - - -
- -conv2d_11.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - dims: 128 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_419 [label="reshape_13.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_442 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_547 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_386 [label="batch_norm_19.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_169 [label="reshape_12.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_366 [label="conv2d_4.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_407 [label=< - - - - - -
- -depthwise_conv2d_5.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - dims: 1 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_160 [label=< - - - - - -
- -batch_norm_32.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_457 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_94 [label="batch_norm_16.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_604 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_559 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_52 [label=< - - - - - -
- -batch_norm_5.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_43 [label=< - - - - - -
- -batch_norm_10.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_133 [label="batch_norm_0.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_542 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_478 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_158 [label="transpose_8.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_156 [label="reshape_4.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_104 [label=< - - - - - -
- -batch_norm_31.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_15 [label="reshape_10.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_189 [label=< - - - - - -
- -conv2d_28.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 24 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_80 [label="batch_norm_12.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_253 [label="conv2d_30.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_562 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_267 [label="batch_norm_5.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_180 [label=< - - - - - -
- -batch_norm_0.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 8 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_66 [label="batch_norm_10.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_118 [label=< - - - - - -
- -batch_norm_20.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_601 [label=<box_coder> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_325 [label="depthwise_conv2d_9.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_520 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_98 [label="batch_norm_25.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_78 [label=< - - - - - -
- -batch_norm_31.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_108 [label=< - - - - - -
- -batch_norm_32.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_141 [label=< - - - - - -
- -batch_norm_12.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_140 [label="batch_norm_30.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_13 [label=< - - - - - -
- -batch_norm_14.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_83 [label=< - - - - - -
- -conv2d_33.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 36 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_546 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_481 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_120 [label="prior_box_1.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_10 [label="reshape_16.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_537 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_438 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_527 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_501 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_461 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_307 [label=< - - - - - -
- -batch_norm_14.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_536 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_130 [label=< - - - - - -
- -batch_norm_34.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_436 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_191 [label=< - - - - - -
- -batch_norm_24.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 256 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_462 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_359 [label=< - - - - - -
- -conv2d_31.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 36 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_395 [label="conv2d_9.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_119 [label="transpose_9.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_451 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_173 [label="batch_norm_3.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_343 [label=< - - - - - -
- -conv2d_24.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 24 - dims: 256 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_539 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_480 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_58 [label="batch_norm_12.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_145 [label="transpose_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_328 [label=< - - - - - -
- -conv2d_18.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - dims: 64 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_421 [label="prior_box_1.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_172 [label="depthwise_conv2d_2.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_53 [label=< - - - - - -
- -batch_norm_10.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_492 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_592 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_463 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_248 [label="batch_norm_12.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_24 [label="conv2d_14.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_292 [label=< - - - - - -
- -batch_norm_8.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_246 [label=< - - - - - -
- -batch_norm_5.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_241 [label=< - - - - - -
- -batch_norm_19.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_371 [label="conv2d_31.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_582 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_560 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_181 [label="batch_norm_21.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_507 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_55 [label="transpose_4.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_19 [label="batch_norm_18.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_196 [label="batch_norm_24.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_363 [label=< - - - - - -
- -conv2d_27.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 36 - dims: 128 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_175 [label="batch_norm_21.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_285 [label="batch_norm_7.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_580 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_372 [label=< - - - - - -
- -conv2d_31.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 36 - dims: 64 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_114 [label=< - - - - - -
- -batch_norm_20.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_432 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_68 [label=< - - - - - -
- -batch_norm_2.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 16 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_482 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_269 [label=< - - - - - -
- -batch_norm_5.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_321 [label="batch_norm_22.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_345 [label="conv2d_23.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_194 [label=< - - - - - -
- -batch_norm_24.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 256 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_61 [label=< - - - - - -
- -batch_norm_24.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 256 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_435 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_209 [label="batch_norm_31.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_123 [label="prior_box_4.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_302 [label="batch_norm_30.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_400 [label=< - - - - - -
- -depthwise_conv2d_12.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 256 - dims: 1 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_503 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_459 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_557 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_21 [label=< - - - - - -
- -batch_norm_19.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_224 [label=< - - - - - -
- -batch_norm_16.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_445 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_593 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_112 [label="concat_1.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_370 [label=< - - - - - -
- -conv2d_30.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 24 - dims: 64 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_595 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_99 [label=< - - - - - -
- -batch_norm_32.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_502 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_5 [label="conv2d_24.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_237 [label=< - - - - - -
- -conv2d_20.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 16 - dims: 64 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_251 [label=< - - - - - -
- -conv2d_29.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 36 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_152 [label=< - - - - - -
- -batch_norm_1.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 8 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_30 [label=< - - - - - -
- -batch_norm_22.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_162 [label="batch_norm_15.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_564 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_228 [label="batch_norm_34.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_523 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_265 [label=< - - - - - -
- -batch_norm_4.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_426 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_97 [label="batch_norm_28.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_347 [label=< - - - - - -
- -conv2d_24.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 24 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_418 [label=< - - - - - -
- -depthwise_conv2d_8.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - dims: 1 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_62 [label="batch_norm_27.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_204 [label="batch_norm_21.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_47 [label=< - - - - - -
- -depthwise_conv2d_2.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - dims: 1 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_458 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_378 [label=< - - - - - -
- -batch_norm_2.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 16 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_214 [label=< - - - - - -
- -batch_norm_2.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 16 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_429 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_544 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_423 [label=< - - - - - -
- -batch_norm_24.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 256 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_60 [label="batch_norm_1.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_460 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_387 [label=< - - - - - -
- -conv2d_4.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - dims: 32 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_427 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_154 [label=< - - - - - -
- -batch_norm_23.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_528 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_304 [label=< - - - - - -
- -conv2d_22.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 12 - dims: 128 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_91 [label="batch_norm_26.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_398 [label=< - - - - - -
- -depthwise_conv2d_10.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - dims: 1 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_454 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_199 [label=< - - - - - -
- -batch_norm_28.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_79 [label="batch_norm_23.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_229 [label="batch_norm_31.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_1 [label=< - - - - - -
- -fetch - -
-type: FETCH_LIST
-
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_179 [label="transpose_5.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_446 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_115 [label=< - - - - - -
- -batch_norm_7.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_198 [label=< - - - - - -
- -batch_norm_27.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_600 [label=<concat> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_183 [label="batch_norm_11.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_28 [label=< - - - - - -
- -batch_norm_16.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_54 [label=< - - - - - -
- -batch_norm_33.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 16 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_149 [label=< - - - - - -
- -conv2d_23.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 18 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_373 [label="conv2d_32.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_514 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_95 [label=< - - - - - -
- -batch_norm_11.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_177 [label=< - - - - - -
- -batch_norm_9.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_205 [label=< - - - - - -
- -batch_norm_31.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_283 [label="reshape_17.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_334 [label=< - - - - - -
- -conv2d_22.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 12 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_147 [label=< - - - - - -
- -batch_norm_14.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_86 [label="conv2d_26.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_497 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_316 [label=< - - - - - -
- -conv2d_1.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 16 - dims: 8 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_518 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_330 [label="batch_norm_22.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_227 [label="batch_norm_20.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_50 [label="depthwise_conv2d_5.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_128 [label=< - - - - - -
- -batch_norm_12.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_474 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_605 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_377 [label="conv2d_33.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_524 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_203 [label="batch_norm_33.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_89 [label=< - - - - - -
- -conv2d_13.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 256 - dims: 256 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_252 [label="batch_norm_34.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_247 [label=< - - - - - -
- -batch_norm_27.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_383 [label="batch_norm_17.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_391 [label="batch_norm_27.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_69 [label="conv2d_20.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_452 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_394 [label="batch_norm_28.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_509 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_351 [label="batch_norm_23.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_495 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_11 [label="reshape_14.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_563 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_4 [label="reshape_25.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_577 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_556 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_250 [label="depthwise_conv2d_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_548 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_491 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_268 [label="batch_norm_5.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_313 [label="transpose_1.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_486 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_349 [label=< - - - - - -
- -conv2d_25.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 36 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_303 [label="concat_0.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_281 [label="prior_box_4.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_87 [label=< - - - - - -
- -batch_norm_17.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_186 [label=< - - - - - -
- -batch_norm_21.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_258 [label="batch_norm_9.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_260 [label="conv2d_6.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_440 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_508 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_352 [label="conv2d_25.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_290 [label=< - - - - - -
- -batch_norm_13.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_573 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_90 [label=< - - - - - -
- -batch_norm_12.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_576 [label=<prior_box> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_143 [label=< - - - - - -
- -conv2d_5.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - dims: 64 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_280 [label=< - - - - - -
- -conv2d_0.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 8 - dims: 3 - dims: 3 - dims: 3 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_223 [label="batch_norm_2.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_38 [label="reshape_6.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_46 [label=< - - - - - -
- -batch_norm_11.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_254 [label="reshape_22.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_106 [label="reshape_7.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_41 [label=< - - - - - -
- -batch_norm_16.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_178 [label="batch_norm_23.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_472 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_356 [label=< - - - - - -
- -conv2d_26.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 24 - dims: 128 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_195 [label="batch_norm_24.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_583 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_338 [label=< - - - - - -
- -batch_norm_33.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 16 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_530 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_150 [label="batch_norm_33.tmp_2" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_3 [label="reshape_3.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_448 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_127 [label=< - - - - - -
- -batch_norm_4.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_77 [label=< - - - - - -
- -batch_norm_7.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_262 [label=< - - - - - -
- -batch_norm_13.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_44 [label=< - - - - - -
- -batch_norm_15.w_2 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_67 [label=< - - - - - -
- -conv2d_29.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 36 - dims: 64 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_236 [label="batch_norm_32.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_221 [label="batch_norm_16.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_408 [label=< - - - - - -
- -conv2d_16.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - dims: 128 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_468 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_88 [label="prior_box_5.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_22 [label=< - - - - - -
- -batch_norm_1.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 8 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_428 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_570 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_586 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_431 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_500 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_355 [label=< - - - - - -
- -conv2d_26.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 24 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_113 [label=< - - - - - -
- -batch_norm_20.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_476 [label=<relu> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_578 [label=<elementwise_add> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_170 [label=< - - - - - -
- -batch_norm_15.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_208 [label=< - - - - - -
- -batch_norm_25.b_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 256 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_496 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_574 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_388 [label=< - - - - - -
- -batch_norm_34.w_1 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 32 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_297 [label=< - - - - - -
- -batch_norm_9.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_284 [label=< - - - - - -
- -batch_norm_15.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_561 [label=<transpose> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_487 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -arg_296 [label="depthwise_conv2d_7.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_48 [label="batch_norm_29.tmp_1" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -param_249 [label=< - - - - - -
- -conv2d_28.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 24 - dims: 64 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_7 [label="conv2d_29.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -arg_12 [label="reshape_11.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_465 [label=<depthwise_conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_346 [label=< - - - - - -
- -conv2d_9.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - dims: 128 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -arg_234 [label="batch_norm_18.tmp_0" ,color="#dddddd",fontcolor="#999999",shape="box",style="rounded,filled,bold",fontname="Arial" ]; -op_535 [label=<reshape> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -op_526 [label=<batch_norm> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_390 [label=< - - - - - -
- -conv2d_6.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - dims: 64 - dims: 1 - dims: 1 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_554 [label=<conv2d> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_279 [label=< - - - - - -
- -batch_norm_30.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 64 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -op_599 [label=<concat> ,fontname="Arial",color="#303A3A",style="rounded, filled, bold",height="0.84",width="1.3",shape="box",fontcolor="#ffffff" ]; -param_105 [label=< - - - - - -
- -batch_norm_18.w_0 - -
-type: LOD_TENSOR
lod_tensor { - tensor { - data_type: FP32 - dims: 128 - } -} - -
> ,fontname="Arial",color="#148b97",style="rounded,filled,bold",width="1.3",shape="none",fontcolor="#ffffff" ]; -param_2 -> op_425 [color="#00000"] -op_425 -> arg_379 [color="#00000"] -param_280 -> op_426 [color="#00000"] -arg_379 -> op_426 [color="#00000"] -op_426 -> arg_315 [color="#00000"] -param_180 -> op_427 [color="#00000"] -param_153 -> op_427 [color="#00000"] -param_121 -> op_427 [color="#00000"] -param_56 -> op_427 [color="#00000"] -arg_315 -> op_427 [color="#00000"] -op_427 -> param_153 [color="#00000"] -op_427 -> arg_45 [color="#00000"] -op_427 -> arg_133 [color="#00000"] -op_427 -> param_56 [color="#00000"] -op_427 -> arg_26 [color="#00000"] -arg_26 -> op_428 [color="#00000"] -op_428 -> arg_26 [color="#00000"] -param_396 -> op_429 [color="#00000"] -arg_26 -> op_429 [color="#00000"] -op_429 -> arg_250 [color="#00000"] -param_37 -> op_430 [color="#00000"] -param_22 -> op_430 [color="#00000"] -param_152 -> op_430 [color="#00000"] -param_40 -> op_430 [color="#00000"] -arg_250 -> op_430 [color="#00000"] -op_430 -> param_22 [color="#00000"] -op_430 -> arg_59 [color="#00000"] -op_430 -> arg_60 [color="#00000"] -op_430 -> param_40 [color="#00000"] -op_430 -> arg_148 [color="#00000"] -arg_148 -> op_431 [color="#00000"] -op_431 -> arg_148 [color="#00000"] -param_316 -> op_432 [color="#00000"] -arg_148 -> op_432 [color="#00000"] -op_432 -> arg_310 [color="#00000"] -param_378 -> op_433 [color="#00000"] -param_242 -> op_433 [color="#00000"] -param_68 -> op_433 [color="#00000"] -param_214 -> op_433 [color="#00000"] -arg_310 -> op_433 [color="#00000"] -op_433 -> param_242 [color="#00000"] -op_433 -> arg_73 [color="#00000"] -op_433 -> arg_223 [color="#00000"] -op_433 -> param_214 [color="#00000"] -op_433 -> arg_85 [color="#00000"] -arg_85 -> op_434 [color="#00000"] -op_434 -> arg_85 [color="#00000"] -param_397 -> op_435 [color="#00000"] -arg_85 -> op_435 [color="#00000"] -op_435 -> arg_410 [color="#00000"] -param_134 -> op_436 [color="#00000"] -param_72 -> op_436 [color="#00000"] -param_93 -> op_436 [color="#00000"] -param_137 -> op_436 [color="#00000"] -arg_410 -> op_436 [color="#00000"] -op_436 -> param_72 [color="#00000"] -op_436 -> arg_151 [color="#00000"] -op_436 -> arg_173 [color="#00000"] -op_436 -> param_137 [color="#00000"] -op_436 -> arg_29 [color="#00000"] -arg_29 -> op_437 [color="#00000"] -op_437 -> arg_29 [color="#00000"] -param_333 -> op_438 [color="#00000"] -arg_29 -> op_438 [color="#00000"] -op_438 -> arg_331 [color="#00000"] -param_127 -> op_439 [color="#00000"] -param_220 -> op_439 [color="#00000"] -param_261 -> op_439 [color="#00000"] -param_265 -> op_439 [color="#00000"] -arg_331 -> op_439 [color="#00000"] -op_439 -> param_220 [color="#00000"] -op_439 -> arg_341 [color="#00000"] -op_439 -> arg_256 [color="#00000"] -op_439 -> param_265 [color="#00000"] -op_439 -> arg_308 [color="#00000"] -arg_308 -> op_440 [color="#00000"] -op_440 -> arg_308 [color="#00000"] -param_47 -> op_441 [color="#00000"] -arg_308 -> op_441 [color="#00000"] -op_441 -> arg_172 [color="#00000"] -param_246 -> op_442 [color="#00000"] -param_52 -> op_442 [color="#00000"] -param_411 -> op_442 [color="#00000"] -param_269 -> op_442 [color="#00000"] -arg_172 -> op_442 [color="#00000"] -op_442 -> param_52 [color="#00000"] -op_442 -> arg_267 [color="#00000"] -op_442 -> arg_357 [color="#00000"] -op_442 -> param_269 [color="#00000"] -op_442 -> arg_268 [color="#00000"] -arg_268 -> op_443 [color="#00000"] -op_443 -> arg_268 [color="#00000"] -param_305 -> op_444 [color="#00000"] -arg_268 -> op_444 [color="#00000"] -op_444 -> arg_335 [color="#00000"] -param_82 -> op_445 [color="#00000"] -param_277 -> op_445 [color="#00000"] -param_276 -> op_445 [color="#00000"] -param_20 -> op_445 [color="#00000"] -arg_335 -> op_445 [color="#00000"] -op_445 -> param_277 [color="#00000"] -op_445 -> arg_273 [color="#00000"] -op_445 -> arg_23 [color="#00000"] -op_445 -> param_20 [color="#00000"] -op_445 -> arg_274 [color="#00000"] -arg_274 -> op_446 [color="#00000"] -op_446 -> arg_274 [color="#00000"] -param_405 -> op_447 [color="#00000"] -arg_274 -> op_447 [color="#00000"] -op_447 -> arg_402 [color="#00000"] -param_299 -> op_448 [color="#00000"] -param_77 -> op_448 [color="#00000"] -param_115 -> op_448 [color="#00000"] -param_100 -> op_448 [color="#00000"] -arg_402 -> op_448 [color="#00000"] -op_448 -> param_77 [color="#00000"] -op_448 -> arg_278 [color="#00000"] -op_448 -> arg_282 [color="#00000"] -op_448 -> param_100 [color="#00000"] -op_448 -> arg_285 [color="#00000"] -arg_285 -> op_449 [color="#00000"] -op_449 -> arg_285 [color="#00000"] -param_387 -> op_450 [color="#00000"] -arg_285 -> op_450 [color="#00000"] -op_450 -> arg_366 [color="#00000"] -param_286 -> op_451 [color="#00000"] -param_289 -> op_451 [color="#00000"] -param_287 -> op_451 [color="#00000"] -param_292 -> op_451 [color="#00000"] -arg_366 -> op_451 [color="#00000"] -op_451 -> param_289 [color="#00000"] -op_451 -> arg_230 [color="#00000"] -op_451 -> arg_159 [color="#00000"] -op_451 -> param_292 [color="#00000"] -op_451 -> arg_184 [color="#00000"] -arg_184 -> op_452 [color="#00000"] -op_452 -> arg_184 [color="#00000"] -param_393 -> op_453 [color="#00000"] -arg_184 -> op_453 [color="#00000"] -op_453 -> arg_353 [color="#00000"] -param_294 -> op_454 [color="#00000"] -param_259 -> op_454 [color="#00000"] -param_297 -> op_454 [color="#00000"] -param_177 -> op_454 [color="#00000"] -arg_353 -> op_454 [color="#00000"] -op_454 -> param_259 [color="#00000"] -op_454 -> arg_235 [color="#00000"] -op_454 -> arg_258 [color="#00000"] -op_454 -> param_177 [color="#00000"] -op_454 -> arg_403 [color="#00000"] -arg_403 -> op_455 [color="#00000"] -op_455 -> arg_403 [color="#00000"] -param_143 -> op_456 [color="#00000"] -arg_403 -> op_456 [color="#00000"] -op_456 -> arg_389 [color="#00000"] -param_53 -> op_457 [color="#00000"] -param_126 -> op_457 [color="#00000"] -param_215 -> op_457 [color="#00000"] -param_43 -> op_457 [color="#00000"] -arg_389 -> op_457 [color="#00000"] -op_457 -> param_126 [color="#00000"] -op_457 -> arg_66 [color="#00000"] -op_457 -> arg_238 [color="#00000"] -op_457 -> param_43 [color="#00000"] -op_457 -> arg_75 [color="#00000"] -arg_75 -> op_458 [color="#00000"] -op_458 -> arg_75 [color="#00000"] -param_407 -> op_459 [color="#00000"] -arg_75 -> op_459 [color="#00000"] -op_459 -> arg_50 [color="#00000"] -param_46 -> op_460 [color="#00000"] -param_264 -> op_460 [color="#00000"] -param_171 -> op_460 [color="#00000"] -param_95 -> op_460 [color="#00000"] -arg_50 -> op_460 [color="#00000"] -op_460 -> param_264 [color="#00000"] -op_460 -> arg_183 [color="#00000"] -op_460 -> arg_161 [color="#00000"] -op_460 -> param_95 [color="#00000"] -op_460 -> arg_63 [color="#00000"] -arg_63 -> op_461 [color="#00000"] -op_461 -> arg_63 [color="#00000"] -param_390 -> op_462 [color="#00000"] -arg_63 -> op_462 [color="#00000"] -op_462 -> arg_260 [color="#00000"] -param_128 -> op_463 [color="#00000"] -param_142 -> op_463 [color="#00000"] -param_141 -> op_463 [color="#00000"] -param_90 -> op_463 [color="#00000"] -arg_260 -> op_463 [color="#00000"] -op_463 -> param_142 [color="#00000"] -op_463 -> arg_248 [color="#00000"] -op_463 -> arg_58 [color="#00000"] -op_463 -> param_90 [color="#00000"] -op_463 -> arg_80 [color="#00000"] -arg_80 -> op_464 [color="#00000"] -op_464 -> arg_80 [color="#00000"] -param_412 -> op_465 [color="#00000"] -arg_80 -> op_465 [color="#00000"] -op_465 -> arg_409 [color="#00000"] -param_290 -> op_466 [color="#00000"] -param_139 -> op_466 [color="#00000"] -param_262 -> op_466 [color="#00000"] -param_31 -> op_466 [color="#00000"] -arg_409 -> op_466 [color="#00000"] -op_466 -> param_139 [color="#00000"] -op_466 -> arg_64 [color="#00000"] -op_466 -> arg_168 [color="#00000"] -op_466 -> param_31 [color="#00000"] -op_466 -> arg_74 [color="#00000"] -arg_74 -> op_467 [color="#00000"] -op_467 -> arg_74 [color="#00000"] -param_225 -> op_468 [color="#00000"] -arg_74 -> op_468 [color="#00000"] -op_468 -> arg_392 [color="#00000"] -param_213 -> op_469 [color="#00000"] -param_147 -> op_469 [color="#00000"] -param_13 -> op_469 [color="#00000"] -param_307 -> op_469 [color="#00000"] -arg_392 -> op_469 [color="#00000"] -op_469 -> param_147 [color="#00000"] -op_469 -> arg_71 [color="#00000"] -op_469 -> arg_39 [color="#00000"] -op_469 -> param_307 [color="#00000"] -op_469 -> arg_27 [color="#00000"] -arg_27 -> op_470 [color="#00000"] -op_470 -> arg_27 [color="#00000"] -param_415 -> op_471 [color="#00000"] -arg_27 -> op_471 [color="#00000"] -op_471 -> arg_296 [color="#00000"] -param_217 -> op_472 [color="#00000"] -param_170 -> op_472 [color="#00000"] -param_284 -> op_472 [color="#00000"] -param_44 -> op_472 [color="#00000"] -arg_296 -> op_472 [color="#00000"] -op_472 -> param_170 [color="#00000"] -op_472 -> arg_231 [color="#00000"] -op_472 -> arg_219 [color="#00000"] -op_472 -> param_44 [color="#00000"] -op_472 -> arg_162 [color="#00000"] -arg_162 -> op_473 [color="#00000"] -op_473 -> arg_162 [color="#00000"] -param_266 -> op_474 [color="#00000"] -arg_162 -> op_474 [color="#00000"] -op_474 -> arg_65 [color="#00000"] -param_49 -> op_475 [color="#00000"] -param_41 -> op_475 [color="#00000"] -param_28 -> op_475 [color="#00000"] -param_224 -> op_475 [color="#00000"] -arg_65 -> op_475 [color="#00000"] -op_475 -> param_41 [color="#00000"] -op_475 -> arg_221 [color="#00000"] -op_475 -> arg_176 [color="#00000"] -op_475 -> param_224 [color="#00000"] -op_475 -> arg_94 [color="#00000"] -arg_94 -> op_476 [color="#00000"] -op_476 -> arg_94 [color="#00000"] -param_418 -> op_477 [color="#00000"] -arg_94 -> op_477 [color="#00000"] -op_477 -> arg_416 [color="#00000"] -param_192 -> op_478 [color="#00000"] -param_233 -> op_478 [color="#00000"] -param_132 -> op_478 [color="#00000"] -param_87 -> op_478 [color="#00000"] -arg_416 -> op_478 [color="#00000"] -op_478 -> param_233 [color="#00000"] -op_478 -> arg_332 [color="#00000"] -op_478 -> arg_383 [color="#00000"] -op_478 -> param_87 [color="#00000"] -op_478 -> arg_288 [color="#00000"] -arg_288 -> op_479 [color="#00000"] -op_479 -> arg_288 [color="#00000"] -param_346 -> op_480 [color="#00000"] -arg_288 -> op_480 [color="#00000"] -op_480 -> arg_395 [color="#00000"] -param_18 -> op_481 [color="#00000"] -param_188 -> op_481 [color="#00000"] -param_105 -> op_481 [color="#00000"] -param_401 -> op_481 [color="#00000"] -arg_395 -> op_481 [color="#00000"] -op_481 -> param_188 [color="#00000"] -op_481 -> arg_234 [color="#00000"] -op_481 -> arg_368 [color="#00000"] -op_481 -> param_401 [color="#00000"] -op_481 -> arg_19 [color="#00000"] -arg_19 -> op_482 [color="#00000"] -op_482 -> arg_19 [color="#00000"] -param_167 -> op_483 [color="#00000"] -arg_19 -> op_483 [color="#00000"] -op_483 -> arg_325 [color="#00000"] -param_354 -> op_484 [color="#00000"] -param_241 -> op_484 [color="#00000"] -param_197 -> op_484 [color="#00000"] -param_21 -> op_484 [color="#00000"] -arg_325 -> op_484 [color="#00000"] -op_484 -> param_241 [color="#00000"] -op_484 -> arg_386 [color="#00000"] -op_484 -> arg_240 [color="#00000"] -op_484 -> param_21 [color="#00000"] -op_484 -> arg_340 [color="#00000"] -arg_340 -> op_485 [color="#00000"] -op_485 -> arg_340 [color="#00000"] -param_270 -> op_486 [color="#00000"] -arg_340 -> op_486 [color="#00000"] -op_486 -> arg_319 [color="#00000"] -param_84 -> op_487 [color="#00000"] -param_114 -> op_487 [color="#00000"] -param_113 -> op_487 [color="#00000"] -param_118 -> op_487 [color="#00000"] -arg_319 -> op_487 [color="#00000"] -op_487 -> param_114 [color="#00000"] -op_487 -> arg_243 [color="#00000"] -op_487 -> arg_227 [color="#00000"] -op_487 -> param_118 [color="#00000"] -op_487 -> arg_271 [color="#00000"] -arg_271 -> op_488 [color="#00000"] -op_488 -> arg_271 [color="#00000"] -param_398 -> op_489 [color="#00000"] -arg_271 -> op_489 [color="#00000"] -op_489 -> arg_239 [color="#00000"] -param_131 -> op_490 [color="#00000"] -param_244 -> op_490 [color="#00000"] -param_186 -> op_490 [color="#00000"] -param_413 -> op_490 [color="#00000"] -arg_239 -> op_490 [color="#00000"] -op_490 -> param_244 [color="#00000"] -op_490 -> arg_175 [color="#00000"] -op_490 -> arg_204 [color="#00000"] -op_490 -> param_413 [color="#00000"] -op_490 -> arg_181 [color="#00000"] -arg_181 -> op_491 [color="#00000"] -op_491 -> arg_181 [color="#00000"] -param_322 -> op_492 [color="#00000"] -arg_181 -> op_492 [color="#00000"] -op_492 -> arg_320 [color="#00000"] -param_30 -> op_493 [color="#00000"] -param_257 -> op_493 [color="#00000"] -param_210 -> op_493 [color="#00000"] -param_157 -> op_493 [color="#00000"] -arg_320 -> op_493 [color="#00000"] -op_493 -> param_257 [color="#00000"] -op_493 -> arg_311 [color="#00000"] -op_493 -> arg_330 [color="#00000"] -op_493 -> param_157 [color="#00000"] -op_493 -> arg_321 [color="#00000"] -arg_321 -> op_494 [color="#00000"] -op_494 -> arg_321 [color="#00000"] -param_263 -> op_495 [color="#00000"] -arg_321 -> op_495 [color="#00000"] -op_495 -> arg_70 [color="#00000"] -param_212 -> op_496 [color="#00000"] -param_57 -> op_496 [color="#00000"] -param_201 -> op_496 [color="#00000"] -param_154 -> op_496 [color="#00000"] -arg_70 -> op_496 [color="#00000"] -op_496 -> param_57 [color="#00000"] -op_496 -> arg_79 [color="#00000"] -op_496 -> arg_351 [color="#00000"] -op_496 -> param_154 [color="#00000"] -op_496 -> arg_178 [color="#00000"] -arg_178 -> op_497 [color="#00000"] -op_497 -> arg_178 [color="#00000"] -param_109 -> op_498 [color="#00000"] -arg_178 -> op_498 [color="#00000"] -op_498 -> arg_369 [color="#00000"] -param_194 -> op_499 [color="#00000"] -param_61 -> op_499 [color="#00000"] -param_423 -> op_499 [color="#00000"] -param_191 -> op_499 [color="#00000"] -arg_369 -> op_499 [color="#00000"] -op_499 -> param_61 [color="#00000"] -op_499 -> arg_196 [color="#00000"] -op_499 -> arg_110 [color="#00000"] -op_499 -> param_191 [color="#00000"] -op_499 -> arg_195 [color="#00000"] -arg_195 -> op_500 [color="#00000"] -op_500 -> arg_195 [color="#00000"] -param_400 -> op_501 [color="#00000"] -arg_195 -> op_501 [color="#00000"] -op_501 -> arg_399 [color="#00000"] -param_208 -> op_502 [color="#00000"] -param_367 -> op_502 [color="#00000"] -param_382 -> op_502 [color="#00000"] -param_146 -> op_502 [color="#00000"] -arg_399 -> op_502 [color="#00000"] -op_502 -> param_367 [color="#00000"] -op_502 -> arg_98 [color="#00000"] -op_502 -> arg_185 [color="#00000"] -op_502 -> param_146 [color="#00000"] -op_502 -> arg_36 [color="#00000"] -arg_36 -> op_503 [color="#00000"] -op_503 -> arg_36 [color="#00000"] -param_89 -> op_504 [color="#00000"] -arg_36 -> op_504 [color="#00000"] -op_504 -> arg_174 [color="#00000"] -param_222 -> op_505 [color="#00000"] -param_111 -> op_505 [color="#00000"] -param_103 -> op_505 [color="#00000"] -param_165 -> op_505 [color="#00000"] -arg_174 -> op_505 [color="#00000"] -op_505 -> param_111 [color="#00000"] -op_505 -> arg_327 [color="#00000"] -op_505 -> arg_91 [color="#00000"] -op_505 -> param_165 [color="#00000"] -op_505 -> arg_129 [color="#00000"] -arg_129 -> op_506 [color="#00000"] -op_506 -> arg_129 [color="#00000"] -param_272 -> op_507 [color="#00000"] -arg_129 -> op_507 [color="#00000"] -op_507 -> arg_24 [color="#00000"] -param_247 -> op_508 [color="#00000"] -param_202 -> op_508 [color="#00000"] -param_198 -> op_508 [color="#00000"] -param_193 -> op_508 [color="#00000"] -arg_24 -> op_508 [color="#00000"] -op_508 -> param_202 [color="#00000"] -op_508 -> arg_62 [color="#00000"] -op_508 -> arg_391 [color="#00000"] -op_508 -> param_193 [color="#00000"] -op_508 -> arg_318 [color="#00000"] -arg_318 -> op_509 [color="#00000"] -op_509 -> arg_318 [color="#00000"] -param_324 -> op_510 [color="#00000"] -arg_318 -> op_510 [color="#00000"] -op_510 -> arg_323 [color="#00000"] -param_207 -> op_511 [color="#00000"] -param_35 -> op_511 [color="#00000"] -param_17 -> op_511 [color="#00000"] -param_199 -> op_511 [color="#00000"] -arg_323 -> op_511 [color="#00000"] -op_511 -> param_35 [color="#00000"] -op_511 -> arg_394 [color="#00000"] -op_511 -> arg_163 [color="#00000"] -op_511 -> param_199 [color="#00000"] -op_511 -> arg_97 [color="#00000"] -arg_97 -> op_512 [color="#00000"] -op_512 -> arg_97 [color="#00000"] -param_408 -> op_513 [color="#00000"] -arg_97 -> op_513 [color="#00000"] -op_513 -> arg_33 [color="#00000"] -param_107 -> op_514 [color="#00000"] -param_122 -> op_514 [color="#00000"] -param_76 -> op_514 [color="#00000"] -param_92 -> op_514 [color="#00000"] -arg_33 -> op_514 [color="#00000"] -op_514 -> param_122 [color="#00000"] -op_514 -> arg_155 [color="#00000"] -op_514 -> arg_48 [color="#00000"] -op_514 -> param_92 [color="#00000"] -op_514 -> arg_124 [color="#00000"] -arg_124 -> op_515 [color="#00000"] -op_515 -> arg_124 [color="#00000"] -param_365 -> op_516 [color="#00000"] -arg_124 -> op_516 [color="#00000"] -op_516 -> arg_291 [color="#00000"] -param_42 -> op_517 [color="#00000"] -param_317 -> op_517 [color="#00000"] -param_279 -> op_517 [color="#00000"] -param_164 -> op_517 [color="#00000"] -arg_291 -> op_517 [color="#00000"] -op_517 -> param_317 [color="#00000"] -op_517 -> arg_302 [color="#00000"] -op_517 -> arg_140 [color="#00000"] -op_517 -> param_164 [color="#00000"] -op_517 -> arg_326 [color="#00000"] -arg_326 -> op_518 [color="#00000"] -op_518 -> arg_326 [color="#00000"] -param_328 -> op_519 [color="#00000"] -arg_326 -> op_519 [color="#00000"] -op_519 -> arg_404 [color="#00000"] -param_205 -> op_520 [color="#00000"] -param_104 -> op_520 [color="#00000"] -param_211 -> op_520 [color="#00000"] -param_78 -> op_520 [color="#00000"] -arg_404 -> op_520 [color="#00000"] -op_520 -> param_104 [color="#00000"] -op_520 -> arg_229 [color="#00000"] -op_520 -> arg_209 [color="#00000"] -op_520 -> param_78 [color="#00000"] -op_520 -> arg_200 [color="#00000"] -arg_200 -> op_521 [color="#00000"] -op_521 -> arg_200 [color="#00000"] -param_414 -> op_522 [color="#00000"] -arg_200 -> op_522 [color="#00000"] -op_522 -> arg_34 [color="#00000"] -param_99 -> op_523 [color="#00000"] -param_108 -> op_523 [color="#00000"] -param_25 -> op_523 [color="#00000"] -param_160 -> op_523 [color="#00000"] -arg_34 -> op_523 [color="#00000"] -op_523 -> param_108 [color="#00000"] -op_523 -> arg_236 [color="#00000"] -op_523 -> arg_232 [color="#00000"] -op_523 -> param_160 [color="#00000"] -op_523 -> arg_226 [color="#00000"] -arg_226 -> op_524 [color="#00000"] -op_524 -> arg_226 [color="#00000"] -param_237 -> op_525 [color="#00000"] -arg_226 -> op_525 [color="#00000"] -op_525 -> arg_69 [color="#00000"] -param_54 -> op_526 [color="#00000"] -param_135 -> op_526 [color="#00000"] -param_338 -> op_526 [color="#00000"] -param_374 -> op_526 [color="#00000"] -arg_69 -> op_526 [color="#00000"] -op_526 -> param_135 [color="#00000"] -op_526 -> arg_125 [color="#00000"] -op_526 -> arg_203 [color="#00000"] -op_526 -> param_374 [color="#00000"] -op_526 -> arg_150 [color="#00000"] -arg_150 -> op_527 [color="#00000"] -op_527 -> arg_150 [color="#00000"] -param_295 -> op_528 [color="#00000"] -arg_150 -> op_528 [color="#00000"] -op_528 -> arg_406 [color="#00000"] -param_187 -> op_529 [color="#00000"] -param_388 -> op_529 [color="#00000"] -param_130 -> op_529 [color="#00000"] -param_216 -> op_529 [color="#00000"] -arg_406 -> op_529 [color="#00000"] -op_529 -> param_388 [color="#00000"] -op_529 -> arg_228 [color="#00000"] -op_529 -> arg_252 [color="#00000"] -op_529 -> param_216 [color="#00000"] -op_529 -> arg_102 [color="#00000"] -arg_102 -> op_530 [color="#00000"] -op_530 -> arg_102 [color="#00000"] -arg_379 -> op_531 [color="#00000"] -arg_321 -> op_531 [color="#00000"] -op_531 -> arg_136 [color="#00000"] -op_531 -> arg_342 [color="#00000"] -param_304 -> op_532 [color="#00000"] -arg_321 -> op_532 [color="#00000"] -op_532 -> arg_336 [color="#00000"] -arg_336 -> op_533 [color="#00000"] -param_334 -> op_533 [color="#00000"] -op_533 -> arg_339 [color="#00000"] -arg_339 -> op_534 [color="#00000"] -op_534 -> arg_145 [color="#00000"] -arg_145 -> op_535 [color="#00000"] -op_535 -> arg_16 [color="#00000"] -param_116 -> op_536 [color="#00000"] -arg_321 -> op_536 [color="#00000"] -op_536 -> arg_344 [color="#00000"] -arg_344 -> op_537 [color="#00000"] -param_149 -> op_537 [color="#00000"] -op_537 -> arg_345 [color="#00000"] -arg_345 -> op_538 [color="#00000"] -op_538 -> arg_313 [color="#00000"] -arg_313 -> op_539 [color="#00000"] -op_539 -> arg_96 [color="#00000"] -arg_379 -> op_540 [color="#00000"] -arg_129 -> op_540 [color="#00000"] -op_540 -> arg_120 [color="#00000"] -op_540 -> arg_421 [color="#00000"] -param_343 -> op_541 [color="#00000"] -arg_129 -> op_541 [color="#00000"] -op_541 -> arg_348 [color="#00000"] -arg_348 -> op_542 [color="#00000"] -param_347 -> op_542 [color="#00000"] -op_542 -> arg_5 [color="#00000"] -arg_5 -> op_543 [color="#00000"] -op_543 -> arg_306 [color="#00000"] -arg_306 -> op_544 [color="#00000"] -op_544 -> arg_6 [color="#00000"] -param_312 -> op_545 [color="#00000"] -arg_129 -> op_545 [color="#00000"] -op_545 -> arg_350 [color="#00000"] -arg_350 -> op_546 [color="#00000"] -param_349 -> op_546 [color="#00000"] -op_546 -> arg_352 [color="#00000"] -arg_352 -> op_547 [color="#00000"] -op_547 -> arg_381 [color="#00000"] -arg_381 -> op_548 [color="#00000"] -op_548 -> arg_3 [color="#00000"] -arg_379 -> op_549 [color="#00000"] -arg_97 -> op_549 [color="#00000"] -op_549 -> arg_245 [color="#00000"] -op_549 -> arg_424 [color="#00000"] -param_356 -> op_550 [color="#00000"] -arg_97 -> op_550 [color="#00000"] -op_550 -> arg_86 [color="#00000"] -arg_86 -> op_551 [color="#00000"] -param_355 -> op_551 [color="#00000"] -op_551 -> arg_32 [color="#00000"] -arg_32 -> op_552 [color="#00000"] -op_552 -> arg_55 [color="#00000"] -arg_55 -> op_553 [color="#00000"] -op_553 -> arg_156 [color="#00000"] -param_363 -> op_554 [color="#00000"] -arg_97 -> op_554 [color="#00000"] -op_554 -> arg_360 [color="#00000"] -arg_360 -> op_555 [color="#00000"] -param_358 -> op_555 [color="#00000"] -op_555 -> arg_362 [color="#00000"] -arg_362 -> op_556 [color="#00000"] -op_556 -> arg_179 [color="#00000"] -arg_179 -> op_557 [color="#00000"] -op_557 -> arg_337 [color="#00000"] -arg_379 -> op_558 [color="#00000"] -arg_326 -> op_558 [color="#00000"] -op_558 -> arg_275 [color="#00000"] -op_558 -> arg_380 [color="#00000"] -param_249 -> op_559 [color="#00000"] -arg_326 -> op_559 [color="#00000"] -op_559 -> arg_364 [color="#00000"] -arg_364 -> op_560 [color="#00000"] -param_189 -> op_560 [color="#00000"] -op_560 -> arg_81 [color="#00000"] -arg_81 -> op_561 [color="#00000"] -op_561 -> arg_144 [color="#00000"] -arg_144 -> op_562 [color="#00000"] -op_562 -> arg_38 [color="#00000"] -param_67 -> op_563 [color="#00000"] -arg_326 -> op_563 [color="#00000"] -op_563 -> arg_7 [color="#00000"] -arg_7 -> op_564 [color="#00000"] -param_251 -> op_564 [color="#00000"] -op_564 -> arg_9 [color="#00000"] -arg_9 -> op_565 [color="#00000"] -op_565 -> arg_14 [color="#00000"] -arg_14 -> op_566 [color="#00000"] -op_566 -> arg_106 [color="#00000"] -arg_379 -> op_567 [color="#00000"] -arg_226 -> op_567 [color="#00000"] -op_567 -> arg_281 [color="#00000"] -op_567 -> arg_123 [color="#00000"] -param_370 -> op_568 [color="#00000"] -arg_226 -> op_568 [color="#00000"] -op_568 -> arg_253 [color="#00000"] -arg_253 -> op_569 [color="#00000"] -param_376 -> op_569 [color="#00000"] -op_569 -> arg_101 [color="#00000"] -arg_101 -> op_570 [color="#00000"] -op_570 -> arg_158 [color="#00000"] -arg_158 -> op_571 [color="#00000"] -op_571 -> arg_300 [color="#00000"] -param_372 -> op_572 [color="#00000"] -arg_226 -> op_572 [color="#00000"] -op_572 -> arg_371 [color="#00000"] -arg_371 -> op_573 [color="#00000"] -param_359 -> op_573 [color="#00000"] -op_573 -> arg_166 [color="#00000"] -arg_166 -> op_574 [color="#00000"] -op_574 -> arg_119 [color="#00000"] -arg_119 -> op_575 [color="#00000"] -op_575 -> arg_293 [color="#00000"] -arg_379 -> op_576 [color="#00000"] -arg_102 -> op_576 [color="#00000"] -op_576 -> arg_88 [color="#00000"] -op_576 -> arg_384 [color="#00000"] -param_51 -> op_577 [color="#00000"] -arg_102 -> op_577 [color="#00000"] -op_577 -> arg_138 [color="#00000"] -arg_138 -> op_578 [color="#00000"] -param_417 -> op_578 [color="#00000"] -op_578 -> arg_373 [color="#00000"] -arg_373 -> op_579 [color="#00000"] -op_579 -> arg_206 [color="#00000"] -arg_206 -> op_580 [color="#00000"] -op_580 -> arg_15 [color="#00000"] -param_385 -> op_581 [color="#00000"] -arg_102 -> op_581 [color="#00000"] -op_581 -> arg_375 [color="#00000"] -arg_375 -> op_582 [color="#00000"] -param_83 -> op_582 [color="#00000"] -op_582 -> arg_377 [color="#00000"] -arg_377 -> op_583 [color="#00000"] -op_583 -> arg_361 [color="#00000"] -arg_361 -> op_584 [color="#00000"] -op_584 -> arg_12 [color="#00000"] -arg_136 -> op_585 [color="#00000"] -op_585 -> arg_169 [color="#00000"] -arg_342 -> op_586 [color="#00000"] -op_586 -> arg_419 [color="#00000"] -arg_120 -> op_587 [color="#00000"] -op_587 -> arg_11 [color="#00000"] -arg_421 -> op_588 [color="#00000"] -op_588 -> arg_190 [color="#00000"] -arg_245 -> op_589 [color="#00000"] -op_589 -> arg_10 [color="#00000"] -arg_424 -> op_590 [color="#00000"] -op_590 -> arg_283 [color="#00000"] -arg_275 -> op_591 [color="#00000"] -op_591 -> arg_8 [color="#00000"] -arg_380 -> op_592 [color="#00000"] -op_592 -> arg_298 [color="#00000"] -arg_281 -> op_593 [color="#00000"] -op_593 -> arg_218 [color="#00000"] -arg_123 -> op_594 [color="#00000"] -op_594 -> arg_182 [color="#00000"] -arg_88 -> op_595 [color="#00000"] -op_595 -> arg_254 [color="#00000"] -arg_384 -> op_596 [color="#00000"] -op_596 -> arg_329 [color="#00000"] -arg_169 -> op_597 [color="#00000"] -arg_11 -> op_597 [color="#00000"] -arg_10 -> op_597 [color="#00000"] -arg_8 -> op_597 [color="#00000"] -arg_218 -> op_597 [color="#00000"] -arg_254 -> op_597 [color="#00000"] -op_597 -> arg_303 [color="#00000"] -arg_419 -> op_598 [color="#00000"] -arg_190 -> op_598 [color="#00000"] -arg_283 -> op_598 [color="#00000"] -arg_298 -> op_598 [color="#00000"] -arg_182 -> op_598 [color="#00000"] -arg_329 -> op_598 [color="#00000"] -op_598 -> arg_112 [color="#00000"] -arg_16 -> op_599 [color="#00000"] -arg_6 -> op_599 [color="#00000"] -arg_156 -> op_599 [color="#00000"] -arg_38 -> op_599 [color="#00000"] -arg_300 -> op_599 [color="#00000"] -arg_15 -> op_599 [color="#00000"] -op_599 -> arg_309 [color="#00000"] -arg_96 -> op_600 [color="#00000"] -arg_3 -> op_600 [color="#00000"] -arg_337 -> op_600 [color="#00000"] -arg_106 -> op_600 [color="#00000"] -arg_293 -> op_600 [color="#00000"] -arg_12 -> op_600 [color="#00000"] -op_600 -> arg_314 [color="#00000"] -arg_303 -> op_601 [color="#00000"] -arg_112 -> op_601 [color="#00000"] -arg_309 -> op_601 [color="#00000"] -op_601 -> arg_301 [color="#00000"] -arg_314 -> op_602 [color="#00000"] -op_602 -> arg_422 [color="#00000"] -arg_422 -> op_603 [color="#00000"] -op_603 -> arg_255 [color="#00000"] -arg_255 -> op_604 [color="#00000"] -op_604 -> arg_4 [color="#00000"] -arg_4 -> op_605 [color="#00000"] -op_605 -> arg_117 [color="#00000"] -arg_301 -> op_606 [color="#00000"] -arg_117 -> op_606 [color="#00000"] -op_606 -> arg_420 [color="#00000"] -arg_420 -> op_607 [color="#00000"] -op_607 -> param_1 [color="#00000"] -} \ No newline at end of file diff --git a/tools/external_converter_v2/parser/fluid/tools/debug.pdf b/tools/external_converter_v2/parser/fluid/tools/debug.pdf deleted file mode 100644 index 6c56b70d04a84aa159c125bff4db4bc2675054b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 152185 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

5Zc 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 Date: Fri, 21 Sep 2018 10:50:52 +0800 Subject: [PATCH 44/51] fix readme --- docs/Manual/Converter_ch.md | 4 ++-- docs/Manual/INSTALL_ch.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/Manual/Converter_ch.md b/docs/Manual/Converter_ch.md index f8573f2f8..afeb37181 100644 --- a/docs/Manual/Converter_ch.md +++ b/docs/Manual/Converter_ch.md @@ -13,8 +13,8 @@ Anakin 模型转换器输入支持 Caffe 和 Fluid 两种格式的预测模型 ## 系统要求 -- Python 2.7+ -- Protobuf 3.1+(务必注意 Python 与系统环境 Protobuf 版本一致) +- Python 2.7 +- Protobuf 3.1+(务必注意 Pip Protobuf 与系统环境 Protobuf 版本一致) - PaddlePaddle 0.12.0+ (Fluid 模式下) - flask, bson, matplotlib, scikit-image - tkinter diff --git a/docs/Manual/INSTALL_ch.md b/docs/Manual/INSTALL_ch.md index 16b13cd9e..038e85918 100644 --- a/docs/Manual/INSTALL_ch.md +++ b/docs/Manual/INSTALL_ch.md @@ -43,7 +43,7 @@ #### Anakin - CPU ### -在编译 CPU 版本前,我们建议您升级 GCC-G++ 至 5.4.0 以上,链接的 libm.so 库版本高于 2.17,以发挥更佳性能。 +在编译 CPU 版本前,我们建议您升级 GCC-G++ 至 5.4.0,链接的 libm.so 库版本高于 2.17,以发挥更佳性能。 #### Anakin - AMDGPU ### From bc6a39ebe48777017431d265c6833e7b7c9854c2 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Fri, 21 Sep 2018 10:57:02 +0800 Subject: [PATCH 45/51] update readme --- docs/Manual/INSTALL_ch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Manual/INSTALL_ch.md b/docs/Manual/INSTALL_ch.md index 038e85918..40c95392f 100644 --- a/docs/Manual/INSTALL_ch.md +++ b/docs/Manual/INSTALL_ch.md @@ -43,7 +43,7 @@ #### Anakin - CPU ### -在编译 CPU 版本前,我们建议您升级 GCC-G++ 至 5.4.0,链接的 libm.so 库版本高于 2.17,以发挥更佳性能。 +在编译 CPU 版本前,我们建议您升级 GCC-G++ 至 5.4.0,链接的 libm.so 库版本为 2.17 ~ 2.23,以发挥更佳性能。 #### Anakin - AMDGPU ### From fed5e697de3850ed2ffbd80bc71756e6369d719a Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Thu, 27 Sep 2018 16:21:41 +0800 Subject: [PATCH 46/51] support new fluid mobilenetssd --- .../fluid/fluid_layer_param_transmit.py | 14 ++ .../parser/fluid/parser_fluid.py | 122 ++++++++++++------ .../parser/operations/ops_fluid.py | 16 ++- 3 files changed, 110 insertions(+), 42 deletions(-) diff --git a/tools/external_converter_v2/parser/fluid/fluid_layer_param_transmit.py b/tools/external_converter_v2/parser/fluid/fluid_layer_param_transmit.py index eb97be479..cfc1cd252 100644 --- a/tools/external_converter_v2/parser/fluid/fluid_layer_param_transmit.py +++ b/tools/external_converter_v2/parser/fluid/fluid_layer_param_transmit.py @@ -447,6 +447,17 @@ def Parser_elementwise_mul(args): else: OpsRegister()["Scale"].bias_term = False +@ParserFeedDecorator("Flatten") +def Parser_flatten(args): + pass + +@ParserFeedDecorator("assign_value") +def Parser_assign_value(args): + pass + +@ParserFeedDecorator("shape") +def Parser_shape(args): + pass FLUID_NODE_FILLER = { "feed":OpsParam().set_parser(Parser_feed), @@ -488,4 +499,7 @@ def Parser_elementwise_mul(args): "layer_norm":OpsParam().set_parser(Parser_layer_norm), "dropout":OpsParam().set_parser(Parser_dropout), "scale":OpsParam().set_parser(Parser_scale), + "flatten":OpsParam().set_parser(Parser_flatten), + "assign_value":OpsParam().set_parser(Parser_assign_value), + "shape":OpsParam().set_parser(Parser_shape), } diff --git a/tools/external_converter_v2/parser/fluid/parser_fluid.py b/tools/external_converter_v2/parser/fluid/parser_fluid.py index ebdcc3790..84efb8949 100644 --- a/tools/external_converter_v2/parser/fluid/parser_fluid.py +++ b/tools/external_converter_v2/parser/fluid/parser_fluid.py @@ -703,18 +703,80 @@ def _DealWithArgmax(self, source_ops, helper): self._RmProtoNode(topk_node_name) self._AddProtoNode(topk_node_name, source_op, helper, private_data) - def _DealWithReshape(self, source_ops, helper): + def _RefreshReshape(self, source_ops, helper, need_assign=False): for source_op in source_ops: if source_op.type == 'reshape': reshape_node_name = self._NameNodeMid(source_op) + # Make sure this node exists in this graph. if reshape_node_name in self.ins: shape_inputs = self.ins[reshape_node_name].targets('Shape') tensor_inputs = self.ins[reshape_node_name].targets('X') if len(shape_inputs) == 1 and len(tensor_inputs) == 1: self.ins[reshape_node_name].rm(shape_inputs[0]) - self.ins[reshape_node_name].add('Shape', shape_inputs[0]) - else: - pass + if shape_inputs[0].split('#')[0] != 'assign_value' \ + or need_assign is True: + self.ins[reshape_node_name].add('Shape', shape_inputs[0]) + else: + self._RmProtoNode(shape_inputs[0]) + self._ClearEdges(shape_inputs[0]) + + def _CutReshape(self, reshape_node_name): + branch = [] + branch.append(reshape_node_name) + shape_inputs = self.ins[reshape_node_name].targets('Shape') + tensor_input = self.ins[reshape_node_name].target('X') + tensor_output = self.outs[reshape_node_name].target('Out') + if len(shape_inputs) == 1: + branch.append(shape_inputs[0]) + if len(branch) == 2 and branch[1].split('#')[0] == 'split': + split_node_name = branch[1] + self.outs[split_node_name].rm(reshape_node_name) + self.ins[reshape_node_name].rm(split_node_name) + if len(self.outs[split_node_name].targets('_Out')) == 0: + input_of_split = self.ins[split_node_name].target('_In') + branch.append(input_of_split) + self._RmProtoNode(split_node_name) + self._ClearEdges(split_node_name) + elif len(branch) == 2 and branch[1].split('#')[0] == 'shape': + shape_node_name = branch[1] + input_of_shape = self.ins[shape_node_name].targets('Input') + assert len(input_of_shape) == 1 + self.outs[input_of_shape[0]].rm(shape_node_name) + self.ins[reshape_node_name].rm(shape_node_name) + self._RmProtoNode(shape_node_name) + self._ClearEdges(shape_node_name) + elif len(branch) == 2 and branch[1].split('#')[0] == 'assign_value': + assign_node_name = branch[1] + self.ins[reshape_node_name].rm(assign_node_name) + self._RmProtoNode(assign_node_name) + self._ClearEdges(assign_node_name) + elif len(branch) == 2 and branch[1].startswith('input'): + raise NameError('ERROR: None-split input of Softmax has not supported.') + else: + pass + self.outs[tensor_input].mv(reshape_node_name, tensor_output) + self.ins[tensor_output].mv(reshape_node_name, tensor_input) + self._RmProtoNode(reshape_node_name) + self._ClearEdges(reshape_node_name) + if len(branch) == 3 and branch[2].startswith('input'): + input_node_name = branch[2] + self._RmProtoNode(input_node_name) + self._ClearEdges(input_node_name) + + def _RefreshSplit(self, split_node_name, helper): + outputs_of_split = self.outs[split_node_name].targets('_Out') + inputs_of_split = self.ins[split_node_name].targets('_In') + assert len(inputs_of_split) == 1 + split_num = len(outputs_of_split) + if split_num == 1: + self.ins[outputs_of_split[0]].mv(split_node_name, inputs_of_split[0]) + self.outs[inputs_of_split[0]].mv(split_node_name, outputs_of_split[0]) + self._RmProtoNode(split_node_name) + self._ClearEdges(split_node_name) + else: + private_data = {'split_num': split_num} + self._RmProtoNode(split_node_name) + self._AddProtoNode(split_node_name, None, helper, private_data, 'split') def _DealWithSoftmax(self, source_ops, helper): for source_op in source_ops: @@ -722,43 +784,19 @@ def _DealWithSoftmax(self, source_ops, helper): softmax_node_name = self._NameNodeMid(source_op) outs_of_softmax = self.outs[softmax_node_name].targets('Out') ins_of_softmax = self.ins[softmax_node_name].targets('X') - def prune(reshape_node_name): - """ - """ - branch = [] - branch.append(reshape_node_name) - shape_inputs = self.ins[reshape_node_name].targets('Shape') - tensor_input = self.ins[reshape_node_name].target('X') - tensor_output = self.outs[reshape_node_name].target('Out') - if len(shape_inputs) == 1: - branch.append(shape_inputs[0]) - if len(branch) == 2 and branch[1].split('#')[0] == 'split': - split_node_name = branch[1] - self.outs[split_node_name].rm(reshape_node_name) - self.ins[reshape_node_name].rm(split_node_name) - if len(self.outs[split_node_name].targets('_Out')) == 0: - input_of_split = self.ins[split_node_name].target('_In') - branch.append(input_of_split) - self._RmProtoNode(split_node_name) - self._ClearEdges(split_node_name) - elif len(branch) == 2 and branch[1].startswith('input'): - raise NameError('ERROR: None-split input of Softmax has not supported.') - self.outs[tensor_input].mv(reshape_node_name, tensor_output) - self.ins[tensor_output].mv(reshape_node_name, tensor_input) - self._RmProtoNode(reshape_node_name) - self._ClearEdges(reshape_node_name) - if len(branch) == 3 and branch[2].startswith('input'): - input_node_name = branch[2] - self._RmProtoNode(input_node_name) - self._ClearEdges(input_node_name) - if outs_of_softmax[0].split('#')[0] == 'reshape' and \ - ins_of_softmax[0].split('#')[0] == 'reshape': - private_data = {} - private_data['axis'] = 3 - prune(outs_of_softmax[0]) - prune(ins_of_softmax[0]) - self._RmProtoNode(softmax_node_name) - self._AddProtoNode(softmax_node_name, source_op, helper, private_data) + if outs_of_softmax[0].split('#')[0] == 'reshape': + if ins_of_softmax[0].split('#')[0] == 'reshape' or \ + ins_of_softmax[0].split('#')[0] == 'flatten': + private_data = {} + private_data['axis'] = 3 + self._CutReshape(outs_of_softmax[0]) + self._CutReshape(ins_of_softmax[0]) + self._RmProtoNode(softmax_node_name) + self._AddProtoNode(softmax_node_name, source_op, helper, private_data) + ins_of_softmax = self.ins[softmax_node_name].targets('X') + print 'ins_of_softmax', ins_of_softmax + assert len(ins_of_softmax) == 1 + self._RefreshSplit(ins_of_softmax[0], helper) def _DealWithMatmal(self, source_ops, helper): for source_op in source_ops: @@ -872,6 +910,8 @@ def _ParseNetwork(self, source_ops, helper): self._DealWithPriorBox(source_ops, helper) self._DealWithDetectionOutput(source_ops, helper) self._DealWithSSD(source_ops, helper) + self._DealWithSoftmax(source_ops, helper) + self._RefreshReshape(source_ops, helper) self._Graph() def _Parsing(self): diff --git a/tools/external_converter_v2/parser/operations/ops_fluid.py b/tools/external_converter_v2/parser/operations/ops_fluid.py index a802e287c..e635763b6 100755 --- a/tools/external_converter_v2/parser/operations/ops_fluid.py +++ b/tools/external_converter_v2/parser/operations/ops_fluid.py @@ -27,8 +27,22 @@ OpsRegister.Register("sequence_conv").set_attr() OpsRegister.Register("stanh").set_attr() - OpsRegister.Register("matmul").set_attr() OpsRegister.Register("layer_norm").set_attr() OpsRegister.Register("dropout").set_attr() OpsRegister.Register("scale").set_attr() +OpsRegister.Register("norm").set_attr() + +OpsRegister.Register("lod_reset").set_attr() +OpsRegister.Register("fill_constant").set_attr() +OpsRegister.Register("lod_rank_table").set_attr() +OpsRegister.Register("max_sequence_len").set_attr() +OpsRegister.Register("less_than").set_attr() +OpsRegister.Register("lod_tensor_to_array").set_attr() +OpsRegister.Register("write_to_array").set_attr() +OpsRegister.Register("reorder_lod_tensor_by_rank").set_attr() +OpsRegister.Register("while").set_attr() +OpsRegister.Register("array_to_lod_tensor").set_attr() + +OpsRegister.Register("assign_value").set_attr() +OpsRegister.Register("shape").set_attr() \ No newline at end of file From 8bc8646136c83091e7e754ac77f9feca5c43d0a0 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Thu, 27 Sep 2018 16:23:37 +0800 Subject: [PATCH 47/51] support new fluid mobilenetssd --- tools/external_converter_v2/parser/operations/ops_fluid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/external_converter_v2/parser/operations/ops_fluid.py b/tools/external_converter_v2/parser/operations/ops_fluid.py index e635763b6..9025a1dd9 100755 --- a/tools/external_converter_v2/parser/operations/ops_fluid.py +++ b/tools/external_converter_v2/parser/operations/ops_fluid.py @@ -45,4 +45,4 @@ OpsRegister.Register("array_to_lod_tensor").set_attr() OpsRegister.Register("assign_value").set_attr() -OpsRegister.Register("shape").set_attr() \ No newline at end of file +OpsRegister.Register("shape").set_attr() From 41fb528bc10883c7b56474d8114a35e17841dd90 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Thu, 27 Sep 2018 21:03:40 +0800 Subject: [PATCH 48/51] add the version check --- tools/external_converter_v2/config.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tools/external_converter_v2/config.py b/tools/external_converter_v2/config.py index ee2ccfdbe..f2eb27f2a 100644 --- a/tools/external_converter_v2/config.py +++ b/tools/external_converter_v2/config.py @@ -3,6 +3,7 @@ # -*- coding: utf-8 -*- import os +import sys import subprocess from yaml import load, dump try: @@ -38,6 +39,8 @@ def __init__(self, config_file_path=ConfigFilePath): # parse TARGET info from config file. if self.framework == "CAFFE": proto_list = data['TARGET'][self.framework]['ProtoPaths'] + assert type(proto_list) == list, \ + "The ProtoPaths format maybe incorrect, please check if there is any HORIZONTAL LINE." self.__generate_pbs(proto_list) self.framework_config_dict = data['TARGET'][self.framework] elif self.framework == "PADDLE": @@ -58,6 +61,21 @@ def __init__(self, config_file_path=ConfigFilePath): except NameError: raise + def check_protobuf_version(self): + for path in sys.path: + module_path = os.path.join(path, 'google', 'protobuf', '__init__.py') + if os.path.exists(module_path): + with open(module_path) as f: + __name__ = '__main__' + exec(f.read(), locals()) + break + protoc_out = subprocess.check_output(["protoc", "--version"]).split()[1] + sys_versions = map(int, protoc_out.split('.')) + pip_versions = map(int, __version__.split('.')) + assert pip_versions[0] >= sys_versions[0], \ + "ERROR: Protobuf must be the same.\nSystem Protobuf %s\nPython Protobuf %s" \ + % (protoc_out, __version__) + def generate_pbs_of_anakin(self): protoFilesStr = subprocess.check_output(["ls", "parser/proto/"]) filesList = protoFilesStr.split('\n') @@ -77,6 +95,7 @@ def __generate_pbs(self, proto_list, default_save_path="parser/pbs/"): proto_list: ['/path/to/proto_0','/path/to/proto_1', ... ] default_save_path: default saved to 'parser/pbs/' """ + self.check_protobuf_version() for pFile in proto_list: subprocess.check_call(['protoc', '-I', os.path.dirname(pFile) + "/", From e6fcf0a5d389c73b525cbe41ab43b59f6c4fdd93 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Thu, 27 Sep 2018 21:13:12 +0800 Subject: [PATCH 49/51] add the version check --- tools/external_converter_v2/config.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/external_converter_v2/config.py b/tools/external_converter_v2/config.py index f2eb27f2a..ee5633ef9 100644 --- a/tools/external_converter_v2/config.py +++ b/tools/external_converter_v2/config.py @@ -69,7 +69,10 @@ def check_protobuf_version(self): __name__ = '__main__' exec(f.read(), locals()) break - protoc_out = subprocess.check_output(["protoc", "--version"]).split()[1] + try: + protoc_out = subprocess.check_output(["protoc", "--version"]).split()[1] + except OSError as exc: + raise OSError('Can not find Protobuf in system environment.') sys_versions = map(int, protoc_out.split('.')) pip_versions = map(int, __version__.split('.')) assert pip_versions[0] >= sys_versions[0], \ From 20e2a7d958f8a6295b9c011060ea29bf81c729f8 Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Thu, 27 Sep 2018 21:20:48 +0800 Subject: [PATCH 50/51] add the version check --- tools/external_converter_v2/config.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/external_converter_v2/config.py b/tools/external_converter_v2/config.py index ee5633ef9..538162457 100644 --- a/tools/external_converter_v2/config.py +++ b/tools/external_converter_v2/config.py @@ -75,9 +75,11 @@ def check_protobuf_version(self): raise OSError('Can not find Protobuf in system environment.') sys_versions = map(int, protoc_out.split('.')) pip_versions = map(int, __version__.split('.')) - assert pip_versions[0] >= sys_versions[0], \ - "ERROR: Protobuf must be the same.\nSystem Protobuf %s\nPython Protobuf %s" \ - % (protoc_out, __version__) + assert sys_versions[0] >= 3 and pip_versions[0] >= 3 , \ + "Protobuf version must be greater than 3.0. Please refer to the Anakin Docs." + assert pip_versions[1] >= sys_versions[1], \ + "ERROR: Protobuf must be the same.\nSystem Protobuf %s\nPython Protobuf %s\n" \ + % (protoc_out, __version__) + "Try to execute pip install protobuf==%s" % (protoc_out) def generate_pbs_of_anakin(self): protoFilesStr = subprocess.check_output(["ls", "parser/proto/"]) From ed08914b910446d2aea050a3310f4005f2f57bba Mon Sep 17 00:00:00 2001 From: Shixiaowei02 Date: Fri, 28 Sep 2018 19:31:37 +0800 Subject: [PATCH 51/51] support new version fluid --- tools/external_converter_v2/parser/fluid/fluid_helper.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/external_converter_v2/parser/fluid/fluid_helper.py b/tools/external_converter_v2/parser/fluid/fluid_helper.py index a17ff10ec..73ad3f931 100644 --- a/tools/external_converter_v2/parser/fluid/fluid_helper.py +++ b/tools/external_converter_v2/parser/fluid/fluid_helper.py @@ -224,7 +224,12 @@ def shape_by_var_name(self, var_name, layout = 'NCHW'): def np_data_by_var_name(self, var_name): ''' ''' - numpy_array = fluid.executor.fetch_var(var_name, self.scope, True) + if hasattr(fluid.executor, '_fetch_var'): + numpy_array = fluid.executor._fetch_var(str(var_name), self.scope, True) + elif hasattr(fluid.executor, 'fetch_var'): + numpy_array = fluid.executor.fetch_var(var_name, self.scope, True) + else: + raise NameError('ERROR: Unknown Fluid version.') return numpy_array def dtype_by_var_name(self, var_name):