The code!

Before we begin, you should make sure you have a folder called images with two subfolders called cats and dogs that contain roughly the same number of images which are all exactly 128*128

Imports

1–9 We import all the libraries that we will be using

Loading X data

11 We create a subroutine called load_images that takes the argument directories which will default to an empty list if the argument is omitted when calling the subroutine

12 We create an empty list called imgs to store our images in

13 We loop over each directory in our directories list, this means we will run the indented code on every directory in the list

14 We loop over each file in a list of all the files in the directory that we are currently on, this means we will run the indented code on every file in the directory

15 We load the image in the directory directory with the filename file

16 We convert img to a numpy array

17 We divide all the values in img by 255 and then append it to imgs. We divide by 255 as it is standard ML practice to normalize data to be between -1 and 1. But with relu all negative numbers=0 so we scale our image data which is formed of values between 0 and 255 for the intensity of red, green and blue to be between 0–1.

A network learn to use 0–255 but weights will typically converge faster with 0–1 and the network we will transfer train later has been trained to expect values 0–1 so we are best off having our training data as 0–1.

19 We return the list of images

Loading Y data

21 We create a subroutine called load_y that takes the argument directories which will default to an empty list if the argument is omitted when calling the subroutine

22 We create a list called y_data to store our Y data in

23–24 We add 1,0 (0 one hot encoded) to y_data the number of times that is the number of files in the first directory in directories (cats)

25–26 We add 0,1 (1 one hot encoded) to y_data the number of times that is the number of files in the second directory in directories (dogs)

28 We return the y_data list

Actually loading the data

30 We store the directories that our images are in in a variable ready to pass to our load_images and load_y subroutines. If for some reason you have your images in different folders change the folders here.

31 We call our load_y subroutine with the directories that dirs we defined on the previous line and store it’s output as a numpy array in the Y variable

32 Same as 30 but with load_images and the X variable

33 We print the length of the output of load_images followed by the word images. If you have a lot of images it would be wise to omit this step.

35 We split the data into train and test sets with 25% of the data in test

Creating the model

37 We store our image dimensions. If you are using different dimensions you should change this line to match your dimensions.

38 We store our image shape in a variable

40 We load mobilenet, which is a common CNN architecture that is optimized for use in apps on mobile devices. As a result of these optimizations, it is quicker to predict and train and has a smaller file size at the cost of some accuracy. Although we won’t be deploying to mobile, we don’t need the power of larger models such as Inception for our binary classification task. We tell Keras to download a model file that has already been trained on all of imagenet, that we don’t want the top (the dense layer after all the convolutional layers) layer and that we want the model that has been trained on and so is expecting images with the same shape (same resolution and in colour) that we defined earlier

41 We create a new sequential model in Keras

42 We add mobilenet in the config we specified on line 39 as our first layer (in reality it’s an entire model but from the viewpoint of this new model it’s a single layer)

43 We add a flattening layer to turn the mobilenet output from a 2D image to 1D data that a dense layer can understand

44 We create our final layer and with 2 neurons as there are 2 columns in our output, the 0th (cat) and the 1st (dog)

46 We print a summary of the model for sanity checking

Callbacks

48–49 We create a ModelCheckpoint callback to save our model, everytime the loss on the test data is the best it’s been so far in training, with the filename model.h5 and put it in a list as this is what Keras requires

Training the model

51 We compile our model with Adam with 0.0001 learning rate instead of the default 0.001 as the model has already learnt and just needs fine tuning

52 We fit the model for only 10 epochs as it is prone to overfitting and shouldn’t take long to fine tune it’s self for our data