Importing necessary libraries and using the GPU¶
import os
import tensorflow as tf
import matplotlib.pyplot as plt
import logging
tf.get_logger().setLevel(logging.ERROR)
# I am using my GPU
gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
try:
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, True)
print('Using GPU - ', gpu)
except RuntimeError as e:
print(e)
Using GPU - PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')
Loading the image datasets and looking into it¶
TRAIN_DIR = 'horse-or-human'
VAL_DIR = 'validation-horse-or-human'
# Directory with training horse pictures
train_horse_dir = os.path.join(TRAIN_DIR, 'horses')
# Directory with training human pictures
train_human_dir = os.path.join(TRAIN_DIR, 'humans')
# Directory with validation horse pictures
validation_horse_dir = os.path.join(VAL_DIR, 'horses')
# Directory with validation human pictures
validation_human_dir = os.path.join(VAL_DIR, 'humans')
sample_image_horse = tf.keras.preprocessing.image.load_img(os.path.join(train_horse_dir, os.listdir(train_horse_dir)[100]))
sample_image_human = tf.keras.preprocessing.image.load_img(os.path.join(train_human_dir, os.listdir(train_human_dir)[100]))
ax = plt.subplot(1, 2, 1)
ax.imshow(sample_image_horse)
ax.set_title('Horse Image')
ax = plt.subplot(1, 2, 2)
ax.imshow(sample_image_human)
ax.set_title('Human Image')
plt.show()
sample_array = tf.keras.preprocessing.image.img_to_array(sample_image_human)
print('Each image has shape : ', sample_array.shape)
Each image has shape : (300, 300, 3)
Creating training, validation, and test dataset¶
def train_val_dataset():
training_dataset = tf.keras.utils.image_dataset_from_directory(
directory = TRAIN_DIR,
image_size=(150, 150),
batch_size=32,
shuffle=True,
seed=7
)
validation_dataset = tf.keras.utils.image_dataset_from_directory(
directory = VAL_DIR,
image_size=(150,150),
batch_size=32,
seed=7
)
return training_dataset, validation_dataset
training_dataset, validation_dataset = train_val_dataset()
Found 1027 files belonging to 2 classes. Found 256 files belonging to 2 classes.
Creating test set out of the validation dataset -
val_batches = int(validation_dataset.cardinality())
test_dataset, validation_dataset = tf.keras.utils.split_dataset(validation_dataset, val_batches//5)
print('Number of validation batches : ', validation_dataset.cardinality())
print('Number of test batches : ', test_dataset.cardinality())
Number of validation batches : tf.Tensor(8, shape=(), dtype=int64) Number of test batches : tf.Tensor(1, shape=(), dtype=int64)
Loading the pretrained model¶
local_weights_file = 'inception_v3_model/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5'
def create_pretrained_model():
pre_trained_model = tf.keras.applications.inception_v3.InceptionV3(
input_shape=(150,150,3),
include_top=False,
weights=None
)
pre_trained_model.load_weights(local_weights_file)
for layer in pre_trained_model.layers:
layer.trainable = False
return pre_trained_model
count_params(): This function returns the total number of trainable and non-trainable parameters in the pre_trained_model. It includes all layers, whether they are frozen (non-trainable) or not. This is useful to understand the model size and complexity.
pre_trained_model.trainable_weights: This returns a list of tensors corresponding to the model's trainable parameters (i.e., weights and biases of trainable layers).
w.shape.num_elements():
- w.shape gives the shape of each weight tensor.
- num_elements() returns the total number of elements (parameters) in that tensor.
- sum([...]): Computes the sum of all trainable parameters
pre_trained_model = create_pretrained_model()
num_total_params = pre_trained_model.count_params()
non_trainable_params = sum([w.shape.num_elements() for w in pre_trained_model.trainable_weights])
num_total_params, non_trainable_params
(21802784, 0)
Output desired layer from pretrained model¶
def output_of_last_layer(pre_trained_model):
last_desired_layer = pre_trained_model.get_layer('mixed7')
last_output = last_desired_layer.output
return last_output
last_output = output_of_last_layer(pre_trained_model)
Creating the final model¶
def create_final_model(pre_trained_model, last_output):
x = tf.keras.layers.Flatten()(last_output)
x = tf.keras.layers.Dense(1024, activation='relu')(x)
x = tf.keras.layers.Dropout(0.2)(x)
x = tf.keras.layers.Dense(1, activation='sigmoid')(x)
model = tf.keras.Model(inputs = pre_trained_model.input, outputs=x)
model.compile(optimizer=tf.keras.optimizers.RMSprop(learning_rate=0.00001), loss='binary_crossentropy', metrics=['accuracy'])
return model
model = create_final_model(pre_trained_model, last_output)
num_total_params = model.count_params()
non_trainable_params = sum([w.shape.num_elements() for w in model.trainable_weights])
num_total_params, non_trainable_params
(47512481, 38537217)
non_trainable_params are non zero since now we have some layers (dense layers) that are trainable.
Preprocess the datasets¶
def preprocess(image, label):
image = tf.keras.applications.inception_v3.preprocess_input(image)
return image, label
training_dataset = training_dataset.map(preprocess)
validation_dataset = validation_dataset.map(preprocess)
test_dataset = test_dataset.map(preprocess)
Creating Callback¶
class EarlyStopCallBack(tf.keras.callbacks.Callback):
def on_epoch_end(self, epoch, logs={}):
if logs['accuracy'] > 0.999:
self.model.stop_training=True
print('Model reached 99.9% accuracy')
Train the model¶
history = model.fit(
training_dataset,
validation_data=validation_dataset,
epochs=100,
verbose=2,
callbacks=[EarlyStopCallBack()]
)
Epoch 1/100 33/33 - 7s - loss: 0.5560 - accuracy: 0.7176 - val_loss: 0.4259 - val_accuracy: 0.7961 - 7s/epoch - 208ms/step Epoch 2/100 33/33 - 3s - loss: 0.3650 - accuracy: 0.8578 - val_loss: 0.3775 - val_accuracy: 0.8510 - 3s/epoch - 96ms/step Epoch 3/100 33/33 - 4s - loss: 0.2935 - accuracy: 0.8929 - val_loss: 0.4253 - val_accuracy: 0.8471 - 4s/epoch - 132ms/step Epoch 4/100 33/33 - 12s - loss: 0.2475 - accuracy: 0.9163 - val_loss: 0.4797 - val_accuracy: 0.7725 - 12s/epoch - 351ms/step Epoch 5/100 33/33 - 12s - loss: 0.2099 - accuracy: 0.9279 - val_loss: 0.3302 - val_accuracy: 0.8196 - 12s/epoch - 350ms/step Epoch 6/100 33/33 - 12s - loss: 0.1839 - accuracy: 0.9396 - val_loss: 0.2993 - val_accuracy: 0.8824 - 12s/epoch - 352ms/step Epoch 7/100 33/33 - 12s - loss: 0.1532 - accuracy: 0.9513 - val_loss: 0.3264 - val_accuracy: 0.8157 - 12s/epoch - 352ms/step Epoch 8/100 33/33 - 12s - loss: 0.1425 - accuracy: 0.9533 - val_loss: 0.3356 - val_accuracy: 0.8784 - 12s/epoch - 350ms/step Epoch 9/100 33/33 - 12s - loss: 0.1354 - accuracy: 0.9562 - val_loss: 0.3686 - val_accuracy: 0.8745 - 12s/epoch - 350ms/step Epoch 10/100 33/33 - 12s - loss: 0.1053 - accuracy: 0.9659 - val_loss: 0.2802 - val_accuracy: 0.8784 - 12s/epoch - 351ms/step Epoch 11/100 33/33 - 12s - loss: 0.1103 - accuracy: 0.9688 - val_loss: 0.4082 - val_accuracy: 0.8667 - 12s/epoch - 351ms/step Epoch 12/100 33/33 - 12s - loss: 0.0928 - accuracy: 0.9766 - val_loss: 0.4829 - val_accuracy: 0.8549 - 12s/epoch - 351ms/step Epoch 13/100 33/33 - 12s - loss: 0.0968 - accuracy: 0.9727 - val_loss: 0.3604 - val_accuracy: 0.8784 - 12s/epoch - 350ms/step Epoch 14/100 33/33 - 12s - loss: 0.0813 - accuracy: 0.9776 - val_loss: 0.2713 - val_accuracy: 0.8980 - 12s/epoch - 349ms/step Epoch 15/100 33/33 - 12s - loss: 0.0710 - accuracy: 0.9864 - val_loss: 0.2716 - val_accuracy: 0.8941 - 12s/epoch - 349ms/step Epoch 16/100 33/33 - 12s - loss: 0.0713 - accuracy: 0.9805 - val_loss: 0.3518 - val_accuracy: 0.8902 - 12s/epoch - 350ms/step Epoch 17/100 33/33 - 12s - loss: 0.0517 - accuracy: 0.9912 - val_loss: 0.3803 - val_accuracy: 0.8275 - 12s/epoch - 350ms/step Epoch 18/100 33/33 - 12s - loss: 0.0540 - accuracy: 0.9844 - val_loss: 0.3012 - val_accuracy: 0.8980 - 12s/epoch - 351ms/step Epoch 19/100 33/33 - 12s - loss: 0.0488 - accuracy: 0.9893 - val_loss: 0.3889 - val_accuracy: 0.8745 - 12s/epoch - 351ms/step Epoch 20/100 33/33 - 12s - loss: 0.0474 - accuracy: 0.9912 - val_loss: 0.2734 - val_accuracy: 0.9020 - 12s/epoch - 350ms/step Epoch 21/100 33/33 - 12s - loss: 0.0431 - accuracy: 0.9922 - val_loss: 0.2982 - val_accuracy: 0.9020 - 12s/epoch - 350ms/step Epoch 22/100 33/33 - 12s - loss: 0.0357 - accuracy: 0.9951 - val_loss: 0.3011 - val_accuracy: 0.9020 - 12s/epoch - 350ms/step Epoch 23/100 33/33 - 12s - loss: 0.0342 - accuracy: 0.9922 - val_loss: 0.2873 - val_accuracy: 0.9059 - 12s/epoch - 351ms/step Epoch 24/100 33/33 - 12s - loss: 0.0320 - accuracy: 0.9951 - val_loss: 0.2933 - val_accuracy: 0.9059 - 12s/epoch - 351ms/step Epoch 25/100 33/33 - 12s - loss: 0.0308 - accuracy: 0.9961 - val_loss: 0.3210 - val_accuracy: 0.9059 - 12s/epoch - 351ms/step Epoch 26/100 33/33 - 12s - loss: 0.0264 - accuracy: 0.9981 - val_loss: 0.3095 - val_accuracy: 0.9059 - 12s/epoch - 350ms/step Epoch 27/100 33/33 - 11s - loss: 0.0281 - accuracy: 0.9922 - val_loss: 0.3529 - val_accuracy: 0.8471 - 11s/epoch - 343ms/step Epoch 28/100 33/33 - 3s - loss: 0.0259 - accuracy: 0.9961 - val_loss: 0.2748 - val_accuracy: 0.8706 - 3s/epoch - 85ms/step Epoch 29/100 33/33 - 3s - loss: 0.0224 - accuracy: 0.9971 - val_loss: 0.3306 - val_accuracy: 0.9059 - 3s/epoch - 82ms/step Epoch 30/100 33/33 - 3s - loss: 0.0231 - accuracy: 0.9961 - val_loss: 0.3015 - val_accuracy: 0.9059 - 3s/epoch - 83ms/step Epoch 31/100 Model reached 99.9% accuracy 33/33 - 3s - loss: 0.0160 - accuracy: 1.0000 - val_loss: 0.5061 - val_accuracy: 0.8706 - 3s/epoch - 84ms/step
def plot_loss_acc(history):
'''Plots the training and validation loss and accuracy from a history object'''
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(len(acc))
fig, ax = plt.subplots(1,2, figsize=(12, 6))
ax[0].plot(epochs, acc, 'bo', label='Training accuracy')
ax[0].plot(epochs, val_acc, 'b', label='Validation accuracy')
ax[0].set_title('Training and validation accuracy')
ax[0].set_xlabel('epochs')
ax[0].set_ylabel('accuracy')
ax[0].legend()
ax[1].plot(epochs, loss, 'bo', label='Training Loss')
ax[1].plot(epochs, val_loss, 'b', label='Validation Loss')
ax[1].set_title('Training and validation loss')
ax[1].set_xlabel('epochs')
ax[1].set_ylabel('loss')
ax[1].legend()
plt.show()
# Plot training results
plot_loss_acc(history)
Testing the model¶
test_loss, test_accuracy = model.evaluate(test_dataset, verbose=False)
test_loss, test_accuracy
(2.7052661607740447e-05, 1.0)
The model achieved a test loss of approximately 2.71×10^−5 and a test accuracy of 100%. This indicates that the model performed exceptionally well on the test data, with minimal loss and perfect classification accuracy.
However, achieving 1.0 (100%) accuracy might suggest possible overfitting, especially if the dataset is small or lacks variability.