Hello world,
in order to become familiar with machine learning I am implementing a CNN to work with the Malaria Cells Dataset from kaggle. The CNN is learning, and it predicts values, but they are completely useless.The accuracy is worse than hell and I dont know why. I paid attention to the topology and implementing non linear layers as well as an appropriate loss function. I wonder why the target tensor is a horizontal and not vertical, but this does not seem to be the problem. The prediction vector [value for class zero, value for class one] is nearly the same for every input. This does not make sense to me. When I use the Softmax Function at the end, then the prediction are nearly [0.5 0.5] for every Input after severa l epochs, but shows a loss of less than one of a thousand. I know, that these ‘predictions’ are in training mode(-/method), but they would perform even worse in evaluation mode I guess. Hence, I did not run the evaluation method and it’s not even implemented correctly. I really appreciate your help and thank you for your time.
Edit: Increasing the learning rate to 0.1 causes an output of nearly [1 0] for every input.
Edit 2: What I tried so far:
use torchvision normalization, use dropout, change SGD to Adam Optimizer, changed Learning Rate. Nothing helped.
Here is the Code
import torch
import torch.nn as nn
import torch.nn.functional
import torch.utils.data as d
import torchvision.datasets as tv
import torchvision.transforms as trans
import torch.nn.functional as F
import torch.optim as opt


class MalariaNetwork(nn.Module):
    
    def __init__(self):
        super(MalariaNetwork, self).__init__()
        
        
        self.conv1 = nn.Conv2d(1,8,kernel_size = (5,5)) 
        self.conv2 = nn.Conv2d(8,16, kernel_size = (3,3))
        self.conv3 = nn.Conv2d(16, 32, kernel_size = (3,3))
        self.conv4 = nn.Conv2d(32,64, kernel_size= (5,5))
        
        #Maxpool Layers
        self.maxp1 = nn.MaxPool2d((2,2))
        self.maxp2 = nn.MaxPool2d((2,2))
        self.maxp3 = nn.MaxPool2d((2,2))
        self.maxp4 = nn.MaxPool2d((2,2))
        
        #Linear Layers
        self.linear1 = nn.Linear(64*5*5, 600)
        self.linear2 = nn.Linear(600,100)
        self.linear3 = nn.Linear(100,2)
        
        
    
    def forward(self,x):
        
        x = F.relu(self.conv1(x))# In: 1*128*128, Out: 8x124x124
        #print(x.size())
        x = self.maxp1(x)        # In: 8x124x124, Out: 8*62*62
        #print(x.size())
        
        x = F.relu(self.conv2(x))# In: 8*62*62,   Out: 16*60*60
        #print(x.size())
        x = self.maxp2(x)        # In: 16x60x60,   Out: 16*30*30
        #print(x.size())
        
        x = F.relu(self.conv3(x))# In: 16*30*30,  Out: 32*28*28
        #print(x.size())
        x = self.maxp3(x)        # In: 32*28*28,  Out: 32*14*14
        #print(x.size())
        
        x = F.relu(self.conv4(x))# In: 32*14*14,  Out:64*10*10
        #print(x.size())
        x = self.maxp4(x)        # In: 64*10*10,  Out:64*5*5
        #print(x.size())
        
        x = x.reshape(-1,64*5*5)
        
        x = F.relu(self.linear1(x))
        #print(x.size())
        x = F.relu(self.linear2(x))
        #print(x.size())
        
        x =self.linear3(x)
        
        #x = F.softmax(x)
        #print(x.size())
        
        
        return x
        

data_transformations = [trans.Grayscale(),
                        trans.CenterCrop(128),
                        trans.ToTensor()]
        
def load_data(data_dir, train_perc = 10, val_perc = 70, batch_size = 10):
        
    dataset = tv.ImageFolder(data_dir, transform = trans.Compose(data_transformations))
    data_size = len(dataset) #Anzahl zu ladender Daten
        
    train_size, val_size = train_perc*data_size//100, val_perc*data_size//100 
    #print(train_size, val_size)
        
    indcs = list(range(data_size))
    train_indcs, val_indcs = indcs[(data_size//2)-(train_size//2) : (data_size//2)+(train_size//2) ], indcs[train_size:val_size] 
        
    train_sampler, val_sampler = d.SubsetRandomSampler(train_indcs), d.SubsetRandomSampler(val_indcs)
        
    train_loader = d.DataLoader(dataset, batch_size = batch_size, sampler = train_sampler) 
    eval_loader = d.DataLoader(dataset, batch_size =  batch_size, sampler = val_sampler) 
        
    return train_loader, eval_loader
        
def train(network =  None, epochs = 0, train_loader =  None, learning_rate = 0.001):
    
    network.train()
    optimizer = opt.SGD(network.parameters(), lr=learning_rate)
    loss_fn = torch.nn.CrossEntropyLoss()
    for epoch in range(epochs):
        
        
        for inputs, targets in train_loader:
            
            
            optimizer.zero_grad()
            
            outputs = network(inputs)
            loss = loss_fn(outputs, targets)
            loss.backward()
            
            optimizer.step()
            print(outputs, targets, epoch)
            #print("OP-Size: ",outputs.size(), "Target-Size: ", targets.size())
    return network
            
def evaluate(trained_network =  None, eval_loader =  None):
    
    trained_network.eval()
    
    for inputs, targets in eval_loader:
        
        output = trained_network(inputs)
        out_idx = torch.argmax(output, dim = 1)
        print(out_idx, targets)
        
    print("I am an evaluating Method!")
        
        
nw = MalariaNetwork()
train_loader, eval_loader = load_data('dir')
#print(nw)
trained_network = train(nw, epochs = 40, train_loader = train_loader, learning_rate= 0.01)
#evaluate(trained_network=trained_network, eval_loader = eval_loader)