Using Transfer Learning and TensorFlow 2.0 To Classify Different Dog Breeds
Using Transfer Learning and TensorFlow 2.0 To Classify Different Dog Breeds
In this project we're going to be using machine learning to help us identify different breeds of dogs.
To do this, we'll be using data from the Kaggle dog breed identification competition. It consists of a
collection of 10,000+ labelled images of 120 different dog breeds.
This kind of problem is called multi-class image classification. It's multi-class because we're trying to
classify mutliple different breeds of dog. If we were only trying to classify dogs versus cats, it would
be called binary classification (one thing versus another).
Multi-class image classification is an important problem because it's the same kind of technology
Tesla uses in their self-driving cars or Airbnb uses in atuomatically adding information to their listings.
Since the most important step in a deep learng problem is getting the data ready (turning it into
numbers), that's what we're going to start with.
4.Evaluating a model (making predictions, comparing them with the ground truth labels).
5.Improve the model through experimentation (start with 1000 images, make sure it works, increase
the number of images).
6.Save, sharing and reloading your model (once you're happy with the results).
For preprocessing our data, we're going to use TensorFlow 2.x. The whole premise here is to get our
data into Tensors (arrays of numbers which can be run on GPUs) and then allow a machine learning
model to find patterns between them.
For our machine learning model, we're going to be using a pretrained deep learning model from
TensorFlow Hub.
The process of using a pretrained model and adapting it to your own problem is called transfer
learning. We do this because rather than train our own model from scratch (could be timely and
expensive), we leverage the patterns of another model which has been trained to classify images.
import tensorflow as tf
print("TF version:",tf.__version__)
TF version: 2.15.0
#!unzip /content/drive/MyDrive/Dog_Breed/dog-breed-identification.zip
import pandas as pd
labels_csv = pd.read_csv("/content/drive/MyDrive/Dog_Breed/labels.csv")
print(labels_csv.describe())
print(labels_csv.head())
id breed
freq 1 126
id breed
0 000bec180eb18c7604dcecc8fe0dba07 boston_bull
1 001513dfcb2ffafc82cccf4d8bbaba97 dingo
2 001cdf01b096e06d78e9e5112d419397 pekinese
3 00214f311d5d2247d5dfe4fe24b2303d bluetick
4 0021f9ceb3235effd7fcde7f7538ed62 golden_retriever
labels_csv.head()
id breed
0 000bec180eb18c7604dcecc8fe0dba07 boston_bull
1 001513dfcb2ffafc82cccf4d8bbaba97 dingo
2 001cdf01b096e06d78e9e5112d419397 pekinese
3 00214f311d5d2247d5dfe4fe24b2303d bluetick
4 0021f9ceb3235effd7fcde7f7538ed62 golden_retriever
labels_csv["breed"].value_counts().plot.bar(figsize=(20,10))
labels_csv["breed"].value_counts().median()
82.0
#Let's view an image
Image("/content/drive/MyDrive/Dog_Breed/train/000bec180eb18c7604dcecc8fe0dba07.jpg")
Since we've got the image ID's and their labels in a DataFrame (labels_csv), we'll use it to create:
filenames[:10]
['/content/drive/My Drive/Dog_Breed/train/000bec180eb18c7604dcecc8fe0dba07.jpg',
'/content/drive/My Drive/Dog_Breed/train/001513dfcb2ffafc82cccf4d8bbaba97.jpg',
'/content/drive/My Drive/Dog_Breed/train/001cdf01b096e06d78e9e5112d419397.jpg',
'/content/drive/My Drive/Dog_Breed/train/00214f311d5d2247d5dfe4fe24b2303d.jpg',
'/content/drive/My Drive/Dog_Breed/train/0021f9ceb3235effd7fcde7f7538ed62.jpg',
'/content/drive/My Drive/Dog_Breed/train/002211c81b498ef88e1b40b9abf84e1d.jpg',
'/content/drive/My Drive/Dog_Breed/train/00290d3e1fdd27226ba27a8ce248ce85.jpg',
'/content/drive/My Drive/Dog_Breed/train/002a283a315af96eaea0e28e7163b21b.jpg',
'/content/drive/My Drive/Dog_Breed/train/003df8b8a8b05244b1d920bb6cf451f9.jpg',
'/content/drive/My Drive/Dog_Breed/train/0042188c895a2f14ef64a918ed9c7b64.jpg']
import os
else:
print("Filenames do not match actual amount of files, check the target directory.")
Image(filenames[8000])
# Check an image directly from a filepath
Image(filenames[5000])
Image(filenames[9000])
labels_csv["breed"][9000]
tibetan_mastiff
import numpy as np
labels = labels_csv["breed"].to_numpy()
labels
len(labels)
10222
if len(labels) == len(filenames):
else:
print("Number of labels does not match number of filenames, check data directories!")
unique_breeds = np.unique(labels)
len(unique_breeds)
120
# Turn a single label into an array of booleans
print(labels[0])
labels[0] == unique_breeds
boston_bull
boolean_labels[:2]
len(boolean_labels)
10222
# Example : Turning boolean array into integers
boston_bull
(array([19]),)
19
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0000000000000000000000000000000000000
0000000000000000000000000000000000000
0 0 0 0 0 0 0 0 0]
print(labels[2])
print(boolean_labels[2].astype(int))
pekinese
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0000000000000000000000000000000000000
0000000000010000000000000000000000000
0 0 0 0 0 0 0 0 0]
filenames[:10]
['/content/drive/My Drive/Dog_Breed/train/000bec180eb18c7604dcecc8fe0dba07.jpg',
'/content/drive/My Drive/Dog_Breed/train/001513dfcb2ffafc82cccf4d8bbaba97.jpg',
'/content/drive/My Drive/Dog_Breed/train/001cdf01b096e06d78e9e5112d419397.jpg',
'/content/drive/My Drive/Dog_Breed/train/00214f311d5d2247d5dfe4fe24b2303d.jpg',
'/content/drive/My Drive/Dog_Breed/train/0021f9ceb3235effd7fcde7f7538ed62.jpg',
'/content/drive/My Drive/Dog_Breed/train/002211c81b498ef88e1b40b9abf84e1d.jpg',
'/content/drive/My Drive/Dog_Breed/train/00290d3e1fdd27226ba27a8ce248ce85.jpg',
'/content/drive/My Drive/Dog_Breed/train/002a283a315af96eaea0e28e7163b21b.jpg',
'/content/drive/My Drive/Dog_Breed/train/003df8b8a8b05244b1d920bb6cf451f9.jpg',
'/content/drive/My Drive/Dog_Breed/train/0042188c895a2f14ef64a918ed9c7b64.jpg']
Since the data from Kaggle doesn't come with validation set
X = filenames
y = boolean_labels
Since we're working with 10,000+ images, it's a good idea to work with a portion of them to make
sure things are working before training on them all.
This is because computing with 10,000+ images could take a fairly long time. And our goal when
working through machine learning projects is to reduce the time between experiments.
NUM_IMAGES
1000
X_train,X_val,y_train,y_val = train_test_split(X[:NUM_IMAGES],y[:NUM_IMAGES],test_size =
0.2,random_state = 42)
len(X_train),len(y_train),len(X_val),len(y_val)
X_train[:5],y_train[:5]
(['/content/drive/My Drive/Dog_Breed/train/00bee065dcec471f26394855c5c2f3de.jpg',
'/content/drive/My Drive/Dog_Breed/train/0d2f9e12a2611d911d91a339074c8154.jpg',
'/content/drive/My Drive/Dog_Breed/train/1108e48ce3e2d7d7fb527ae6e40ab486.jpg',
'/content/drive/My Drive/Dog_Breed/train/0dc3196b4213a2733d7f4bdcd41699d3.jpg',
'/content/drive/My Drive/Dog_Breed/train/146fbfac6b5b1f0de83a5d0c1b473377.jpg'],
preprocess our images into Tensors we're going to write a function which does a few things:
A good place to read about this type of function is the TensorFlow documentation on loading images.
You might be wondering why (224, 224), which is (heigh, width). It's because this is the size of input
our model (we'll see this soon) takes, an image which is (224, 224, 3).
What? Where's the 3 from? We're getting ahead of ourselves but that's the number of colour
channels per pixel, red, green and blue.
image.shape
(257, 350, 3)
tf.constant(image)[:2]
...,
...,
IMG_SIZE = 224
def process_image(image_path):
"""
Takes an image file path and turns the image into a Tensor
"""
image = tf.io.read_file(image_path)
#Turn the jpeg image into numerical Tensor with 3 colours channels(RGB)
image = tf.image.decode_jpeg(image,channels = 3)
image = tf.image.convert_image_dtype(image,tf.float32)
return image