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()

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 [1]:
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
#import gc

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_)

    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
                feed_dict = {input_: images}
                codes_batch = sess.run(vgg.relu6, feed_dict=feed_dict)
                
                # 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 = []
                #gc.collect()
                print('{} images processed'.format(ii))


/home/carnd/transfer-learning/tensorflow_vgg/vgg16.npy
npy file loaded
build model started
build model finished: 0s
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 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 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
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

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 [2]:
# 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))

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 [3]:
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 [4]:
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 = len(val_idx)//2
val_idx, test_idx = val_idx[:half], val_idx[half:]

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 [5]:
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 [25]:
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

hidden_units = 256
fc = tf.contrib.layers.fully_connected(inputs_, hidden_units)

logits = tf.contrib.layers.fully_connected(fc, labels_vecs.shape[1], activation_fn=None)
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=labels_)
cost = tf.reduce_mean(cross_entropy)

optimizer = tf.train.AdamOptimizer().minimize(cost)

# 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 [7]:
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 [30]:
epochs = 20
batch_n = 0
saver = tf.train.Saver()
with tf.Session() as sess:
    
    sess.run(tf.global_variables_initializer())
    for e in range(epochs):
        for batch_x, batch_y in get_batches(train_x, train_y):
            feed = {inputs_: batch_x, labels_: batch_y}
            loss, _ = sess.run([cost, optimizer], feed_dict=feed)
            print("Epoch: {}/{}".format(e+1, epochs),
                  "Iteration: {}".format(batch_n),
                  "Training loss: {:.5f}".format(loss))
            if batch_n%5 == 0:
                feed = {inputs_: val_x, labels_: val_y}
                acc = sess.run(accuracy, feed_dict=feed)
                print("Epoch: {}/{}".format(e+1, epochs),
                  "Iteration: {}".format(batch_n),
                  "Validation accuracy: {:.5f}".format(acc))
            batch_n += 1
        
    saver.save(sess, "checkpoints/flowers.ckpt")


Epoch: 1/20 Iteration: 0 Training loss: 7.08549
Epoch: 1/20 Iteration: 0 Validation accuracy: 0.30245
Epoch: 1/20 Iteration: 1 Training loss: 17.78593
Epoch: 1/20 Iteration: 2 Training loss: 17.04443
Epoch: 1/20 Iteration: 3 Training loss: 5.77578
Epoch: 1/20 Iteration: 4 Training loss: 5.75394
Epoch: 1/20 Iteration: 5 Training loss: 3.88733
Epoch: 1/20 Iteration: 5 Validation accuracy: 0.65123
Epoch: 1/20 Iteration: 6 Training loss: 3.80693
Epoch: 1/20 Iteration: 7 Training loss: 3.45670
Epoch: 1/20 Iteration: 8 Training loss: 3.49217
Epoch: 1/20 Iteration: 9 Training loss: 1.47856
Epoch: 2/20 Iteration: 10 Training loss: 1.03618
Epoch: 2/20 Iteration: 10 Validation accuracy: 0.80654
Epoch: 2/20 Iteration: 11 Training loss: 0.73631
Epoch: 2/20 Iteration: 12 Training loss: 0.87972
Epoch: 2/20 Iteration: 13 Training loss: 1.04164
Epoch: 2/20 Iteration: 14 Training loss: 0.79590
Epoch: 2/20 Iteration: 15 Training loss: 1.17501
Epoch: 2/20 Iteration: 15 Validation accuracy: 0.79564
Epoch: 2/20 Iteration: 16 Training loss: 1.10661
Epoch: 2/20 Iteration: 17 Training loss: 1.00909
Epoch: 2/20 Iteration: 18 Training loss: 1.25361
Epoch: 2/20 Iteration: 19 Training loss: 0.67814
Epoch: 3/20 Iteration: 20 Training loss: 0.58689
Epoch: 3/20 Iteration: 20 Validation accuracy: 0.78747
Epoch: 3/20 Iteration: 21 Training loss: 0.49069
Epoch: 3/20 Iteration: 22 Training loss: 0.46562
Epoch: 3/20 Iteration: 23 Training loss: 0.44582
Epoch: 3/20 Iteration: 24 Training loss: 0.42552
Epoch: 3/20 Iteration: 25 Training loss: 0.37806
Epoch: 3/20 Iteration: 25 Validation accuracy: 0.83924
Epoch: 3/20 Iteration: 26 Training loss: 0.34888
Epoch: 3/20 Iteration: 27 Training loss: 0.35634
Epoch: 3/20 Iteration: 28 Training loss: 0.45944
Epoch: 3/20 Iteration: 29 Training loss: 0.28749
Epoch: 4/20 Iteration: 30 Training loss: 0.38091
Epoch: 4/20 Iteration: 30 Validation accuracy: 0.83106
Epoch: 4/20 Iteration: 31 Training loss: 0.30180
Epoch: 4/20 Iteration: 32 Training loss: 0.38446
Epoch: 4/20 Iteration: 33 Training loss: 0.37542
Epoch: 4/20 Iteration: 34 Training loss: 0.31471
Epoch: 4/20 Iteration: 35 Training loss: 0.27721
Epoch: 4/20 Iteration: 35 Validation accuracy: 0.84469
Epoch: 4/20 Iteration: 36 Training loss: 0.22170
Epoch: 4/20 Iteration: 37 Training loss: 0.24902
Epoch: 4/20 Iteration: 38 Training loss: 0.26913
Epoch: 4/20 Iteration: 39 Training loss: 0.17221
Epoch: 5/20 Iteration: 40 Training loss: 0.19827
Epoch: 5/20 Iteration: 40 Validation accuracy: 0.87193
Epoch: 5/20 Iteration: 41 Training loss: 0.20603
Epoch: 5/20 Iteration: 42 Training loss: 0.20841
Epoch: 5/20 Iteration: 43 Training loss: 0.23723
Epoch: 5/20 Iteration: 44 Training loss: 0.21453
Epoch: 5/20 Iteration: 45 Training loss: 0.22535
Epoch: 5/20 Iteration: 45 Validation accuracy: 0.85831
Epoch: 5/20 Iteration: 46 Training loss: 0.16106
Epoch: 5/20 Iteration: 47 Training loss: 0.19311
Epoch: 5/20 Iteration: 48 Training loss: 0.22762
Epoch: 5/20 Iteration: 49 Training loss: 0.13633
Epoch: 6/20 Iteration: 50 Training loss: 0.14477
Epoch: 6/20 Iteration: 50 Validation accuracy: 0.87738
Epoch: 6/20 Iteration: 51 Training loss: 0.15443
Epoch: 6/20 Iteration: 52 Training loss: 0.14694
Epoch: 6/20 Iteration: 53 Training loss: 0.17593
Epoch: 6/20 Iteration: 54 Training loss: 0.15025
Epoch: 6/20 Iteration: 55 Training loss: 0.12753
Epoch: 6/20 Iteration: 55 Validation accuracy: 0.88283
Epoch: 6/20 Iteration: 56 Training loss: 0.11509
Epoch: 6/20 Iteration: 57 Training loss: 0.15156
Epoch: 6/20 Iteration: 58 Training loss: 0.15627
Epoch: 6/20 Iteration: 59 Training loss: 0.10442
Epoch: 7/20 Iteration: 60 Training loss: 0.10588
Epoch: 7/20 Iteration: 60 Validation accuracy: 0.89373
Epoch: 7/20 Iteration: 61 Training loss: 0.10834
Epoch: 7/20 Iteration: 62 Training loss: 0.11687
Epoch: 7/20 Iteration: 63 Training loss: 0.13877
Epoch: 7/20 Iteration: 64 Training loss: 0.11782
Epoch: 7/20 Iteration: 65 Training loss: 0.09121
Epoch: 7/20 Iteration: 65 Validation accuracy: 0.88828
Epoch: 7/20 Iteration: 66 Training loss: 0.08120
Epoch: 7/20 Iteration: 67 Training loss: 0.10979
Epoch: 7/20 Iteration: 68 Training loss: 0.12132
Epoch: 7/20 Iteration: 69 Training loss: 0.07661
Epoch: 8/20 Iteration: 70 Training loss: 0.07955
Epoch: 8/20 Iteration: 70 Validation accuracy: 0.88828
Epoch: 8/20 Iteration: 71 Training loss: 0.08265
Epoch: 8/20 Iteration: 72 Training loss: 0.07933
Epoch: 8/20 Iteration: 73 Training loss: 0.10393
Epoch: 8/20 Iteration: 74 Training loss: 0.09044
Epoch: 8/20 Iteration: 75 Training loss: 0.06829
Epoch: 8/20 Iteration: 75 Validation accuracy: 0.90463
Epoch: 8/20 Iteration: 76 Training loss: 0.05971
Epoch: 8/20 Iteration: 77 Training loss: 0.07982
Epoch: 8/20 Iteration: 78 Training loss: 0.09004
Epoch: 8/20 Iteration: 79 Training loss: 0.06260
Epoch: 9/20 Iteration: 80 Training loss: 0.06315
Epoch: 9/20 Iteration: 80 Validation accuracy: 0.90191
Epoch: 9/20 Iteration: 81 Training loss: 0.06429
Epoch: 9/20 Iteration: 82 Training loss: 0.06183
Epoch: 9/20 Iteration: 83 Training loss: 0.08061
Epoch: 9/20 Iteration: 84 Training loss: 0.07352
Epoch: 9/20 Iteration: 85 Training loss: 0.05208
Epoch: 9/20 Iteration: 85 Validation accuracy: 0.90463
Epoch: 9/20 Iteration: 86 Training loss: 0.04558
Epoch: 9/20 Iteration: 87 Training loss: 0.06027
Epoch: 9/20 Iteration: 88 Training loss: 0.06908
Epoch: 9/20 Iteration: 89 Training loss: 0.04571
Epoch: 10/20 Iteration: 90 Training loss: 0.04715
Epoch: 10/20 Iteration: 90 Validation accuracy: 0.90463
Epoch: 10/20 Iteration: 91 Training loss: 0.04805
Epoch: 10/20 Iteration: 92 Training loss: 0.05120
Epoch: 10/20 Iteration: 93 Training loss: 0.06025
Epoch: 10/20 Iteration: 94 Training loss: 0.05879
Epoch: 10/20 Iteration: 95 Training loss: 0.04169
Epoch: 10/20 Iteration: 95 Validation accuracy: 0.90736
Epoch: 10/20 Iteration: 96 Training loss: 0.03511
Epoch: 10/20 Iteration: 97 Training loss: 0.04735
Epoch: 10/20 Iteration: 98 Training loss: 0.05109
Epoch: 10/20 Iteration: 99 Training loss: 0.03627
Epoch: 11/20 Iteration: 100 Training loss: 0.03577
Epoch: 11/20 Iteration: 100 Validation accuracy: 0.90736
Epoch: 11/20 Iteration: 101 Training loss: 0.03723
Epoch: 11/20 Iteration: 102 Training loss: 0.04062
Epoch: 11/20 Iteration: 103 Training loss: 0.04630
Epoch: 11/20 Iteration: 104 Training loss: 0.04891
Epoch: 11/20 Iteration: 105 Training loss: 0.03350
Epoch: 11/20 Iteration: 105 Validation accuracy: 0.90463
Epoch: 11/20 Iteration: 106 Training loss: 0.02612
Epoch: 11/20 Iteration: 107 Training loss: 0.03615
Epoch: 11/20 Iteration: 108 Training loss: 0.04167
Epoch: 11/20 Iteration: 109 Training loss: 0.02961
Epoch: 12/20 Iteration: 110 Training loss: 0.02713
Epoch: 12/20 Iteration: 110 Validation accuracy: 0.90463
Epoch: 12/20 Iteration: 111 Training loss: 0.02805
Epoch: 12/20 Iteration: 112 Training loss: 0.03302
Epoch: 12/20 Iteration: 113 Training loss: 0.03582
Epoch: 12/20 Iteration: 114 Training loss: 0.04136
Epoch: 12/20 Iteration: 115 Training loss: 0.02778
Epoch: 12/20 Iteration: 115 Validation accuracy: 0.90463
Epoch: 12/20 Iteration: 116 Training loss: 0.02008
Epoch: 12/20 Iteration: 117 Training loss: 0.02718
Epoch: 12/20 Iteration: 118 Training loss: 0.03385
Epoch: 12/20 Iteration: 119 Training loss: 0.02371
Epoch: 13/20 Iteration: 120 Training loss: 0.02134
Epoch: 13/20 Iteration: 120 Validation accuracy: 0.90736
Epoch: 13/20 Iteration: 121 Training loss: 0.02232
Epoch: 13/20 Iteration: 122 Training loss: 0.02663
Epoch: 13/20 Iteration: 123 Training loss: 0.02808
Epoch: 13/20 Iteration: 124 Training loss: 0.03486
Epoch: 13/20 Iteration: 125 Training loss: 0.02398
Epoch: 13/20 Iteration: 125 Validation accuracy: 0.90463
Epoch: 13/20 Iteration: 126 Training loss: 0.01631
Epoch: 13/20 Iteration: 127 Training loss: 0.02113
Epoch: 13/20 Iteration: 128 Training loss: 0.02706
Epoch: 13/20 Iteration: 129 Training loss: 0.02049
Epoch: 14/20 Iteration: 130 Training loss: 0.01724
Epoch: 14/20 Iteration: 130 Validation accuracy: 0.90736
Epoch: 14/20 Iteration: 131 Training loss: 0.01770
Epoch: 14/20 Iteration: 132 Training loss: 0.02206
Epoch: 14/20 Iteration: 133 Training loss: 0.02273
Epoch: 14/20 Iteration: 134 Training loss: 0.02950
Epoch: 14/20 Iteration: 135 Training loss: 0.02021
Epoch: 14/20 Iteration: 135 Validation accuracy: 0.90463
Epoch: 14/20 Iteration: 136 Training loss: 0.01413
Epoch: 14/20 Iteration: 137 Training loss: 0.01744
Epoch: 14/20 Iteration: 138 Training loss: 0.02326
Epoch: 14/20 Iteration: 139 Training loss: 0.01714
Epoch: 15/20 Iteration: 140 Training loss: 0.01456
Epoch: 15/20 Iteration: 140 Validation accuracy: 0.90463
Epoch: 15/20 Iteration: 141 Training loss: 0.01443
Epoch: 15/20 Iteration: 142 Training loss: 0.01788
Epoch: 15/20 Iteration: 143 Training loss: 0.01886
Epoch: 15/20 Iteration: 144 Training loss: 0.02521
Epoch: 15/20 Iteration: 145 Training loss: 0.01765
Epoch: 15/20 Iteration: 145 Validation accuracy: 0.90463
Epoch: 15/20 Iteration: 146 Training loss: 0.01161
Epoch: 15/20 Iteration: 147 Training loss: 0.01427
Epoch: 15/20 Iteration: 148 Training loss: 0.01961
Epoch: 15/20 Iteration: 149 Training loss: 0.01493
Epoch: 16/20 Iteration: 150 Training loss: 0.01205
Epoch: 16/20 Iteration: 150 Validation accuracy: 0.90463
Epoch: 16/20 Iteration: 151 Training loss: 0.01184
Epoch: 16/20 Iteration: 152 Training loss: 0.01500
Epoch: 16/20 Iteration: 153 Training loss: 0.01586
Epoch: 16/20 Iteration: 154 Training loss: 0.02123
Epoch: 16/20 Iteration: 155 Training loss: 0.01566
Epoch: 16/20 Iteration: 155 Validation accuracy: 0.90463
Epoch: 16/20 Iteration: 156 Training loss: 0.01016
Epoch: 16/20 Iteration: 157 Training loss: 0.01226
Epoch: 16/20 Iteration: 158 Training loss: 0.01728
Epoch: 16/20 Iteration: 159 Training loss: 0.01276
Epoch: 17/20 Iteration: 160 Training loss: 0.01018
Epoch: 17/20 Iteration: 160 Validation accuracy: 0.90463
Epoch: 17/20 Iteration: 161 Training loss: 0.01012
Epoch: 17/20 Iteration: 162 Training loss: 0.01242
Epoch: 17/20 Iteration: 163 Training loss: 0.01360
Epoch: 17/20 Iteration: 164 Training loss: 0.01793
Epoch: 17/20 Iteration: 165 Training loss: 0.01394
Epoch: 17/20 Iteration: 165 Validation accuracy: 0.90463
Epoch: 17/20 Iteration: 166 Training loss: 0.00872
Epoch: 17/20 Iteration: 167 Training loss: 0.01039
Epoch: 17/20 Iteration: 168 Training loss: 0.01544
Epoch: 17/20 Iteration: 169 Training loss: 0.01136
Epoch: 18/20 Iteration: 170 Training loss: 0.00890
Epoch: 18/20 Iteration: 170 Validation accuracy: 0.90463
Epoch: 18/20 Iteration: 171 Training loss: 0.00874
Epoch: 18/20 Iteration: 172 Training loss: 0.01065
Epoch: 18/20 Iteration: 173 Training loss: 0.01180
Epoch: 18/20 Iteration: 174 Training loss: 0.01512
Epoch: 18/20 Iteration: 175 Training loss: 0.01251
Epoch: 18/20 Iteration: 175 Validation accuracy: 0.90463
Epoch: 18/20 Iteration: 176 Training loss: 0.00766
Epoch: 18/20 Iteration: 177 Training loss: 0.00909
Epoch: 18/20 Iteration: 178 Training loss: 0.01392
Epoch: 18/20 Iteration: 179 Training loss: 0.01003
Epoch: 19/20 Iteration: 180 Training loss: 0.00784
Epoch: 19/20 Iteration: 180 Validation accuracy: 0.90463
Epoch: 19/20 Iteration: 181 Training loss: 0.00767
Epoch: 19/20 Iteration: 182 Training loss: 0.00937
Epoch: 19/20 Iteration: 183 Training loss: 0.01042
Epoch: 19/20 Iteration: 184 Training loss: 0.01260
Epoch: 19/20 Iteration: 185 Training loss: 0.01153
Epoch: 19/20 Iteration: 185 Validation accuracy: 0.90463
Epoch: 19/20 Iteration: 186 Training loss: 0.00689
Epoch: 19/20 Iteration: 187 Training loss: 0.00797
Epoch: 19/20 Iteration: 188 Training loss: 0.01257
Epoch: 19/20 Iteration: 189 Training loss: 0.00887
Epoch: 20/20 Iteration: 190 Training loss: 0.00693
Epoch: 20/20 Iteration: 190 Validation accuracy: 0.90463
Epoch: 20/20 Iteration: 191 Training loss: 0.00675
Epoch: 20/20 Iteration: 192 Training loss: 0.00823
Epoch: 20/20 Iteration: 193 Training loss: 0.00929
Epoch: 20/20 Iteration: 194 Training loss: 0.01077
Epoch: 20/20 Iteration: 195 Training loss: 0.01044
Epoch: 20/20 Iteration: 195 Validation accuracy: 0.90463
Epoch: 20/20 Iteration: 196 Training loss: 0.00609
Epoch: 20/20 Iteration: 197 Training loss: 0.00700
Epoch: 20/20 Iteration: 198 Training loss: 0.01161
Epoch: 20/20 Iteration: 199 Training loss: 0.00804

Testing

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


In [31]:
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))


Test accuracy: 0.9101

In [32]:
%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 [33]:
test_img_path = 'flower_photos/roses/10894627425_ec76bbc757_n.jpg'
test_img = imread(test_img_path)
plt.imshow(test_img)


Out[33]:
<matplotlib.image.AxesImage at 0x7fe06a605d68>

In [34]:
# 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_)


/home/carnd/transfer-learning/tensorflow_vgg/vgg16.npy
npy file loaded
build model started
build model finished: 0s

In [35]:
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()

In [36]:
plt.imshow(test_img)


Out[36]:
<matplotlib.image.AxesImage at 0x7fe069b4e828>

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



In [ ]: