1 | initial version |
python ~/tensorflow/tensorflow/python/tools/optimize_for_inference.py \
--input model.pb \
--output opt_model.pb \
--input_names input_1 \
--output_names output_node0
See http://answers.opencv.org/question/183507/opencv-dnn-import-error-for-keras-pretrained-vgg16-model/
Remove nodes flatten/Shape
, flatten/strided_slice
, flatten/Prod
, flatten/stack
Replace
node {
name: "flatten/Reshape"
op: "Reshape"
input: "block5_pool/MaxPool"
input: "flatten/stack"
}
to
node {
name: "flatten/Reshape"
op: "Flatten"
input: "block5_pool/MaxPool"
}
Remove nodes dropout_1/keras_learning_phase
, dropout_1/cond/Switch
, dropout_1/cond/mul/Switch
, dropout_1/cond/mul
, dropout_1/cond/dropout/Shape
, dropout_1/cond/dropout/random_uniform/RandomUniform
, dropout_1/cond/dropout/random_uniform/sub
, dropout_1/cond/dropout/random_uniform/mul
, dropout_1/cond/dropout/random_uniform
, dropout_1/cond/dropout/add
, dropout_1/cond/dropout/Floor
, dropout_1/cond/dropout/div
, dropout_1/cond/dropout/mul
, dropout_1/cond/Switch_1
, dropout_1/cond/Merge
.
Replace input: "dropout_1/cond/Merge"
onto input: "dense_1/Relu"
.
import tensorflow as tf
import cv2 as cv
import numpy as np
# Read the graph.
with tf.gfile.FastGFile('model.pb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
np.random.seed(223)
inp = np.random.standard_normal([1, 224, 224, 3]).astype(np.float32)
with tf.Session() as sess:
# Restore session
sess.graph.as_default()
tf.import_graph_def(graph_def, name='')
out = sess.run(sess.graph.get_tensor_by_name('output_node0:0'),
feed_dict={'input_1:0': inp})
cvNet = cv.dnn.readNetFromTensorflow('model.pb', 'graph.pbtxt')
cvNet.setInput(inp.transpose(0, 3, 1, 2))
cvOut = cvNet.forward()
print np.max(np.abs(cvOut - out))
Here it's a graph:
node {
name: "input_1"
op: "Placeholder"
attr {
key: "dtype"
value {
type: DT_FLOAT
}
}
}
node {
name: "block1_conv1/convolution"
op: "Conv2D"
input: "input_1"
input: "block1_conv1/kernel"
attr {
key: "padding"
value {
s: "SAME"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 1
i: 1
i: 1
}
}
}
}
node {
name: "block1_conv1/BiasAdd"
op: "BiasAdd"
input: "block1_conv1/convolution"
input: "block1_conv1/bias"
}
node {
name: "block1_conv1/Relu"
op: "Relu"
input: "block1_conv1/BiasAdd"
}
node {
name: "block1_conv2/convolution"
op: "Conv2D"
input: "block1_conv1/Relu"
input: "block1_conv2/kernel"
attr {
key: "padding"
value {
s: "SAME"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 1
i: 1
i: 1
}
}
}
}
node {
name: "block1_conv2/BiasAdd"
op: "BiasAdd"
input: "block1_conv2/convolution"
input: "block1_conv2/bias"
}
node {
name: "block1_conv2/Relu"
op: "Relu"
input: "block1_conv2/BiasAdd"
}
node {
name: "block1_pool/MaxPool"
op: "MaxPool"
input: "block1_conv2/Relu"
attr {
key: "ksize"
value {
list {
i: 1
i: 2
i: 2
i: 1
}
}
}
attr {
key: "padding"
value {
s: "VALID"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 2
i: 2
i: 1
}
}
}
}
node {
name: "block2_conv1/convolution"
op: "Conv2D"
input: "block1_pool/MaxPool"
input: "block2_conv1/kernel"
attr {
key: "padding"
value {
s: "SAME"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 1
i: 1
i: 1
}
}
}
}
node {
name: "block2_conv1/BiasAdd"
op: "BiasAdd"
input: "block2_conv1/convolution"
input: "block2_conv1/bias"
}
node {
name: "block2_conv1/Relu"
op: "Relu"
input: "block2_conv1/BiasAdd"
}
node {
name: "block2_conv2/convolution"
op: "Conv2D"
input: "block2_conv1/Relu"
input: "block2_conv2/kernel"
attr {
key: "padding"
value {
s: "SAME"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 1
i: 1
i: 1
}
}
}
}
node {
name: "block2_conv2/BiasAdd"
op: "BiasAdd"
input: "block2_conv2/convolution"
input: "block2_conv2/bias"
}
node {
name: "block2_conv2/Relu"
op: "Relu"
input: "block2_conv2/BiasAdd"
}
node {
name: "block2_pool/MaxPool"
op: "MaxPool"
input: "block2_conv2/Relu"
attr {
key: "ksize"
value {
list {
i: 1
i: 2
i: 2
i: 1
}
}
}
attr {
key: "padding"
value {
s: "VALID"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 2
i: 2
i: 1
}
}
}
}
node {
name: "block3_conv1/convolution"
op: "Conv2D"
input: "block2_pool/MaxPool"
input: "block3_conv1/kernel"
attr {
key: "padding"
value {
s: "SAME"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 1
i: 1
i: 1
}
}
}
}
node {
name: "block3_conv1/BiasAdd"
op: "BiasAdd"
input: "block3_conv1/convolution"
input: "block3_conv1/bias"
}
node {
name: "block3_conv1/Relu"
op: "Relu"
input: "block3_conv1/BiasAdd"
}
node {
name: "block3_conv2/convolution"
op: "Conv2D"
input: "block3_conv1/Relu"
input: "block3_conv2/kernel"
attr {
key: "padding"
value {
s: "SAME"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 1
i: 1
i: 1
}
}
}
}
node {
name: "block3_conv2/BiasAdd"
op: "BiasAdd"
input: "block3_conv2/convolution"
input: "block3_conv2/bias"
}
node {
name: "block3_conv2/Relu"
op: "Relu"
input: "block3_conv2/BiasAdd"
}
node {
name: "block3_conv3/convolution"
op: "Conv2D"
input: "block3_conv2/Relu"
input: "block3_conv3/kernel"
attr {
key: "padding"
value {
s: "SAME"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 1
i: 1
i: 1
}
}
}
}
node {
name: "block3_conv3/BiasAdd"
op: "BiasAdd"
input: "block3_conv3/convolution"
input: "block3_conv3/bias"
}
node {
name: "block3_conv3/Relu"
op: "Relu"
input: "block3_conv3/BiasAdd"
}
node {
name: "block3_pool/MaxPool"
op: "MaxPool"
input: "block3_conv3/Relu"
attr {
key: "ksize"
value {
list {
i: 1
i: 2
i: 2
i: 1
}
}
}
attr {
key: "padding"
value {
s: "VALID"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 2
i: 2
i: 1
}
}
}
}
node {
name: "block4_conv1/convolution"
op: "Conv2D"
input: "block3_pool/MaxPool"
input: "block4_conv1/kernel"
attr {
key: "padding"
value {
s: "SAME"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 1
i: 1
i: 1
}
}
}
}
node {
name: "block4_conv1/BiasAdd"
op: "BiasAdd"
input: "block4_conv1/convolution"
input: "block4_conv1/bias"
}
node {
name: "block4_conv1/Relu"
op: "Relu"
input: "block4_conv1/BiasAdd"
}
node {
name: "block4_conv2/convolution"
op: "Conv2D"
input: "block4_conv1/Relu"
input: "block4_conv2/kernel"
attr {
key: "padding"
value {
s: "SAME"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 1
i: 1
i: 1
}
}
}
}
node {
name: "block4_conv2/BiasAdd"
op: "BiasAdd"
input: "block4_conv2/convolution"
input: "block4_conv2/bias"
}
node {
name: "block4_conv2/Relu"
op: "Relu"
input: "block4_conv2/BiasAdd"
}
node {
name: "block4_conv3/convolution"
op: "Conv2D"
input: "block4_conv2/Relu"
input: "block4_conv3/kernel"
attr {
key: "padding"
value {
s: "SAME"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 1
i: 1
i: 1
}
}
}
}
node {
name: "block4_conv3/BiasAdd"
op: "BiasAdd"
input: "block4_conv3/convolution"
input: "block4_conv3/bias"
}
node {
name: "block4_conv3/Relu"
op: "Relu"
input: "block4_conv3/BiasAdd"
}
node {
name: "block4_pool/MaxPool"
op: "MaxPool"
input: "block4_conv3/Relu"
attr {
key: "ksize"
value {
list {
i: 1
i: 2
i: 2
i: 1
}
}
}
attr {
key: "padding"
value {
s: "VALID"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 2
i: 2
i: 1
}
}
}
}
node {
name: "block5_conv1/convolution"
op: "Conv2D"
input: "block4_pool/MaxPool"
input: "block5_conv1/kernel"
attr {
key: "padding"
value {
s: "SAME"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 1
i: 1
i: 1
}
}
}
}
node {
name: "block5_conv1/BiasAdd"
op: "BiasAdd"
input: "block5_conv1/convolution"
input: "block5_conv1/bias"
}
node {
name: "block5_conv1/Relu"
op: "Relu"
input: "block5_conv1/BiasAdd"
}
node {
name: "block5_conv2/convolution"
op: "Conv2D"
input: "block5_conv1/Relu"
input: "block5_conv2/kernel"
attr {
key: "padding"
value {
s: "SAME"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 1
i: 1
i: 1
}
}
}
}
node {
name: "block5_conv2/BiasAdd"
op: "BiasAdd"
input: "block5_conv2/convolution"
input: "block5_conv2/bias"
}
node {
name: "block5_conv2/Relu"
op: "Relu"
input: "block5_conv2/BiasAdd"
}
node {
name: "block5_conv3/convolution"
op: "Conv2D"
input: "block5_conv2/Relu"
input: "block5_conv3/kernel"
attr {
key: "padding"
value {
s: "SAME"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 1
i: 1
i: 1
}
}
}
}
node {
name: "block5_conv3/BiasAdd"
op: "BiasAdd"
input: "block5_conv3/convolution"
input: "block5_conv3/bias"
}
node {
name: "block5_conv3/Relu"
op: "Relu"
input: "block5_conv3/BiasAdd"
}
node {
name: "block5_pool/MaxPool"
op: "MaxPool"
input: "block5_conv3/Relu"
attr {
key: "ksize"
value {
list {
i: 1
i: 2
i: 2
i: 1
}
}
}
attr {
key: "padding"
value {
s: "VALID"
}
}
attr {
key: "strides"
value {
list {
i: 1
i: 2
i: 2
i: 1
}
}
}
}
node {
name: "flatten/Reshape"
op: "Flatten"
input: "block5_pool/MaxPool"
}
node {
name: "dense_1/MatMul"
op: "MatMul"
input: "flatten/Reshape"
input: "dense_1/kernel"
attr {
key: "transpose_a"
value {
b: false
}
}
attr {
key: "transpose_b"
value {
b: false
}
}
}
node {
name: "dense_1/BiasAdd"
op: "BiasAdd"
input: "dense_1/MatMul"
input: "dense_1/bias"
}
node {
name: "dense_1/Relu"
op: "Relu"
input: "dense_1/BiasAdd"
}
node {
name: "dense_2/MatMul"
op: "MatMul"
input: "dense_1/Relu"
input: "dense_2/kernel"
attr {
key: "transpose_a"
value {
b: false
}
}
attr {
key: "transpose_b"
value {
b: false
}
}
}
node {
name: "dense_2/BiasAdd"
op: "BiasAdd"
input: "dense_2/MatMul"
input: "dense_2/bias"
}
node {
name: "dense_2/Softmax"
op: "Softmax"
input: "dense_2/BiasAdd"
}
node {
name: "output_node0"
op: "Identity"
input: "dense_2/Softmax"
}