In [2]:
import tensorflow as tf
import keras as keras
In [3]:
# --------------------------------------------------------------------------------------- +
# Implementing VGG Model / Architecture
# https://www.tensorflow.org/tutorials/layers
# https://towardsdatascience.com/components-of-convolutional-neural-networks-6ff66296b456
# --------------------------------------------------------------------------------------- +
# 1. parameters
model_params = {
"num_classes": 10,
"input_shape": (32, 32, 3),
"conv_kernel": (3,3),
"pool_kernel": (2,2),
"batch_size" : 32
}
hyper_params = {
"l2_regularization" : 0.0005,
"dropout": 0.5,
"learning_rate": 0.0001
}
In [4]:
# 2a. conv2d layer
def conv2d(filters):
return keras.layers.Conv2D(filters,
model_params["conv_kernel"],
padding='same',
activation=tf.nn.relu,
kernel_regularizer=tf.contrib.layers.l2_regularizer(hyper_params["l2_regularization"]))
In [5]:
# 2b. convolutional block
def setConvBlock(filters, inputs):
net = conv2d(filters)(inputs)
net = keras.layers.BatchNormalization()(net)
net = conv2d(filters)(net)
net = keras.layers.MaxPool2D(model_params["pool_kernel"])(net)
return keras.layers.Dropout(0.25)(net)
def convBlock(filters):
def convBlockWrapped(inputs):
return setConvBlock(filters, inputs)
return convBlockWrapped
In [6]:
# 2c. dense block
def setDenseBlock(units, inputs):
net = keras.layers.Dense(units)(inputs)
return keras.layers.Dropout(hyper_params["dropout"])(net)
def denseBlock(units):
def denseBlockWrapped(inputs):
return setDenseBlock(units, inputs)
return denseBlockWrapped
In [7]:
# 3. Simplified VGG Model
def VGG():
# tensorflow default graph
tf.reset_default_graph()
# input image tensor
inputs = keras.layers.Input(shape=model_params["input_shape"])
# convolutional blocks
net = convBlock(64)(inputs)
net = convBlock(128)(net)
net = convBlock(256)(net)
net = keras.layers.Flatten()(net)
# fully connected
net = denseBlock(1024)(net)
net = denseBlock(512)(net)
# final layer
outputs = keras.layers.Dense(model_params["num_classes"],
activation = tf.nn.softmax)(net)
# model
model = keras.models.Model(inputs=inputs, outputs=outputs)
return model
In [8]:
# 4. Compile Model
# - add loss function, optimizer and the metrics
def compile_model(model):
# loss
loss = keras.losses.categorical_crossentropy
# adam optimizer
optimizer = keras.optimizers.Adam(lr=hyper_params["learning_rate"])
# metrics
metrics = [keras.metrics.categorical_accuracy,
keras.metrics.top_k_categorical_accuracy]
# compile
model.compile(loss=loss,
optimizer=optimizer,
metrics=metrics)
print(model.summary())
return model
In [9]:
vgg = VGG()
vgg = compile_model(vgg)
In [34]:
#--------------------------------------------------------------------------+
# 5. Try it out on a dataset !
#--------------------------------------------------------------------------+
# load CIFAR10 dataset
# https://www.cs.toronto.edu/~kriz/cifar.html
(x_train, y_train), (x_test, y_test) = keras.datasets.cifar10.load_data()
In [35]:
# set target values to one-hot encoded vectors
y_train = keras.utils.to_categorical(y_train, model_params["num_classes"])
y_test = keras.utils.to_categorical(y_test, model_params["num_classes"])
In [36]:
# data augmentation : generate more dataset
train_aug = tf.contrib.keras.preprocessing.image.ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_aug = tf.contrib.keras.preprocessing.image.ImageDataGenerator(
rescale=1./255)
In [37]:
# training generator
train_gen = train_aug.flow(x=x_train, y=y_train, batch_size=model_params["batch_size"])
# testing generator
test_gen = test_aug.flow(x=x_test, y=y_test, batch_size=model_params["batch_size"])
In [40]:
In [ ]:
# train Simplified-VGG on CIFAR10
fitvgg = vgg.fit_generator(train_aug.flow(x_train, y_train, batch_size=32),
validation_data=[x_test, y_test],
epochs=10,
steps_per_epoch=300,
verbose=1,
workers=4)
In [ ]:
# train Simplified-VGG on CIFAR10
fitvgg = vgg.fit_generator(train_gen,
steps_per_epoch=300,
epochs=10,
validation_data=test_gen,
validation_steps=100)
In [ ]:
#--------------------------------------------------------------------------+
# 6. evaluate model performance
#--------------------------------------------------------------------------+
loss, acc, top_k_acc = vgg.evaluate_generator(test_gen, steps=200)
print("loss: {}".format(loss))
print("accuracy: {}".format(acc))
print("top 5 accuracy: {}".format(top_k_acc))
In [ ]:
# make predictions on trained VGG
predictions = vgg.predict_generator(test_gen, steps=100)
In [ ]:
# plot accuracy and loss over time
def plot_accuracy_and_loss(fitvgg):
plt.figure(1, figsize=(15, 10))
# plot train and test accuracy
plt.subplot(221)
plt.plot(fitvgg.history['categorical_accuracy'])
plt.plot(fitvgg.history['val_categorical_accuracy'])
plt.title('VGG Accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
# plot train and test loss
plt.subplot(222)
plt.plot(fitvgg.history['loss'])
plt.plot(fitvgg.history['val_loss'])
plt.title('VGG Loss')
plt.ylable('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper right')
plt.show()
In [ ]:
plot_accuracy_and_loss(fitvgg)
In [ ]:
#--------------------------------------------------------------------------+
# 7. save model architecture and weights
#--------------------------------------------------------------------------+
myvgg = vgg.to_json()
open('simplified_cifar10_vgg.json','w').write(myvgg)
vgg.save_weights('image_classifier_cifar10.h5', overwrite=True)
In [ ]:
## --+
In [ ]:
# Transfer Learning
# 1. via Feature Extraction
# 2. via Fine Tuning
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]: