Panicking student.. How do I run a basic CNN? ):

Hello everyone! I’m trying to create a basic CNN using PyTorch, to classify 21 different types of land use. I have very limited time and my teachers are never available, so I’m placing my little S.O.S. here instead…

My data consists of 2100 RGB images, 100 for each class, and is stored in a list of format [image, label].

Data preparation is not the problem, but in case anyone needs to see how my data is loaded and formatted:

# Libraries.
import matplotlib.pyplot as plt
import cv2
import numpy as np
from skimage.io import imread
import random
from sklearn.model_selection import train_test_split
import os
import zipfile

# Create an empty training data list.
training_data = []

#Importing data:
datadir = "/content/ucmdata/Images" # Setting the common directory.
categories = ['agricultural', 'airplane', 'baseballdiamond', 'beach', 'buildings', 'chaparral', 'denseresidential', 'forest', 'freeway', 
              'golfcourse', 'harbor', 'intersection', 'mediumresidential', 'mobilehomepark', 'overpass', 'parkinglot', 'river',
              'runway', 'sparseresidential', 'storagetanks', 'tenniscourt']

# A function for loading in all data.
def create_training_data():
  # For each category of image:
  for category in categories:
    # Open the folder.
    path = os.path.join(datadir, category)
    # Take the index as a class number.
    class_number = categories.index(category)
    # For all images within:
    for image in os.listdir(path):
      # Read the image.
      image_array = cv2.imread(os.path.join(path, image))
      # Turn it into type float.
      image_array = image_array.astype('float32')
      # Normalize the image values between 0 and 1.
      image_array /= 255.0
      # Add it to the training data list.
      training_data.append([image_array, class_number])

# Run the function.
create_training_data()
# Review the length: 100 pictures x 21 categories should yield 2100 images.
print(len(training_data))
# Shuffle the data so that it is randomly ordered.
random.shuffle(training_data)

This is all fine. The problem is creating and running an actual CNN with this data. I understand the theory behind how CNNs work and thought I knew how to code one in a basic manner, but I was wrong.

I’ve scoured the internet for tutorials but every one I find seems to disagree with the other. I have made several attempts at different kinds of models, but all to no avail.

Here is my latest attempt… It’s a lot of code, and it’s a mess! I’m sorry :confused:

# Some tutorials tell me I need to split my training data into X and y lists.
# Others don't. I'm unsure what difference it makes.

# Create empty lists X (images), and y (labels).
X = []
y = []

# Create lists with images and class numbers respectively.
for image, classnum in training_data:
  # Transform the image into a tensor.
  image = torch.as_tensor(image)
  # Add it to list X.
  X.append(image)
  # Add the class numbers to list y.
  y.append(classnum)
# Each individual image is 256 by 256 by 3.

# I know what these parameters do, just haven't finetuned them.
num_epochs = 5
num_classes = 10
batch_size = 100
learning_rate = 0.001

# The model I ideally would like to run: 
model = nn.Sequential(
        # 1st convolution 5x5, padding 2, 6 output channels 
        nn.Conv2d(in_channels = 1, out_channels = 6, kernel_size = 5, padding = 0),
        # 1st activation function (sigmoid)
        nn.Sigmoid(),
        # 1st average pooling 2x2
        nn.MaxPool2d(2),

        # 2nd convolution 5x5, no padding, 16 output channels
        nn.Conv2d(in_channels = 6, out_channels = 16, kernel_size = 5),
        # 2nd activation function (sigmoid)
        nn.Sigmoid(),
        # 2nd avg pooling
        nn.MaxPool2d(2),

        # Flatten for the dense layers
        nn.Flatten(),
        
        # 3rd layer fully connected, outputs 120
        nn.Linear(16 * 5 * 5, 120), 
        # 3rd activation function (sigmoid)
        nn.Sigmoid(),
        
        # 4th layer fully connected, outputs 84
        nn.Linear(120, 84), 
        # 4th activation function (sigmoid)
        nn.Sigmoid(),

        # 5th layer fully connected, outputs 21 (for 21 classes?)
        nn.Linear(84, 21)
        )

# Forward: Some tutorials tell me I need this, others say I don't? What is forward?
#def forward(self, x):
#    out = self.layer1(x)
#    out = self.layer2(out)
#    out = out.reshape(out.size(0), -1)
#    out = self.drop_out(out)
#    out = self.fc1(out)
#    out = self.fc2(out)
#    return out

# The loss and optimizer, copypasted from a tutorial:
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

# The following code was also taken from one of the tutorials. I simply adjusted the variables.
# Gives me a "NotImplemented Error".
# No idea what's going wrong...
total_step = len(training_data)
loss_list = []
acc_list = []
# Training:
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(training_data):
        # Run the forward pass
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss_list.append(loss.item())

        # Backprop and perform Adam optimisation
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        # Track the accuracy
        total = labels.size(0)
        _, predicted = torch.max(outputs.data, 1)
        correct = (predicted == labels).sum().item()
        acc_list.append(correct / total)

        if (i + 1) % 100 == 0:
            print('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}, Accuracy: {:.2f}%'
                  .format(epoch + 1, num_epochs, i + 1, total_step, loss.item(),
                          (correct / total) * 100))

There’s a lot going on here, and I understand I can’t ask help for everything. My main question would therefore be limited to how I can get the basic model, the nn.Sequential(), in my code to work?

Any help would be greatly appreciated! I’m on a tight deadline and the teachers just practically not existing makes the task very overwhelming…

(I wish I could also attach the images I’m using, but unfortunately it’s a large zip and I’m (understandably) not allowed to. I hope what I was able to share still gives a good indication!)

Hi Belinda!

Excellent! This sounds like a worthy neural-network problem.

We may not be able to help with this bit. It takes a fair amount of time
to learn to design neural networks, and it takes a fair amount of time
to actually code them. (It takes a fair amount of time to actually code
anything – at least correctly.)

With this the forum will be able to help.

But you’ll need to ask concise questions about one issue at a time.

Best of all is if you can post a short, but complete and runnable script
that illustrates the specific issue you are asking about. Something like:
“I need to get result A, but calling function f() in my example script
gives me B. Why do I get B and what do I need to do to get A?”

(And then post your complete, runnable script that gives result B.)

Also, pytorch is pretty big, with lots of classes and functions (because
neural networks can be complicated with lots of different building
blocks inside of them).

I would strongly advise to go through some of the core building blocks
step by step before putting them together into a more complicated
“real” project. Pytorch has many good tutorials to help you do this.
Depending on your working style, I think the What is torch.nn really?
tutorial could be a very good place to start.

Good luck.

K. Frank

Thank you so much for your reply! I realize my own reply is a bit late, but that is because the link you have sent me has worked wonders so far. :slight_smile: It starts from the very beginning and shows everything step by step without assuming you know a lot already, and that turned out to be exactly what I needed.

I have now managed to get a dummy network running (though I’m still figuring out how to display its results, but it runs over my training data at the very least!). I’m now going to work on retrieving the output so I can see what it actually does. And I’ll still have to incorporate validation data, too. I’m no doubt going to run into more issues further down the line, but I can post them in this thread if I get stuck again.

For the time being, I just wanted to thank you and let you know that the link has really helped!

Hi Belinda!

Great news – Happy Neural-Network Programming!

If you have more questions, please feel free to post them. But please
start new threads for them. Post one reasonably-self-contained question
in an individual thread that has a (reasonably) self-explanatory title.

Good luck.

K. Frank