Image classification from scratch in keras. Beginner friendly, intermediate exciting and expert refreshing. | by Rising Odegua | Towards Data Science

Last weekend I was thinking out loud .
what if I had a really really small data set of images that I captured myself and wanted to teach a computer to recognize or distinguish between some specified categories.
Let’s say I have a few thousand images and I want to train a model to automatically detect one class from another. Would I be able to train a deep neural network to successfully classify these images since I have such little data?
Well, after doing some research, I found out that having to train deep neural network with little data was a common situation people encountered in the field of computer vision.
well let’s face it, not everyone has access to big data like the Googs or the Faces, and some data are very difficult to obtain.
But I also found out that the solution to this problem was quite easy. So today I’m going to walk you through training a Convolutional Neural Network using that little Image data you have to get a really good classifier which will have an accuracy of about 81%.
In this post, I introduced a really powerful technique called transfer learning that helps us increase our accuracy up to about 95%.
Alright you can go out and start gathering your data.
I’ll be using an existing data set of dogs and cats available on the Kaggle platform. — -Yes, I’m lazy. I can’t get my own data.
Kaggle is the home of data science and machine learning practitioners worldwide. They host some of the biggest data science competitions and it is a great place for getting open source data as well as learning from winning experts.
Well, I feel I should say this. If you’re from Africa, we have a new platform called Zindi which is like Kaggle but fine tuned to the Africa society. It contains data sets that are collected from African businesses and organisation. This is a big step in preventing bias in AI, and Zindi is a great platform.
So watch out for the Zindians, we’re coming.
Okay, back to getting the data. We head over to this page on Kaggle. Here we have two options, we can either download the data and train our model locally on our Laptop or we can use Kaggle kernels which gives us more compute power, access to a GPU, and almost all the libraries pre-installed for machine learning and deep learning.
I don’t know about you, but I’d rather go with Kaggle kernels unless I have a GPU.
If you can afford a GPU or you’re a gamaic [I totally made up that word] and already have a GPU and you want to train your model on your PC because you love your PC too much , then you can follow this tutorial or this one on setting up your own deep learning work station.
For the rest of the lazy-or-cannot-currently-afford-a-GP-us, let’s head over to Kaggle and start this engine.
Clicking on the link, we teleport here.
Note: It is generally a good idea to read the data description when you visit a Kaggle competition page.
Next, click on Kernels then the blue New Kernel button on the top right corner, this will ask you to Select Kernel Type. Pick Notebook so we can do some interactive programming.
If you don’t know what a Notebook is or need to refresh your notebooking skills, here and here are great sites with tutorials on Jupyter Notebook.
Clicking on Notebook creates a new private kernel for you and automatically adds the dogs vs cats dataset to your file path — in the cloud of course.
Give your Kernel a name and put on your super power (GPU) for faster compute time.
Now that our kernel is ready, let’s import some of the libraries we’re going to use. Type the following code and press shift Enter to run the cell.
cv2 cv2 also called OpenCV, is an image and video processing library available in Python and many other high level programming languages. It is used for all sorts of image and video analysis, like facial recognition and detection, license plate reading, photo editing, advanced robotic vision, optical character recognition, and a whole lot more. In this tutorial, we are going to use it in reading and resizing our Images.NumPy is the most popular mathematical library in Python. It makes working and computing large, multi-dimensional arrays and matrices super easy and fast. It has a large collection of high-level mathematical functions to operate on these arrays.Pandas pandas is a software library written for the Python programming language for data manipulation and analysis. In particular, it offers data structures and operations for manipulating numerical tables and time series.Matplotlib is a plotting library for the Python. It can be used for plotting lines, bar-chart, graphs, histograms and even displaying Images.%matplotlib inline is a command that makes our plots appear in the notebook.os is an inbuilt python package for accessing your computer and file system. It can be used to display content in directories, create new folders and even delete folders.random will help us create random numbers which will be used when we split or shuffle our data set.gc short for garbage collector is an important tool for manually cleaning and deleting unnecessary variables. We’ll actively use this on Kaggle kernels because the free memory allocated to us may get full since we are working on Image datasets.
cv2 cv2 also called OpenCV, is an image and video processing library available in Python and many other high level programming languages. It is used for all sorts of image and video analysis, like facial recognition and detection, license plate reading, photo editing, advanced robotic vision, optical character recognition, and a whole lot more. In this tutorial, we are going to use it in reading and resizing our Images.
NumPy is the most popular mathematical library in Python. It makes working and computing large, multi-dimensional arrays and matrices super easy and fast. It has a large collection of high-level mathematical functions to operate on these arrays.
Pandas pandas is a software library written for the Python programming language for data manipulation and analysis. In particular, it offers data structures and operations for manipulating numerical tables and time series.
Matplotlib is a plotting library for the Python. It can be used for plotting lines, bar-chart, graphs, histograms and even displaying Images.
%matplotlib inline is a command that makes our plots appear in the notebook.
os is an inbuilt python package for accessing your computer and file system. It can be used to display content in directories, create new folders and even delete folders.
random will help us create random numbers which will be used when we split or shuffle our data set.
gc short for garbage collector is an important tool for manually cleaning and deleting unnecessary variables. We’ll actively use this on Kaggle kernels because the free memory allocated to us may get full since we are working on Image datasets.
After importing the necessary libraries, we read our Images in to memory. The data is stored as Zip files in our kernel.
We can see three files:
sample submission.csv This is a csv (comma seperated value) file that is used for making submission after training your model and testing it on the test files given to you. Since this competition is over, we cannot make submissions, so we’ll ignore this file.test.zipThis file contains the Images we’re going to test our models on after training, to know if our model has learnt to differentiate dogs from cats.train.zipThis is the food for our model. It contains the data we’re going to use to teach our model what a dog or a cat looks like.
sample submission.csv This is a csv (comma seperated value) file that is used for making submission after training your model and testing it on the test files given to you. Since this competition is over, we cannot make submissions, so we’ll ignore this file.
test.zipThis file contains the Images we’re going to test our models on after training, to know if our model has learnt to differentiate dogs from cats.
train.zipThis is the food for our model. It contains the data we’re going to use to teach our model what a dog or a cat looks like.
Now to access our training Images, we’re going to use the os package which we imported earlier.
Note: All data file paths on kaggle start with the root directory ../input. for example the file path to the train data in this kernel will be ../input/train
Here we create a file path to our train and test dataHere we create two variables train_dogs and train_cats. One for all dog images and the other for cat images. We write a list comprehension that uses the command os.listdir() to get all the images in the train data zip file and retrieve all images with dog in their name. ** We do the same for cat images.We get our test images too.The train data set contains a total of 25,000 images, but since we are experimenting working with a small data set and we obviously have access to little computational power, we’re going to extract only 2000 images from both classes.  ** 2000 dog images and 2000 cat images, making a training data set of 4000 images.So we grab the first 2000 images from the train_dogs and train_cats, then concatenate them into one train set called train_imgs.VERY IMPORTANT! we randomly shuffle the train_imgs .Here we do some cleaning. As you may have noticed, we now have train_imgs meaning train_dogs and train_cats variables are useless and taking unnecessary space. If we don’t delete them, we might run out of memory when we start training our model.
Here we create a file path to our train and test data
Here we create two variables train_dogs and train_cats. One for all dog images and the other for cat images. We write a list comprehension that uses the command os.listdir() to get all the images in the train data zip file and retrieve all images with dog in their name. ** We do the same for cat images.
We get our test images too.
The train data set contains a total of 25,000 images, but since we are experimenting working with a small data set and we obviously have access to little computational power, we’re going to extract only 2000 images from both classes.  ** 2000 dog images and 2000 cat images, making a training data set of 4000 images.So we grab the first 2000 images from the train_dogs and train_cats, then concatenate them into one train set called train_imgs.
VERY IMPORTANT! we randomly shuffle the train_imgs .
Here we do some cleaning. As you may have noticed, we now have train_imgs meaning train_dogs and train_cats variables are useless and taking unnecessary space. If we don’t delete them, we might run out of memory when we start training our model.
Okay, lets view some images in our train_imgs.
Import an image plotting module from matplotlibRun a for loop to plot the first three images in train_imgs
Import an image plotting module from matplotlib
Run a for loop to plot the first three images in train_imgs
Remember its a random list, but luckily when I ran the code the first three images was made up to two dogs and one cat and notice that they have different dimensions.
In the next code block we’re going resize the images using the cv2 module.First let’s declare the new dimensions we want to use. Here I’m using 150 by 150 for height and width and 3 channels.
A colored Image is made up of 3 channels, i.e 3 arrays of red, green and blue pixel values. We could use 1 channel which would read our images in gray-scale format (black and white).
Now, lets write a little function that helps also read and then resize our images to the height and width stated above.
Create a new variable X which will hold the new training set and y which will hold our training labels. (1 if the image is a dog and 0 if it is a cat)we read our images one after the other and resize them with the cv2 commands.We append 1 to y if the image is a dog and 0 if it is a cat.
Create a new variable X which will hold the new training set and y which will hold our training labels. (1 if the image is a dog and 0 if it is a cat)
we read our images one after the other and resize them with the cv2 commands.
We append 1 to y if the image is a dog and 0 if it is a cat.
Now, let’s call our function and process the images.
X, y = read_and_process_image(train_imgs)
X is now an array of image pixel values and y is a list of labels. Let’s preview the first image in X.
And that my friend is a dog image. Or we can say what our computer calls a dog. Wait! how did I know its a dog? well, lets look at the corresponding value in the label list y.
Well, remember we said lets 1 and 0 represent dogs and cats respectively.
Still don’t believe me. Then, let’s plot the first 5 arrays of X. We can’t plot the images in X with the mpimg module of matplotlib.image above because these are now arrays of pixels not raw jpg files. So we should use the imshow() command.
Now that we’re confident that our training set contains the appropriate images of dogs and cats, let’s look at our labels. Remember we have a total of 4000 images (2000 dogs and 2000 cats), therefore our label list y should contain 2000 of 1s and 2000 of 0s. Let’s plot this and confirm.
We import seaborn package, another plotting package built on top of matplotlib that gives very beautiful plots.Remember we are neat people and we don’t wait for the garbage man to do the cleaning for us. So we delete the train_imgs, since it has already been converted to an array and saved in X.X and y are currently of type list (list of python array), we will convert these to numpy array so we can feed it into our model.Plot a colorful diagram to confirm the number of classes in our y label variable
We import seaborn package, another plotting package built on top of matplotlib that gives very beautiful plots.
Remember we are neat people and we don’t wait for the garbage man to do the cleaning for us. So we delete the train_imgs, since it has already been converted to an array and saved in X.
X and y are currently of type list (list of python array), we will convert these to numpy array so we can feed it into our model.
Plot a colorful diagram to confirm the number of classes in our y label variable
Great! we have 2000 classes of both dogs and cats. Let’s move on.
Next let’s check the shape of our data. Always check and confirm the shapes of your data, it is super important.
We can see that our image is a tensor of rank 4, or we could say a 4 dimensional array with dimensions 4000 x 150 x 150 x 3 which correspond to the batch size, height, width and channels respectively.
The shape of our image array is important for the keras model we’re going to build. The model takes as input an array of ( height, width,channels)
Now that our data is ready (X,y) we could start training, but first we have to do something that is very important, which is to split our data into train and validation set. This is one of the most important things to do before you start training your model.
For splitting, we’re going to use a handy function from a popular machine learning package in python called sklearn.
Imports train_test_split from sklearnWe tell the function we want 20% of the data to be assigned to the validation set and the other 80% to the train set.Here we print the shape of the new train and validation set
Imports train_test_split from sklearn
We tell the function we want 20% of the data to be assigned to the validation set and the other 80% to the train set.
Here we print the shape of the new train and validation set
Next, we’re going to declare some important variables that will be used when training our model.
Yes, we’re still cleaning.get the length of the train and validation set.
Yes, we’re still cleaning.
get the length of the train and validation set.
Wheeeeeew....Now its time to create our model.
We are going to use a Convolutional Neural Network (convnet) to train our model. Convets are currently the standard when it comes to Computer Vision problems. They have always outperform other types of neural network in any image problem.
New to convnets? At the end of this post, there are good links to sites where you can learn all about them.
In creating our model we’re going to use KERAS.
According to wikipedia...
Keras is an open source neural network library written in Python. It is capable of running on top of TensorFlow, Microsoft Cognitive Toolkit, or Theano. Designed to enable fast experimentation with deep neural networks, it focuses on being user-friendly, modular, and extensible.
First let’s import the neccessary keras modules we are going to use
Here we import keras layers module which contains different types of layers used in deep learning such as:** Convolutional layer (Mostly used in computer vision)** Pooling layer (also used in computer vision)** Recurrent layer (Mostly used in sequential and time series modelling)** Embedding layers (Mostly used in Natural Language processing)** Normalization layers ** and many moreHere we import keras models which contains two types:**Sequential model which we’ll be using in this tutorial and**The model with the Functional APIHere we import keras optimizer, a module that contains different types of back propagation algorithm for training our model. Some of these optimizers are:**sgd (stochastic gradient descent)**rmsprop (root mean square propagation)**Adams**Adagrad**AdadeltaHere we import one of the most important function (ImageDataGenerator) used when working with a small data set. More on this below.
Here we import keras layers module which contains different types of layers used in deep learning such as:** Convolutional layer (Mostly used in computer vision)** Pooling layer (also used in computer vision)** Recurrent layer (Mostly used in sequential and time series modelling)** Embedding layers (Mostly used in Natural Language processing)** Normalization layers ** and many more
Here we import keras models which contains two types:**Sequential model which we’ll be using in this tutorial and**The model with the Functional API
Here we import keras optimizer, a module that contains different types of back propagation algorithm for training our model. Some of these optimizers are:**sgd (stochastic gradient descent)**rmsprop (root mean square propagation)**Adams**Adagrad**Adadelta
Here we import one of the most important function (ImageDataGenerator) used when working with a small data set. More on this below.
Now lets create our Network architecture. We are going to follow a popular, effective and simple architecture called the VGGnet
Network architecture is just the way we arrange our convolution layers
We are going to use a small vggnet, but you can see below that our filter size increases as we go down layers.
32 → 64 →128 →512 — and final layer is 1
Here we create a sequential model. This tells keras to stack all layers sequentially.Here we create the first layer by calling the .add() function on the model we created and pass the type of layer we want — a Conv2D layer. This first layer is called the input layer and has some important parameters we need to set.** filter size [32]: This is the size of the output dimension (i.e. the number of output filters in the convolution)** kernel_size [3,3]: This specifies the height and width of the 2D convolution window.** activation [‘relu’]: We select an activation function also called non-linearity to be used by our neural network. ReLU (Rectified Linear Unit) is the most common activation function used today, other variations are leaky ReLU and eLU.** input shape [150,150,3]: Remember the dimensions we resized our images to? 150 by 150 right? we pass that here including the channel of 3. We do not pass the first dimension of 4000 because that is the batch dimension.Here we add a MaxPool2D layer. Its function is to reduce the spatial size of the incoming features and therefore helps reduce the number of parameters and computation in the network, thereby helping to reduce overfitting.
Here we create a sequential model. This tells keras to stack all layers sequentially.
Here we create the first layer by calling the .add() function on the model we created and pass the type of layer we want — a Conv2D layer. This first layer is called the input layer and has some important parameters we need to set.** filter size [32]: This is the size of the output dimension (i.e. the number of output filters in the convolution)** kernel_size [3,3]: This specifies the height and width of the 2D convolution window.** activation [‘relu’]: We select an activation function also called non-linearity to be used by our neural network. ReLU (Rectified Linear Unit) is the most common activation function used today, other variations are leaky ReLU and eLU.** input shape [150,150,3]: Remember the dimensions we resized our images to? 150 by 150 right? we pass that here including the channel of 3. We do not pass the first dimension of 4000 because that is the batch dimension.
Here we add a MaxPool2D layer. Its function is to reduce the spatial size of the incoming features and therefore helps reduce the number of parameters and computation in the network, thereby helping to reduce overfitting.
Overfitting happens when our model memorizes the training data. The model will perform excellently at training time but fail at test time.
Here we add a Flatten layer. A conv2D layers extract and learn spatial features which are then passed to a dense layer after it has been flattened. This is the work of the flatten layer.Here we add a Dropout layer with value 0.5. Dropout randomly drops some layers in a neural networks and then learns with the reduced network. This way, the network learns to be independent and not reliable on a single layer. Bottom-line is that it helps in overfitting.0.5 means to randomly drop half of the layers.The last layer has an output size of 1 and a different activation function called sigmoid. This is because we’re trying to detect if an image is a dog or a cat. i.e we want the model to output a probability of how sure an image is a dog and not a cat, that means we want a probability score where higher values means the classifier believes the image is a dog and lower values means it is a cat.The sigmoid is perfect for this because it takes in a set of numbers and returns a probability distribution in the range of 0 to 1.
Here we add a Flatten layer. A conv2D layers extract and learn spatial features which are then passed to a dense layer after it has been flattened. This is the work of the flatten layer.
Here we add a Dropout layer with value 0.5. Dropout randomly drops some layers in a neural networks and then learns with the reduced network. This way, the network learns to be independent and not reliable on a single layer. Bottom-line is that it helps in overfitting.0.5 means to randomly drop half of the layers.
The last layer has an output size of 1 and a different activation function called sigmoid. This is because we’re trying to detect if an image is a dog or a cat. i.e we want the model to output a probability of how sure an image is a dog and not a cat, that means we want a probability score where higher values means the classifier believes the image is a dog and lower values means it is a cat.The sigmoid is perfect for this because it takes in a set of numbers and returns a probability distribution in the range of 0 to 1.
We can preview the arrangement and parameter size of our convnet by calling the Keras function .summary() on the model object.
We can see the number of parameters we want to train (3 million-plus) and the general arrangement of the different layers.
The next step is to compile our model.
We pass three parameters to the model.compile() command
Loss [‘binary_crossentropy’]: We specify a loss function that our optimizer will minimize. In this case, since we’re working with a two-class problem, we use binary cross-entropy loss.Remember the optimizers we defined earlier? we’re going to use one of them called the rmsprop. This is not a fixed choice, it is part of a process called hyperparameter tuning which may be the difference between a world-class model and a naive one.Here we specify which metric we want to use in measuring our model’s performance after training. We want to know if our model is doing well or not. Since we’re doing a classification problem, the accuracy metric (acc) is a good choice. Note: The metric you use in measuring the performance of your model will depend on the type of problem you’re dealing with.
Loss [‘binary_crossentropy’]: We specify a loss function that our optimizer will minimize. In this case, since we’re working with a two-class problem, we use binary cross-entropy loss.
Remember the optimizers we defined earlier? we’re going to use one of them called the rmsprop. This is not a fixed choice, it is part of a process called hyperparameter tuning which may be the difference between a world-class model and a naive one.
Here we specify which metric we want to use in measuring our model’s performance after training. We want to know if our model is doing well or not. Since we’re doing a classification problem, the accuracy metric (acc) is a good choice. Note: The metric you use in measuring the performance of your model will depend on the type of problem you’re dealing with.
Finally, before we start training our model we need to perform some Normalization. i.e scale our image pixel values to have a unit standard deviation and a mean of 0.
We’ll use an important module in Keras called ImageDataGenerator which performs some important functions when we’re feeding Images into our model during training.
But...but what is an ImageDataGenerator?
According to the creator of Keras François Chollet, Keras ImageDataGenerator() lets us quickly set-up python generators that automatically turn image files into preprocessed tensors that can be fed directly into models during training. It performs the following functions for us easily:1. Decode the JPEG content to RGB grids of pixels.2. Convert these into floating-point tensors.3. Rescale the pixel values (between 0 and 255) to the [0, 1] interval ( neural networks perform better with normalize data).4. It helps us easily augment images. (An important feature we’ll be using since we’re training on a small data set).
Okay, let’s create our ImageDataGenerator object. We’re going to create two generators, one for the training set and the other for our validation set.
We pass the rescale option to the ImageDataGenerator object. The rescale=1./255 option is a very IMPORTANT parameter. It normalizes the image pixel values to have zero mean and standard deviation of 1. It helps your model to generally learn and update its parameters efficiently.The second set of options is Image augmentation. They tell the ImageDataGenerator to randomly apply some transformation to the Image. This will help to augment our data-set and improve generalization.Here we also create an ImageDataGenerator object for our validation set. Note: we don’t do data augmentation here. We only perform rescale.
We pass the rescale option to the ImageDataGenerator object. The rescale=1./255 option is a very IMPORTANT parameter. It normalizes the image pixel values to have zero mean and standard deviation of 1. It helps your model to generally learn and update its parameters efficiently.
The second set of options is Image augmentation. They tell the ImageDataGenerator to randomly apply some transformation to the Image. This will help to augment our data-set and improve generalization.
Here we also create an ImageDataGenerator object for our validation set. Note: we don’t do data augmentation here. We only perform rescale.
Now that we have the ImageDataGenerator objects, let's create python generators from them by passing our train and validation set.
We call the .flow( ) method on the data generators we created above passing in the data and label set. X_train and y_train for training then X_val and y_val for validation.The batch size tells the data generator to only take the specified batch(32 in our case) of Images at a time.Now we train our network by calling .fit( ) method on the model and passing some parameters. The first parameter is the training set ImageDataGenerator object [train_generator].Here we specify the number of steps per epoch. This tells our model how many images we want to process before making a gradient update to our loss function.A total of 3200 images divided by the batch size of 32 will give us 100 steps. This means we going to make a total of 100 gradient update to our model in one pass through the entire training set.An epoch is a full-cycle or pass through the entire training set. In our case, an epoch is reached when we make 100 gradient updates as specified by our steps_per_epoch parameter. Epochs = 64, means we want to go over our training data 64 times and each time we will make gradient updates 100 times.We pass in our validation data generator.We set the step size here too. I’m going to use the same step size as stated above.
We call the .flow( ) method on the data generators we created above passing in the data and label set. X_train and y_train for training then X_val and y_val for validation.The batch size tells the data generator to only take the specified batch(32 in our case) of Images at a time.
Now we train our network by calling .fit( ) method on the model and passing some parameters. The first parameter is the training set ImageDataGenerator object [train_generator].
Here we specify the number of steps per epoch. This tells our model how many images we want to process before making a gradient update to our loss function.A total of 3200 images divided by the batch size of 32 will give us 100 steps. This means we going to make a total of 100 gradient update to our model in one pass through the entire training set.
An epoch is a full-cycle or pass through the entire training set. In our case, an epoch is reached when we make 100 gradient updates as specified by our steps_per_epoch parameter. Epochs = 64, means we want to go over our training data 64 times and each time we will make gradient updates 100 times.
We pass in our validation data generator.
We set the step size here too. I’m going to use the same step size as stated above.
Run the cell to start training....This will take a while. Go disturb someone on twitter...
Well after just 64 epochs, I got an accuracy of roughly 80%.
Not bad for a model we trained from scratch with very little data.
Maybe increasing the number of epochs and playing with some hyperparameters like batch size and the optimizer will help improve this score.
I ‘ll leave that to you to explore.
Next, we save our model, with the simple Keras function shown below, this way we can re-use it anytime instead of training again when rerunning our notebook.
#Save the modelmodel.save_weights('model_wieghts.h5')model.save('model_keras.h5')
We’ll plot some graphs of the accuracy and the loss in both the train and validation set to see if we can get some insights.
After training a Keras model, it always calculates and saves the metric we specified when we compiled our model in a variable called history. We can extract these values and plot them.Note: The history object contains all the updates that happened during training.Here we simply get the size of our epoch from the number of values in the ‘acc’ list.Here we plot the accuracy against the epoch size.Here we plot the loss against the epoch size.
After training a Keras model, it always calculates and saves the metric we specified when we compiled our model in a variable called history. We can extract these values and plot them.Note: The history object contains all the updates that happened during training.
Here we simply get the size of our epoch from the number of values in the ‘acc’ list.
Here we plot the accuracy against the epoch size.
Here we plot the loss against the epoch size.
So what can we take away from this plot?
The first thing to note is that we’re not overfitting as the train and validation accuracy are pretty close and following each other.We can also notice that the accuracy keeps increasing as the epoch increases, giving us the intuition that increasing the epoch size will likely give us a higher accuracy.
The first thing to note is that we’re not overfitting as the train and validation accuracy are pretty close and following each other.
We can also notice that the accuracy keeps increasing as the epoch increases, giving us the intuition that increasing the epoch size will likely give us a higher accuracy.
We’re still not overfitting as both train and validation loss are trending down closely just like the accuracy plot above and the loss will likely go lower if we increase the epoch size..
So there, you’ve got some intuition. Now try increasing the epoch size and play around with some hyperparameters.
Before I conclude this tutorial we’re going to test our model on some Images from the test set.
We perform the same pre-processing we did on the train and validation set.
We read and convert the first 10 images in our test set to a list of array.Note: y_test will be empty because the test set has no label.We convert the list of array to one big numpy array.We create a test ImageDataGenerator and perform normalization only.Note: We do not augment the test set .
We read and convert the first 10 images in our test set to a list of array.Note: y_test will be empty because the test set has no label.
We convert the list of array to one big numpy array.
We create a test ImageDataGenerator and perform normalization only.Note: We do not augment the test set .
Now we’ll create a simple for loop, that iterates over the Images from the generator to make predictions. Then we’ll plot the results.
Create a list to hold the labels we are going to generate.We set the figure size of the images we’re going to plot.Here we make a prediction on that particular image provided by the ImageDataGenerator by calling the .predict( ) method on our trained model.The pred variable is a probability of how sure the model is that the current image is a dog. Since we gave dogs a label of 1, a high probability — at least greater than average 0.5 — means our model is very confident that the image is a Dog, otherwise it is a cat.So we simply create an if -else statement that appends the string ‘Dog’ if the probability is greater than 0.5 otherwise it appends ‘cat’ to the text_label.We do this so we can add a title to the image when we plot it.Here we add a subplot so we can plot multiple images.Here we add the predicted class as a title to the image plot.We finally plot the image.
Create a list to hold the labels we are going to generate.
We set the figure size of the images we’re going to plot.
Here we make a prediction on that particular image provided by the ImageDataGenerator by calling the .predict( ) method on our trained model.
The pred variable is a probability of how sure the model is that the current image is a dog. Since we gave dogs a label of 1, a high probability — at least greater than average 0.5 — means our model is very confident that the image is a Dog, otherwise it is a cat.So we simply create an if -else statement that appends the string ‘Dog’ if the probability is greater than 0.5 otherwise it appends ‘cat’ to the text_label.We do this so we can add a title to the image when we plot it.
Here we add a subplot so we can plot multiple images.
Here we add the predicted class as a title to the image plot.
We finally plot the image.
Let’s see how our model performed on previously unseen images.
Well....our model got one wrong from five images. I didn’t say it was at its best....at least not yet.
Wheeeew.... it’s been a long post, but I guess it was worth it. In this next tutorial, we improved our model to achieve an accuracy of about 95% by using a pre-trained network. A process called Transfer Learning.
Well, bye for now and happy coding.
Link to this notebook on Github.
Some amazing post and write-ups on CNN and Keras.
CS231n Convolutional Neural Networks for Visual Recognition.
Deep learning with python by Francois Chollet the creator of Keras.
Convolution Neural network basics.
A great medium post on CNN.
An Intuitive guide to CNN | medium post.
Keras tutorial.
Questions, comments and contributions are welcome.
Connect with me on twitter .
Connect with me on Instagram.