Output classes not matching with the labels


(Shikhar Saxena) #1

Hi,
I have constructed a neural network with as follows:
class Network(nn.Module):

class Network(nn.Module):
    
    def __init__(self):
        super().__init__()
        self.fc1=nn.Linear(3840, 256)
        self.fc2=nn.Linear(256,128)
        self.fc3=nn.Linear(128,64)       
        self.fc4=nn.Linear(64,1)
        
    def forward(self,x):
        x=F.relu(self.fc1(x))
        x=F.relu(self.fc2(x))
        x=F.relu(self.fc3(x))
        x=self.fc4(x)
        
        return x
    ```
Here I expect the output to be just one value. However, I get the above error while calculating the crossentropyloss. When i checked my target , it has values ranging from 0 to 7 indicating the number of classes to be 8. I am providing a one dimensional vector as my target and converting it into tensor using

Variable(torch.FloatTensor(labels).long(),requires_grad=False)

However, when I changed the number of output nodes in my network to 8, my network is training properly.
Can anyone tell me why this problem is occuring?
My whole code is: 

class Network(nn.Module):

def __init__(self):
    super().__init__()
    self.fc1=nn.Linear(3840, 256)
    self.fc2=nn.Linear(256,128)
    self.fc3=nn.Linear(128,64)       
    self.fc4=nn.Linear(64,1)
    
def forward(self,x):
    x=F.relu(self.fc1(x))
    x=F.relu(self.fc2(x))
    x=F.relu(self.fc3(x))
    x=self.fc4(x)
    
    return x

data1 = pd.read_csv(“features_cnormal.csv”, index_col=0, header=0)
X = data1.values

target = pd.read_csv(“y.csv”)
y=target.values

model = Network()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr = 0.01)

scaler = preprocessing.StandardScaler()
Xs = scaler.fit_transform(X)

Xtrain, ytrain = Xs, y

XTrain = torch.from_numpy(Xtrain).type(torch.FloatTensor)
YTrain = torch.from_numpy(np.array(ytrain).reshape((-1, 1))).type(torch.FloatTensor)

train = torch.utils.data.TensorDataset(XTrain, YTrain)

train_loader = torch.utils.data.DataLoader(train, batch_size=10, shuffle=True)

#print(data for i, data in enumerate(train_loader))
epochs = 100

for e in range(epochs):
running_loss = 0
for i, data in enumerate(train_loader):
inputs, labels = data

    X1, Y1 = Variable(torch.FloatTensor(inputs),requires_grad=False), \
                                            Variable(torch.FloatTensor(labels).long(),requires_grad=False)
 
    output = model(X1)

    Y1=Y1.view(-1)
    loss = criterion(output, Y1)

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    
    running_loss += loss.item()
    
else:
    print(f"Training loss: {running_loss/len(train_loader)}")

(Ashish Gupta) #2

You are doing a classification problem as I understand. CrossEntropy loss will convert each target value in one hot vector ranging to 7(one hot vector conversion is done by framework on its own).
So to calculate loss you need your network to output values as a vector contaning 8 values .
As in labels/target contain–
eg-[1 0 0 0 0 0 0 0] represents 0 and -[0 0 0 0 1 0 0 0] represents 4 and cross entropy will then calculate loss one by one.
Thats why it gives error when your network will output single value . As it cannot able to compare single by network to 8 values(one hot) in target.


(Shikhar Saxena) #3

Thanks for the reply @Ashish_Gupta1. That is indeed what is happening.
However, I want my network to give single float output and then calculate loss with respect to the target. How should I go about doing that? Do I have to use some other loss function ?


(Ashish Gupta) #4

If you want your network to give a single output then just try changing the loss to L1Loss. https://pytorch.org/docs/stable/nn.html#l1loss

But as I know if you are doing a classification problem then you need to follow something else. Just apply an activation after the last layer(containing 8 nodes). And then go by cross-entropy.
Basically, then your network will output 8 different values and each value tell the probability to occur for that class. So the node that contains the max value will be your class(predicted output).

I am still don’t get why you want to output a single value.
Please print your target/label and post it.