ValueError: Target and input must have the same number of elements. target nelement (20) != input nelement (1)

i’m trying to run my neural network on catVSdog dataset with the following script:

from sklearn.metrics import accuracy_score, roc_auc_score
import numpy as pp
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import TensorDataset, random_split, DataLoader
import os, cv2
import tqdm
### process data ###
data = []
i = 0

for image in tqdm.tqdm(os.listdir('Cat')):
    try:
        image = cv2.resize(cv2.imread(f'Cat/{image}', 0), (60, 60)) / 255.
        data.append((image, 1))
    except:
        i += 1
ii = 0
for image in tqdm.tqdm(os.listdir('Dog')):
    try:
        image = cv2.resize(cv2.imread(f'Dog/{image}', 0), (60, 60)) / 255.
        data.append((image, 0))
    except:
        ii += 1

print(f'total errors in cat files: {i}')
print(f'total errors in dog files: {ii}')
pp.random.shuffle(data)
labels = torch.tensor([data[i][1] for i in range(len(data))]).type(torch.FloatTensor)
images = torch.tensor([data[i][0] for i in range(len(data))]).type(torch.FloatTensor).reshape(-1, 1, 60, 60)

# torch.save(labels, 'labels.pt')
# torch.save(images, 'images.pt')

### prepare data for training ###

# images = torch.load('images.pt')
# labels = torch.load('labels.pt')

trainSet, testSet = random_split(TensorDataset(images, labels), [19956, 4990])

trainLoader = DataLoader(trainSet, 20, True)
testLoader = DataLoader(testSet, 20, True)


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, 3, padding=1)
        self.pool1 = nn.MaxPool2d(2, 2)

        self.conv2 = nn.Conv2d(10, 20, 3, padding=1)
        self.pool2 = nn.MaxPool2d(2, 2)

        self.fc1 = nn.Linear(90000, 120)
        self.fc2 = nn.Linear(120, 100)
        self.fc3 = nn.Linear(100, 1)

    def forward(self, x):
        x = self.pool1(F.relu(self.conv1(x)))
        x = self.pool2(F.relu(self.conv2(x)))
        x = x.view(-1, 90000)

        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return torch.sigmoid(x)


clf = Net()
optim = torch.optim.Adam(clf.parameters(), 0.01)
lossfn = nn.BCELoss()


def training_loop(epochs, optim, clf, lossf, train_loader):
    for epoch in range(1, epochs + 1):
        loss_train = 0.0
        for imgs, labels in train_loader:
            imgs, labels = torch.autograd.Variable(imgs), torch.autograd.Variable(labels)

            output = clf(imgs)
            loss = lossf(output, labels)

            optim.zero_grad()
            loss.backward()
            optim.step()

            loss_train += loss.item()
        print(f'Epoch: {epoch}, Batch Loss: {loss_train}, Training Loss: {loss_train / len(train_loader)}')


# validataion loop
def val_loop(clf, train_loader, val_loader):
    for name, loader in [('train', train_loader), ('val', val_loader)]:
        scores = []
        with torch.no_grad():
            for img, labels in loader:
                output = clf(img)
                scores.append(roc_auc_score(labels, torch.round(output)))

        print(f'{name} Accuracy : {pp.mean(scores)}')


print('start training')
training_loop(5, optim, clf, lossfn, trainLoader)

print('start val')
val_loop(clf, trainLoader, testLoader)

but when i run the script i get this problem:

C:\Users\BHAAK\AppData\Local\Programs\Python\Python36\lib\site-packages\torch\nn\modules\loss.py:529: UserWarning: Using a target size (torch.Size([20])) that is different to the input size (torch.Size([1, 1])) is deprecated. Please ensure they have the same size.
  return F.binary_cross_entropy(input, target, weight=self.weight, reduction=self.reduction)
Traceback (most recent call last):
  File "C:/Users/BHAAK/Desktop/ML_PATH/dirty-hands/dirty hands file 1/parser.py", line 111, in <module>
    training_loop(5, optim, clf, lossfn, trainLoader)
  File "C:/Users/BHAAK/Desktop/ML_PATH/dirty-hands/dirty hands file 1/parser.py", line 85, in training_loop
    loss = lossf(output, labels)
  File "C:\Users\BHAAK\AppData\Local\Programs\Python\Python36\lib\site-packages\torch\nn\modules\module.py", line 722, in _call_impl
    result = self.forward(*input, **kwargs)
  File "C:\Users\BHAAK\AppData\Local\Programs\Python\Python36\lib\site-packages\torch\nn\modules\loss.py", line 529, in forward
    return F.binary_cross_entropy(input, target, weight=self.weight, reduction=self.reduction)
  File "C:\Users\BHAAK\AppData\Local\Programs\Python\Python36\lib\site-packages\torch\nn\functional.py", line 2477, in binary_cross_entropy
    "!= input nelement ({})".format(target.numel(), input.numel()))
ValueError: Target and input must have the same number of elements. target nelement (20) != input nelement (1)

it raise because of this line loss = lossf(output, labels) in :

def training_loop(epochs, optim, clf, lossf, train_loader):
    for epoch in range(1, epochs + 1):
        loss_train = 0.0
        for imgs, labels in train_loader:
            imgs, labels = torch.autograd.Variable(imgs), torch.autograd.Variable(labels)

            output = clf(imgs)
            loss = lossf(output, labels)
            ....

when i print the shape of labels and output i get this

# labels
tensor([1., 1., 1., 1., 1., 1., 1., 1., 1., 0., 1., 0., 0., 0., 1., 1., 1., 0.,
        1., 1.])
torch.Size([20])

# output
tensor([[0.0430]], grad_fn=<AddmmBackward>)
torch.Size([1, 1])

according to my knowledge, the output shape should be exactly like labels shape.
any one can help… thank you :smile:

I guess this view operation might remove the batch dimension and flatten all elements into the feature dim:

x = x.view(-1, 90000)

Replace it with:

x = x.view(x.size(0), -1)

to keep the batch size constant and adapt the number of input features for the following linear layer, if necessary.

i got another error:


raceback (most recent call last):
  File "C:/Users/BHAAK/Desktop/ML_PATH/dirty-hands/dirty hands file 1/parser.py", line 116, in <module>
    training_loop(5, optim, clf, criterion, trainLoader)
  File "C:/Users/BHAAK/Desktop/ML_PATH/dirty-hands/dirty hands file 1/parser.py", line 89, in training_loop
    output = clf(imgs)
  File "C:\Users\BHAAK\AppData\Local\Programs\Python\Python36\lib\site-packages\torch\nn\modules\module.py", line 722, in _call_impl
    result = self.forward(*input, **kwargs)
  File "C:/Users/BHAAK/Desktop/ML_PATH/dirty-hands/dirty hands file 1/parser.py", line 71, in forward
    x = F.relu(self.fc1(x))
  File "C:\Users\BHAAK\AppData\Local\Programs\Python\Python36\lib\site-packages\torch\nn\modules\module.py", line 722, in _call_impl
    result = self.forward(*input, **kwargs)
  File "C:\Users\BHAAK\AppData\Local\Programs\Python\Python36\lib\site-packages\torch\nn\modules\linear.py", line 91, in forward
    return F.linear(input, self.weight, self.bias)
  File "C:\Users\BHAAK\AppData\Local\Programs\Python\Python36\lib\site-packages\torch\nn\functional.py", line 1674, in linear
    ret = torch.addmm(bias, input, weight.t())
RuntimeError: size mismatch, m1: [20 x 9000], m2: [180000 x 50] at ..\aten\src\TH/generic/THTensorMath.cpp:41

x shape after the line you told me to replace with:

torch.Size([20, 9000])

x shape before the line you told me to replace with:
torch.Size([20, 10, 30, 30]) # this is the shape without flatting

is there any idea about what’s happening !

Finally I fixed the problem !

it was because of this line:
self.fc3 = nn.Linear(100, 1) this line is the final layer in the network.

I must replace ‘1’ with 2 because there is two outputs.
I ruled this out at first because it didn’t make any sense to me, I mean if my label was 1, 0 (binary) I must use 1 output but it didn’t work until I changed to (one_hot_encoding) [0, 1]
problem which is 2 need two output.

I hope my explanation make sense to you.

That’s not the error you were seeing.

As said before, after fixing the view operations I assumed you would run into a shape mismatch so you would need to adapt the in_features of the next linear layer.
In your case it seems that the in_features should be defined as 9000 in self.fc1.

For a binary classification you can use a single output unit and nn.BCEWithLogitsLoss or two output units and nn.CrossEntropyLoss.

1 Like

Actually I used this nn.BCELoss but it didn’t fix the problem, and I don’t know the difference
between nn.BCELoss and nn.BCEWithLogitsLoss.

Can you tell me what is the difference that makes it slove the problem ?

This post gives you a quick overview for the different approaches for a binary classification use case.
Basically you can treat it as a “real” binary classification with a single output unit (and nn.BCEWithLogitsLoss) or as a mutli-class classification using 2 classes (and nn.CrossEntropyLoss).

For the first use case, pass the raw logits to nn.BCEWithLogitsLoss for more numerical stability compared to sigmoid + nn.BCELoss.

1 Like