I have retrained Inception-v3 model using (Tensorflow) Python API and saved a standalone Graph in .pb by modifying tensorflow/tensorflow/examples/image_retraining/retrain.py with the following modification to add a drop out layer before the classification layer:
def nn_layer(input_tensor, input_dim, output_dim, layer_name, activation_name='activation', act=tf.nn.softmax):
# Adding a name scope ensures logical grouping of the layers in the graph.
with tf.name_scope(layer_name):
# This Variable will hold the state of the weights for the layer
with tf.name_scope('weights'):
weights = weight_variable([input_dim, output_dim])
variable_summaries(weights, layer_name + '/weights')
with tf.name_scope('dropout'):
keep_prob = tf.placeholder(tf.float32)
tf.scalar_summary('dropout_keep_probability', keep_prob)
drop = tf.nn.dropout(input_tensor, keep_prob)
variable_summaries(drop, layer_name + '/dropout')
with tf.name_scope('biases'):
biases = bias_variable([output_dim])
variable_summaries(biases, layer_name + '/biases')
preactivate = tf.matmul(drop, weights) + biases
tf.histogram_summary(layer_name + '/pre_activations', preactivate)
with tf.name_scope(activation_name):
activations = act(preactivate)
tf.histogram_summary(layer_name + '/activations', activations)
return preactivate, activations, keep_prob
The code to generate predictions in python is as follows:
softmax_tensor = sess.graph.get_tensor_by_name('final_layer/final_result/Softmax:0')
predictions = sess.run(softmax_tensor, { 'DecodeJpeg/contents:0':image_data, 'final_layer/dropout/Placeholder:0': 1.})
The C++ counterpart of the python code is as follows:
string input_layer = "Mul";
string output_layer = "final_layer/dropout/Placeholder:0";
Status run_status = session->Run({{input_layer, resized_tensor}}, {output_layer}, {}, &outputs);
The C++ code ends up with the following error message:
Running model failed: Invalid argument: You must feed a value for placeholder tensor 'final_layer/dropout/Placeholder'
What should I change in the above C++ code to remove this error? In other words, how do I change a placeholder value in the C++ code as in python code. I am stuck in this problem since many days. Any help will be highly appreciated.
Your C++ code is not the counterpart of your Python code.
In python you got
softmax_tensor = sess.graph.get_tensor_by_name('final_layer/final_result/Softmax:0')
predictions = sess.run(softmax_tensor, { 'DecodeJpeg/contents:0':image_data, 'final_layer/dropout/Placeholder:0': 1.})
Thus, your feed_dict
is { 'DecodeJpeg/contents:0':image_data, 'final_layer/dropout/Placeholder:0': 1.}
.
that means: override the value of DecodeJpeg/contents:0
with image_data
and override the value of final_layer/dropout/Placeholder:0
with 1.
.
In C++, instead, you got:
Status run_status = session->Run({{input_layer, resized_tensor}}, {output_layer}, {}, &outputs);
This, your feed_dict
equivalent is the first input parameter, that is:
{{input_layer, resized_tensor}}
That means: override input_layer
with resized_tensor
.
The first problem is that you're trying overriding the node Mul
and not node DecodeJpeg/contents:0
as above.
Moreover, is missing the overriding of the placeholder.
However, there's some mess in your C++ code, because you called output_tensor
what in fact is the placeholder
.
The counterpart if your Python code, should be something like
Status run_status = session->Run({
{"DecodeJpeg/contents", resized_tensor},
{"final_layer/dropout/Placeholder", 1f}
}, {"final_layer/final_result/Softmax"}, {}, &outputs);
that means:
override the node value of DecodeJpeg/contents
with resize_tensor
.
override the node value of final_layer/dropout/Placeholder
with 1.
fetch the value of the node final_layer/final_result/Softmax
.
put the results into outputs