Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Raenir Salazar
Nov 5, 2010

College Slice
I have a project where I need to train a CNN into detecting different classifications of lets say images of cars. Ford, Ferrari, Mitsubishi, and Toyota; while I can get datasets with lots of cars and maybe a dataset that is only ford I cannot seem to find a convenient dataset that has all four neatly divided into categories.

Is there a trick I can do on a dataset that I know has all four mixed together to neatly divide them (like I dunno, some sort of unsupervized clustering to try to pre-divide/sort the data to cut down on the work I have to do manually) or do I basically have to divide it all manually?

Or do we have a more dedicated data science thread for this question?

Adbot
ADBOT LOVES YOU

Raenir Salazar
Nov 5, 2010

College Slice
The requirements are for a minimum of 1200 training images and 400 testing images balanced between the four classes. Is it normal to just use the Mark 1 Eyeball for this? The programmer in me definitely feels like if there was a way to conveniently automate this I should, but that also sounds suspiciously exactly like the point of the project :v:

Raenir Salazar
Nov 5, 2010

College Slice
Just to be clear this is a university/school project, not something I'd have a budget for. :D The class is an introduction to AI sort of course as part of completing my BCompSci.

Raenir Salazar
Nov 5, 2010

College Slice
Yeah that's why I was checking to make sure I wasn't overcomplicating things or missing anything that I *should* be doing.

Raenir Salazar
Nov 5, 2010

College Slice
I went and by hand separated my images into their folders, took me like 8 hours while watching Let's Plays in the background. :toot:

My next challenge was to how to use these datasets with the example code of the various Labs we did in class so far.

I managed to stumble on Neural Network Console by Sony, which seems to not only let me produce a image classifier dataset, but works with subfolders and assigns labels based on the subfolders; yay.

Took me a couple of tries as while it will output a training set and a testing set, the code example I had would auto divide it randomly for me so I just outputted the whole dataset as 1 csv file which I loaded using a custom loader using some code I found online in a youtube tutorial.

This seems to work but then turns out my python environment is hosed because I get the error "Initializing libiomp5md.dll, but found mk2iomp5md.dll already initialized" with the problem being I must have some conflicted python library installed.

I pushed my code and now I wait as I try to reinstall spyder in a new conda python environment and reinstall my modules and hope that works.

Anyways here's my code so far:

(my loader)
code:
import os
import pandas as pd
import torch 
from torch.utils.data import Dataset 
from skimage import io

class CoolCarsDatasetLoader(Dataset):
    def __init__(self, csv_file, root_dir, transform=None):
        self.annotations = pd.read_csv(csv_file)
        self.root_dir = root_dir
        self.transform = transform
        
    def __len__(self):
        return len(self.annotations)
    
    def __getitem__(self, index):
        img_path = os.path.join(self.root_dir, self.annotations.iloc[index,0])
        image = io.imread(img_path)
        y_label = torch.tensor(int(self.annotaions.iloc[index, 1]))
        
        if self.transform:
            image = self.transform(image)
        return (image, y_label)
(using the loader)
code:
    dataset = CoolCarsDatasetLoader(csv_file = './data/project1dataset/coolcarsdataset.csv', 
                                     root_dir = './data/project1dataset',
                                     transform = transforms.ToTensor())
    # I had 1733+44 images in total
    train_set, test_set = torch.utils.data.random_split(dataset, [1733, 400])
    
    print("Train_set size: ", len(train_set)) # seems to work?
    print("Test_set size: ", len(test_set)) # seems to work?
    
    train_loader = DataLoader(dataset=train_set, batch_size=32, shuffle=True)
    test_loader = DataLoader(dataset=test_set, batch_size=32, shuffle=True)
Didn't seem to throw any fits until I added the code from my project partners to my code (my partners part of the code is actually constructing the CNN, training the CNN and evaluating it, we're a team of 3, so this is divided between us).

Raenir Salazar fucked around with this message at 23:35 on Jun 8, 2022

Raenir Salazar
Nov 5, 2010

College Slice
So after having to completely reinstall python/anaconda I managed to get cuda working for the PyTorch CNN; but the "Skorch" version just refuses to work on my GPU. I have device='cuda' in the NeuralNetClassifier constructor and I've confirmed that cuda/my gpu is available and working correctly, at least with PyTorch, but Skorch I have no indication that it's working; GPU usage is 2-5% when working with PyTorch but 0% when it gets to the Skorch version of my network.

Raenir Salazar
Nov 5, 2010

College Slice
So here's my current problem for a university project and my attempt to make it go a little faster using my GPU.

code:
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    if torch.cuda.is_available():
        print("CUDA is Available")
        print(torch.cuda.device(0))
        print(torch.cuda.get_device_name(0))
    else:
        print("Get a better computer.")
    
    model = CNN()
    model.to(device)
    criterion = nn.CrossEntropyLoss()
    optimizer = torch.optim.Adam(model.parameters(), lr=m_learning_rate)
    
    #training
    total_step = len(train_loader)
    loss_list = []
    acc_list = []
    
    for epoch in range(m_num_epochs):
        print("Epoch: ", epoch)
        for i, (images, labels) in enumerate(train_loader):
            #images = images.view(images.size(0), -1)
            images, labels = images.to(device), labels.to(device)
            #print("i: ", i)
            # Forward pass
            outputs = model(images)
            loss = criterion(outputs, labels)
            loss_list.append(loss.item())
    
            # Backprop and optimisation
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            # Train accuracy
            total = labels.size(0)
            _, predicted = torch.max(outputs.data, 1)
            correct = (predicted == labels).sum().item()
            acc_list.append(correct / total)
            if (i + 1) % 10 == 0:
                print('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}, Accuracy: {:.2f}%'
                .format(epoch + 1, m_num_epochs, i + 1, total_step, loss.item(),
                (correct / total) * 100))
This seems to work, and is faster, and using the GPU, albeit only 3-5% of the GPU is actually being utilized.

However using skorch it seems to be much slower and not using the GPU at all:

code:
    from torch.utils.data import random_split
    from sklearn.model_selection import cross_val_score
    from skorch.helper import SliceDataset
    
    m = len(train_set)
    train_set_size = int(m - m * 0.2)
    test_set_size = int(m * 0.2)
    rem = m - train_set_size - test_set_size
    train_data, val_data = random_split(train_set, [train_set_size+ rem, test_set_size])
    y_train = np.array([y for x, y in iter(train_data)])
    
    classes = ( 'cloth', 'n95', 'none', 'surgical' )
    new_net = NeuralNetClassifier(
        CNN,    # should match the part 1 for the model training
        max_epochs=m_num_epochs,
        iterator_train__num_workers=8,
        iterator_valid__num_workers=8,
        lr=m_learning_rate,  # maybe need to match
        batch_size=m_batch_size,  # maybe need to match
        optimizer=optim.Adam,
        criterion=nn.CrossEntropyLoss,
        device='cuda'
    )
Any idea what's up? I've tried googling but not much comes up that seems relevant to my use case.

Raenir Salazar
Nov 5, 2010

College Slice
Alrighty, I managed to determine that if I go to the Windows task manager performance monitor, and switch one of the windows to "CUDA" I can actually confirm that CUDA ranges between 41% to 94% usage; yay. So I guess my GPU IS being used, it's still going to be drat slow for reasons unknown to me then. Perhaps I'm loading/transfering the data in a way that isn't optimal?

Here's my network for reference:

code:
import torch.nn as nn

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.flatten = nn.Flatten()
        self.conv_layer = nn.Sequential(
            nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, padding=1),
            nn.BatchNorm2d(32),
            nn.LeakyReLU(inplace=True),
            nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, padding=1),
            nn.BatchNorm2d(32),
            nn.LeakyReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1),
            nn.BatchNorm2d(64),
            nn.LeakyReLU(inplace=True),
            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, padding=1),
            nn.BatchNorm2d(64),
            nn.LeakyReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2), # kernel size times image dims
        )
        
        self.fc_layer = nn.Sequential(
            nn.Dropout(p=0.1),
            nn.Linear(65536, 1000), # what it wants for a dataset with 128x128 images
            #nn.Linear(8 * 8 * 64, 1000), # original
            nn.ReLU(inplace=True),
            nn.Linear(1000, 512),
            nn.ReLU(inplace=True),
            nn.Dropout(p=0.1),
            nn.Linear(512, 4)
        )
        
    def forward(self, x):
        # conv layers
        x = self.conv_layer(x)
        # flatten
        x = x.view(x.size(0), -1) # batch size here?
        # fc layer
        x = self.fc_layer(x)
        return x
Which begs a follow up question; originally in the lab it was suggested 8 * 8 * 64 (64 being original batch size?) for the input size for the nn.Linear; but when I changed the resolution of my images to 128 by 128 pixels this gave me a mat1 and mat2 shapes cannot be multiplied error.

Based on googling the input for that first nn.Linear should be something like (??? * imageWidth * imageHeight) where ??? I think relates to the last output size of the last convolution layer? Is that the MaxPool2d since its a 2x2 matrix (4?)? 4*128*128 adds up to 65536 which is what the error is telling me it wants. "(32x65536 and 32768x1000)" as an example for an error I got when I thought it was 32 * 32 * 32.

The values otherwise for the Linear and Conv layers are all basically taken as-is from the class Labs and are essentially arbitrary as far as I'm aware; I have no idea if they are good values, I am reading https://towardsdatascience.com/pytorch-layer-dimensions-what-sizes-should-they-be-and-why-4265a41e01fd but their examples are a little different from the code I was given so I'm not really 100% understanding what's going on.

If I'm guess right here; originally the CIFAR10 dataset maybe was 32 by 32 images; there's two pooling layers (MaxPool2d) which I read somewhere does some math and cuts the resolution in half? So 32/2/2 is 8. So 8*8, and then the last Conv layer was 64 as its output, which would correspond to the original 8*8*64? Is that right?

So for 128by128, that would imply, 32*32*64? That would add up? Is that right?

Ideally I'd like to setup the inputs to be either automatic or easy to calculate based on my dataset image resolution and settings; and set it up so CUDA will do its drat job so I'm not twiddling my thumbs with my tiny dataset of just 2,000 images.

Raenir Salazar
Nov 5, 2010

College Slice
I think it might be how the data is loaded, because when I use pytorch it's blazingly fast.

As an aside, I can't figure this out but now my new problem is no matter what settings I adjust, like batch size, epochs, test data size etc, testing accuracy never gets above 47%. But the training accuracy easily reaches 100% with 20ish epochs.

Is this likely a result of bad data? Is 2,000 images total not enough?

Adbot
ADBOT LOVES YOU

Raenir Salazar
Nov 5, 2010

College Slice
I had an idea once back when I did QA work for (indirectly) WoTC of scanning MTG cards from the god book we were given for key phrases and use grammar rules to try to output all of our test cases/scripts for testing the cards in order to automate our work of thinking of and writing those test cases. My lead discouraged me from doing it so I never went through with it as I wanted to actually be paid for potentially eliminating my own job :v:

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply