Basic Convolutional Neural Network: Image Processing


In [2]:
# TODO:  @Sam, please fill this in...

In [3]:
import tensorflow as tf
import numpy as np
from IPython.display import clear_output, Image, display, HTML

In [4]:
# Note:  All datasets are available here:  /root/pipeline/datasets/...

In [5]:
# Modules required for file download and extraction
import os
import sys
import tarfile
from six.moves.urllib.request import urlretrieve

def maybe_download(filename, url, force=False):
  """Download a file if not present."""
  if force or not os.path.exists('/root/pipeline/datasets/notmnist/' + filename):
    filename, _ = urlretrieve(url + filename, '/root/pipeline/datasets/notmnist/' + filename)
    print('\nDownload complete for {}'.format(filename))
  else:
    print('File {} already present.'.format(filename))
  return filename

def maybe_extract(filename, force=False):
  root = os.path.splitext(os.path.splitext(filename)[0])[0]  # remove .tar.gz
  if os.path.isdir(root) and not force:
    # You may override by setting force=True.
    print('{} already present - Skipping extraction of {}.'.format(root, filename))
  else:
    print('Extracting data for {}. This may take a while. Please wait.'.format(root))
    tar = tarfile.open(filename)
    sys.stdout.flush()
    tar.extractall(root)
    tar.close()
  data_folders = [
    os.path.join(root, d) for d in sorted(os.listdir(root))
    if os.path.isdir(os.path.join(root, d))]
  print(data_folders)
  return data_folders

In [6]:
#maybe_extract('/root/pipeline/datasets/notmnist/notMNIST_large.tar.gz')
#maybe_extract('/root/pipeline/datasets/notmnist/notMNIST_small.tar.gz')

In [7]:
ll /root/pipeline/datasets


total 64
drwxr-xr-x 14 root 4096 Jun  4 13:50 dating/
drwxr-xr-x  3 root 4096 Jun  4 13:51 eigenface/
drwxr-xr-x  2 root 4096 May 31 05:40 email/
drwxr-xr-x  2 root 4096 May 31 05:40 geo/
drwxr-xr-x  2 root 4096 Jun  4 14:52 graph/
drwxr-xr-x  2 root 4096 May 31 05:40 inception/
drwxr-xr-x  2 root 4096 May 31 05:40 lsh/
drwxr-xr-x  2 root 4096 May 31 05:40 meetup/
drwxr-xr-x  2 root 4096 May 31 05:40 mnist/
drwxr-xr-x  5 root 4096 Jun  4 13:49 movielens/
drwxr-xr-x  2 root 4096 May 31 05:40 nlp/
drwxr-xr-x  3 root 4096 Jun  4 13:51 notmnist/
drwxr-xr-x  3 root 4096 May 31 05:40 ptb/
drwxr-xr-x  4 root 4096 Jun  4 13:51 serving/
drwxr-xr-x  2 root 4096 May 31 05:40 sort/
drwxr-xr-x  4 root 4096 Jun  4 13:51 tensorflow/

In [10]:
# Prepare input for the format expected by the graph
t_input = tf.placeholder(np.float32, name='our_input') # define the input tensor
imagenet_mean = 117.0
t_preprocessed = tf.expand_dims(t_input-imagenet_mean, 0)

# Load graph and import into graph used by our session
model_fn = '/root/pipeline/datasets/inception/classify_image_graph_def.pb'
graph_def = tf.GraphDef.FromString(open(model_fn).read())
tf.import_graph_def(graph_def, {'input':t_preprocessed})



ValueErrorTraceback (most recent call last)
<ipython-input-10-59700d3cccb4> in <module>()
      7 model_fn = '/root/pipeline/datasets/inception/classify_image_graph_def.pb'
      8 graph_def = tf.GraphDef.FromString(open(model_fn).read())
----> 9 tf.import_graph_def(graph_def, {'input':t_preprocessed})

/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/importer.pyc in import_graph_def(graph_def, input_map, return_elements, name, op_dict)
    347       raise ValueError(
    348           'Attempted to map inputs that were not found in graph_def: [%s]'
--> 349           % ', '.join(unused_input_keys))
    350 
    351     if return_elements is None:

ValueError: Attempted to map inputs that were not found in graph_def: [input:0]

Utility Functions to Display TensorBoard Inline


In [ ]:
# Helper functions for TF Graph visualization
def strip_consts(graph_def, max_const_size=32):
    """Strip large constant values from graph_def."""
    strip_def = tf.GraphDef()
    for n0 in graph_def.node:
        n = strip_def.node.add() 
        n.MergeFrom(n0)
        if n.op == 'Const':
            tensor = n.attr['value'].tensor
            size = len(tensor.tensor_content)
            if size > max_const_size:
                tensor.tensor_content = "<stripped %d bytes>"%size
    return strip_def
  
def rename_nodes(graph_def, rename_func):
    res_def = tf.GraphDef()
    for n0 in graph_def.node:
        n = res_def.node.add() 
        n.MergeFrom(n0)
        n.name = rename_func(n.name)
        for i, s in enumerate(n.input):
            n.input[i] = rename_func(s) if s[0]!='^' else '^'+rename_func(s[1:])
    return res_def
  
def show_graph(graph_def, max_const_size=32):
    """Visualize TensorFlow graph."""
    if hasattr(graph_def, 'as_graph_def'):
        graph_def = graph_def.as_graph_def()
    strip_def = strip_consts(graph_def, max_const_size=max_const_size)
    code = """
        <script>
          function load() {{
            document.getElementById("{id}").pbtxt = {data};
          }}
        </script>
        <link rel="import" href="https://tensorboard.appspot.com/tf-graph-basic.build.html" onload=load()>
        <div style="height:600px">
          <tf-graph-basic id="{id}"></tf-graph-basic>
        </div>
    """.format(data=repr(str(strip_def)), id='graph'+str(np.random.rand()))
  
    iframe = """
        <iframe seamless style="width:800px;height:620px;border:0" srcdoc="{}"></iframe>
    """.format(code.replace('"', '&quot;'))
    display(HTML(iframe))

# Visualizing the network graph. Be sure expand the "mixed" nodes to see their 
# internal structure. We are going to visualize "Conv2D" nodes.
tmp_def = rename_nodes(graph_def, lambda s:"/".join(s.split('_',1)))
#show_graph(tmp_def)

Irrelevant code - only placed here to demo Inline TensorBoard


In [ ]:
k = np.float32([1,4,6,4,1])
k = np.outer(k, k)
k5x5 = k[:,:,None,None]/k.sum()*np.eye(3, dtype=np.float32)

def lap_split(img):
    '''Split the image into lo and hi frequency components'''
    with tf.name_scope('split'):
        lo = tf.nn.conv2d(img, k5x5, [1,2,2,1], 'SAME')  # Blurred image -- low frequencies only
        lo2 = tf.nn.conv2d_transpose(lo, k5x5*4, tf.shape(img), [1,2,2,1]) 
        hi = img-lo2 # hi is img with low frequencies removed
    return lo, hi

def lap_split_n(img, n):
    '''Build Laplacian pyramid with n splits'''
    levels = []
    for i in xrange(n):
        img, hi = lap_split(img)
        levels.append(hi)
    levels.append(img)
    return levels[::-1] # List of images with lower and lower frequencies

def lap_merge(levels):
    '''Merge Laplacian pyramid'''
    img = levels[0]
    for hi in levels[1:]:
        with tf.name_scope('merge'):
            img = tf.nn.conv2d_transpose(img, k5x5*4, tf.shape(hi), [1,2,2,1]) + hi
    return img # Reconstructed image, all frequencies added back together

def normalize_std(img, eps=1e-10):
    '''Normalize image by making its standard deviation = 1.0'''
    with tf.name_scope('normalize'):
        std = tf.sqrt(tf.reduce_mean(tf.square(img)))
        return img/tf.maximum(std, eps)

def lap_normalize(img, scale_n=4):
    '''Perform the Laplacian pyramid normalization.'''
    img = tf.expand_dims(img,0)
    tlevels = lap_split_n(img, scale_n) # Split into frequencies
    tlevels = map(normalize_std, tlevels) # Normalize each frequency band
    out = lap_merge(tlevels) # Put image back together
    return out[0,:,:,:]

In [ ]:
# Showing the lap_normalize graph with TensorBoard
lap_graph = tf.Graph()
with lap_graph.as_default():
    lap_in = tf.placeholder(np.float32, name='lap_in')
    lap_out = lap_normalize(lap_in)
show_graph(lap_graph)

In [ ]: