Invoking a Tensflow model

that was trained with the transfer learning method in Google's Tensorflow for Poets".

In this case we have used the Inception_V3 model. You need to clone the github repo with the command

git clone https://github.com/googlecodelabs/tensorflow-for-poets-2
cd tensorflow-for-poets-2
Next go to the subdirectory tf_files and create a new directory there called "galaxies" and put four subdirectories there: barredspiral, spiral, elliptical, irregular with each containing the corresponding training images. Next do
pip install --upgrade tensorflow

The command to "retrain" the inception model is

python -m scripts.retrain \
  --bottleneck_dir=tf_files/bottlenecks \
  --how_many_training_steps=500 \
  --model_dir=tf_files/models/ \
  --summaries_dir=tf_files/training_summaries/"inception_v3" \
  --output_graph=tf_files/retrained_graph.pb \
  --output_labels=tf_files/retrained_labels.txt \
  --architecture="inception_v3" \
  --image_dir=tf_files/galaxies
If all goes well you will finally get the results that look like this
INFO:tensorflow:Final test accuracy = 88.9% (N=9)

The code that follows shows how to invoke the model. But first do

In [1]:
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import argparse
import sys
import time

import numpy as np
import tensorflow as tf
/Users/dennisgannon/anaconda3/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters
In [2]:
def load_graph(model_file):
    graph = tf.Graph()
    graph_def = tf.GraphDef()

    with open(model_file, "rb") as f:
        graph_def.ParseFromString(f.read())
    with graph.as_default():
        tf.import_graph_def(graph_def)

    return graph

The following function resizes our images to 299 by 299 which is what is needed by the model.

In [3]:
def read_tensor_from_image_file(file_name, input_height=299, input_width=299,
                                input_mean=0, input_std=255):
    input_name = "file_reader"
    output_name = "normalized"
    file_reader = tf.read_file(file_name, input_name)
    if file_name.endswith(".png"):
        image_reader = tf.image.decode_png(file_reader, channels = 3,
                                       name='png_reader')
    elif file_name.endswith(".gif"):
        image_reader = tf.squeeze(tf.image.decode_gif(file_reader,
                                                  name='gif_reader'))
    elif file_name.endswith(".bmp"):
        image_reader = tf.image.decode_bmp(file_reader, name='bmp_reader')
    else:
        image_reader = tf.image.decode_jpeg(file_reader, channels = 3,
                                        name='jpeg_reader')
    float_caster = tf.cast(image_reader, tf.float32)
    dims_expander = tf.expand_dims(float_caster, 0);
    resized = tf.image.resize_bilinear(dims_expander, [input_height, input_width])
    normalized = tf.divide(tf.subtract(resized, [input_mean]), [input_std])
    sess = tf.Session()
    result = sess.run(normalized)

    return result

    

this makes a list of the class labels.

In [4]:
def load_labels(label_file):
    label = []
    proto_as_ascii_lines = tf.gfile.GFile(label_file).readlines()
    for l in proto_as_ascii_lines:
        label.append(l.rstrip())
    return label

The following are the parameters we will use to invoke the model. This is different from the ones in the documentation. That version is for the mobilenet model. this one is for inception_v3. note the input_layer and the output_layer and the height andd weight.

In [12]:
model_file = "/Users/dennisgannon/GitHub/tensorflow-for-poets-2/tf_files/retrained_graph.pb"
label_file = "/Users/dennisgannon/GitHub/tensorflow-for-poets-2/tf_files/retrained_labels.txt"
input_height = 299
input_width = 299
input_mean = 128
input_std = 128
input_layer = "Mul"
output_layer = "final_result"
In [13]:
graph = load_graph(model_file)

Let's try it out on one of the test cases (which is a spiral galaxy)

In [14]:
file_name = '/Users/dennisgannon/OneDrive/Docs9/galaxies/bigtest/t31.jpg'
In [15]:
t = read_tensor_from_image_file(file_name,
  input_height=input_height,
  input_width=input_width,
  input_mean=input_mean,
  input_std=input_std)
In [17]:
input_name = "import/" + input_layer
output_name = "import/" + output_layer
input_operation = graph.get_operation_by_name(input_name);
output_operation = graph.get_operation_by_name(output_name);
In [18]:
with tf.Session(graph=graph) as sess:
    start = time.time()
    results = sess.run(output_operation.outputs[0],
                  {input_operation.outputs[0]: t})
    end=time.time()
In [19]:
results = np.squeeze(results)

top_k = results.argsort()[-5:][::-1]
labels = load_labels(label_file)

print('\nEvaluation time (1-image): {:.3f}s\n'.format(end-start))
Evaluation time (1-image): 1.883s

In [23]:
for i in top_k:
    print(labels[i], results[i])
spiral 0.6392077
barredspiral 0.30974352
irregular 0.049187053
elliptical 0.0018616947
In [20]:
top_k[0]
Out[20]:
3

the predict_image function

which takes a filename and returns a tuple consisting of the top prediction and the score.

In [21]:
def predict_image(file_name):
    t = read_tensor_from_image_file(file_name,
      input_height=input_height,
      input_width=input_width,
      input_mean=input_mean,
      input_std=input_std)
    input_name = "import/" + input_layer
    output_name = "import/" + output_layer
    input_operation = graph.get_operation_by_name(input_name);
    output_operation = graph.get_operation_by_name(output_name);
    with tf.Session(graph=graph) as sess:
        start = time.time()
        results = sess.run(output_operation.outputs[0],
                      {input_operation.outputs[0]: t})
        end=time.time()

    results = np.squeeze(results)

    top_k = results.argsort()[-5:][::-1]
    labels = load_labels(label_file)

    #print('\nEvaluation time (1-image): {:.3f}s\n'.format(end-start))
    return [labels[top_k[0]], results[top_k[0]]]
    
In [22]:
predict_image(file_name)
Out[22]:
['spiral', 0.6392077]

now compute confusion matrix

first for the test set and then for the training set

In [24]:
test_out = []
for i in range(0,40):
    file_name = '/Users/dennisgannon/OneDrive/Docs9/galaxies/bigtest/t'+str(i)+'.jpg'
    test_out.append(predict_image(file_name)) 
In [25]:
mydict = {'spiral': {'spiral':0.0, 'barredspiral':0.0, 'elliptical':0.0, 'irregular':0.0},
          'barredspiral': {'spiral':0.0, 'barredspiral':0.0, 'elliptical':0.0, 'irregular':0.0},
          'elliptical': {'spiral':0.0, 'barredspiral':0.0, 'elliptical':0.0, 'irregular':0.0},
          'irregular': {'spiral':0.0, 'barredspiral':0.0, 'elliptical':0.0, 'irregular':0.0}}
In [26]:
for i in range(0,40):
    truev = 'barredspiral'
    if i > 9:
        truev= 'elliptical'
    if i > 19:
        truev = 'irregular'
    if i > 29:
        truev = 'spiral'
    mydict[truev][test_out[i][0]]+= 1
#    print(i, truev, test_out[i])
In [27]:
import pandas as pd
In [28]:
df = pd.DataFrame.from_dict(mydict)
In [29]:
df.transpose()
Out[29]:
barredspiral elliptical irregular spiral
barredspiral 7.0 0.0 0.0 3.0
elliptical 1.0 8.0 1.0 0.0
irregular 0.0 1.0 6.0 3.0
spiral 4.0 0.0 0.0 6.0
In [30]:
traindict = {'spiral': {'spiral':0.0, 'barredspiral':0.0, 'elliptical':0.0, 'irregular':0.0},
          'barredspiral': {'spiral':0.0, 'barredspiral':0.0, 'elliptical':0.0, 'irregular':0.0},
          'elliptical': {'spiral':0.0, 'barredspiral':0.0, 'elliptical':0.0, 'irregular':0.0},
          'irregular': {'spiral':0.0, 'barredspiral':0.0, 'elliptical':0.0, 'irregular':0.0}}
In [31]:
for i in range(1,20):
    file_name = '/Users/dennisgannon/OneDrive/Docs9/galaxies/bigspiral/s'+str(i)+'.jpg'
    traindict['spiral'][predict_image(file_name)[0]] +=1 
In [32]:
for i in range(1,20):
    file_name = '/Users/dennisgannon/OneDrive/Docs9/galaxies/bigbarred/bs'+str(i)+'.jpg'
    traindict['barredspiral'][predict_image(file_name)[0]] +=1 
In [33]:
for i in range(1,20):
    file_name = '/Users/dennisgannon/OneDrive/Docs9/galaxies/bigelliptical/e'+str(i)+'.jpg'
    traindict['elliptical'][predict_image(file_name)[0]] +=1 
In [34]:
for i in range(1,20):
    file_name = '/Users/dennisgannon/OneDrive/Docs9/galaxies/bigirregular/i'+str(i)+'.jpg'
    traindict['irregular'][predict_image(file_name)[0]] +=1 
In [35]:
tdf = pd.DataFrame.from_dict(traindict)
In [36]:
tdf.transpose()
Out[36]:
barredspiral elliptical irregular spiral
barredspiral 18.0 0.0 0.0 1.0
elliptical 1.0 18.0 0.0 0.0
irregular 0.0 0.0 19.0 0.0
spiral 3.0 0.0 0.0 16.0

at the end of the training: INFO:tensorflow:Final test accuracy = 88.9% (N=9)