Getting Started with Custom Neural Network, Help Needed

Hi All,

I’m having an issue getting started with training a neural network with a custom dataset. My code is included below:

import torch
from torch import nn
from torch.utils.data import Dataset, DataLoader, random_split
import os
import pandas as pd
from NNModel import NeuralNetwork

# Define Custom Dataset to contain all the training data
class CustomDataLoader(Dataset):
    def __init__(self, annotations_file, data_dir):
        self.labels = pd.read_csv(annotations_file)
        self.data_dir = data_dir

    def __len__(self):
        return len(self.labels)

    def __getitem__(self, idx):
        data_path = os.path.join(self.data_dir, self.labels.iloc[idx,0])
        data = pd.read_csv(data_path)
        mu = self.labels.iloc[idx,1]
        sigma = self.labels.iloc[idx,2]
        return data, mu, sigma

# Parameters for taking a random sample of the data for validation
dataset = CustomDataLoader("data/labels.csv", "data")
batch_size = 100
validation_split = 0.25
random_seed = 42

# Split data into Training data and Validation data
train_set, valid_set = random_split(dataset, [1 - validation_split, validation_split], generator=torch.Generator().manual_seed(random_seed))

# Ensure GPU is available
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Device being utilized: {device}")

# Load DataLoaders
train_loader = DataLoader(train_set.dataset, batch_size=batch_size, shuffle=True, pin_memory_device=device, pin_memory=True)
valid_loader = DataLoader(valid_set.dataset, batch_size=batch_size, shuffle=True, pin_memory_device=device, pin_memory=True)

# Create NN model to train
model = NeuralNetwork().to(device)
print(f"{model}\n")

# Define model loss function and optimizer
loss_fn = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)

# Define the training method for the NN
def train(dataloader, model, loss_fn, optimizer):
    size = len(dataloader.dataset)
    model.train()
    for batch, (X, mu, sigma) in enumerate(dataloader):
        X, mu, sigma = X.to(device), mu.to(device), sigma.to(device)

        # Compute prediction error
        pred = model(X)
        target = torch.column_stack((mu,sigma)).to(torch.float32).to(device)
        loss = loss_fn(pred, target)

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

        if batch % 10 == 0:
            loss, current = loss.item(), batch * len(X)
            print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}]")

# Define the testing methodfor the NN
def test(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    model.eval()
    test_loss, correct = 0, 0
    with torch.no_grad():
        for X, mu, sigma in dataloader:
            X, mu, sigma = X.to(device), mu.to(device), sigma.to(device)
            pred = model(X)
            target = torch.column_stack((mu,sigma)).to(torch.float32).to(device)
            test_loss += loss_fn(pred, target).item()
            correct += (pred == target).sum().item()
    test_loss /= num_batches
    correct /= size
    print(f"Test Error: \n Accuracy: {(100*correct):>1f}%, Avg Loss: {test_loss:>8f} \n")

if __name__ == '__main__':
    # Train the Model
    epochs = 5
    for t in range(epochs):
        print(f"Epoch {t+1}\n----------------------------------------")
        train(train_loader, model, loss_fn, optimizer)
        test(valid_loader, model, loss_fn)
    print("Done!")

    torch.save(model.state_dict(), "model.pth")
    print("Saved PyTorch Model State to model.pth")

The model is defined like so:

import torch
from torch import nn

class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(2400, 1200),
            nn.ReLU(),
            nn.Linear(1200, 600),
            nn.ReLU(),
            nn.Linear(600, 300),
            nn.ReLU(),
            nn.Linear(300, 150),
            nn.ReLU(),
            nn.Linear(150, 75),
            nn.ReLU(),
            nn.Linear(75, 38),
            nn.ReLU(),
            nn.Linear(38, 19),
            nn.ReLU(),
            nn.Linear(19, 10),
            nn.ReLU(),
            nn.Linear(10, 5),
            nn.ReLU(),
            nn.Linear(5,2)
        )

    def forward(self, x):
        x = self.flatten(x)
        logits = self.linear_relu_stack(x)
        return logits

However, when I run, I get the following output and I cannot work out what to do. So would really appreciate any help:

Device being utilized: cuda
NeuralNetwork(
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (linear_relu_stack): Sequential(
    (0): Linear(in_features=2400, out_features=1200, bias=True)
    (1): ReLU()
    (2): Linear(in_features=1200, out_features=600, bias=True)
    (3): ReLU()
    (4): Linear(in_features=600, out_features=300, bias=True)
    (5): ReLU()
    (6): Linear(in_features=300, out_features=150, bias=True)
    (7): ReLU()
    (8): Linear(in_features=150, out_features=75, bias=True)
    (9): ReLU()
    (10): Linear(in_features=75, out_features=38, bias=True)
    (11): ReLU()
    (12): Linear(in_features=38, out_features=19, bias=True)
    (13): ReLU()
    (14): Linear(in_features=19, out_features=10, bias=True)
    (15): ReLU()
    (16): Linear(in_features=10, out_features=5, bias=True)
    (17): ReLU()
    (18): Linear(in_features=5, out_features=2, bias=True)
  )
)

Epoch 1
----------------------------------------
Traceback (most recent call last):
  File ".\NNTrain.py", line 92, in <module>
    train(train_loader, model, loss_fn, optimizer)
  File ".\NNTrain.py", line 53, in train
    for batch, (X, mu, sigma) in enumerate(dataloader):
  File ".\AppData\Roaming\Python\Python310\site-packages\torch\utils\data\dataloader.py", line 628, in __next__
    data = self._next_data()
  File ".\AppData\Roaming\Python\Python310\site-packages\torch\utils\data\dataloader.py", line 671, in _next_data
    data = self._dataset_fetcher.fetch(index)  # may raise StopIteration
  File ".\AppData\Roaming\Python\Python310\site-packages\torch\utils\data\_utils\fetch.py", line 61, in fetch
    return self.collate_fn(data)
  File ".\AppData\Roaming\Python\Python310\site-packages\torch\utils\data\_utils\collate.py", line 265, in default_collate
    return collate(batch, collate_fn_map=default_collate_fn_map)
  File ".\AppData\Roaming\Python\Python310\site-packages\torch\utils\data\_utils\collate.py", line 143, in collate
    return [collate(samples, collate_fn_map=collate_fn_map) for samples in transposed]  # Backwards compatibility.
  File ".\AppData\Roaming\Python\Python310\site-packages\torch\utils\data\_utils\collate.py", line 143, in <listcomp>
    return [collate(samples, collate_fn_map=collate_fn_map) for samples in transposed]  # Backwards compatibility.
  File ".\AppData\Roaming\Python\Python310\site-packages\torch\utils\data\_utils\collate.py", line 151, in collate
    raise TypeError(default_collate_err_msg_format.format(elem_type))
TypeError: default_collate: batch must contain tensors, numpy arrays, numbers, dicts or lists; found <class 'pandas.core.frame.DataFrame'>

Can anyone help?

Your dataloader is giving Pandas objects out. Need to convert them to Numpy or Torch tensors before sending to the model.

Hello,

Could you try returning tensors instead in CustomDataloader class ?

def __getitem__(self, idx):
        data_path = os.path.join(self.data_dir, self.labels.iloc[idx,0])
        data = pd.read_csv(data_path)
        mu = self.labels.iloc[idx,1]
        sigma = self.labels.iloc[idx,2]
        return torch.from_numpy(data.values).float(), torch.from_numpy(mu.values).float(), torch.from_numpy(sigma.values).float() 

Medhy

Thanks so much for your help! This has resolved the current issue.
Now just have to work out a better way of quantifying the “correctness” of the prediction.

I have now been able to train my model. I am now attempting to use the model to make predictions, however, once I pass the data tensor to the model:

import torch
from NNModel import NeuralNetwork
import numpy as np
from numpy import genfromtxt

model = NeuralNetwork()
model.load_state_dict(torch.load("model_100Epoch.pth"))

print(model)

data_path = "5.csv"
g = genfromtxt(data_path, delimiter=',')
g = g[:,1]
window_size = 10
window = np.divide(np.ones(window_size), window_size)
g_s = np.convolve(g, window, mode='valid')
g_s = np.multiply(g_s, -1)
g_s = np.divide(np.subtract(g_s, np.min(g_s)), np.max(g_s))
idx = np.argmax(g_s)
g_c = torch.from_numpy(g_s[(idx - 1200):(idx + 1200)]).to(torch.float32)

model.eval()
results = model(g_c)

I get the following error:

NeuralNetwork(
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (tanhshrink_stack): Sequential(
    (0): Linear(in_features=2400, out_features=1200, bias=True)
    (1): Linear(in_features=1200, out_features=600, bias=True)
    (2): Linear(in_features=600, out_features=300, bias=True)
    (3): Linear(in_features=300, out_features=150, bias=True)
    (4): Linear(in_features=150, out_features=75, bias=True)
    (5): Linear(in_features=75, out_features=38, bias=True)
    (6): Linear(in_features=38, out_features=19, bias=True)
    (7): Linear(in_features=19, out_features=10, bias=True)
    (8): Linear(in_features=10, out_features=5, bias=True)
    (9): Linear(in_features=5, out_features=2, bias=True)
  )
)
Traceback (most recent call last):
  File ".\Measure.py", line 23, in <module>
    results = model(g_c)
  .\AppData\Roaming\Python\Python310\site-packages\torch\nn\modules\module.py", line 1190, in _call_impl
    return forward_call(*input, **kwargs)
  File ".\NNModel.py", line 22, in forward
    x = self.flatten(x)
  .\AppData\Roaming\Python\Python310\site-packages\torch\nn\modules\module.py", line 1190, in _call_impl
    return forward_call(*input, **kwargs)
  .\AppData\Roaming\Python\Python310\site-packages\torch\nn\modules\flatten.py", line 46, in forward
    return input.flatten(self.start_dim, self.end_dim)
IndexError: Dimension out of range (expected to be in range of [-1, 0], but got 1)

What does this error mean? Am I passing the data to the model incorrectly?