What causes this model to not improve?

51 views Asked by At

I'm very new to pytorch and have a system that I believe can unpack and run through data, but when it does so the accuracy it returns with, even after hundreds of epochs, is still worse than random guessing.

I've tried altering batch size, layers, epoch numbers, learning rate, but nothing has worked. Here is the full code:

import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as pl
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
import numpy as np
import torch.optim

# device config
#device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
device = torch.device('cpu')

input_size = 5
hidden_size = 10
num_classes = 3
num_epochs = 100
batch_size = 10
learning_rate = 0.0001

class SDSS(Dataset):

    def __init__(self):
        # Initialize data, download, etc.
        # read with numpy or pandas
        xy = np.loadtxt('SDSS.csv', delimiter=',', dtype=np.float32, skiprows=0)
        self.n_samples = xy.shape[0]

        # here the first column is the class label, the rest are the features
        self.x_data = torch.from_numpy(xy[:, 1:]) # size [n_samples, n_features]
        self.y_data = torch.from_numpy(xy[:, [0]]) # size [n_samples, 1]

    # support indexing such that dataset[i] can be used to get i-th sample
    def __getitem__(self, index):
        return self.x_data[index], self.y_data[index]

    # we can call len(dataset) to return the size
    def __len__(self):
        return self.n_samples


#I like having this separate, so I remember why I called it when I look back.  Also, if I want to change only this later, I can.
class testSDSS(Dataset):

    def __init__(self):
        # Initialize data, download, etc.
        # read with numpy or pandas
        xy = np.loadtxt('SDSS.csv', delimiter=',', dtype=np.float32, skiprows=0)
        self.n_samples = xy.shape[0]

        # here the first column is the class label, the rest are the features
        self.x_data = torch.from_numpy(xy[:, 1:]) # size [n_samples, n_features]
        self.y_data = torch.from_numpy(xy[:, [0]]) # size [n_samples, 1]

    # support indexing such that dataset[i] can be used to get i-th sample
    def __getitem__(self, index):
        return self.x_data[index], self.y_data[index]

    # we can call len(dataset) to return the size
    def __len__(self):
        return self.n_samples

#easy to read labels 
dataset = SDSS()
test_dataset = testSDSS()

data_loader = DataLoader(dataset=dataset, batch_size=batch_size, shuffle=True, num_workers=0)
test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False, num_workers=0)

#Use LeakyReLu to preserve backwards attempts
#softmax is applied in pytorch through cross entropy
class NeuralNet(nn.Module):
    def __init__(self, input_size, hidden_size, num_classes):
        super(NeuralNet,self).__init__()
        self.l1 = nn.Linear(input_size, hidden_size)
        self.relu = nn.LeakyReLU()
        self.l2 = nn.Linear(hidden_size, num_classes)

    def forward(self, x):
        out = self.l1(x)
        out = self.relu(out)
        out = self.l2(out)
        return out

model = NeuralNet(input_size, hidden_size, num_classes)

dataiter = iter(data_loader)
data = next(dataiter)
features, labels = data

# loss and optimizer
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

#training loop

n_total_steps = len(dataset)
for epoch in range(num_epochs):

    print(f'epoch: {epoch} / {num_epochs}')

    for i, (inputs, labels) in enumerate(data_loader):

        #forward
        labels = labels.to(device)
        outputs = model(inputs)
        inputs = torch.flatten(inputs)
        labels = torch.flatten(labels)
        loss = criterion(outputs, labels.long())

        #backward
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if (i+1)%100 == 0:
            print(f'epoch {epoch + 1} / {num_epochs}, step {i+1}/{n_total_steps}, loss = {loss.item():.4f}')

#test
with torch.no_grad():
    n_correct = 0
    n_samples = 0
    for inputs, labels in test_loader:
        labels = labels.to(device)
        outputs = model(inputs)
        inputs = torch.flatten(inputs)
        labels = torch.flatten(labels)

        _, predictions = torch.max(outputs, 1)
        n_samples += labels.shape[0]
        n_correct = (predictions == labels).sum().item()
    
    acc = 100 * n_correct / n_samples
    print(f'accuracy = {acc}')
1

There are 1 answers

0
khushi-411 On

This happens because you are incorrectly accumulating the correct prediction (n_correct).

Just replace this line:

n_correct = (predictions == labels).sum().item()

with:

n_correct += (predictions == labels).sum().item()

Hope this helps you! Hit me up if you have any other questions. Thanks!