Do the reading

Before you attempt this assignment you should read chapters seven and eight in the textbook, and also look over the supplemental notes on the history of neural networks for image processing that we linked to from the course web site.

Grab the data set

To download the data set of images we will be using for this assignment, run the following two commands in a terminal pane in your server account:

wget http://www.lawrence.edu/fast/greggj/CMSC490/cats_vs_dogs_small.zip
unzip cats_vs_dogs_small.zip

Inside the expanded folder you will find various subfolders containing images of cats and dogs for training and for testing.

You will be doing all of your work for this assignment in a Jupyter notebook. Set up a new, empty notebook in the same directory where your images folder is located.

Study an example online

In this assignment we are going to construct a model that can correctly distinguish images of dogs from images of cats.

For almost any problem you set out to solve in neural networks, someone has already solved a similar problem. Often, you can get a head start on solving your problem by studying the solution to a similar problem.

For this assignment I have located an example online where someone has used a transfer learning strategy to train a pytorch network to distinguish two classes of images.

You can find that starter code at this URL:

https://www.kaggle.com/code/pmigdal/transfer-learning-with-resnet-50-in-pytorch

In that example code you will see the author setting up some code to load the data from the image files. The strategy that the author of the page uses to build a classifier is a widely-used strategy called transfer learning. In this approach we start with a pretrained image classifier network and then add an addition classifier layer on top to solve the task at hand. In the example code the author uses a pretrained ResNet50 network. To build our classifier we freeze the parameters in the network and bolt on a final classifier layer that is trainable:

resnet = models.resnet50(pretrained=True).to(device)

for param in resnet.parameters():
    param.requires_grad = False   
    
resnet.fc = nn.Sequential(
               nn.Linear(2048, 128),
               nn.ReLU(inplace=True),
               nn.Linear(128, 2)).to(device)

We can use exactly the same approach.

Modify the example as needed

Although we will be using the same network architecture as the online example, we will have to make some adjustments.

The main adjustment will be necessary to handle some differences in the image data set the author is using the data set we have to work with. This will require us to use slightly different preprocessing logic when setting up our datasets. Replace the author's preprocessing logic with transforms that do the following:

  1. Resize the images to 224 by 224 pixels.
  2. Convert the images to pytorch tensors.
  3. Normalize the images using the same logic that our textbook uses in chapter 7.

You can use the same training loop as the author. You will have to experiment with the number of epochs to run to get reasonable results. (Be careful that you don't set the number of epochs too high at start - it will take forever to run through the training if you do.)

Note that our data set contains separate training, validation and test sets. After you train the network you would run the test data set through it to see how well the network does on that set.

Turn in your work

When you are finished, upload your Jupyter notebook to the course Canvas page.