Negative output from neural network?

I’m currently trying to build a network for Human Activity Recognition using pyTorch and DSADS dataset.

This is my neural network definition.

import torch.nn as nn

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.relu = nn.ReLU()
        self.pool = nn.MaxPool2d((1, 2), stride=2)

        self.conv1 = nn.Conv2d(6,16, (1, 6))
        self.conv2 = nn.Conv2d(16,32, (1, 6))

        self.fc1 = nn.Linear(32 * 1 * 3, 70)
        self.fc2 = nn.Linear(70, 30)
        self.fc3 = nn.Linear(30, 19)

    def forward(self, x):
        x = self.conv1(x)
        x = self.relu(x)
        x = self.pool(x)
        x = self.conv2(x)
        x = self.relu(x)
        x = self.pool(x)
        x = x.view(x.size()[0], -1)
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        x = self.relu(x)
        x = self.fc3(x)
        return x

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.0001, momentum=0.9, weight_decay=0.005)

This is how I load train and test data.

class data_loader(Dataset):
    def __init__(self, samples, labels, t):
        self.samples = samples
        self.labels = labels
        self.T = t
        
    def __getitem__(self, index):
        sample, target = self.samples[index], self.labels[index]
        if self.T:
            return self.T(sample), target
        else:
            return sample, target

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

# train_data_reshaped: numpy array of dimension (57000, 6, 1, 30)
# test_data_reshaped: numpy array of dimension (22800, 6, 1, 30)
train_set = data_loader(train_data_reshaped, train_labels, transform)
    test_set = data_loader(test_data_reshaped, test_labels, transform)
    train_loader = DataLoader(train_set, batch_size=64, shuffle=True, drop_last=True)
    test_loader = DataLoader(test_set, batch_size=64, shuffle=False)

Training and testing:

for epoch in range(30):
    for (inputs, labels) in train_loader:
        inputs, labels = inputs.to(device).float(), labels.to(device)
        inputs = inputs.view(-1, 6, 1, 30)
        labels = labels[:, -1].long()
        labels = labels - 1        
        optimizer.zero_grad()
        outputs = net(inputs)
        print("outputs: ", outputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

    for (inputs, labels) in test_loader:
        inputs, labels = inputs.to(device).float(), labels.to(device)
        inputs = inputs.view(-1, 6, 1, 30)        
        labels = labels[:, -1].long()
        labels = labels - 1
        optimizer.zero_grad()
        outputs = net(inputs)
        loss = criterion(outputs, labels)

I expect the net will produce non-negative outputs each of them represents probability. However, my net produces negative output like this:

outputs:  tensor([[-0.2586, -0.0550,  0.2156,  ...,  0.0132, -0.1516,  0.0052],
        [-0.2586, -0.0952,  0.2352,  ...,  0.0199, -0.1925,  0.0107],
        [-0.4870, -0.0813,  0.4605,  ...,  0.0353, -0.1569,  0.0322],
        ...,
        [-0.2445, -0.1426,  0.1625,  ...,  0.0872, -0.1863,  0.0826],
        [-0.3659, -0.1266,  0.3297,  ...,  0.0860, -0.1500,  0.0035],
        [-0.3237, -0.0675,  0.2883,  ...,  0.0384, -0.2692,  0.0562]],
       grad_fn=<AddmmBackward>)

Any idea of what I did wrong? Thanks in advance.

It’s okay that the net produces negative output, to get the actual prediction you can use argmax, or if you prefer the probabilities use softmax after net output

Thank you for your reply. However, my accuracy and loss did not change much in the whole learning process. I have tried changing the optimizer to Adam optimizer, learning rate, but the accuracy and loss still do not change.
Any idea where I can start inspecting?

This is how I calculated accuracy and loss

for (inputs, labels) in test_loader:
        inputs, labels = inputs.to(device).float(), labels.to(device)
        inputs = inputs.view(-1, 6, 1, 30)        
        labels = labels[:, -1].long()
        labels = labels - 1
        optimizer.zero_grad()
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        sum_loss += loss.item()
        predicted = torch.argmax(outputs, dim=1)
        sum_total += labels.size(0)
        sum_correct += (predicted == labels).sum().item()
        print("test  mean loss={}, accuracy={}"
            .format(sum_loss*BATCH_SIZE/len(test_loader.dataset), float(sum_correct/sum_total)))
    test_loss_value.append(sum_loss*BATCH_SIZE/len(test_loader.dataset))
    test_acc_value.append(float(sum_correct/sum_total))

Accuracy:

Loss looks like this:

Try to scale down the use case and overfit a small dataset, e.g. just 10 samples by playing around with the hyperparameters.
If that doesn’t work at all there might be an issue in the code we haven’t seen yet.

Hi @SarahTeoh. I’m facing a problem almost exactly like the one you have described here. Have you found out what was wrong?