From 588ebc5ccab2e47c42c3e9303306e3744834f52f Mon Sep 17 00:00:00 2001 From: Georgios Pinitas Date: Fri, 21 Dec 2018 13:39:07 +0000 Subject: COMPMID-1839: Add script from extracting tf frozen models. Change-Id: I9a61b9005ea829cd9ecae5bebf8985fe72e28b8e Reviewed-on: https://review.mlplatform.org/448 Reviewed-by: Manuel Bottini Tested-by: Arm Jenkins Reviewed-by: Michele Di Giorgio --- docs/03_scripts.dox | 55 ++++++++++++++++++++++++++++++ examples/graph_alexnet.cpp | 2 ++ examples/graph_googlenet.cpp | 2 ++ examples/graph_inception_resnet_v2.cpp | 2 ++ examples/graph_inception_v3.cpp | 2 ++ examples/graph_inception_v4.cpp | 2 ++ examples/graph_mobilenet.cpp | 3 ++ examples/graph_mobilenet_v2.cpp | 2 ++ examples/graph_resnet50.cpp | 2 ++ examples/graph_resnet_v2_50.cpp | 2 ++ examples/graph_shufflenet.cpp | 2 ++ examples/graph_squeezenet.cpp | 2 ++ examples/graph_squeezenet_v1_1.cpp | 2 ++ examples/graph_ssd_mobilenet.cpp | 2 ++ examples/graph_vgg16.cpp | 2 ++ examples/graph_vgg19.cpp | 2 ++ scripts/tf_frozen_model_extractor.py | 62 ++++++++++++++++++++++++++++++++++ 17 files changed, 148 insertions(+) create mode 100644 scripts/tf_frozen_model_extractor.py diff --git a/docs/03_scripts.dox b/docs/03_scripts.dox index 11deea2bc1..6b715908dd 100644 --- a/docs/03_scripts.dox +++ b/docs/03_scripts.dox @@ -114,5 +114,60 @@ If the script runs successfully, it prints the names and shapes of each paramete The arm_compute::utils::load_trained_data shows how one could load the weights and biases into tensor from the .npy file by the help of Accessor. + +@section tf_frozen_model_extractor Extract data from pre-trained frozen tensorflow model + +The script tf_frozen_model_extractor.py extracts trainable parameters (e.g. values of weights and biases) from a +frozen trained Tensorflow model. + +@subsection tensorflow_frozen_how_to How to use the script + +Install Tensorflow and NumPy. + +Download the pre-trained Tensorflow model and freeze the model using the architecture and the checkpoint file. + +Run tf_frozen_model_extractor.py with + + python tf_frozen_model_extractor -m -d + +For example, to extract the data from pre-trained Tensorflow model to binary files: + + python tf_frozen_model_extractor -m /path/to/inceptionv3.pb -d ./data + +@subsection tensorflow_frozen_result What is the expected output from the script + +If the script runs successfully, it prints the names and shapes of each parameter onto the standard output and generates + *.npy files containing the weights and biases of each layer. + +The arm_compute::utils::load_trained_data shows how one could load +the weights and biases into tensor from the .npy file by the help of Accessor. + +@section validate_examples Validating examples +Using one of the provided scripts will generate files containing the trainable parameters. + +You can validate a given graph example on a list of inputs by running: + + LD_LIBRARY_PATH=lib ./ --validation-range='' --validation-file='' --validation-path='/path/to/test/images/' --data='/path/to/weights/' + +e.g: + +LD_LIBRARY_PATH=lib ./bin/graph_alexnet --target=CL --layout=NHWC --type=F32 --threads=4 --validation-range='16666,24998' --validation-file='val.txt' --validation-path='images/' --data='data/' + +where: + validation file is a plain document containing a list of images along with their expected label value. + e.g: + + val_00000001.JPEG 65 + val_00000002.JPEG 970 + val_00000003.JPEG 230 + val_00000004.JPEG 809 + val_00000005.JPEG 516 + + --validation-range is the index range of the images within the validation file you want to check: + e.g: + + --validation-range='100,200' will validate 100 images starting from 100th one in the validation file. + + This can be useful when parallelizing the validation process is needed. */ } \ No newline at end of file diff --git a/examples/graph_alexnet.cpp b/examples/graph_alexnet.cpp index cfa8e94d10..989e23266f 100644 --- a/examples/graph_alexnet.cpp +++ b/examples/graph_alexnet.cpp @@ -176,6 +176,8 @@ private: * "ImageNet Classification with Deep Convolutional Neural Networks" * Alex Krizhevsky and Sutskever, Ilya and Hinton, Geoffrey E * + * Provenance: https://github.com/BVLC/caffe/tree/master/models/bvlc_alexnet + * * @note To list all the possible arguments execute the binary appended with the --help option * * @param[in] argc Number of arguments diff --git a/examples/graph_googlenet.cpp b/examples/graph_googlenet.cpp index a55c884ca2..0e9ac20996 100644 --- a/examples/graph_googlenet.cpp +++ b/examples/graph_googlenet.cpp @@ -203,6 +203,8 @@ private: * "Going deeper with convolutions" * Christian Szegedy, Wei Liu, Yangqing Jia, Pierre Sermanet, Scott Reed, Dragomir Anguelov, Dumitru Erhan, Vincent Vanhoucke, Andrew Rabinovich * + * Provenance: https://github.com/BVLC/caffe/tree/master/models/bvlc_googlenet + * * @note To list all the possible arguments execute the binary appended with the --help option * * @param[in] argc Number of arguments diff --git a/examples/graph_inception_resnet_v2.cpp b/examples/graph_inception_resnet_v2.cpp index 4c74041eb3..8e799783f2 100644 --- a/examples/graph_inception_resnet_v2.cpp +++ b/examples/graph_inception_resnet_v2.cpp @@ -787,6 +787,8 @@ private: * "Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning" * Christian Szegedy, Sergey Ioffe, Vincent Vanhoucke, Alex Alemi * + * Provenance: download.tensorflow.org/models/inception_resnet_v2_2016_08_30.tar.gz + * * @note To list all the possible arguments execute the binary appended with the --help option * * @param[in] argc Number of arguments diff --git a/examples/graph_inception_v3.cpp b/examples/graph_inception_v3.cpp index 86b223e9e5..517e4920cb 100644 --- a/examples/graph_inception_v3.cpp +++ b/examples/graph_inception_v3.cpp @@ -851,6 +851,8 @@ private: * "Rethinking the Inception Architecture for Computer Vision" * Christian Szegedy, Vincent Vanhoucke, Sergey Ioffe, Jonathon Shlens, Zbigniew Wojna * + * Provenance: download.tensorflow.org/models/inception_v3_2016_08_28.tar.gz + * * @note To list all the possible arguments execute the binary appended with the --help option * * @param[in] argc Number of arguments diff --git a/examples/graph_inception_v4.cpp b/examples/graph_inception_v4.cpp index 3bedc4ccea..3de61dac7d 100644 --- a/examples/graph_inception_v4.cpp +++ b/examples/graph_inception_v4.cpp @@ -725,6 +725,8 @@ private: * "Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning" * Christian Szegedy, Sergey Ioffe, Vincent Vanhoucke, Alex Alemi * + * Provenance: download.tensorflow.org/models/inception_v4_2016_09_09.tar.gz + * * @note To list all the possible arguments execute the binary appended with the --help option * * @param[in] argc Number of arguments diff --git a/examples/graph_mobilenet.cpp b/examples/graph_mobilenet.cpp index 8d5e7f6dc4..10bb890372 100644 --- a/examples/graph_mobilenet.cpp +++ b/examples/graph_mobilenet.cpp @@ -345,6 +345,9 @@ private: * "MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications" * Andrew G. Howard, Menglong Zhu, Bo Chen, Dmitry Kalenichenko, Weijun Wang, Tobias Weyand, Marco Andreetto, Hartwig Adam * + * Provenance: download.tensorflow.org/models/mobilenet_v1_2018_08_02/mobilenet_v1_1.0_224.tgz + * download.tensorflow.org/models/mobilenet_v1_2018_08_02/mobilenet_v1_0.75_160.tgz + * * @note To list all the possible arguments execute the binary appended with the --help option * * @param[in] argc Number of arguments diff --git a/examples/graph_mobilenet_v2.cpp b/examples/graph_mobilenet_v2.cpp index 9fe61fb4c1..429a3d2cc0 100644 --- a/examples/graph_mobilenet_v2.cpp +++ b/examples/graph_mobilenet_v2.cpp @@ -451,6 +451,8 @@ private: * "MobileNetV2: Inverted Residuals and Linear Bottlenecks" * Mark Sandler, Andrew Howard, Menglong Zhu, Andrey Zhmoginov, Liang-Chieh Chen * + * Provenance: https://storage.googleapis.com/mobilenet_v2/checkpoints/mobilenet_v2_1.0_224.tgz + * * @note To list all the possible arguments execute the binary appended with the --help option * * @param[in] argc Number of arguments diff --git a/examples/graph_resnet50.cpp b/examples/graph_resnet50.cpp index 0a96840e3d..25e0bd47c3 100644 --- a/examples/graph_resnet50.cpp +++ b/examples/graph_resnet50.cpp @@ -240,6 +240,8 @@ private: * "Deep Residual Learning for Image Recognition" * Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun * + * Provenance: download.tensorflow.org/models/resnet_v1_50_2016_08_28.tar.gz + * * @note To list all the possible arguments execute the binary appended with the --help option * * @param[in] argc Number of arguments diff --git a/examples/graph_resnet_v2_50.cpp b/examples/graph_resnet_v2_50.cpp index 24cd68cb21..3b6f8d3fa1 100644 --- a/examples/graph_resnet_v2_50.cpp +++ b/examples/graph_resnet_v2_50.cpp @@ -235,6 +235,8 @@ private: * "Identity Mappings in Deep Residual Networks" * Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun * + * Provenance: download.tensorflow.org/models/resnet_v2_50_2017_04_14.tar.gz + * * @note To list all the possible arguments execute the binary appended with the --help option * * @param[in] argc Number of arguments diff --git a/examples/graph_shufflenet.cpp b/examples/graph_shufflenet.cpp index 88ee520770..39c2227022 100644 --- a/examples/graph_shufflenet.cpp +++ b/examples/graph_shufflenet.cpp @@ -244,6 +244,8 @@ private: * "ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices" * Xiangyu Zhang, Xinyu Zhou, Mengxiao Lin, Jian Sun * + * Provenance: https://s3.amazonaws.com/download.onnx/models/opset_9/shufflenet.tar.gz + * * @note To list all the possible arguments execute the binary appended with the --help option * * @param[in] argc Number of arguments diff --git a/examples/graph_squeezenet.cpp b/examples/graph_squeezenet.cpp index ad5fc21acd..4bc516a363 100644 --- a/examples/graph_squeezenet.cpp +++ b/examples/graph_squeezenet.cpp @@ -206,6 +206,8 @@ private: * "SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <0.5MB model size" * Forrest N. Iandola, Song Han, Matthew W. Moskewicz, Khalid Ashraf, William J. Dally, Kurt Keutzer * + * Provenance: https://github.com/DeepScale/SqueezeNet/blob/master/SqueezeNet_v1.0/squeezenet_v1.0.caffemodel + * * @note To list all the possible arguments execute the binary appended with the --help option * * @param[in] argc Number of arguments diff --git a/examples/graph_squeezenet_v1_1.cpp b/examples/graph_squeezenet_v1_1.cpp index 95c99c0770..745d089fdb 100644 --- a/examples/graph_squeezenet_v1_1.cpp +++ b/examples/graph_squeezenet_v1_1.cpp @@ -206,6 +206,8 @@ private: * "SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <0.5MB model size" * Forrest N. Iandola, Song Han, Matthew W. Moskewicz, Khalid Ashraf, William J. Dally, Kurt Keutzer * + * Provenance: https://github.com/DeepScale/SqueezeNet/blob/master/SqueezeNet_v1.1/squeezenet_v1.1.caffemodel + * * @note To list all the possible arguments execute the binary appended with the --help option * * @param[in] argc Number of arguments diff --git a/examples/graph_ssd_mobilenet.cpp b/examples/graph_ssd_mobilenet.cpp index 676c5e9167..780ee38670 100644 --- a/examples/graph_ssd_mobilenet.cpp +++ b/examples/graph_ssd_mobilenet.cpp @@ -365,6 +365,8 @@ private: * SSD: Single Shot MultiBox Detector * Wei Liu, Dragomir Anguelov, Dumitru Erhan, Christian Szegedy, Scott Reed, Cheng-Yang Fu, Alexander C. Berg * + * Provenance: https://github.com/chuanqi305/MobileNet-SSD + * * @note To list all the possible arguments execute the binary appended with the --help option * * @param[in] argc Number of arguments diff --git a/examples/graph_vgg16.cpp b/examples/graph_vgg16.cpp index 482aab1683..290d1e7e98 100644 --- a/examples/graph_vgg16.cpp +++ b/examples/graph_vgg16.cpp @@ -251,6 +251,8 @@ private: * "Very Deep Convolutional Networks for Large-Scale Image Recognition" * Karen Simonyan, Andrew Zisserman * + * Provenance: www.robots.ox.ac.uk/~vgg/software/very_deep/caffe/VGG_ILSVRC_16_layers.caffemodel + * * @note To list all the possible arguments execute the binary appended with the --help option * * @param[in] argc Number of arguments diff --git a/examples/graph_vgg19.cpp b/examples/graph_vgg19.cpp index 3b1773519a..298ffa06ef 100644 --- a/examples/graph_vgg19.cpp +++ b/examples/graph_vgg19.cpp @@ -262,6 +262,8 @@ private: * "Very Deep Convolutional Networks for Large-Scale Image Recognition" * Karen Simonyan, Andrew Zisserman * + * Provenance: www.robots.ox.ac.uk/~vgg/software/very_deep/caffe/VGG_ILSVRC_19_layers.caffemodel + * * @note To list all the possible arguments execute the binary appended with the --help option * * @param[in] argc Number of arguments diff --git a/scripts/tf_frozen_model_extractor.py b/scripts/tf_frozen_model_extractor.py new file mode 100644 index 0000000000..fbd5b38019 --- /dev/null +++ b/scripts/tf_frozen_model_extractor.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +""" Extract trainable parameters from a frozen model and stores them in numpy arrays. +Usage: + python tf_frozen_model_extractor -m path_to_frozem_model -d path_to_store_the_parameters + +Saves each variable to a {variable_name}.npy binary file. + +Note that the script permutes the trainable parameters to NCHW format. This is a pretty manual step thus it's not thoroughly tested. +""" +import argparse +import os +import numpy as np +import tensorflow as tf +from tensorflow.python.platform import gfile + +strings_to_remove=["read", "/:0"] +permutations = { 1 : [0], 2 : [1, 0], 3 : [2, 1, 0], 4 : [3, 2, 0, 1]} + +if __name__ == "__main__": + # Parse arguments + parser = argparse.ArgumentParser('Extract TensorFlow net parameters') + parser.add_argument('-m', dest='modelFile', type=str, required=True, help='Path to TensorFlow frozen graph file (.pb)') + parser.add_argument('-d', dest='dumpPath', type=str, required=False, default='./', help='Path to store the resulting files.') + parser.add_argument('--nostore', dest='storeRes', action='store_false', help='Specify if files should not be stored. Used for debugging.') + parser.set_defaults(storeRes=True) + args = parser.parse_args() + + # Create directory if not present + if not os.path.exists(args.dumpPath): + os.makedirs(args.dumpPath) + + # Extract parameters + with tf.Graph().as_default() as graph: + with tf.Session() as sess: + print("Loading model.") + with gfile.FastGFile(args.modelFile, 'rb') as f: + graph_def = tf.GraphDef() + graph_def.ParseFromString(f.read()) + sess.graph.as_default() + + tf.import_graph_def(graph_def, input_map=None, return_elements=None, name="", op_dict=None, producer_op_list=None) + + for op in graph.get_operations(): + for op_val in op.values(): + varname = op_val.name + + # Skip non-const values + if "read" in varname: + t = op_val.eval() + tT = t.transpose(permutations[len(t.shape)]) + t = np.ascontiguousarray(tT) + + for s in strings_to_remove: + varname = varname.replace(s, "") + if os.path.sep in varname: + varname = varname.replace(os.path.sep, '_') + print("Renaming variable {0} to {1}".format(op_val.name, varname)) + + # Store files + if args.storeRes: + print("Saving variable {0} with shape {1} ...".format(varname, t.shape)) + np.save(os.path.join(args.dumpPath, varname), t) -- cgit v1.2.1