In [1]:
import os
import pickle
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from skimage import io
from sklearn.cross_validation import train_test_split

from keras.models import Sequential, model_from_json
from keras.layers.core import Dense, Dropout, Flatten
from keras.layers.convolutional import Convolution2D, MaxPooling2D, ZeroPadding2D
from keras.optimizers import SGD
from keras.utils import np_utils
Using Theano backend.
Using gpu device 0: GRID K520 (CNMeM is disabled, CuDNN not available)
/usr/local/lib/python3.4/dist-packages/theano/tensor/signal/downsample.py:6: UserWarning: downsample module has been moved to the theano.tensor.signal.pool module.
  "downsample module has been moved to the theano.tensor.signal.pool module.")
In [2]:
%matplotlib inline
In [4]:
PUG_IMG_DIR = "../data/pugs_cropped"
CHI_IMG_DIR = "../data/chihuahuas_cropped"
IMG_ROWS, IMG_COLS = 224, 224
IMG_CHANNELS = 3
In [5]:
n_pug_images = len(os.listdir(PUG_IMG_DIR))
pug_images = np.empty((n_pug_images, IMG_CHANNELS, IMG_ROWS, IMG_COLS), dtype="uint8")

n_chi_images = len(os.listdir(CHI_IMG_DIR))
chi_images = np.empty((n_chi_images, IMG_CHANNELS, IMG_ROWS, IMG_COLS), dtype="uint8")
In [6]:
for n, image in enumerate(os.listdir(PUG_IMG_DIR)):
    pug_images[n] = io.imread(PUG_IMG_DIR+"/"+image).transpose()

for n, image in enumerate(os.listdir(CHI_IMG_DIR)):
    chi_images[n] = io.imread(CHI_IMG_DIR+"/"+image).transpose()
In [7]:
print(pug_images.shape)
print(chi_images.shape)
(904, 3, 224, 224)
(1224, 3, 224, 224)
In [8]:
pug_labels = np.ones(n_pug_images)
chi_labels = np.zeros(n_chi_images)
In [9]:
plt.axis('off')
plt.imshow(pug_images[0].transpose())
Out[9]:
<matplotlib.image.AxesImage at 0x7f72be1e5668>
In [ ]:
plt.axis('off')
plt.imshow(chi_images[0].transpose())
In [10]:
X = np.concatenate([pug_images, chi_images])
y = np.concatenate([pug_labels, chi_labels])
In [11]:
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.60, stratify=y)
In [12]:
with open("../data/pugs_vs_chihuahuas_data.pkl.gz", "wb") as pickle_file:
    pickle.dump((X_train, X_test, y_train, y_test), pickle_file)
In [13]:
#Or just open pickle file here
with open("../data/pugs_vs_chihuahuas_data.pkl.gz", "rb") as pickle_file:
    X_train, X_test, y_train, y_test = pickle.load(pickle_file)
In [14]:
X_val, X_test, y_val, y_test = train_test_split(X_train, y_train, test_size=0.50)
In [15]:
print(X_train.shape)
print(X_val.shape)
print(X_test.shape)
(1276, 3, 224, 224)
(638, 3, 224, 224)
(638, 3, 224, 224)
In [16]:
plt.axis('off')
plt.imshow(X_val[0].transpose())
Out[16]:
<matplotlib.image.AxesImage at 0x7f72bda64278>
In [ ]:
# we're going to use a pre-trained deep network and chop off the
# last dense layer; we'll freeze the weights in the early layers
# and then train just the final set of dense weights
# see https://gist.github.com/baraldilorenzo/07d7802847aaad0a35d3
def VGG_16(weights_path=None):
    model = Sequential()
    model.add(ZeroPadding2D((1,1),input_shape=(IMG_CHANNELS, IMG_ROWS, IMG_COLS), trainable=False))
    model.add(Convolution2D(64, 3, 3, activation='relu', trainable=False))
    model.add(ZeroPadding2D((1,1), trainable=False))
    model.add(Convolution2D(64, 3, 3, activation='relu', trainable=False))
    model.add(MaxPooling2D((2,2), strides=(2,2), trainable=False))

    model.add(ZeroPadding2D((1,1)))
    model.add(Convolution2D(128, 3, 3, activation='relu', trainable=False))
    model.add(ZeroPadding2D((1,1), trainable=False))
    model.add(Convolution2D(128, 3, 3, activation='relu', trainable=False))
    model.add(MaxPooling2D((2,2), strides=(2,2), trainable=False))

    model.add(ZeroPadding2D((1,1), trainable=False))
    model.add(Convolution2D(256, 3, 3, activation='relu', trainable=False))
    model.add(ZeroPadding2D((1,1), trainable=False))
    model.add(Convolution2D(256, 3, 3, activation='relu', trainable=False))
    model.add(ZeroPadding2D((1,1), trainable=False))
    model.add(Convolution2D(256, 3, 3, activation='relu', trainable=False))
    model.add(MaxPooling2D((2,2), strides=(2,2), trainable=False))

    model.add(ZeroPadding2D((1,1), trainable=False))
    model.add(Convolution2D(512, 3, 3, activation='relu', trainable=False))
    model.add(ZeroPadding2D((1,1), trainable=False))
    model.add(Convolution2D(512, 3, 3, activation='relu', trainable=False))
    model.add(ZeroPadding2D((1,1), trainable=False))
    model.add(Convolution2D(512, 3, 3, activation='relu', trainable=False))
    model.add(MaxPooling2D((2,2), strides=(2,2), trainable=False))

    model.add(ZeroPadding2D((1,1), trainable=False))
    model.add(Convolution2D(512, 3, 3, activation='relu', trainable=False))
    model.add(ZeroPadding2D((1,1), trainable=False))
    model.add(Convolution2D(512, 3, 3, activation='relu', trainable=False))
    model.add(ZeroPadding2D((1,1), trainable=False))
    model.add(Convolution2D(512, 3, 3, activation='relu', trainable=False))
    model.add(MaxPooling2D((2,2), strides=(2,2), trainable=False))

    model.add(Flatten())
    model.add(Dense(4096, activation='relu', trainable=False))
    model.add(Dropout(0.5))
    model.add(Dense(4096, activation='relu', trainable=False))
    model.add(Dropout(0.5))
    model.add(Dense(1000, activation='softmax'))

    if weights_path:
        model.load_weights(weights_path)

    return model
In [18]:
batch_size = 32
n_classes = 2
n_epochs = 10
In [ ]:
# load our pre-trained model
model = VGG_16('vgg16_weights.h5')

# chop off the final layer
model.layers = model.layers[:-1]

# and add in a new one appropriate to our task
model.add(Dense(n_classes, activation='softmax'))
In [19]:
Y_train = np_utils.to_categorical(y_train, n_classes)
Y_val = np_utils.to_categorical(y_val, n_classes)
Y_test = np_utils.to_categorical(y_test, n_classes)
In [20]:
print(Y_train.shape)
print(Y_val.shape)
print(Y_test.shape)
(1276, 2)
(638, 2)
(638, 2)
In [21]:
sgd = SGD(lr=0.0001, decay=1e-6, momentum=0.9, nesterov=True)
In [ ]:
model.compile(optimizer=sgd, loss='categorical_crossentropy')
In [ ]:
model.fit(X_train, Y_train, batch_size=batch_size,
          nb_epoch=n_epochs, show_accuracy=True,
          validation_data=(X_val, Y_val), shuffle=True)
In [ ]:
#Let's save this deep learning model
json_string = model.to_json()
open('chi_model_architecture.json', 'w').write(json_string)
model.save_weights('chi_model_weights.h5',overwrite=True)
In [22]:
#Load model from saved weights and architecture
model_2 = model_from_json(open('chi_model_architecture.json').read())
model_2.load_weights('chi_model_weights.h5')
model_2.compile(optimizer=sgd, loss='categorical_crossentropy')
In [ ]:
#Supposed to predict accuracy, but I ran out of memory on AWS ec2.
y_pred = model_2.predict_classes(X_test)
accuracy = np.sum(y_pred == y_test) / float(len(y_test))
print(accuracy)
In [65]:
#Let's see how we did on a test image.  Change the index and recompile as many times as you like.
i=136
my_img = X_test[i].transpose()
plt.axis('off')
plt.imshow(my_img)
img = np.array(my_img).transpose()
img = img.reshape((1, 3, 224, 224))
mypred = model_2.predict_classes(img)
print("Was it correct?")
print(mypred == y_test[i])
1/1 [==============================] - 0s
Was it correct?
[ True]
In [ ]: