Search code examples
pythonc++machine-learningtensorflowdeep-learning

Feeding a value for placeholder tensor in Tensorflow C++ API


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.


Solution

  • 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.

    TL;DR

    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