Error: AttributeError: 'tuple' object has no attribute 'size'

Hi, I am working on Age and Gender prediction. I get this error "AttributeError: ‘tuple’ object has no attribute ‘size’ ".
‘’’

Combine Gender and Age

y_gender_age = np.stack((y_gender, y_age), axis=1)
y_gender_age[0:5]

array([[ 0, 100],
[ 0, 100],
[ 1, 100],
[ 1, 100],
[ 1, 100]], dtype=int64)

type(y_gender_age)

numpy.ndarray

X_train, X_test, y_train, y_test = train_test_split(X, y_gender_age, test_size=0.3, random_state=42, shuffle=True)

‘’’

Building Model

import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
def init(self):
super(Net, self).init()

    self.conv1 = nn.Conv2d(in_channels = 128, out_channels = 32,
                           kernel_size = 1)
    
    self.pool = nn.MaxPool2d(kernel_size = 1)
    
    self.conv2 = nn.Conv2d(in_channels = 32, out_channels = 64,
                           kernel_size = 1)
    
    self.conv3 = nn.Conv2d(in_channels = 64, out_channels = 128,
                           kernel_size = 1)
    
    self.conv4 = nn.Conv2d(in_channels = 128, out_channels = 256,
                           kernel_size = 1)
    nn.Flatten()
    
    self.fc1 = nn.Linear(in_features = 32768, out_features = 256)
    
    self.fc2 = nn.Linear(in_features = 256, out_features = 100) 
    
    self.linear1 = nn.Linear(in_features = 100, out_features = 1) # age_out
    self.linear2 = nn.Linear(in_features = 100, out_features = 2) # gender_out
    self.dropout = nn.Dropout(p=0.2)
def forward(self, x):
    x = F.relu(self.conv1(x))
    x = F.relu(self.conv2(x))
    x = F.relu(self.conv3(x))
    x = F.relu(self.conv4(x))
    
    x = x.view(x.size(0),-1)
    x = self.dropout(F.relu(self.fc1(x)))
    x = self.dropout(F.relu(self.fc2(x)))
    output1 = F.relu(self.linear1(x))         # age_output1
    output2 = F.sigmoid(self.linear2(x))      # gender_output2
    return output1, output2

import torch.optim as optim

For multilabel output: age

criterion1_mae_age = nn.L1Loss()

for binary output : Gender

criterion2_binary_gender = nn.BCELoss()

optimizer = optim.SGD(net.parameters(), lr = 0.001)

def train_model(model, criterion1, criterion2, optimizer, n_epochs = 25):
“”" returns trained model “”"
# initialize tracker for minimum validation loss
# criterion1 is for age mean_absolute_error, cricriterion2 is for Binary_crossentropy_loss
valid_loss_min = np.Inf
for epoch in range(1, n_epochs):
train_loss = 0.0
valid_loss = 0.0

    # train the model #
    net.train()
    for i, data in enumerate(trainloader):
        image, labels = data
        optimizer.zero_grad() # zero the parameter gradient
        output = net(image.float())
        output = net(image.float())
        #label1_hat = output['label1']
        #label2_hat = output['label2']
        
        # calculate loss
        loss1 = criterion1(output, labels.squeeze().type(torch.LongTensor))
        loss2 = criterion2(output, labels)
        loss = loss1 + loss2
        
        # back prop
        loss.backward()
        #grad
        optimizer.step()
        
        train_loss = train_loss + ((1 / (i + 1)) * (loss.data - train_loss))
        
        if i % 50 == 0:
            print('Epoch %d, Batch %d loss: %.6f' %
              (epoch, i + 1, train_loss))

net_conv = train_model(net, criterion1_mae_age, criterion2_binary_gender, optimizer)
‘’’
Please help me where did I wrote wrong code.

Your model returns two outputs while the criterionX expects a single tensor as the model output.
You might thus want to index the output tensor as:

loss1 = criterion1(output[0], labels.squeeze().type(torch.LongTensor))
loss2 = criterion2(output[1], labels)

It works. Thank you. But for training the model it shows the loss in negative.
‘’’
net_conv = train_model(net, criterion1_mae_age, criterion2_binary_gender, optimizer)

Epoch 1, Batch 1 loss: -1768.040283
Epoch 1, Batch 51 loss: -1648.417969
Epoch 2, Batch 1 loss: -1692.807739
Epoch 2, Batch 51 loss: -1661.417725
Epoch 3, Batch 1 loss: -1587.873901
Epoch 3, Batch 51 loss: -1656.926147
Epoch 4, Batch 1 loss: -1680.994141
Epoch 4, Batch 51 loss: -1659.505493

‘’’
Total 25 epochs are there.

Please help me where it was wrong.

Check the model output and target ranges and make sure the loss functions are getting the expected value ranges.
Negative losses are often caused if the value range is wrong as seen e.g. here:

x = torch.randn(10, 1)
y = torch.full((10, 1), 10.) # wrong range as [0, 1] is expected

criterion = nn.BCEWithLogitsLoss()
loss = criterion(x, y)
print(loss)
# tensor(-3.7555)

I have checked the model output it gives
(tensor([[0.5390, 1.0000],
[0.5459, 1.0000],
[0.4461, 1.0000],
[0.4954, 1.0000],
[0.5492, 1.0000],
[0.5866, 1.0000],
.
.
.
[0.5192, 1.0000],
[0.5108, 1.0000],
[0.5286, 1.0000],
[0.5216, 1.0000]], grad_fn=), tensor([[20.3634],
[13.3107],
[19.4743],
[19.3773],
.
.
.
[22.8109],
[14.3605],
[12.5779]], grad_fn=))
Epoch 1, Batch 1 loss: -1268.372437

It shows like this. I am newbie in this I really don’t understand how to check this model. Please help me where did I wrote wrong code.

That’s quite unexpected since your model returns:

    output1 = F.relu(self.linear1(x))         # age_output1
    output2 = F.sigmoid(self.linear2(x))      # gender_output2
    return output1, output2

which indicates that the second output would be in the range [0, 1] via the torch.sigmoid operation while the printed outputs are showing the opposite value ranges. Also, it seems as if no grad_fn are visible, which is also not expected.
In any case, check the target values too and make sure they are valid.

What should I do? Where should I correct my model.