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

username: Bahaa_Kattan
cooked: <p>i’m trying to run my neural network on catVSdog dataset with the following script:</p>
<pre><code class="lang-auto">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)
</code></pre>
<p>but when i run the script i get this problem:</p>
<pre><code class="lang-auto">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 &lt;module&gt;
    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)
</code></pre>
<p>it raise because of this line   <code> loss = lossf(output, labels)</code> in :</p>
<pre><code class="lang-auto">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)
            ....
</code></pre>
<p>when i print the shape of labels and output i get this</p>
<pre><code class="lang-auto"># 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=&lt;AddmmBackward&gt;)
torch.Size([1, 1])
</code></pre>
<p>according to my knowledge, the output shape should be exactly like labels shape.<br>
any one can help…  thank you <img src="https://discuss.pytorch.org/images/emoji/apple/smile.png?v=9" title=":smile:" class="emoji" alt=":smile:"></p>

username: ptrblck
cooked: <p>I guess this <code>view</code> operation might remove the batch dimension and flatten all elements into the feature dim:</p>
<pre><code class="lang-python">x = x.view(-1, 90000)
</code></pre>
<p>Replace it with:</p>
<pre><code class="lang-python">x = x.view(x.size(0), -1)
</code></pre>
<p>to keep the batch size constant and adapt the number of input features for the following linear layer, if necessary.</p>

username: Bahaa_Kattan
cooked: <aside class="quote no-group" data-username="ptrblck" data-post="2" data-topic="97547">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/ptrblck/48/1823_2.png" class="avatar"> ptrblck:</div>
<blockquote>
<pre><code class="lang-auto">x = x.view(x.size(0), -1)
</code></pre>
</blockquote>
</aside>
<p>i got another error:</p>
<pre><code class="lang-auto">
raceback (most recent call last):
  File "C:/Users/BHAAK/Desktop/ML_PATH/dirty-hands/dirty hands file 1/parser.py", line 116, in &lt;module&gt;
    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
</code></pre>
<p>x shape after the line you told me to replace with:</p>
<p><code> torch.Size([20, 9000])</code></p>
<p>x shape before the line you told me to replace with:<br>
<code>torch.Size([20, 10, 30, 30])</code> # this is the shape without flatting</p>
<p>is there any idea about what’s happening !</p>

username: Bahaa_Kattan
cooked: <p>Finally I fixed the problem !</p>
<p>it was because of this line:<br>
<code>self.fc3 = nn.Linear(100, 1)</code> this line is the final layer in the network.</p>
<p>I must replace ‘1’  with 2 because there is two outputs.<br>
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]<br>
problem which is 2 need two output.</p>
<p>I hope my explanation make sense to you.</p>

username: ptrblck
cooked: <aside class="quote no-group" data-username="Bahaa_Kattan" data-post="4" data-topic="97547">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/bahaa_kattan/48/28782_2.png" class="avatar"> Bahaa_Kattan:</div>
<blockquote>
<p>I must replace ‘1’ with 2 because there is two outputs.<br>
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]<br>
problem which is 2 need two output.</p>
</blockquote>
</aside>
<p>That’s not the error you were seeing.</p>
<p>As said before, after fixing the <code>view</code> operations I assumed you would run into a shape mismatch so you would need to adapt the <code>in_features</code> of the next linear layer.<br>
In your case it seems that the <code>in_features</code> should be defined as <code>9000</code> in <code>self.fc1</code>.</p>
<p>For a binary classification you can use a single output unit and <code>nn.BCEWithLogitsLoss</code> or two output units and <code>nn.CrossEntropyLoss</code>.</p>

username: Bahaa_Kattan
cooked: <aside class="quote no-group" data-username="ptrblck" data-post="5" data-topic="97547" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/ptrblck/48/1823_2.png" class="avatar"> ptrblck:</div>
<blockquote>
<p>For a binary classification you can use a single output unit and <code>nn.BCEWithLogitsLoss</code> or two output units and <code>nn.CrossEntropyLoss</code>.</p>
</blockquote>
</aside>
<p>Actually I used this <code>nn.BCELoss</code> but it didn’t fix the problem, and I don’t know the difference<br>
between  <code>nn.BCELoss</code> and  <code>nn.BCEWithLogitsLoss</code>.</p>
<p>Can you tell me what is the difference that makes it slove the problem ?</p>

username: ptrblck
cooked: <p><a href="https://discuss.pytorch.org/t/simple-2-class-mlp/27297/4">This post</a> gives you a quick overview for the different approaches for a binary classification use case.<br>
Basically you can treat it as a “real” binary classification with a single output unit (and <code>nn.BCEWithLogitsLoss</code>) or as a mutli-class classification using 2 classes (and <code>nn.CrossEntropyLoss</code>).</p>
<p>For the first use case, pass the raw logits to <code>nn.BCEWithLogitsLoss</code> for more numerical stability compared to <code>sigmoid</code> + <code>nn.BCELoss</code>.</p>