Transfer Learning

Most of the time you won't want to train a whole convolutional network yourself. Modern ConvNets training on huge datasets like ImageNet take weeks on multiple GPUs. Instead, most people use a pretrained network either as a fixed feature extractor, or as an initial network to fine tune. In this notebook, you'll be using VGGNet trained on the ImageNet dataset as a feature extractor. Below is a diagram of the VGGNet architecture.

VGGNet is great because it's simple and has great performance, coming in second in the ImageNet competition. The idea here is that we keep all the convolutional layers, but replace the final fully connected layers with our own classifier. This way we can use VGGNet as a feature extractor for our images then easily train a simple classifier on top of that. What we'll do is take the first fully connected layer with 4096 units, including thresholding with ReLUs. We can use those values as a code for each image, then build a classifier on top of those codes.

You can read more about transfer learning from the CS231n course notes.

Pretrained VGGNet

We'll be using a pretrained network from https://github.com/machrisaa/tensorflow-vgg. This code is already included in 'tensorflow_vgg' directory, sdo you don't have to clone it.

This is a really nice implementation of VGGNet, quite easy to work with. The network has already been trained and the parameters are available from this link. You'll need to clone the repo into the folder containing this notebook. Then download the parameter file using the next cell.


In [1]:
from urllib.request import urlretrieve
from os.path import isfile, isdir
from tqdm import tqdm

vgg_dir = 'tensorflow_vgg/'
# Make sure vgg exists
if not isdir(vgg_dir):
    raise Exception("VGG directory doesn't exist!")

class DLProgress(tqdm):
    last_block = 0

    def hook(self, block_num=1, block_size=1, total_size=None):
        self.total = total_size
        self.update((block_num - self.last_block) * block_size)
        self.last_block = block_num

if not isfile(vgg_dir + "vgg16.npy"):
    with DLProgress(unit='B', unit_scale=True, miniters=1, desc='VGG16 Parameters') as pbar:
        urlretrieve(
            'https://s3.amazonaws.com/content.udacity-data.com/nd101/vgg16.npy',
            vgg_dir + 'vgg16.npy',
            pbar.hook)
else:
    print("Parameter file already exists!")


Parameter file already exists!

Flower power

Here we'll be using VGGNet to classify images of flowers. To get the flower dataset, run the cell below. This dataset comes from the TensorFlow inception tutorial.


In [2]:
import tarfile

dataset_folder_path = 'flower_photos'

class DLProgress(tqdm):
    last_block = 0

    def hook(self, block_num=1, block_size=1, total_size=None):
        self.total = total_size
        self.update((block_num - self.last_block) * block_size)
        self.last_block = block_num

if not isfile('flower_photos.tar.gz'):
    with DLProgress(unit='B', unit_scale=True, miniters=1, desc='Flowers Dataset') as pbar:
        urlretrieve(
            'http://download.tensorflow.org/example_images/flower_photos.tgz',
            'flower_photos.tar.gz',
            pbar.hook)

if not isdir(dataset_folder_path):
    with tarfile.open('flower_photos.tar.gz') as tar:
        tar.extractall()
        tar.close()


Flowers Dataset: 229MB [01:21, 2.80MB/s]                           

ConvNet Codes

Below, we'll run through all the images in our dataset and get codes for each of them. That is, we'll run the images through the VGGNet convolutional layers and record the values of the first fully connected layer. We can then write these to a file for later when we build our own classifier.

Here we're using the vgg16 module from tensorflow_vgg. The network takes images of size $224 \times 224 \times 3$ as input. Then it has 5 sets of convolutional layers. The network implemented here has this structure (copied from the source code):

self.conv1_1 = self.conv_layer(bgr, "conv1_1")
self.conv1_2 = self.conv_layer(self.conv1_1, "conv1_2")
self.pool1 = self.max_pool(self.conv1_2, 'pool1')

self.conv2_1 = self.conv_layer(self.pool1, "conv2_1")
self.conv2_2 = self.conv_layer(self.conv2_1, "conv2_2")
self.pool2 = self.max_pool(self.conv2_2, 'pool2')

self.conv3_1 = self.conv_layer(self.pool2, "conv3_1")
self.conv3_2 = self.conv_layer(self.conv3_1, "conv3_2")
self.conv3_3 = self.conv_layer(self.conv3_2, "conv3_3")
self.pool3 = self.max_pool(self.conv3_3, 'pool3')

self.conv4_1 = self.conv_layer(self.pool3, "conv4_1")
self.conv4_2 = self.conv_layer(self.conv4_1, "conv4_2")
self.conv4_3 = self.conv_layer(self.conv4_2, "conv4_3")
self.pool4 = self.max_pool(self.conv4_3, 'pool4')

self.conv5_1 = self.conv_layer(self.pool4, "conv5_1")
self.conv5_2 = self.conv_layer(self.conv5_1, "conv5_2")
self.conv5_3 = self.conv_layer(self.conv5_2, "conv5_3")
self.pool5 = self.max_pool(self.conv5_3, 'pool5')

self.fc6 = self.fc_layer(self.pool5, "fc6")
self.relu6 = tf.nn.relu(self.fc6)

So what we want are the values of the first fully connected layer, after being ReLUd (self.relu6). To build the network, we use

with tf.Session() as sess:
    vgg = vgg16.Vgg16()
    input_ = tf.placeholder(tf.float32, [None, 224, 224, 3])
    with tf.name_scope("content_vgg"):
        vgg.build(input_)

This creates the vgg object, then builds the graph with vgg.build(input_). Then to get the values from the layer,

feed_dict = {input_: images}
codes = sess.run(vgg.relu6, feed_dict=feed_dict)

In [3]:
import os

import numpy as np
import tensorflow as tf

from tensorflow_vgg import vgg16
from tensorflow_vgg import utils

In [4]:
data_dir = 'flower_photos/'
contents = os.listdir(data_dir)
classes = [each for each in contents if os.path.isdir(data_dir + each)]

Below I'm running images through the VGG network in batches.

Exercise: Below, build the VGG network. Also get the codes from the first fully connected layer (make sure you get the ReLUd values).


In [5]:
# Set the batch size higher if you can fit in in your GPU memory
batch_size = 10
codes_list = []
labels = []
batch = []

codes = None

with tf.Session() as sess:
    
    # TODO: Build the vgg network here
    vgg = vgg16.Vgg16()
    input_ = tf.placeholder(tf.float32, [None, 224, 224, 3])
    with tf.name_scope("content_vgg"):
        vgg.build(input_)

    for each in classes:
        print("Starting {} images".format(each))
        class_path = data_dir + each
        files = os.listdir(class_path)
        for ii, file in enumerate(files, 1):
            # Add images to the current batch
            # utils.load_image crops the input images for us, from the center
            img = utils.load_image(os.path.join(class_path, file))
            batch.append(img.reshape((1, 224, 224, 3)))
            labels.append(each)
            
            # Running the batch through the network to get the codes
            if ii % batch_size == 0 or ii == len(files):
                
                # Image batch to pass to VGG network
                images = np.concatenate(batch)
                
                # TODO: Get the values from the relu6 layer of the VGG network
                codes_batch = sess.run(vgg.relu6, feed_dict={input_ : images})
                
                # Here I'm building an array of the codes
                if codes is None:
                    codes = codes_batch
                else:
                    codes = np.concatenate((codes, codes_batch))
                
                # Reset to start building the next batch
                batch = []
                print('{} images processed'.format(ii))


/Users/ggururaj/ml/deep-learning/transfer-learning/tensorflow_vgg/vgg16.npy
npy file loaded
build model started
build model finished: 0s
Starting daisy images
10 images processed
20 images processed
30 images processed
40 images processed
50 images processed
60 images processed
70 images processed
80 images processed
90 images processed
100 images processed
110 images processed
120 images processed
130 images processed
140 images processed
150 images processed
160 images processed
170 images processed
180 images processed
190 images processed
200 images processed
210 images processed
220 images processed
230 images processed
240 images processed
250 images processed
260 images processed
270 images processed
280 images processed
290 images processed
300 images processed
310 images processed
320 images processed
330 images processed
340 images processed
350 images processed
360 images processed
370 images processed
380 images processed
390 images processed
400 images processed
410 images processed
420 images processed
430 images processed
440 images processed
450 images processed
460 images processed
470 images processed
480 images processed
490 images processed
500 images processed
510 images processed
520 images processed
530 images processed
540 images processed
550 images processed
560 images processed
570 images processed
580 images processed
590 images processed
600 images processed
610 images processed
620 images processed
630 images processed
633 images processed
Starting dandelion images
10 images processed
20 images processed
30 images processed
40 images processed
50 images processed
60 images processed
70 images processed
80 images processed
90 images processed
100 images processed
110 images processed
120 images processed
130 images processed
140 images processed
150 images processed
160 images processed
170 images processed
180 images processed
190 images processed
200 images processed
210 images processed
220 images processed
230 images processed
240 images processed
250 images processed
260 images processed
270 images processed
280 images processed
290 images processed
300 images processed
310 images processed
320 images processed
330 images processed
340 images processed
350 images processed
360 images processed
370 images processed
380 images processed
390 images processed
400 images processed
410 images processed
420 images processed
430 images processed
440 images processed
450 images processed
460 images processed
470 images processed
480 images processed
490 images processed
500 images processed
510 images processed
520 images processed
530 images processed
540 images processed
550 images processed
560 images processed
570 images processed
580 images processed
590 images processed
600 images processed
610 images processed
620 images processed
630 images processed
640 images processed
650 images processed
660 images processed
670 images processed
680 images processed
690 images processed
700 images processed
710 images processed
720 images processed
730 images processed
740 images processed
750 images processed
760 images processed
770 images processed
780 images processed
790 images processed
800 images processed
810 images processed
820 images processed
830 images processed
840 images processed
850 images processed
860 images processed
870 images processed
880 images processed
890 images processed
898 images processed
Starting roses images
10 images processed
20 images processed
30 images processed
40 images processed
50 images processed
60 images processed
70 images processed
80 images processed
90 images processed
100 images processed
110 images processed
120 images processed
130 images processed
140 images processed
150 images processed
160 images processed
170 images processed
180 images processed
190 images processed
200 images processed
210 images processed
220 images processed
230 images processed
240 images processed
250 images processed
260 images processed
270 images processed
280 images processed
290 images processed
300 images processed
310 images processed
320 images processed
330 images processed
340 images processed
350 images processed
360 images processed
370 images processed
380 images processed
390 images processed
400 images processed
410 images processed
420 images processed
430 images processed
440 images processed
450 images processed
460 images processed
470 images processed
480 images processed
490 images processed
500 images processed
510 images processed
520 images processed
530 images processed
540 images processed
550 images processed
560 images processed
570 images processed
580 images processed
590 images processed
600 images processed
610 images processed
620 images processed
630 images processed
640 images processed
641 images processed
Starting sunflowers images
10 images processed
20 images processed
30 images processed
40 images processed
50 images processed
60 images processed
70 images processed
80 images processed
90 images processed
100 images processed
110 images processed
120 images processed
130 images processed
140 images processed
150 images processed
160 images processed
170 images processed
180 images processed
190 images processed
200 images processed
210 images processed
220 images processed
230 images processed
240 images processed
250 images processed
260 images processed
270 images processed
280 images processed
290 images processed
300 images processed
310 images processed
320 images processed
330 images processed
340 images processed
350 images processed
360 images processed
370 images processed
380 images processed
390 images processed
400 images processed
410 images processed
420 images processed
430 images processed
440 images processed
450 images processed
460 images processed
470 images processed
480 images processed
490 images processed
500 images processed
510 images processed
520 images processed
530 images processed
540 images processed
550 images processed
560 images processed
570 images processed
580 images processed
590 images processed
600 images processed
610 images processed
620 images processed
630 images processed
640 images processed
650 images processed
660 images processed
670 images processed
680 images processed
690 images processed
699 images processed
Starting tulips images
10 images processed
20 images processed
30 images processed
40 images processed
50 images processed
60 images processed
70 images processed
80 images processed
90 images processed
100 images processed
110 images processed
120 images processed
130 images processed
140 images processed
150 images processed
160 images processed
170 images processed
180 images processed
190 images processed
200 images processed
210 images processed
220 images processed
230 images processed
240 images processed
250 images processed
260 images processed
270 images processed
280 images processed
290 images processed
300 images processed
310 images processed
320 images processed
330 images processed
340 images processed
350 images processed
360 images processed
370 images processed
380 images processed
390 images processed
400 images processed
410 images processed
420 images processed
430 images processed
440 images processed
450 images processed
460 images processed
470 images processed
480 images processed
490 images processed
500 images processed
510 images processed
520 images processed
530 images processed
540 images processed
550 images processed
560 images processed
570 images processed
580 images processed
590 images processed
600 images processed
610 images processed
620 images processed
630 images processed
640 images processed
650 images processed
660 images processed
670 images processed
680 images processed
690 images processed
700 images processed
710 images processed
720 images processed
730 images processed
740 images processed
750 images processed
760 images processed
770 images processed
780 images processed
790 images processed
799 images processed

In [6]:
# write codes to file
with open('codes', 'w') as f:
    codes.tofile(f)
    
# write labels to file
import csv
with open('labels', 'w') as f:
    writer = csv.writer(f, delimiter='\n')
    writer.writerow(labels)

Building the Classifier

Now that we have codes for all the images, we can build a simple classifier on top of them. The codes behave just like normal input into a simple neural network. Below I'm going to have you do most of the work.


In [7]:
# read codes and labels from file
import csv

with open('labels') as f:
    reader = csv.reader(f, delimiter='\n')
    labels = np.array([each for each in reader if len(each) > 0]).squeeze()
with open('codes') as f:
    codes = np.fromfile(f, dtype=np.float32)
    codes = codes.reshape((len(labels), -1))

In [23]:
codes[0:3]


Out[23]:
array([[  0.        ,   8.27728939,   4.82542372, ...,   0.        ,
          0.        ,   2.73614955],
       [  0.        ,  22.90328407,   0.        , ...,   0.        ,
          0.        ,   0.        ],
       [  0.        ,   0.        ,   8.11145496, ...,   0.        ,
          1.11438441,   0.        ]], dtype=float32)

Data prep

As usual, now we need to one-hot encode our labels and create validation/test sets. First up, creating our labels!

Exercise: From scikit-learn, use LabelBinarizer to create one-hot encoded vectors from the labels.


In [54]:
from sklearn.preprocessing import LabelBinarizer
lb = LabelBinarizer()
lb.fit(labels)

labels_vecs = lb.transform(labels)# Your one-hot encoded labels array here

Now you'll want to create your training, validation, and test sets. An important thing to note here is that our labels and data aren't randomized yet. We'll want to shuffle our data so the validation and test sets contain data from all classes. Otherwise, you could end up with testing sets that are all one class. Typically, you'll also want to make sure that each smaller set has the same the distribution of classes as it is for the whole data set. The easiest way to accomplish both these goals is to use StratifiedShuffleSplit from scikit-learn.

You can create the splitter like so:

ss = StratifiedShuffleSplit(n_splits=1, test_size=0.2)

Then split the data with

splitter = ss.split(x, y)

ss.split returns a generator of indices. You can pass the indices into the arrays to get the split sets. The fact that it's a generator means you either need to iterate over it, or use next(splitter) to get the indices. Be sure to read the documentation and the user guide.

Exercise: Use StratifiedShuffleSplit to split the codes and labels into training, validation, and test sets.


In [55]:
from sklearn.model_selection import StratifiedShuffleSplit

ss = StratifiedShuffleSplit(n_splits=1, test_size=0.2)

train_idx, val_idx = next(ss.split(codes, labels))

half_val_len = int(len(val_idx)/2)
val_idx, test_idx = val_idx[:half_val_len], val_idx[half_val_len:]

train_x, train_y = codes[train_idx], labels_vecs[train_idx]
val_x, val_y = codes[val_idx], labels_vecs[val_idx]
test_x, test_y = codes[test_idx], labels_vecs[test_idx]

In [56]:
print("Train shapes (x, y):", train_x.shape, train_y.shape)
print("Validation shapes (x, y):", val_x.shape, val_y.shape)
print("Test shapes (x, y):", test_x.shape, test_y.shape)


Train shapes (x, y): (2936, 4096) (2936, 5)
Validation shapes (x, y): (367, 4096) (367, 5)
Test shapes (x, y): (367, 4096) (367, 5)

If you did it right, you should see these sizes for the training sets:

Train shapes (x, y): (2936, 4096) (2936, 5)
Validation shapes (x, y): (367, 4096) (367, 5)
Test shapes (x, y): (367, 4096) (367, 5)

Classifier layers

Once you have the convolutional codes, you just need to build a classfier from some fully connected layers. You use the codes as the inputs and the image labels as targets. Otherwise the classifier is a typical neural network.

Exercise: With the codes and labels loaded, build the classifier. Consider the codes as your inputs, each of them are 4096D vectors. You'll want to use a hidden layer and an output layer as your classifier. Remember that the output layer needs to have one unit for each class and a softmax activation function. Use the cross entropy to calculate the cost.


In [77]:
inputs_ = tf.placeholder(tf.float32, shape=[None, codes.shape[1]])
labels_ = tf.placeholder(tf.int64, shape=[None, labels_vecs.shape[1]])

# TODO: Classifier layers and operations
fc1 = tf.layers.dense(inputs=inputs_, units=128, activation=tf.nn.relu)

logits = logits = tf.layers.dense(inputs=fc1, units=5, activation=None)# output layer logits
entropy = tf.losses.softmax_cross_entropy(onehot_labels=labels_, logits=logits)# cross entropy loss

cost = tf.reduce_mean(entropy)

optimizer = tf.train.AdamOptimizer(0.001).minimize(cost) # training optimizer

# Operations for validation/test accuracy
predicted = tf.nn.softmax(logits)
correct_pred = tf.equal(tf.argmax(predicted, 1), tf.argmax(labels_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))

Batches!

Here is just a simple way to do batches. I've written it so that it includes all the data. Sometimes you'll throw out some data at the end to make sure you have full batches. Here I just extend the last batch to include the remaining data.


In [78]:
def get_batches(x, y, n_batches=10):
    """ Return a generator that yields batches from arrays x and y. """
    batch_size = len(x)//n_batches
    
    for ii in range(0, n_batches*batch_size, batch_size):
        # If we're not on the last batch, grab data with size batch_size
        if ii != (n_batches-1)*batch_size:
            X, Y = x[ii: ii+batch_size], y[ii: ii+batch_size] 
        # On the last batch, grab the rest of the data
        else:
            X, Y = x[ii:], y[ii:]
        # I love generators
        yield X, Y

Training

Here, we'll train the network.

Exercise: So far we've been providing the training code for you. Here, I'm going to give you a bit more of a challenge and have you write the code to train the network. Of course, you'll be able to see my solution if you need help. Use the get_batches function I wrote before to get your batches like for x, y in get_batches(train_x, train_y). Or write your own!


In [80]:
saver = tf.train.Saver()
with tf.Session() as sess:
    epochs = 10
    sess.run(tf.global_variables_initializer())
    for e in range(epochs):
        for x, y in get_batches(train_x, train_y):
            batch_cost, _, batch_acc = sess.run([cost, optimizer, accuracy], feed_dict={inputs_: x,
                                                             labels_: y})
            print("Epoch: {}/{}...".format(e+1, epochs),
              "Training loss: {:.4f}".format(batch_cost),
                "Accuracy: {:.4f}".format(batch_acc))

    # TODO: Your training code here
    saver.save(sess, "checkpoints/flowers.ckpt")


Epoch: 1/10... Training loss: 9.2033 Accuracy: 0.2082
Epoch: 1/10... Training loss: 11.9687 Accuracy: 0.2423
Epoch: 1/10... Training loss: 16.5342 Accuracy: 0.2696
Epoch: 1/10... Training loss: 11.8486 Accuracy: 0.3413
Epoch: 1/10... Training loss: 6.5876 Accuracy: 0.4608
Epoch: 1/10... Training loss: 4.8562 Accuracy: 0.5017
Epoch: 1/10... Training loss: 4.9963 Accuracy: 0.5188
Epoch: 1/10... Training loss: 4.3653 Accuracy: 0.5119
Epoch: 1/10... Training loss: 2.2250 Accuracy: 0.6519
Epoch: 1/10... Training loss: 1.5864 Accuracy: 0.6990
Epoch: 2/10... Training loss: 0.8865 Accuracy: 0.8191
Epoch: 2/10... Training loss: 0.7767 Accuracy: 0.8089
Epoch: 2/10... Training loss: 0.9559 Accuracy: 0.7509
Epoch: 2/10... Training loss: 0.9942 Accuracy: 0.7543
Epoch: 2/10... Training loss: 0.7940 Accuracy: 0.7713
Epoch: 2/10... Training loss: 0.8185 Accuracy: 0.7747
Epoch: 2/10... Training loss: 0.7902 Accuracy: 0.7406
Epoch: 2/10... Training loss: 0.7208 Accuracy: 0.7782
Epoch: 2/10... Training loss: 0.6393 Accuracy: 0.8055
Epoch: 2/10... Training loss: 0.6564 Accuracy: 0.7726
Epoch: 3/10... Training loss: 0.4585 Accuracy: 0.8430
Epoch: 3/10... Training loss: 0.4699 Accuracy: 0.8191
Epoch: 3/10... Training loss: 0.5500 Accuracy: 0.8225
Epoch: 3/10... Training loss: 0.5471 Accuracy: 0.8294
Epoch: 3/10... Training loss: 0.4702 Accuracy: 0.7850
Epoch: 3/10... Training loss: 0.4499 Accuracy: 0.8157
Epoch: 3/10... Training loss: 0.5168 Accuracy: 0.8294
Epoch: 3/10... Training loss: 0.3890 Accuracy: 0.8703
Epoch: 3/10... Training loss: 0.3374 Accuracy: 0.8635
Epoch: 3/10... Training loss: 0.4032 Accuracy: 0.8629
Epoch: 4/10... Training loss: 0.3039 Accuracy: 0.8840
Epoch: 4/10... Training loss: 0.2926 Accuracy: 0.9044
Epoch: 4/10... Training loss: 0.3619 Accuracy: 0.8396
Epoch: 4/10... Training loss: 0.3734 Accuracy: 0.8669
Epoch: 4/10... Training loss: 0.3003 Accuracy: 0.8874
Epoch: 4/10... Training loss: 0.2856 Accuracy: 0.8771
Epoch: 4/10... Training loss: 0.3192 Accuracy: 0.8771
Epoch: 4/10... Training loss: 0.3336 Accuracy: 0.8703
Epoch: 4/10... Training loss: 0.2496 Accuracy: 0.9078
Epoch: 4/10... Training loss: 0.3120 Accuracy: 0.8997
Epoch: 5/10... Training loss: 0.2122 Accuracy: 0.9317
Epoch: 5/10... Training loss: 0.2352 Accuracy: 0.9215
Epoch: 5/10... Training loss: 0.2429 Accuracy: 0.9181
Epoch: 5/10... Training loss: 0.3274 Accuracy: 0.8908
Epoch: 5/10... Training loss: 0.2515 Accuracy: 0.9078
Epoch: 5/10... Training loss: 0.2138 Accuracy: 0.9181
Epoch: 5/10... Training loss: 0.2311 Accuracy: 0.9044
Epoch: 5/10... Training loss: 0.2299 Accuracy: 0.9181
Epoch: 5/10... Training loss: 0.1853 Accuracy: 0.9317
Epoch: 5/10... Training loss: 0.2335 Accuracy: 0.9197
Epoch: 6/10... Training loss: 0.1594 Accuracy: 0.9556
Epoch: 6/10... Training loss: 0.1597 Accuracy: 0.9386
Epoch: 6/10... Training loss: 0.1741 Accuracy: 0.9420
Epoch: 6/10... Training loss: 0.2329 Accuracy: 0.9181
Epoch: 6/10... Training loss: 0.1602 Accuracy: 0.9488
Epoch: 6/10... Training loss: 0.1716 Accuracy: 0.9249
Epoch: 6/10... Training loss: 0.1735 Accuracy: 0.9352
Epoch: 6/10... Training loss: 0.2038 Accuracy: 0.9249
Epoch: 6/10... Training loss: 0.1358 Accuracy: 0.9556
Epoch: 6/10... Training loss: 0.1854 Accuracy: 0.9465
Epoch: 7/10... Training loss: 0.1240 Accuracy: 0.9659
Epoch: 7/10... Training loss: 0.1162 Accuracy: 0.9625
Epoch: 7/10... Training loss: 0.1208 Accuracy: 0.9590
Epoch: 7/10... Training loss: 0.1750 Accuracy: 0.9454
Epoch: 7/10... Training loss: 0.1282 Accuracy: 0.9590
Epoch: 7/10... Training loss: 0.1312 Accuracy: 0.9590
Epoch: 7/10... Training loss: 0.1274 Accuracy: 0.9522
Epoch: 7/10... Training loss: 0.1459 Accuracy: 0.9488
Epoch: 7/10... Training loss: 0.1036 Accuracy: 0.9625
Epoch: 7/10... Training loss: 0.1445 Accuracy: 0.9666
Epoch: 8/10... Training loss: 0.0966 Accuracy: 0.9761
Epoch: 8/10... Training loss: 0.0844 Accuracy: 0.9727
Epoch: 8/10... Training loss: 0.0931 Accuracy: 0.9795
Epoch: 8/10... Training loss: 0.1288 Accuracy: 0.9727
Epoch: 8/10... Training loss: 0.1028 Accuracy: 0.9795
Epoch: 8/10... Training loss: 0.1083 Accuracy: 0.9659
Epoch: 8/10... Training loss: 0.0957 Accuracy: 0.9659
Epoch: 8/10... Training loss: 0.1156 Accuracy: 0.9625
Epoch: 8/10... Training loss: 0.0749 Accuracy: 0.9761
Epoch: 8/10... Training loss: 0.1167 Accuracy: 0.9732
Epoch: 9/10... Training loss: 0.0753 Accuracy: 0.9863
Epoch: 9/10... Training loss: 0.0676 Accuracy: 0.9863
Epoch: 9/10... Training loss: 0.0743 Accuracy: 0.9863
Epoch: 9/10... Training loss: 0.1028 Accuracy: 0.9829
Epoch: 9/10... Training loss: 0.0823 Accuracy: 0.9863
Epoch: 9/10... Training loss: 0.0885 Accuracy: 0.9761
Epoch: 9/10... Training loss: 0.0743 Accuracy: 0.9863
Epoch: 9/10... Training loss: 0.0853 Accuracy: 0.9761
Epoch: 9/10... Training loss: 0.0577 Accuracy: 0.9761
Epoch: 9/10... Training loss: 0.0967 Accuracy: 0.9833
Epoch: 10/10... Training loss: 0.0540 Accuracy: 0.9863
Epoch: 10/10... Training loss: 0.0503 Accuracy: 0.9898
Epoch: 10/10... Training loss: 0.0592 Accuracy: 0.9898
Epoch: 10/10... Training loss: 0.0813 Accuracy: 0.9863
Epoch: 10/10... Training loss: 0.0652 Accuracy: 0.9898
Epoch: 10/10... Training loss: 0.0753 Accuracy: 0.9761
Epoch: 10/10... Training loss: 0.0603 Accuracy: 0.9898
Epoch: 10/10... Training loss: 0.0679 Accuracy: 0.9795
Epoch: 10/10... Training loss: 0.0460 Accuracy: 0.9829
Epoch: 10/10... Training loss: 0.0809 Accuracy: 0.9833

Testing

Below you see the test accuracy. You can also see the predictions returned for images.


In [81]:
with tf.Session() as sess:
    saver.restore(sess, tf.train.latest_checkpoint('checkpoints'))
    
    feed = {inputs_: test_x,
            labels_: test_y}
    test_acc = sess.run(accuracy, feed_dict=feed)
    print("Test accuracy: {:.4f}".format(test_acc))


INFO:tensorflow:Restoring parameters from checkpoints/flowers.ckpt
Test accuracy: 0.8747

In [82]:
%matplotlib inline

import matplotlib.pyplot as plt
from scipy.ndimage import imread

Below, feel free to choose images and see how the trained classifier predicts the flowers in them.


In [83]:
test_img_path = 'flower_photos/roses/10894627425_ec76bbc757_n.jpg'
test_img = imread(test_img_path)
plt.imshow(test_img)


Out[83]:
<matplotlib.image.AxesImage at 0x192039a20>

In [ ]:
# Run this cell if you don't have a vgg graph built
if 'vgg' in globals():
    print('"vgg" object already exists.  Will not create again.')
else:
    #create vgg
    with tf.Session() as sess:
        input_ = tf.placeholder(tf.float32, [None, 224, 224, 3])
        vgg = vgg16.Vgg16()
        vgg.build(input_)

In [84]:
with tf.Session() as sess:
    img = utils.load_image(test_img_path)
    img = img.reshape((1, 224, 224, 3))

    feed_dict = {input_: img}
    code = sess.run(vgg.relu6, feed_dict=feed_dict)
        
saver = tf.train.Saver()
with tf.Session() as sess:
    saver.restore(sess, tf.train.latest_checkpoint('checkpoints'))
    
    feed = {inputs_: code}
    prediction = sess.run(predicted, feed_dict=feed).squeeze()


INFO:tensorflow:Restoring parameters from checkpoints/flowers.ckpt

In [85]:
plt.imshow(test_img)


Out[85]:
<matplotlib.image.AxesImage at 0x196b36cf8>

In [86]:
plt.barh(np.arange(5), prediction)
_ = plt.yticks(np.arange(5), lb.classes_)



In [ ]: