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

username: Niraja
cooked: <p>Hi, I am working on Age and Gender prediction. I get this error "AttributeError: ‘tuple’ object has no attribute ‘size’ ".<br>
‘’’</p>
<h1><a name="combine-gender-and-age-1" class="anchor" href="#combine-gender-and-age-1"></a>Combine Gender and Age</h1>
<p>y_gender_age = np.stack((y_gender, y_age), axis=1)<br>
y_gender_age[0:5]</p>
<blockquote>
<blockquote>
<blockquote>
<blockquote>
<p>array([[  0, 100],<br>
[  0, 100],<br>
[  1, 100],<br>
[  1, 100],<br>
[  1, 100]], dtype=int64)</p>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
<p>type(y_gender_age)</p>
<blockquote>
<blockquote>
<blockquote>
<blockquote>
<p>numpy.ndarray</p>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
<p>X_train, X_test, y_train, y_test = train_test_split(X, y_gender_age, test_size=0.3, random_state=42, shuffle=True)</p>
<p>‘’’</p>
<h1><a name="building-model-2" class="anchor" href="#building-model-2"></a>Building Model</h1>
<p>import torch.nn as nn<br>
import torch.nn.functional as F</p>
<p>class Net(nn.Module):<br>
def <strong>init</strong>(self):<br>
super(Net, self).<strong>init</strong>()</p>
<pre><code>    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
</code></pre>
<p>import torch.optim as optim</p>
<h1><a name="for-multilabel-output-age-3" class="anchor" href="#for-multilabel-output-age-3"></a>For multilabel output: age</h1>
<p>criterion1_mae_age = nn.L1Loss()</p>
<h1><a name="for-binary-output-gender-4" class="anchor" href="#for-binary-output-gender-4"></a>for binary output : Gender</h1>
<p>criterion2_binary_gender = nn.BCELoss()</p>
<p>optimizer = optim.SGD(net.parameters(), lr = 0.001)</p>
<p>def train_model(model, criterion1, criterion2, optimizer, n_epochs = 25):<br>
“”" returns trained model “”"<br>
# initialize tracker for minimum validation loss<br>
# criterion1 is for age mean_absolute_error, cricriterion2 is for Binary_crossentropy_loss<br>
valid_loss_min = np.Inf<br>
for epoch in range(1, n_epochs):<br>
train_loss = 0.0<br>
valid_loss = 0.0</p>
<pre><code>    # 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))
</code></pre>
<p>net_conv = train_model(net, criterion1_mae_age, criterion2_binary_gender, optimizer)<br>
‘’’<br>
Please help me where did I wrote wrong code.</p>

username: ptrblck
cooked: <p>Your model returns two outputs while the <code>criterionX</code> expects a single tensor as the model output.<br>
You might thus want to index the <code>output</code> tensor as:</p>
<pre><code class="lang-python">loss1 = criterion1(output[0], labels.squeeze().type(torch.LongTensor))
loss2 = criterion2(output[1], labels)
</code></pre>

username: Niraja
cooked: <p>It works. Thank you. But for training the model it shows the loss in negative.<br>
‘’’<br>
net_conv = train_model(net, criterion1_mae_age, criterion2_binary_gender, optimizer)</p>
<blockquote>
<p>Epoch 1, Batch 1 loss: -1768.040283<br>
Epoch 1, Batch 51 loss: -1648.417969<br>
Epoch 2, Batch 1 loss: -1692.807739<br>
Epoch 2, Batch 51 loss: -1661.417725<br>
Epoch 3, Batch 1 loss: -1587.873901<br>
Epoch 3, Batch 51 loss: -1656.926147<br>
Epoch 4, Batch 1 loss: -1680.994141<br>
Epoch 4, Batch 51 loss: -1659.505493</p>
</blockquote>
<p>‘’’<br>
Total 25 epochs are there.</p>
<p>Please help me where it was wrong.</p>

username: ptrblck
cooked: <p>Check the model output and target ranges and make sure the loss functions are getting the expected value ranges.<br>
Negative losses are often caused if the value range is wrong as seen e.g. here:</p>
<pre><code class="lang-python">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)
</code></pre>

username: Niraja
cooked: <p>I have checked the model output it gives<br>
(tensor([[0.5390, 1.0000],<br>
[0.5459, 1.0000],<br>
[0.4461, 1.0000],<br>
[0.4954, 1.0000],<br>
[0.5492, 1.0000],<br>
[0.5866, 1.0000],<br>
.<br>
.<br>
.<br>
[0.5192, 1.0000],<br>
[0.5108, 1.0000],<br>
[0.5286, 1.0000],<br>
[0.5216, 1.0000]], grad_fn=), tensor([[20.3634],<br>
[13.3107],<br>
[19.4743],<br>
[19.3773],<br>
.<br>
.<br>
.<br>
[22.8109],<br>
[14.3605],<br>
[12.5779]], grad_fn=))<br>
Epoch 1, Batch 1 loss: -1268.372437</p>
<p>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.</p>

username: ptrblck
cooked: <p>That’s quite unexpected since your model returns:</p>
<pre><code class="lang-python">    output1 = F.relu(self.linear1(x))         # age_output1
    output2 = F.sigmoid(self.linear2(x))      # gender_output2
    return output1, output2
</code></pre>
<p>which indicates that the second output would be in the range <code>[0, 1]</code> via the <code>torch.sigmoid</code> operation while the printed outputs are showing the opposite value ranges. Also, it seems as if no <code>grad_fn</code> are visible, which is also not expected.<br>
In any case, check the target values too and make sure they are valid.</p>

username: Niraja
cooked: <p>What should I do? Where should I correct my model.</p>