Dog_VS_Cat
A tutorial on using CNN to predict dog vs cat.
- Import tools
- Getting our data ready
- Preprocessing Images
- Turning our data into Batches
- Visualizing Data Batches
- Building a model
- Creating callbacks
- Training a model
- Making and evaluating prediction using a trained model
- Saving and reloading a trained model
- Predict on custom data
- Testing Fun
import tensorflow as tf
import tensorflow_hub as hub
print("TF version:", tf.__version__)
print("TF Hub version:", hub.__version__)
import pandas as pd
labels_csv = pd.read_csv("/content/drive/MyDrive/COLAB_PROJECT/1.CNN/Dog_vs_cat/Dog_vs_cat.csv")
labels_csv.drop('Unnamed: 0',axis=1, inplace=True)
labels_csv
labels_csv = labels_csv.sample(frac = 1)
labels_csv
import matplotlib.pyplot as plt
labels_csv["category"].value_counts().plot.bar(figsize=(5, 5));
from IPython.display import Image
Image("/content/drive/MyDrive/COLAB_PROJECT/1.CNN/Dog_vs_cat/train/dog.10.jpg")
filenames = ["/content/drive/MyDrive/COLAB_PROJECT/1.CNN/Dog_vs_cat/train/" + fname for fname in labels_csv["filename"]]
# Check the first 15
filenames[:15]
Image(filenames[2509])
labels_csv["category"][2509]
let's prepare our labels.
import numpy as np
labels = labels_csv["category"].to_numpy()
labels
len(labels)
if len(labels) == len(filenames):
print("labels matches number of filenames!")
else:
print("labels does not match number of filenames")
unique_category = np.unique(labels)
len(unique_category)
unique_category
print(labels[0])
labels[0] == unique_category
boolean_labels = [label == unique_category for label in labels]
boolean_labels[:2]
len(boolean_labels)
print(labels[0])
print(np.where(unique_category == labels[0]))
print(boolean_labels[0].argmax())
print(boolean_labels[0].astype(int))
filenames[:10]
X = filenames
y = boolean_labels
from sklearn.model_selection import train_test_split
# Into train and valid
X_train, X_val, y_train, y_val = train_test_split(X,
y,
test_size=0.2,
random_state=42)
len(X_train), len(X_val), len(y_train), len(y_val)
X_train[:5],y_train[:5]
from matplotlib.pyplot import imread
image = imread(filenames[42])
image.shape
tf.constant(image)
IMG_SIZE = 224
# Function
def process_image(image_path, image_size=IMG_SIZE):
"""
Takes an image file path and turns the image into a Tensor.
"""
# Read in an image file
image = tf.io.read_file(image_path)
# Turn the jpg image into numerical Tensor with 3 colour channel(RGB)
image = tf.image.decode_jpeg(image,channels=3)
# Convert the color channel values to (0-1) values
image = tf.image.convert_image_dtype(image,tf.float32)
# Resize the image to (224,224)
image = tf.image.resize(image, size=[image_size,image_size])
return image
def get_image_lable(image_path,label):
"""
Takes an image file path name and the label,
processes the image and return a tuple (image, label).
"""
image = process_image(image_path)
return image,label
Let's make a function to turn all of data into batches!
BATCH_SIZE = 32
# Function to convert data into batches
def create_data_batches(X,y=None, batch_size=BATCH_SIZE,valid_data=False):
"""
Creates batches of data of image (X) and label (y) pairs.
Shuffle the data if it's training data but doesn't shuffle if it's validation data.
"""
# If data is valid dataset (NO SHUFFLE)
if valid_data:
print("Creating valid data batches.........")
data = tf.data.Dataset.from_tensor_slices((tf.constant(X),
tf.constant(y)))
data_batch = data.map(get_image_lable).batch(batch_size)
return data_batch
else:
print("Creating train data batches.........")
# Turn filepaths and labels into Tensors
data = tf.data.Dataset.from_tensor_slices((tf.constant(X),
tf.constant(y)))
# Shuffling pathname and labels before mapping image processor fun
data = data.shuffle(buffer_size=len(X))
data_batch = data.map(get_image_lable).batch(batch_size)
return data_batch
train_data = create_data_batches(X_train, y_train)
val_data = create_data_batches(X_val, y_val, valid_data=True)
train_data.element_spec, val_data.element_spec
import matplotlib.pyplot as plt
# Create fun for viewing in a data batch
def show_images(images, labels):
"""
Displays a plot of 25 images and their labels from a data batch.
"""
plt.figure(figsize=(20, 20))
for i in range(25):
# Subplot
ax = plt.subplot(5,5,i+1)
plt.imshow(images[i])
plt.title(unique_category[labels[i].argmax()])
plt.axis("Off")
train_images, train_labels = next(train_data.as_numpy_iterator())
train_images, train_labels
len(train_images), len(train_labels)
train_images, train_labels = next(train_data.as_numpy_iterator())
show_images(train_images,train_labels)
val_images, val_labels = next(val_data.as_numpy_iterator())
show_images(val_images, val_labels)
INPUT_SHAPE = [None, IMG_SIZE, IMG_SIZE, 3] # Batch, height, width, Colour_chanels
# Setup output shape of the model
OUTPUT_SHAPE = len(unique_category)
# Setup model URL
MODEL_URL = "https://tfhub.dev/google/imagenet/mobilenet_v2_130_224/classification/4"
def create_model(input_shape=INPUT_SHAPE,output_shape=OUTPUT_SHAPE, model_url=MODEL_URL):
print("Building model with:", model_url)
# Setup the model
model = tf.keras.Sequential([
hub.KerasLayer(model_url),
tf.keras.layers.Dense(units=output_shape,
activation="softmax")
])
# Compile the model
model.compile(
loss = tf.keras.losses.BinaryCrossentropy(),
optimizer = tf.keras.optimizers.Adam(),
metrics = ["accuracy"]
)
# Build the model
model.build(input_shape)
return model
model = create_model()
model.summary()
%load_ext tensorboard
import datetime
import os
# Create a function to build a TensorBoard callback
def create_tensorboard_callback():
logdir = os.path.join("/content/drive/MyDrive/COLAB_PROJECT/1.CNN/Dog_vs_cat/log",
datetime.datetime.now().strftime("%Y%m%d-%H%M%S"))
return tf.keras.callbacks.TensorBoard(logdir)
early_stopping = tf.keras.callbacks.EarlyStopping(monitor="val_accuracy",
patience = 3)
NUM_EPOCHS = 100
print("GPU is on" if tf.config.list_physical_devices("GPU") else "No GPU :(")
def train_model():
tensorboard = create_tensorboard_callback()
# Fit the model
model.fit(x=train_data,
epochs= NUM_EPOCHS,
validation_data=val_data,
validation_freq = 1,
callbacks = [tensorboard,early_stopping])
return model
model = train_model()
%tensorboard --logdir /content/drive/MyDrive/COLAB_PROJECT/1.CNN/Dog_vs_cat/log
predictions = model.predict(val_data, verbose=1)
predictions
predictions.shape
np.sum(predictions[0])
def make_prediction(prediction_probabilities):
"""
Turns an array of prediction probabilities into a label.
"""
return unique_category[np.argmax(prediction_probabilities)]
pred_label = make_prediction(predictions[17])
pred_label
val_data
def unbatchify(data):
"""
Takes a batched dataset of (image, label) Tensors and reutrns separate arrays
of images and labels.
"""
images = []
labels = []
# Loop through unbatched data
for image, label in data.unbatch().as_numpy_iterator():
images.append(image)
labels.append(unique_category[np.argmax(label)])
return images, labels
# Unbatchify the validation data
val_images, val_labels = unbatchify(val_data)
val_images[0], val_labels[0]
def plot_pred(prediction_probabilities, labels, images, n=1):
"""
View the prediction, ground truth and image for sample n
"""
pred_prob, true_label, image = prediction_probabilities[n], labels[n], images[n]
# Get the pred label
pred_label = make_prediction(pred_prob)
# Plot image & remove ticks
plt.imshow(image)
plt.xticks([])
plt.yticks([])
# Change the colour of the title depending on if the prediction is right or wrong
if pred_label == true_label:
color = "green"
else:
color = "red"
# Change plot title to be predicted, probability of prediction and truth label
plt.title("{} {:2.0f}% {}".format(pred_label,
np.max(pred_prob)*100,
true_label),
color=color)
plot_pred(prediction_probabilities=predictions,
labels=val_labels,
images=val_images,
n=15)
def plot_pred_conf(prediction_probabilities, labels, n=1):
"""
Plus the top 10 highest prediction confidences along with the truth label for sample n.
"""
pred_prob, true_label = prediction_probabilities[n], labels[n]
# Get the predicted label
pred_label = make_prediction(pred_prob)
# Find the top 10 prediction confidence indexes
top_10_pred_indexes = pred_prob.argsort()[-10:][::-1]
# Find the top 10 prediction confidence values
top_10_pred_values = pred_prob[top_10_pred_indexes]
# Find the top 10 prediction labels
top_10_pred_labels = unique_category[top_10_pred_indexes]
# Setup plot
top_plot = plt.bar(np.arange(len(top_10_pred_labels)),
top_10_pred_values,
color="grey")
plt.xticks(np.arange(len(top_10_pred_labels)),
labels=top_10_pred_labels,
rotation="vertical")
# Change color of true label
if np.isin(true_label, top_10_pred_labels):
top_plot[np.argmax(top_10_pred_labels == true_label)].set_color("green")
else:
pass
plot_pred_conf(prediction_probabilities=predictions,
labels=val_labels,
n=9)
i_multiplier = 20
num_rows = 5
num_cols = 5
num_images = num_rows*num_cols
plt.figure(figsize=(10*num_cols, 5*num_rows))
for i in range(num_images):
plt.subplot(num_rows, 2*num_cols, 2*i+1)
plot_pred(prediction_probabilities=predictions,
labels=val_labels,
images=val_images,
n=i+i_multiplier)
plt.subplot(num_rows, 2*num_cols, 2*i+2)
plot_pred_conf(prediction_probabilities=predictions,
labels=val_labels,
n=i+i_multiplier)
plt.tight_layout(h_pad=1.0)
plt.show()
def save_model(model, suffix=None):
"""
Saves a given model in a models directory and appends a suffix (string).
"""
# Create a model directory pathname with current time
modeldir = "/content/drive/MyDrive/COLAB_PROJECT/1.CNN/Dog_vs_cat/"
model_path = modeldir + "-" + suffix + ".h5" # save format of model
print(f"Saving model to: {model_path}...")
model.save(model_path)
return model_path
save_model(model, suffix="mobilenetv2-Adam")
model.evaluate(val_data)
test = '/content/drive/MyDrive/dog.jpg'
test = imread(test)
test = tf.image.convert_image_dtype(test,tf.float32)
test = tf.image.resize(test, size=[224,224])
test = np.expand_dims(test,axis=0)
test.shape
pred = model.predict(test)
pred
pred_label = make_prediction(pred)
pred_label
test1 = '/content/drive/MyDrive/cat.jpg'
test1 = imread(test1)
test1 = tf.image.convert_image_dtype(test1,tf.float32)
test1 = tf.image.resize(test1, size=[224,224])
test1 = np.expand_dims(test1,axis=0)
pred1 = model.predict(test1)
pred1
pred_label = make_prediction(pred1)
pred_label
def test_data(path):
demo = imread(path)
demo = tf.image.convert_image_dtype(demo,tf.float32)
demo = tf.image.resize(demo,size=[224,224])
demo = np.expand_dims(demo,axis=0)
pred = model.predict(demo)
result = unique_category[np.argmax(pred)]
return result
path = '/content/drive/MyDrive/COLAB_PROJECT/1.CNN/Dog_vs_cat/test/cat.jpg'
path1 ='/content/drive/MyDrive/COLAB_PROJECT/1.CNN/Dog_vs_cat/test/dog.jpg'
test_data(path)
test_data(path1)