From 8644e3eec2ba127a53b5746be51df8fac3b5f1c6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=EC=9C=A4=EC=A7=80=EC=98=81/=EB=8F=99=EC=9E=91=EC=A0=9C?= =?utf8?q?=EC=96=B4Lab=28SR=29/Engineer/=EC=82=BC=EC=84=B1=EC=A0=84?= =?utf8?q?=EC=9E=90?= Date: Fri, 9 Nov 2018 14:20:39 +0900 Subject: [PATCH] Create tflkit directory (#3438) * Create tflite_easytool directory This directory is created to make it easier to run frequently used tools in scripts. Now, it has two functions: - Summraize PB model - Summraize TfLite model Signed-off-by: Jiyoung Yun * Change the directory name to tflkit Also changes the relative path to absolute path Signed-off-by: Jiyoung Yun * Add Prerequires and TF tool guideline Signed-off-by: Jiyoung Yun * Add additional description for prerequires Signed-off-by: Jiyoung Yun --- tools/tflkit/README.md | 111 +++++++++++++++++++++++++++++++++++++++ tools/tflkit/summarize_pb.py | 111 +++++++++++++++++++++++++++++++++++++++ tools/tflkit/summarize_pb.sh | 3 ++ tools/tflkit/summarize_tflite.sh | 4 ++ 4 files changed, 229 insertions(+) create mode 100644 tools/tflkit/README.md create mode 100644 tools/tflkit/summarize_pb.py create mode 100755 tools/tflkit/summarize_pb.sh create mode 100755 tools/tflkit/summarize_tflite.sh diff --git a/tools/tflkit/README.md b/tools/tflkit/README.md new file mode 100644 index 0000000..2a2769e --- /dev/null +++ b/tools/tflkit/README.md @@ -0,0 +1,111 @@ +# tflkit + +## Purpose + +There are a lot of tools related to TfLite. However, it is inconvenient to use the tools directly because there are many locations and parameters. The tflkit has been created to make it easier to run frequently used tools in scripts. The function provided in this directory uses existing tools rather than implementing them directly. So, additional modifications may occur depending on the TensorFlow version or other external factors. The function provided in this directory will be gradually expanded. + +## Prerequisites + +The scripts here use TensorFlow's tools, so you need an environment to build TensorFlow. +Running the scripts within this tutorial requires: +* [Install Bazel](https://docs.bazel.build/versions/master/install.html), the build tool used to compile TensorFlow. + +Initially, no external packages are installed on this project. Therefore, before running these scripts, you should install the associcated packages by running the following command once. +``` +make configure +``` + +## Summarize TF model + +### TensorFlow + +TensorFlow uses `summarize_graph` tool to inspect the model and provide guesses about likely input and output nodes, as well as other information that's useful for debugging. For more information, see [Inspecting Graphs](https://github.com/tensorflow/tensorflow/tree/9590c4c32dd4346ea5c35673336f5912c6072bf2/tensorflow/tools/graph_transforms#inspecting-graphs) page. + +Usage: +``` +$ bazel build tensorflow/tools/graph_transforms:summarize_graph +$ bazel-bin/tensorflow/tools/graph_transforms/summarize_graph --in_graph= +``` + +### tflkit + +Usage: +``` +$ ./summarize_pb.sh +``` + +The results shown below: +``` +$ ./summarize_pb.sh inception_v3.pb + + inception_v3.pb + +Inputs + name=input + type=float(1) + shape=[?,299,299,3] +Outputs + name=InceptionV3/Predictions/Reshape_1, op=Reshape +Op Types + 488 Const + 379 Identity + 95 Conv2D + 94 FusedBatchNorm + 94 Relu + 15 ConcatV2 + 10 AvgPool + 4 MaxPool + 2 Reshape + 1 BiasAdd + 1 Placeholder + 1 Shape + 1 Softmax + 1 Squeeze + + 14 Total +``` + +## Summarize TfLite model + +### tflkit + +Usage: +``` +$ ./summarize_tflite.sh +``` + +The results shown below: +``` +$ ./summarize_tflite.sh inception_v3.tflite +[Main model] + +Main model input tensors: [317] +Main model output tensors: [316] + +Operator 0: CONV_2D (instrs: 39,073,760, cycls: 39,073,760) + Fused Activation: RELU + Input Tensors[317, 0, 5] + Tensor 317 : buffer 183 | Empty | FLOAT32 | Shape [1, 299, 299, 3] (b'input') + Tensor 0 : buffer 205 | Filled | FLOAT32 | Shape [32, 3, 3, 3] (b'InceptionV3/Conv2d_1a_3x3/weights') + Tensor 5 : buffer 52 | Filled | FLOAT32 | Shape [32] (b'InceptionV3/InceptionV3/Conv2d_1a_3x3/Conv2D_bias') + Output Tensors[6] + Tensor 6 : buffer 285 | Empty | FLOAT32 | Shape [1, 149, 149, 32] (b'InceptionV3/InceptionV3/Conv2d_1a_3x3/Relu') + +[...] + +Operator 125: SOFTMAX (instrs: 4,003, cycls: 4,003) + Input Tensors[225] + Tensor 225 : buffer 142 | Empty | FLOAT32 | Shape [1, 1001] (b'InceptionV3/Logits/SpatialSqueeze') + Output Tensors[316] + Tensor 316 : buffer 53 | Empty | FLOAT32 | Shape [1, 1001] (b'InceptionV3/Predictions/Reshape_1') + + +Number of all operator types: 6 + CONV_2D : 95 (instrs: 11,435,404,777) + MAX_POOL_2D : 4 (instrs: 12,755,516) + AVERAGE_POOL_2D : 10 (instrs: 36,305,334) + CONCATENATION : 15 (instrs: 0) + RESHAPE : 1 (instrs: ???) + SOFTMAX : 1 (instrs: 4,003) +Number of all operators : 126 (total instrs: 11,484,469,630) +``` diff --git a/tools/tflkit/summarize_pb.py b/tools/tflkit/summarize_pb.py new file mode 100644 index 0000000..6338041 --- /dev/null +++ b/tools/tflkit/summarize_pb.py @@ -0,0 +1,111 @@ +import argparse +import os +import subprocess +import re + + +class cd: + """Context manager for changing the current working directory""" + + def __init__(self, newPath): + self.newPath = os.path.expanduser(newPath) + + def __enter__(self): + self.savedPath = os.getcwd() + os.chdir(self.newPath) + + def __exit__(self, etype, value, traceback): + os.chdir(self.savedPath) + + +def CheckExt(choices, name): + ext = os.path.splitext(name)[1][1:] + if ext not in choices: + parser.error("file does not end with one of {}".format(choices)) + return name + + +def PrintName(path): + print("") + print('\t' + os.path.basename(path)) + print("") + + +def PrintInput(data): + print("Inputs") + sub = data.split('(', 1)[1].rsplit(')', 1)[0] + for i in re.split(', ', sub): + print('\t' + i) + + +def PrintOutput(data): + print("Outputs") + sub = re.findall('\((.*?)\)', data) + for i in sub: + print('\t' + i) + + +def PrintOpType(data): + print("Op Types") + cnt = 0 + sub = data.rsplit(':', 1)[1].split(',') + for i in sub: + cnt = cnt + 1 + print('\t' + i.lstrip()) + print('\t{0} Total'.format(cnt)) + + +def BuildTensorFlowSummarizeGraph(tensorflow_path): + with cd(tensorflow_path): + subprocess.call( + ['bazel', 'build', 'tensorflow/tools/graph_transforms:summarize_graph']) + + +def SummarizeGraph(args): + if args.verbose is True: + vstr = "" + PrintName(args.input_file) + with cd(args.tensorflow_path): + proc = subprocess.Popen( + [ + 'bazel-bin/tensorflow/tools/graph_transforms/summarize_graph', + '--in_graph=' + args.input_file + ], + stdout=subprocess.PIPE) + while True: + line = proc.stdout.readline().decode() + if args.verbose: + vstr += line + if line != '': + if 'inputs:' in line: + PrintInput(line) + elif 'outputs:' in line: + PrintOutput(line) + elif 'Op types used:' in line: + PrintOpType(line) + else: + break + + if args.verbose: + print(vstr) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + '--input_file', + required=True, + type=lambda s: CheckExt((['pb']), s), + help='pb file to read') + parser.add_argument( + '--tensorflow_path', + default='../../externals/tensorflow', + help='TensorFlow git repository path') + parser.add_argument('--verbose', action='store_true') + args = parser.parse_args() + + # Build summarize_graph in external/tensorflow + BuildTensorFlowSummarizeGraph(args.tensorflow_path) + + # Summarize graph + SummarizeGraph(args) diff --git a/tools/tflkit/summarize_pb.sh b/tools/tflkit/summarize_pb.sh new file mode 100755 index 0000000..141f27b --- /dev/null +++ b/tools/tflkit/summarize_pb.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +python summarize_pb.py --input_file=$1 $2 diff --git a/tools/tflkit/summarize_tflite.sh b/tools/tflkit/summarize_tflite.sh new file mode 100755 index 0000000..3560de2 --- /dev/null +++ b/tools/tflkit/summarize_tflite.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +SCRIPT_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +python "${SCRIPT_PATH}/../tflitefile_tool/model_parser.py" $1 -- 2.7.4