TypeError when trying to compute the loss

Hello,

I am trying to create a CNN implemented with data augmentation in pytorch to classify dogs and cats. The issue that I am having is that when I try to input my dataset and enumerate through it I keep getting this error:

TypeError: eq received an invalid combination of arguments - got (Variable), but expected one of:
 * (int value)
     didn't match because some of the arguments have invalid types: (!Variable!)
 * (torch.LongTensor other)
     didn't match because some of the arguments have invalid types: (!Variable!)

and I really dont know whats wrong with my code. I have provided the code below:

# Importing the libraries
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable
import torchvision
from torchvision import transforms

#Creating the CNN Model
class CNN(nn.Module):
    def __init__(self, nb_outputs):
        super(CNN, self).__init__() #activates the inheritance and allows the use of all the tools in the nn.Module
        #making the 3 convolutional layers that will be used in the convolutional neural network
        self.convolution1 = nn.Conv2d(in_channels = 3, out_channels = 32, kernel_size = 5) #kernal_size -> the deminson of the feature detector e.g kernel_size = 5 => feature detector of size 5x5
        self.convolution2 = nn.Conv2d(in_channels = 32, out_channels = 64, kernel_size = 2)
        #making 2 full connections one to connect the inputs of the ANN to the hidden layer and another to connect the hidden layer to the outputs of the ANN
        self.fc1 = nn.Linear(in_features = self.count_neurons((3, 64,64)), out_features = 40)
        self.fc2 = nn.Linear(in_features = 40, out_features = nb_outputs)
    
    def count_neurons(self, image_dim):
        x = Variable(torch.rand(1, *image_dim)) #this variable repersents a fake image to allow us to compute the number of neruons
        #in order to pass the elements of the tuple image_dim into our function as a list of arguments we need to add a * before image_dim
        #since x will be going into our neural network we need to convert it into a torch variable using the Variable() function
        x = F.relu(F.max_pool2d(self.convolution1(x), 3, 2)) #first we apply the convolution to x then apply max_pooling to the convolutional fake images and then activate all the neurons in the pooling layer
        x = F.relu(F.max_pool2d(self.convolution2(x), 3, 2)) #the signals are now propragated up to the thrid convoulational layer
        #Now to flatten x to obtain the number of neurons in the flattening layer
        return x.data.view(1, -1).size(1) #this will flatten x into a huge vector and returns the size of the vector, that size repersents the number of neurons that will be inputted into the ANN
        #even though x is not a real image from the game since the size of the flattened vector only depends on the dimention of the inputted image we can just set x to have the same dimentions as the image

    def forward(self, x):
        x = F.relu(F.max_pool2d(self.convolution1(x), 3, 2)) #first we apply the convolution to x then apply max_pooling to the convolutional fake images and then activate all the neurons in the pooling layer
        x = F.relu(F.max_pool2d(self.convolution2(x), 3, 2)) 
        #flattening layer of the CNN
        x = x.view(x.size(0), -1)
        #x is now the inputs to the ANN
        x = F.relu(self.fc1(x)) #we propagte the signals from the flatten layer to the full connected layer and activate the neruons by breaking the linearilty with the relu function
        x = F.sigmoid(self.fc2(x))
        #x is now the output neurons of the ANN
        return x 
    
train_tf = transforms.Compose([transforms.RandomHorizontalFlip(),
                               transforms.Resize((64,64)),
                               transforms.RandomRotation(20),
                               transforms.RandomGrayscale(.2),
                               transforms.ToTensor()])   

test_tf = transforms.Compose([transforms.Resize((64,64)),
                              transforms.ToTensor()])    
    
training_set = torchvision.datasets.ImageFolder(root = './dataset/training_set',
                                                transform = train_tf)
test_set = torchvision.datasets.ImageFolder(root = './dataset/test_set',
                                                transform = test_tf)
    
trainloader = torch.utils.data.DataLoader(training_set, batch_size=32,
                                              shuffle=True, num_workers=0)
testloader = torch.utils.data.DataLoader(test_set, batch_size= 32,
                                             shuffle=False, num_workers=0)
    

#training the model
cnn = CNN(1)
cnn.train()
loss = nn.BCELoss()
optimizer = optim.Adam(cnn.parameters(), lr = 0.001) #the optimizer => Adam optimizer
nb_epochs = 25

for epoch in range(nb_epochs):
    train_loss = 0.0
    train_acc = 0.0
    total = 0.0
    for i, (inputs, labels) in enumerate(trainloader):
        inputs, labels = Variable(inputs), Variable(labels)
        cnn.zero_grad()
        outputs = cnn(inputs)
        loss_error = loss(outputs.squeeze(1), labels.float())
        optimizer.step()
        
        _, pred = torch.max(outputs.data, 1)
        total += labels.size(0)
        train_loss += loss_error.data[0]
        train_acc += (pred == labels).sum()
    
    train_loss = train_loss/len(trainloader)
    train_acc = train_acc/total
    print('Epoch: %d, loss: %.4f, accuracy: %.4f' %(epoch+1, train_loss, train_acc))

The folder arrangement for the code is /dataset/training_set and inside the training_set folder are two more folders one for all the cat images and the other for all the dog images. Each image is name either dog.xxxx.jpg or cat.xxxx.jpg, where the xxxx represents the number so for the first cat image it would be cat.1.jpg up to cat.4000.jpg. This is the same format for the test_set folder. The number of training images is 8000 and the number of test images is 2000. If anyone can point out my error I would greatly appreciate it.

Thank you

Hi,

I think the problem is that your loss function expect the labels as LongTensors and you give them as FloatTensors. You should try replacing labels.float() by labels.long().

But when I do that I get this error:

RuntimeError: Expected object of type Variable[torch.FloatTensor] but found type 
Variable[torch.LongTensor] for argument #1 'target'

Then it’s not that :slight_smile:
Where is the error raised exactly?

this is the full error message that is outputted:

Traceback (most recent call last):

File "<ipython-input-146-14775fff4081>", line 78, in <module>
   loss_error = loss(outputs.squeeze(1), labels.long())

File "/usr/local/lib/python3.6/site-packages/torch/nn/modules/module.py", line 325, in __call__
    result = self.forward(*input, **kwargs)

File "/usr/local/lib/python3.6/site-packages/torch/nn/modules/loss.py", line 372, in forward
    size_average=self.size_average)

File "/usr/local/lib/python3.6/site-packages/torch/nn/functional.py", line 1179, in binary_cross_entropy
    return torch._C._nn.binary_cross_entropy(input, target, weight, size_average)

RuntimeError: Expected object of type Variable[torch.FloatTensor] but found type 
Variable[torch.LongTensor] for argument #1 'target'

@albanD here is the other error message that I get when I use the initial code above:

File "<ipython-input-147-5a55720cc37f>", line 84, in <module>
    train_acc += (pred == labels).sum()

File "/usr/local/lib/python3.6/site-packages/torch/tensor.py", line 348, in __eq__
    return self.eq(other)

TypeError: eq received an invalid combination of arguments - got (Variable), but expected one of:
 * (int value)
      didn't match because some of the arguments have invalid types: (!Variable!)
 * (torch.LongTensor other)
      didn't match because some of the arguments have invalid types: (!Variable!)

What about trying

train_acc += (pred == labels.long()).sum()

@jpeg729 I get the same error:

Traceback (most recent call last):

File "<ipython-input-148-3ebf3de49d3a>", line 84, in <module>
train_acc += (pred == labels.long()).sum()

File "/usr/local/lib/python3.6/site-packages/torch/tensor.py", line 348, in __eq__
return self.eq(other)

TypeError: eq received an invalid combination of arguments - got (Variable), but expected one of:
* (int value)
  didn't match because some of the arguments have invalid types: (!Variable!)
* (torch.LongTensor other)
  didn't match because some of the arguments have invalid types: (!Variable!)

Try

train_acc += (pred == labels.data.long()).sum()