ValueError: Using a target size (torch.Size([100, 2, 1])) that is different to the input size (torch.Size([100, 1])) is deprecated. Please ensure they have the same size

Niraja: <p>Hello. I am trying to solve age and gender prediction using CNN in PyTorch. I am using classes for age as well as for gender distribution. I am using UTKFace dataset. According to dataset annotation [0] is for age, [1] is for gender i am consider.<br>
‘’’</p>
<h1>
<a name="labels-age-gender-ethnicity-as-per-image-notation-1" class="anchor" href="#labels-age-gender-ethnicity-as-per-image-notation-1"></a>labels age, gender, ethnicity as per image notation</h1>
<p>image_paths = []<br>
age_labels = []<br>
gender_labels = []</p>
<p>for filename in tqdm(os.listdir(base_dir)):<br>
image_path = os.path.join(base_dir, filename)<br>
temp = filename.split(‘_’)<br>
age = int(temp[0])<br>
gender = int(temp[1])<br>
image_paths.append(image_path)<br>
age_labels.append(age)<br>
gender_labels.append(gender)</p>
<h1>
<a name="convert-to-dataframe-2" class="anchor" href="#convert-to-dataframe-2"></a>convert to dataframe</h1>
<p>df = pd.DataFrame()<br>
df[‘image’], df[‘age’], df[‘gender’] = image_paths, age_labels, gender_labels<br>
df.head()</p>
<h1>
<a name="age-class-labels-3" class="anchor" href="#age-class-labels-3"></a>Age class labels</h1>
<p>def class_labels_reassign(age_labels):</p>
<pre><code>if 1 &lt;= age_labels &lt;= 2:
    return 0
elif 3 &lt;= age_labels &lt;= 9:
    return 1
elif 10 &lt;= age_labels &lt;= 20:
    return 2
elif 21 &lt;= age_labels &lt;= 25:
    return 3
elif 26 &lt;= age_labels &lt;= 27:
    return 4
elif 28 &lt;= age_labels &lt;= 31:
    return 5
elif 32 &lt;= age_labels &lt;= 36:
    return 6
elif 37 &lt;= age_labels &lt;= 45:
    return 7
elif 46 &lt;= age_labels &lt;= 54:
    return 8
elif 55 &lt;= age_labels &lt;= 65:
    return 9
else:
    return 10
</code></pre>
<h1>
<a name="gender-label-reassign-4" class="anchor" href="#gender-label-reassign-4"></a>gender label reassign</h1>
<p>def class_gender_labels(gender_labels):</p>
<pre><code>if gender_labels == 0:
    return 0
else:
    return 1
</code></pre>
<h1>
<a name="map-the-age-class-labels-as-per-ages-5" class="anchor" href="#map-the-age-class-labels-as-per-ages-5"></a>map the age class labels as per ages</h1>
<p>df[‘target_age’] = df[‘age’].map(class_labels_reassign) #= df[‘gender’].map(class_gender_labels)<br>
df[‘target_gender’] = df[‘gender’].map(class_gender_labels)<br>
df.head()</p>
<p>target_age = np.array(df[‘target_age’])<br>
target_gender = np.array(df[‘target_gender’])</p>
<h1>
<a name="creating-the-labels-list-of-age-and-gender-from-list-of-ages-and-genders-6" class="anchor" href="#creating-the-labels-list-of-age-and-gender-from-list-of-ages-and-genders-6"></a>creating the labels list of age and gender from list of ages, and genders</h1>
<p>labels = []</p>
<p>i = 0<br>
while i &lt; len(target_age):<br>
label = []<br>
label.append([target_age[i]])<br>
label.append([target_gender[i]])<br>
labels.append(label)<br>
i += 1</p>
<h1>
<a name="convert-labels-list-to-numpy-array-7" class="anchor" href="#convert-labels-list-to-numpy-array-7"></a>convert labels list to numpy array</h1>
<p>age_gender_labels = np.array(labels)<br>
print(type(age_gender_labels))<br>
age_gender_labels.shape<br>
‘’’</p>
<p>‘’’<br>
X_train, X_test, y_train, y_test = train_test_split(images, age_gender_labels, test_size=0.3, random_state=42, shuffle=True )</p>
<p>X_test, X_for_pred, y_test, y_for_pred = train_test_split(X_test, y_test, test_size=0.1, random_state=42, shuffle=True)</p>
<p>train=torch.utils.data.TensorDataset(x_train_tensor,y_train_label)<br>
trainloader=torch.utils.data.DataLoader(train,batch_size=100,shuffle=True, num_workers=1)</p>
<p>test=torch.utils.data.TensorDataset(x_test_tensor,y_test_label)<br>
testloader=torch.utils.data.DataLoader(test,batch_size=100,shuffle=True, num_workers=1)</p>
<p>for_pred=torch.utils.data.TensorDataset(x_for_pred_label,y_for_pred_label)<br>
for_pred_loader=torch.utils.data.DataLoader(for_pred,batch_size=100,shuffle=False)</p>
<h1>
<a name="build-model-8" class="anchor" href="#build-model-8"></a>Build Model</h1>
<p>import torch.nn as nn<br>
import torch.nn.functional as F</p>
<p>class CNNModel(nn.Module):<br>
def <strong>init</strong>(self):<br>
super(CNNModel, self).<strong>init</strong>()</p>
<pre><code>    self.cnn1 = nn.Conv2d(in_channels = 1, out_channels = 16, kernel_size = 3, padding = 1)
    self.relu = nn.ReLU()
    
    self.maxpool = nn.MaxPool2d(kernel_size = 2)
    
    #self.Batch1=nn.BatchNorm2d(16)
    #self.Batch2=nn.BatchNorm2d(32)
    #self.Batch3=nn.BatchNorm2d(64)
    #self.Batch4=nn.BatchNorm2d(128)
    
    self.Drop1=nn.Dropout(0.2)
    self.Drop2=nn.Dropout(0.5)


    self.cnn2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3)
    self.cnn3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3)
    self.cnn4 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3)
    
    

    # Fully connected 1 (readout)
    self.fc1 = nn.Linear(128 * 1 * 1, 128) 
    self.fc2=nn.Linear(128,256)
    self.fc3=nn.Linear(256,1)   # age output
    #self.fc4=nn.Linear(256,1)   # gender output

def forward(self, x):

    out = self.cnn1(x) 
    out = self.relu(out)
    out = self.maxpool(out)
    #out=self.Batch1(out)
    out=self.Drop1(out)

    out = self.cnn2(out)
    out = self.relu(out)
    out = self.maxpool(out)
    #out=self.Batch2(out)
    out=self.Drop1(out)
    
    out = self.cnn3(out)
    out = self.relu(out)
    out = self.maxpool(out)
    #out=self.Batch3(out)
    out=self.Drop1(out)
    
    out = self.cnn4(out)
    out = self.relu(out)
    out = self.maxpool(out)
    #out=self.Batch4(out)
    out=self.Drop1(out)
    

    # Resize
    # Original size: (100, 32, 7, 7)
    # out.size(0): 100
    # New out size: (100, 32*7*7)
    out = out.view(out.size(0), -1)

    # Linear function (readout)
    out = self.fc1(out)
    
    out=self.Drop2(out)
    
    out=self.fc2(out)
    
    out=self.Drop2(out)
    
    out=self.fc3(out)
    #out=self.fc4(out)
    
    

    return out
</code></pre>
<p>model = CNNModel()</p>
<p>learning_rate=0.001<br>
import torch.optim as optim</p>
<h1>
<a name="loss-and-optimizer-9" class="anchor" href="#loss-and-optimizer-9"></a>Loss and optimizer</h1>
<p>criterion = nn.BCELoss()<br>
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)</p>
<h1>
<a name="training-model-10" class="anchor" href="#training-model-10"></a>training model</h1>
<p>t1_start = perf_counter()<br>
for epoch in range(2):<br>
running_loss = 0.0<br>
for i, data in enumerate(trainloader,0):<br>
images, labels = data<br>
<span class="hashtag">#labels</span> = labels.unsqueeze(0)<br>
optimizer.zero_grad()  # zero the parameter gradients</p>
<pre><code>    #outputs = model(images.float())  # forward
    outputs = model(images.float())  # forward
    
    loss = criterion(outputs, labels)  #calculate the loss between the target and the actuals
    
    loss.backward() #Gradient calculation uisng backward pass
    
    optimizer.step()  # update the weights
    

    
    running_loss = loss.item()
    if i % 10 == 0:
        print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                    epoch, i * len(images), len(trainloader.dataset),
                    100. * i / len(trainloader), loss.item()))
</code></pre>
<p>‘’’</p>
<p>Please help me to solve this problem. I don’t understand where i am wrong.<br>
Thank you in advance.</p>

ptrblck: <p>As indicated in the error message the model output and target tensor shapes should be equal during the loss calculation in <code>nn.BCELoss</code>. Check what the dimensions and shapes of your tensors mean and make sure each logit or probability of the model output matches a target.<br>
Also, since you are using <code>nn.BCELoss</code> you would have to apply a <code>sigmoid</code> on the output. The better approach would be to stick to the output of raw logits and to use <code>nn.BCEWithLogits</code> instead for better numerical stability.</p>

Niraja: <p>Thank you sir. and Sorry for the late reply.</p>

Niraja: <p>How to improve the neural network programming skills. Your advice will be highly beneficial to me. Thank you in advance.</p>

nwn: <p>Generally, I would differentiate between programming skills and ML/AI background knowledge. When it comes to the programming task, I think it is always create to know some software engineering basics such as building flexible code or using a debugger. Especially, the latter helped me a lot. For sure, it is helpful to understand how a stacktrace works. Apart from that, there are great classes on e.g. Coursera that you can take. If you are new to the topic, I think it is quite calming to realize that really understanding some algorithms and the theory behind those is an ongoing (and probably never ending) process. Hence, don’t be disappointed, if you are not able to understand an algorithm at first sight.</p>

Niraja: <p>Thank you. Your guidance has been highly helpful to me.</p>

Niraja: <p>I am still getting “ValueError: Target size (torch.Size([2, 2, 1])) must be the same as input size (torch.Size([2, 2]))” this error. I have changed the loss function with  nn.BCEWithLogitsLoss() and add sigmoid on output side. I changed the batch_size to 2.<br>
I am a newbie in this neural network. I am developing a model for age and gender detection. I have used the map function for age classes as well as for gender also.<br>
For eg., If we want to get the age and gender for the 100th image then it shows<br>
age_gender_labels[100]</p>
<blockquote>
<blockquote>
<blockquote>
<blockquote>
<p>array([[2],<br>
[1]], dtype=int64)<br>
The first array ([[2] shows the age range i.e. between age range 10-20. and [1] shows it is female gender.<br>
So, is it possible to get this type of output? And what should be the output_feature in this case?</p>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
<p>Please help me to how to solve this error.</p>
<p>This my Model.<br>
import torch.nn as nn<br>
import torch.nn.functional as F</p>
<p>class CNNModel(nn.Module):<br>
def <strong>init</strong>(self):<br>
super(CNNModel, self).<strong>init</strong>()</p>
<pre><code>    self.conv1 = nn.Conv2d(in_channels=1, out_channels=16,
                          kernel_size=3, stride=1, padding=1)
    
    self.maxpool = nn.MaxPool2d(kernel_size = 2)
    self.Drop1=nn.Dropout(0.2)
    self.Drop2=nn.Dropout(0.5)
    
    self.conv2 = nn.Conv2d(in_channels=16, out_channels=32,
                          kernel_size=3, stride=1, padding=1)
    
    self.conv3 = nn.Conv2d(in_channels=32, out_channels=64,
                          kernel_size=3, stride=1, padding=1)
    
    self.conv4 = nn.Conv2d(in_channels=64, out_channels=128,
                          kernel_size=3, stride=1, padding=1)
    
    self.fc1 = nn.Linear(in_features=1152, out_features=128)  #self.fc1 = nn.Linear(128 * 1 * 1, 128) 
    self.fc2 = nn.Linear(in_features=128, out_features=256)       #self.fc2=nn.Linear(128,256)
    self.fc3 = nn.Linear(in_features=256, out_features=2)
    
    
def forward(self, x):
    x = F.relu(self.conv1(x))
    x = self.maxpool(x)
    x = self.Drop1(x)
    
    x = F.relu(self.conv2(x))
    x = self.maxpool(x)
    x = self.Drop1(x)
    
    x = F.relu(self.conv3(x))
    x = self.maxpool(x)
    x = self.Drop1(x)
    
    x = F.relu(self.conv4(x))
    x = self.maxpool(x)
    x = self.Drop1(x)
    
    print('x_shape: ',x.shape)
    x = x.view(x.size(0),-1)
    
    x = F.relu(self.fc1(x))
    x = self.Drop2(x)
    
    x = F.relu(self.fc2(x))
    x = self.Drop2(x)
    
    x = F.sigmoid(self.fc3(x))
    return x
</code></pre>
<p>model = CNNModel()</p>
<p>learning_rate=0.001<br>
import torch.optim as optim</p>
<h1><a name="loss-and-optimizer-1" class="anchor" href="#loss-and-optimizer-1"></a>Loss and optimizer</h1>
<p>criterion = nn.BCEWithLogitsLoss()<br>
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)</p>
<p>t1_start = perf_counter()<br>
for epoch in range(2):<br>
running_loss = 0.0<br>
for i, data in enumerate(trainloader,0):<br>
images, labels = data<br>
<span class="hashtag-raw">#labels</span> = labels.unsqueeze(0)<br>
optimizer.zero_grad()  # zero the parameter gradients</p>
<pre><code>    outputs = model(images.float())  # forward
    #outputs.squeeze(-1)
    #data = data.unsqueeze(1)
    loss = criterion(outputs, labels)  #calculate the loss between the target and the actuals
    
    loss.backward() #Gradient calculation uisng backward pass
    
    optimizer.step()  # update the weights
    

    
    running_loss = loss.item()
    if i % 10 == 0:
        print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                    epoch, i * len(images), len(trainloader.dataset),
                    100. * i / len(trainloader), loss.item()))
</code></pre>
<p>Thank you in advance</p>

ptrblck: <aside class="quote no-group" data-username="Niraja" data-post="7" data-topic="167929">
<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/niraja/48/61924_2.png" class="avatar"> Niraja:</div>
<blockquote>
<p>I have changed the loss function with nn.BCEWithLogitsLoss() and add sigmoid on output side.</p>
</blockquote>
</aside>
<p>This is wrong since <code>nn.BCEWithLogitsLoss</code> expects logits as the model output, so remove the <code>sigmoid</code> activation.</p>
<aside class="quote no-group" data-username="Niraja" data-post="7" data-topic="167929">
<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/niraja/48/61924_2.png" class="avatar"> Niraja:</div>
<blockquote>
<p>I have used the map function for age classes as well as for gender also.<br>
For eg., If we want to get the age and gender for the 100th image then it shows<br>
age_gender_labels[100]</p>
</blockquote>
</aside>
<p>I don’t fully understand this approach, as it seems your use case would need to be split into a:</p>
<ul>
<li>regression output for the “age”</li>
<li>and a classification output for the “gender” target.</li>
</ul>
<p>If so, then you should use different output layers or at least use a regression criterion (e.g. <code>nn.MSELoss</code>) for the “age” output.</p>
<aside class="quote no-group" data-username="Niraja" data-post="7" data-topic="167929">
<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/niraja/48/61924_2.png" class="avatar"> Niraja:</div>
<blockquote>
<p>I am still getting “ValueError: Target size (torch.Size([2, 2, 1])) must be the same as input size (torch.Size([2, 2]))” this error.</p>
</blockquote>
</aside>
<p>As the error message explains the model output and target shape should be equal. Check what each dimension represents and consider removing <code>dim2</code> from the target if needed.</p>