I have retrained two different classification models models using retrain.py.
For predicting labels for two images I have created getLabel method from Label_image.py as follows:
def getLabel(localFile, graphKey, labelKey):
image_data_str = tf.gfile.FastGFile(localFile, 'rb').read()
# Loads label file, strips off carriage return
label_lines = [line.rstrip() for line
in tf.gfile.GFile(labelKey)]
# Unpersists graph from file
with tf.gfile.FastGFile(graphKey, 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
_ = tf.import_graph_def(graph_def, name='')
sess = tf.Session()
with sess:
# Feed the image_data as input to the graph and get first prediction
softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
predictions = sess.run(softmax_tensor, {'DecodeJpeg/contents:0': image_data_str})
# Sort to show labels of first prediction in order of confidence
top_k = predictions[0].argsort()[-len(predictions[0]):][::-1]
series = []
count = 1
for node_id in top_k:
human_string = label_lines[node_id]
if count==1:
label = human_string
count+=1
score = predictions[0][node_id]
print('%s (score = %.5f)' % (human_string, score))
series.append({"name": human_string, "data": [score * 100]})
sess.close()
return label, series
And I am calling them as
label,series = predict.getLabel(localFile, 'graph1.pb', 'labels1.txt')
label,series = predict.getLabel(localFile, 'graph2.pb', 'labels2.txt')
But for the second function call it is using the old graph i.e. graph1.pb & it is giving below error since model 1 has more categories than model 2.
human_string = label_lines[node_id]
IndexError: list index out of range
I am not able to understand why is this happening. Can someone tell how to load second graph??
It looks like what is happening is that you are calling the same session for both calls to predict.getFinalLabel. What you should do is define two separate sessions, and initialize each separately (e.g. have predict1.getFinalLabel and predict2.getFinalLabel). If you post more of your code, I can provide more detail and code.
Related
I'm trying to print the prediction results and the labels, in addition to accuracy from a model.
I'm not sure what I'm doing wrong here
for mfcc, label in test_data:
prediction = tflite_inference(mfcc, tflite_path)
predicted_indices.append(np.squeeze(tf.argmax(prediction, axis=1)))
strlabel="C:/tmp/speech_commands_train/conv_labels.txt"
labels_list= [line.rstrip() for line in tf.io.gfile.GFile(strlabel)]
top_k = prediction.argsort()[-5:][::-1]
for node_id in top_k:
human_string = labels_list[node_id]
score = predicted_indices[node_id]
print('%s (score = %.5f)' % (human_string, score))
test_accuracy = calculate_accuracy(predicted_indices, expected_indices)
confusion_matrix = tf.math.confusion_matrix(expected_indices, predicted_indices,
num_classes=model_settings['label_count'])
`
Error message
human_string = labels_list[node_id] TypeError: only integer scalar arrays can be converted to a scalar index
Thank you in advance for your help.
EDITED ANSWER (after some clarification regarding the problem):
Here I assume that the prediction variable is the output of your model for a single input. With this assumption, your top_k should contain top 5 indices with the highest probability.
To do that you should do the following:
Reshape your predictions variable:
predictions = predictions.reshape(-1) # this will make the predicitions a vector
Get the top_k
# this step is same but this time the output will be a vector instead of a matrix
top_k = prediction.argsort()[-5:][::-1]
Use the loop
# This is also same but as the `top_k` is a vector instead of a matrix there
# won't be any issues/errors.
for node_id in top_k:
human_string = labels_list[node_id]
score = predicted_indices[node_id]
print('%s (score = %.5f)' % (human_string, score))
with tf.Session() as sess:
out = open('output.csv', 'a')
for image_path in glob.glob(folder_path+'/*'):
# Read in the image_data
image_data = tf.gfile.FastGFile(image_path, 'rb').read()
# Feed the image_data as input to the graph and get first prediction
softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
predictions = sess.run(softmax_tensor, \
{'DecodeJpeg/contents:0': image_data})
#print("%s\t%s\t%s\t%s\t%s\t%s\n" % (image_path,predictions[0][1],predictions[0][0],predictions[0][2], predictions[0][3],predictions[0][4]))
for i in predictions:
predictions= pd.DataFrame([image_path,i[0][1],i[0][0],i[0][2], i[0][3],i[0][4]], columns = ['predictions']).to_csv('prediction.csv')
#f = open('/tf_files/testinnggg', 'w')
#for row in predictions:
# f.write(row[0])
# f.close()
#test = []
#test.append([predictions[0][1],predictions[0][0],predictions[0][2], predictions[0][3],predictions[0][4]])
#THIS ACTUALLY WORKS, I see in my terminal "/tf_files/tested/pic1.jpg 0.00442768 0.995572"
#np.savetxt('testinnggg', test, delimiter = ',')#,[predictions[0][0],predictions[0][2],predictions[0][3],predictions[0][4],delimiter = ',')
#out.write("%s\t%s\t%s\n" % (image_path,predictions[0][1],predictions[0][0]))
#This does not work, because output.csv is not modified
out.close()
When using the pandas option to save the predictions,the only prediction that gets saved is the final file,i think it is overwrting the previous ones.Any suggestions as to how do i get all the predictions in the loop.
Thank you
I was playing around with Tensorflow for image classification. I used the image_retraining/retrain.py to retrain the inception library with new categories and used it to classify images using label_image.py from https://github.com/llSourcell/tensorflow_image_classifier/blob/master/src/label_image.py as below:
import tensorflow as tf
import sys
# change this as you see fit
image_path = sys.argv[1]
# Read in the image_data
image_data = tf.gfile.FastGFile(image_path, 'rb').read()
# Loads label file, strips off carriage return
label_lines = [line.rstrip() for line
in tf.gfile.GFile("/root/tf_files/output_labels.txt")]
# Unpersists graph from file
with tf.gfile.FastGFile("/root/tf_files/output_graph.pb", 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
_ = tf.import_graph_def(graph_def, name='')
with tf.Session() as sess:
# Feed the image_data as input to the graph and get first prediction
softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
#predictions = sess.run(softmax_tensor,{'DecodeJpeg/contents:0': image_data})
predictions = sess.run(softmax_tensor,{'DecodePng/contents:0': image_data})
# Sort to show labels of first prediction in order of confidence
top_k = predictions[0].argsort()[-len(predictions[0]):][::-1]
for node_id in top_k:
human_string = label_lines[node_id]
score = predictions[0][node_id]
print('%s (score = %.5f)' % (human_string, score))
I noticed two issues. When I retrain with new categories, it only trains JPG images. I am a noob in machine learning so not sure whether this is a limitation or is it possible to train other extension images like PNG, GIF?
Another one is when classifying the images the input is again only for JPG. I tried to change DecodeJpeg to DecodePng in label_image.py above but couldn't work. Another way I tried was to convert other formats into JPG before passing them in for classification like:
im = Image.open('/root/Desktop/200_s.gif').convert('RGB')
im.save('/root/Desktop/test.jpg', "JPEG")
image_path1 = '/root/Desktop/test.jpg'
Is there any other way to do this? Does Tensorflow have functions to handle other image formats other than JPG?
I tried the following by feeding in parsed image as compared to JPEG as suggested by #mrry
import tensorflow as tf
import sys
import numpy as np
from PIL import Image
# change this as you see fit
image_path = sys.argv[1]
# Read in the image_data
image_data = tf.gfile.FastGFile(image_path, 'rb').read()
image = Image.open(image_path)
image_array = np.array(image)[:,:,0:3] # Select RGB channels only.
# Loads label file, strips off carriage return
label_lines = [line.rstrip() for line
in tf.gfile.GFile("/root/tf_files/output_labels.txt")]
# Unpersists graph from file
with tf.gfile.FastGFile("/root/tf_files/output_graph.pb", 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
_ = tf.import_graph_def(graph_def, name='')
with tf.Session() as sess:
# Feed the image_data as input to the graph and get first prediction
softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
predictions = sess.run(softmax_tensor,{'DecodeJpeg:0': image_array})
# Sort to show labels of first prediction in order of confidence
top_k = predictions[0].argsort()[-len(predictions[0]):][::-1]
for node_id in top_k:
human_string = label_lines[node_id]
score = predictions[0][node_id]
print('%s (score = %.5f)' % (human_string, score))
It works for JPEG images but when I use PNG or GIF it throws
Traceback (most recent call last):
File "label_image.py", line 17, in <module>
image_array = np.array(image)[:,:,0:3] # Select RGB channels only.
IndexError: too many indices for array
The model can only train on (and evaluate) JPEG images, because the GraphDef that you've saved in /root/tf_files/output_graph.pb only contains a tf.image.decode_jpeg() op, and uses the output of that op for making predictions. There are at least a couple of options for using other image formats:
Feed in parsed images rather than JPEG data. In the current program, you feed in a JPEG-encoded image as a string value for the tensor "DecodeJpeg/contents:0". Instead, you can feed in a 3-D array of decoded image data for the tensor "DecodeJpeg:0" (which represents the output of the tf.image.decode_jpeg() op), and you can use NumPy, PIL, or some other Python library to create this array.
Remap the image input in tf.import_graph_def(). The tf.import_graph_def() function enables you to connect two different graphs together by remapping individual tensor values. For example, you could do something like the following to add a new image-processing op to the existing graph:
image_string_input = tf.placeholder(tf.string)
image_decoded = tf.image.decode_png(image_string_input)
# Unpersists graph from file
with tf.gfile.FastGFile("/root/tf_files/output_graph.pb", 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
softmax_tensor, = tf.import_graph_def(
graph_def,
input_map={"DecodeJpeg:0": image_decoded},
return_operations=["final_result:0"])
with tf.Session() as sess:
# Feed the image_data as input to the graph and get first prediction
predictions = sess.run(softmax_tensor, {image_string_input: image_data})
# ...
You should have a look at the tf.image package. It's got good functions to decode / encode JPEGs, GIFs and PNGs.
Following #mrry's suggestion to feed in parsed image, converted the image data into array and convert into RGB as stated below in the code. Now I am able to feed in JPG,PNG and GIF.
import tensorflow as tf
import sys
import numpy as np
from PIL import Image
# change this as you see fit
image_path = sys.argv[1]
# Read in the image_data
image_data = tf.gfile.FastGFile(image_path, 'rb').read()
image = Image.open(image_path)
image_array = image.convert('RGB')
# Loads label file, strips off carriage return
label_lines = [line.rstrip() for line
in tf.gfile.GFile("/root/tf_files/output_labels.txt")]
# Unpersists graph from file
with tf.gfile.FastGFile("/root/tf_files/output_graph.pb", 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
_ = tf.import_graph_def(graph_def, name='')
with tf.Session() as sess:
# Feed the image_data as input to the graph and get first prediction
softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
predictions = sess.run(softmax_tensor,{'DecodeJpeg:0': image_array})
# Sort to show labels of first prediction in order of confidence
top_k = predictions[0].argsort()[-len(predictions[0]):][::-1]
for node_id in top_k:
human_string = label_lines[node_id]
score = predictions[0][node_id]
print('%s (score = %.5f)' % (human_string, score))
I went through the Tensorflow for poets Tutorial and then classified my own images, this is all done in the TF docker container provided. The model has a validation accuracy in the mid to low 90's. There is a separate file that makes predictions for new images(below).
I copied the files 'retrained_labels_corn.txt' and 'retrained_graph_corn.pd' and the file holding the code seen below to a directory(and changed the file paths) to see if I could make predictions while not in the docker container. I made sure I give it a valid image path as the system arg but it always predicts the image as one class with a probability above 97%. When I do the same thing while in the docker container everything works fine. I even tried pointing the labeling file to the exact same files that docker container uses and I am getting the same result of it always predicting one class with a high degree of certainty.
What did I do wrong?
import tensorflow as tf, sys
image_path = sys.argv[1]
# Read in the image_data
image_data = tf.gfile.FastGFile(image_path, 'rb').read()
# Loads label file, strips off carriage return
label_lines = [line.rstrip() for line
in tf.gfile.GFile("/tf_files/retrained_labels_corn.txt")]
# Unpersists graph from file
with tf.gfile.FastGFile("/tf_files/retrained_graph_corn.pb", 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
_ = tf.import_graph_def(graph_def, name='')
with tf.Session() as sess:
# Feed the image_data as input to the graph and get first prediction
softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
predictions = sess.run(softmax_tensor, \
{'DecodeJpeg/contents:0': image_data})
# Sort to show labels of first prediction in order of confidence
top_k = predictions[0].argsort()[-len(predictions[0]):][::-1]
for node_id in top_k:
human_string = label_lines[node_id]
score = predictions[0][node_id]
print('%s (score = %.5f)' % (human_string, score))
I am on Ubuntu version 16.04 and TF 0.10
I've made a learning on Tensorflow (MNIST) and I've saved the weights in a .ckpt.
Now I want to test my neural network on this weights, with the same images translated of a few pixels to the right and bottom.
The loading weigths works well, but when I print an eval, Tensorflow display always the same results (0.9630 for the test), whatever the translation is about 1 or 14px.
Here is my code for the function which print the eval :
def eval_translation(sess, eval_correct, images_pl, labels_pl, dataset):
print('Test Data Eval:')
for i in range(28):
true_count = 0 # Counts the number of correct predictions.
steps_per_epoch = dataset.num_examples // FLAGS.batch_size
nb_exemples = steps_per_epoch * FLAGS.batch_size
for step in xrange(steps_per_epoch):
images_feed, labels_feed = dataset.next_batch(FLAGS.batch_size)
feed_dict = {images_pl: translate_right(images_feed, i), labels_pl: labels_feed}
true_count += sess.run(eval_correct, feed_dict=feed_dict)
precision = true_count / nb_exemples
print('Translation: %d Num examples: %d Num correct: %d Precision # 1: %0.04f' % (i, nb_exemples, true_count, precision))
This is the function which with I load the datas and which with I print the test results.
Here is my translation function :
def translate_right(images, dev):
for i in range(len(images)):
for j in range(len(images[i])):
images[i][j] = np.roll(images[i][j], dev)
return images
I call this function in place of the learning just after initialise all the variables :
with tf.Graph().as_default():
# Generate placeholders for the images and labels.
images_placeholder, labels_placeholder = placeholder_inputs(FLAGS.batch_size)
# Build a Graph that computes predictions from the inference model.
weights, logits = mnist.inference(images_placeholder, neurons)
# Add to the Graph the Ops for loss calculation.
loss = mnist.loss(logits, labels_placeholder)
# Add to the Graph the Ops that calculate and apply gradients.
train_op = mnist.training(loss, learning_rate)
# Add the Op to compare the logits to the labels during evaluation.
eval_correct = mnist.evaluation(logits, labels_placeholder)
# Build the summary operation based on the TF collection of Summaries.
summary_op = tf.merge_all_summaries()
# Create a saver for writing training checkpoints.
save = {}
for i in range(len(weights)):
save['weights' + str(i)] = weights[i]
saver = tf.train.Saver(save)
# Create a session for running Ops on the Graph.
sess = tf.Session()
init = tf.initialize_all_variables()
sess.run(init)
# load weights
saver.restore(sess, restore_path)
# Instantiate a SummaryWriter to output summaries and the Graph.
summary_writer = tf.train.SummaryWriter(FLAGS.train_dir, sess.graph)
temps_total = time.time()
eval_translation(sess, eval_correct, images_placeholder, labels_placeholder, dataset.test)
I don't know what's wrong with my code, and why Tensorflow seems to ignore my images.
Can someone could help me please ?
Thanks !
You function translate_right doesn't work, because images[i, j] is just one pixel (containing 1 value if you have greyscale images).
You should use the argument axis of np.roll:
def translate_right(images, dev):
return np.roll(images, dev, axis=1)