TensorFlow parser (Tensorflow -> IR part) is an experimental product, since the granularity of TensorFlow checkpoint graph is much finer than other platform. We have to use graph matching-like method to retrieve operators.
We tested the slim pre-trained models. Any contribution is welcome.
Models | Caffe | CoreML | CNTK | Keras | MXNet | PyTorch | ONNX |
---|---|---|---|---|---|---|---|
Vgg19 | √ | √ | √ | √ | √ | √ | √ |
Inception_v1 | √ | √ | o | √ | √ | √ | √ |
Inception_v3 | √ | √ | √ | o | √ | √ | √ |
ResNet V1 | √ | √ | o | √ | √ | √ | √ |
ResNet V2 | √ | √ | √ | √ | √ | √ | √ |
MobileNet V1 | x | √ | o | √ | √ | √ | √ |
MobileNet V2 | x | √ | o | √ | √ | √ | √ |
NasNet-A | x | x | x | x | √ | √ | √ |
√ - Correctness tested
o - Some difference after conversion
x - Can not be converted
We will give an example to convert TensorFlow resnet slim model with checkpoint files to caffe.
# Download TensorFlow pre-trained model first
$ mmdownload -f tensorflow -n resnet_v2_152
Downloading file [./resnet_v2_152_2017_04_14.tar.gz] from [http://download.tensorflow.org/models/resnet_v2_152_2017_04_14.tar.gz]
100% [......................................................................] 675629399 / 675629399
Model saved in file: ./imagenet_resnet_v2_152.ckpt
# Convert the TensorFlow model to Caffe
$ mmconvert -sf tensorflow -in imagenet_resnet_v2_152.ckpt.meta -iw imagenet_resnet_v2_152.ckpt --dstNodeName MMdnn_Output -df caffe -om tf_resnet
.
.
Caffe model files are saved as [tf_resnet.prototxt] and [tf_resnet.caffemodel], generated by [203e03ef187a42f59942737dace8773d.py] and [203e03ef187a42f59942737dace8773d.npy].
-in is used to specify the ".ckpt.meta" file.
-iw is used to specify the ".ckpt" file.
--dstNodeName is used to specify the output node of your model, which can be found in your code or tensorboard graph. We provide a tool vis_meta to help visualize your meta graph.
We will give an example to convert TensorFlow mobilenet slim model with frozen_pb to caffe
# Download TensorFlow pre-trained model first
$ mmdownload -f tensorflow -n mobilenet_v1_1.0_frozen
Downloading file [mobilenet_v1_1.0_224_frozen.tgz] from [https://storage.googleapis.com/download.tensorflow.org/models/mobilenet_v1_1.0_224_frozen.tgz]
progress: 18712.0 KB downloaded, 100%k
# Convert the TensorFlow model to Caffe
$ mmconvert -sf tensorflow -iw mobilenet_v1_1.0_224/frozen_graph.pb --inNodeName input --inputShape 224,224,3 --dstNodeName MobilenetV1/Predictions/Softmax -df caffe -om tf_mobilenet
.
.
Caffe model files are saved as [tf_mobilenet.prototxt] and [tf_mobilenet.caffemodel], generated by [e96550a4c55141afa8cd94372b858613.py] and [e96550a4c55141afa8cd94372b858613.npy].
For frozen graph parser, --inNodeName and --inputShape are required, and don't need to set -in.
You can refer Slim Model Extractor to extract your own tensorflow model, which is a sample tool to extract both architecture and weights from slim pre-trained models.
$ mmdownload -f tensorflow
Supported models: ['inception_v3_frozen', 'resnet_v2_200', 'inception_v1', 'mobilenet_v1_1.0', 'mobilenet_v2_1.0_224', 'resnet_v2_152', 'vgg16', 'mobilenet_v1_1.0_frozen', 'resnet_v1_50', 'resnet_v2_50', 'inception_v3', 'inception_resnet_v2', 'resnet_v1_152', 'inception_v1_frozen', 'vgg19', 'nasnet-a_large']
[Note!] The extractor create a Squeeze operator named MMdnn_Output as the output node of the models.
Mainly extract code like:
with slim.arg_scope(...):
data_input = tf.placeholder(name='input', dtype=tf.float32, shape=[...])
logits = your_own_network_builder(data_input)
if logits.op.type == 'Squeeze':
labels = tf.identity(logits, name='MMdnn_Output')
else:
labels = tf.squeeze(logits, name='MMdnn_Output')
When you prepared your checkpoint, you can find the output node name from the graph by Tensorboard.
$ mmvismeta imagenet_resnet_v2_152.ckpt.meta ./logs/
TensorBoard 0.4.0rc3 at http://kit-station:6006 (Press CTRL+C to quit)
We will give an example to convert TensorFlow mobilenet slim model with frozen_pb to caffe.
# Convert frozen graph to IR
$ mmtoir -f tensorflow -w mobilenet_v1_1.0_224/frozen_graph.pb --inNodeName input --inputShape 224,224,3 --dstNodeName MobilenetV1/Predictions/Softmax -o mobilenet_v1
IR network structure is saved as [mobilenet_v1.json].
IR network structure is saved as [mobilenet_v1.pb].
IR weights are saved as [mobilenet_v1.npy].
# Convert IR to Caffe network building code
$ mmtocode -f caffe -n mobilenet_v1.pb -w mobilenet_v1.npy -o tf_mobilenet.py -ow tf_mobilenet.npy
Parse file [mobilenet_v1.pb] with binary format successfully.
Target network code snippet is saved as [tf_mobilenet.py].
Target weights are saved as [tf_mobilenet.npy].
# Use Caffe network building code to generate an original Caffe model
$ mmtomodel -f caffe -in tf_mobilenet.py -iw tf_mobilenet.npy -o tf_mobilenet
.
.
.
Caffe model files are saved as [tf_mobilenet.prototxt] and [tf_mobilenet.caffemodel], generated by [tf_mobilenet.py] and [tf_mobilenet.npy].
The you can use tf_mobilenet.prototxt and tf_mobilenet.caffemodel in Caffe directly.
We will give you an example to convert models from other frameworks to tensorflow.
$ mmtocode -f tensorflow --IRModelPath resnet152.pb --IRWeightPath resnet152.npy --dstModelPath tf_resnet152.py
Parse file [resnet152.pb] with binary format successfully.
Target network code snippet is saved as [tf_resnet152.py].
After generating the Tensorflow code snippet, you can convert the Tensorflow code snippet and IR weights file to Tensorflow original model for further usage.There are two types of dump tags: SERVING and TRAINING.
$ mmtomodel -f tensorflow -in tf_resnet152.py -iw resnet152.npy -o tf_resnet152 --dump_tag SERVING
.
.
.
Tensorflow file is saved as [tf_resnet152/saved_model.pb], generated by [tf_resnet152.py] and [resnet152.npy].
If you want to retrain the converted model, you can change the variable is_train from "False" to "True" in the converted code file and then use '--dump_tag TRAINING' to dump it.
export_dir = "./tf_resnet152"
with tf.Session(graph=tf.Graph()) as sess:
tf.saved_model.loader.load(sess, [tf.saved_model.tag_constants.TRAINING], export_dir)
x = sess.graph.get_tensor_by_name('input:0')
y = sess.graph.get_tensor_by_name('xxxxxx:0')
......
_y = sess.run(y, feed_dict={x: _x})
Ubuntu 16.04 with
- Tensorflow 1.8
@ 2018/07/05
- Currently no RNN related operations support.
- Frozen graph parser is not well tested.