Noob question about how Loss functions work in PyTorch

qavvv: <p>I am new to PyTorch and making a transition from TF/keras to PyTorch so I apologize if my question is very basic.</p>
<p>I have started with some tutorials and in one of them I have the following training loop function where it iterates over the dataset, trains the model for 1 epoch computes the loss and updates the weights.<br>
<div class="lightbox-wrapper"><a class="lightbox" href="https://discuss.pytorch.org/uploads/default/original/3X/1/b/1b775410523d625f4e101a680636c7d2b7620902.jpeg" data-download-href="https://discuss.pytorch.org/uploads/default/1b775410523d625f4e101a680636c7d2b7620902" title="train loop fn"><img src="https://discuss.pytorch.org/uploads/default/optimized/3X/1/b/1b775410523d625f4e101a680636c7d2b7620902_2_465x375.jpeg" alt="train loop fn" data-base62-sha1="3UYycdfbZ7ugjmoPhk9EYCqhdqG" width="465" height="375" srcset="https://discuss.pytorch.org/uploads/default/optimized/3X/1/b/1b775410523d625f4e101a680636c7d2b7620902_2_465x375.jpeg, https://discuss.pytorch.org/uploads/default/original/3X/1/b/1b775410523d625f4e101a680636c7d2b7620902.jpeg 1.5x, https://discuss.pytorch.org/uploads/default/original/3X/1/b/1b775410523d625f4e101a680636c7d2b7620902.jpeg 2x" data-dominant-color="F2F2F2"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">train loop fn</span><span class="informations">644×518 52.7 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div></p>
<p>So far so good. The problem I have is when I try to return the loss value from this function and print its value after each epoch (see below) the model seems to be not working anymore.</p>
<pre><code class="lang-auto">    for epoch in range(EPOCHS):
        train_loop_fn(train_data_loader, model, optimizer, device, scheduler)
#      loss =  train_loop_fn(train_data_loader, model, optimizer, device, scheduler)
        outputs, targets = eval_loop_fn(valid_data_loader, model, device)
        
        spear = []
        for jj in range(targets.shape[1]):
            p1 = list(targets[:, jj])
            p2 = list(outputs[:, jj])
            
            coef, _ = np.nan_to_num(stats.spearmanr(p1, p2))
            spear.append(coef)
        
        spear_mean = np.mean(spear)
        
#print(f'spear={spear_mean}\tLoss:{loss.item()}')
        print(f'spear={spear_mean}')
</code></pre>
<p>When I don’t return the loss function, I can clearly see that the model is training because the <code>spear_mean</code> keeps increasing epoch by epoch but after I uncomment the lines in images and try to print <code>loss.item()</code> the code no longer follows a general pattern and I get random values of <code>spear_mean</code> and <code>loss.item()</code> in every epoch. I don’t really see what is going wrong here and why would returning the loss value mess things up here. Any help is greatly appreciated. Thank you in advance.</p>

ptrblck: <p>If you didn’t change the training loop besides returning the <code>loss</code>, nothing should change.<br>
How reproducible is this effect? I.e. if you compare the initial code to the modified one (with returned loss) for e.g. 10 runs, what’s the mean and stddev of the final accuracy?</p>

qavvv: <p>Thank you for your quick reply. It is reproducible. Refer to <a href="https://www.kaggle.com/mhviraf/qa-bert-pytorch?scriptVersionId=28476451;" rel="nofollow noopener">https://www.kaggle.com/mhviraf/qa-bert-pytorch?scriptVersionId=28476451;</a> versions 2 and 8 work perfectly fine. versions 3 through 7 doesn’t. I don’t know how familiar you are with Kaggle notebooks but if you click on the “8 commits” link on the top left of the page it lets you see the difference between versions 7 and 8.</p>
<p>I ran the original version twice and both times the mean_spearman goes up to 0.54 after about 10 epochs. Whilst, I ran the modified version where the loss is returned for 5 times and every time spear_mean jumps back and forth between -0.05 and 0.16 through epochs.</p>
<p>One thing that is very suspicious is that when I return the loss it iterates very fast over epochs and the runtime becomes about 10sec/epoch while in the original code the runtime is about 400sec/epoch.</p>

ptrblck: <p>Thanks for the notebook!<br>
Your indentation of the <code>return loss</code> statement is wrong as you would return after a single iteration, which also explains the runtime difference.</p>