Error: grad can be implicitly created only for scalar outputs

onimusha702: <p>So i am trying to train a Variational Auto Encoder, and i have created a custom loss function to train the network, the network throws the error</p>
<pre><code class="lang-auto">RuntimeError: grad can be implicitly created only for scalar outputs
</code></pre>
<p>heres the Loss function</p>
<pre><code class="lang-auto">def loss_function(recon_x, x, mu, logvar):
    BCE = F.binary_cross_entropy(recon_x, x, reduction='none')
    KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())
    the_loss = BCE + KLD
    return the_loss
</code></pre>
<p>and My training Code</p>
<pre><code class="lang-auto">optimizer = torch.optim.Adam(model.parameters(), lr=1e-3,
                             weight_decay=1e-4)

num_epochs = 150

running_loss = 0
steps = 0
print_every = 1
for epoch in range(num_epochs):
    model.train()
    for data in trainloader:
        steps += 1
        img, _ = data
        img = img.cuda()
        
        decoded, mu, logvar = model(img)
        loss = loss_function(decoded, img, mu, logvar)
        
        optimizer.zero_grad()
        loss.backward()  # &lt;------- Error On this Line
        optimizer.step()
        running_loss += loss.item()
        if steps % print_every == 0:
            model.eval()

            with torch.no_grad():
                valid_loss = validation(model, validloader)
            
            model.train()
            
            print("Epoch: {}/{}.. ".format(epoch+1, num_epochs),
                  "Training Loss: {:.4f}.. ".format(running_loss/print_every),
                  "valid Loss: {:.4f}.. ".format(valid_loss/len(validloader)))
            running_loss = 0
    if epoch % 10 == 0:
        save_im(output, 'epoch '+str(epoch))
</code></pre>
<p>Image size is 64, 3, 96, 96</p>

bharat0to: <p>Try printing the losses, it should be a tensor with single number</p>

onimusha702: <p>even if it prints the autograd throws an error, so no point in printing it when i can’t train the model</p>

ptrblck: <p>As <a class="mention" href="/u/bharat0to">@bharat0to</a> said, your <code>loss</code> is most likely a multi-dimensional tensor, which will thus throw this error.<br>
You could add some reduction or pass a <code>gradient</code> with the same shape as <code>loss</code>.</p>

onimusha702: <p>I tried printing the loss, it was a series of values, so decided to reduce the loss using the <code>reduction='sum'</code> parameter in this function <code>binary_cross_entropy</code>.</p>
<p>It started training though the loss is quite high.</p>

ptrblck: <p>You could try to use <code>reduction='mean'</code> which would lower the loss value or just remove the <code>reduction</code> argument, as <code>mean</code> is the default.</p>

onimusha702: <p>It helped, Thanks for the suggestion!</p>

Sanjayvarma11: <p>hi ptrblck.I am big fan of your support to this community.I am trying to generate a depth map for a given image.So i used BCELoss() for this where  output(to loss function by model) is of size  [10,1,250,250] and target(to loss function ground depth) is [10,1,250,250].<br>
Now i am thinking of  using reduction="mean’ and  backpropagate it.But it is giving me huge values as loss.Plz let me know your opinion.plz tell me which loss function is better in this scenario</p>

ptrblck: <p>If you are using <code>nn.BCELoss</code>, I assume you are using a <code>sigmoid</code> at the end of your model?<br>
I would generally recommend to output raw logits and use <code>nn.BCEWithLogitsLoss</code> as it’ll give you more numerical stability.</p>
<p>Could you check the min and max values of your target, please?<br>
How large is the loss at the moment?</p>

Sanjayvarma11: <p>The saviour ptrblck sir Thank you so much for replying to me.Yeah i looked the min and max value of my target label and since it is a depth image it is in mostly having values 2 and 245.so i divided it by 255 and now the loss is decreased and it is good right now.But i am always having trouble understanding that we are creating an image from an input image then we can just do l1 loss for it but why you are suggesting BCEwithlogitloss.Can you tell me the intuition behind using the BCEwithlogitloss??.Thank you sir</p>

ptrblck: <p><code>nn.BCEWithLogitsLoss</code> was just the better alternative to <code>nn.BCEWithLogitsLoss</code>.<br>
For a depth estimation I would guess that <code>nn.L1Loss</code> or <code>nn.MSELoss</code> might work better, but you should try out different approaches. <img src="https://discuss.pytorch.org/images/emoji/apple/wink.png?v=9" title=":wink:" class="emoji" alt=":wink:"></p>

Sanjayvarma11: <p>But the nn.MSELoss might not give good results for punishing the small<br>
values.Is it right??</p>

ptrblck: <p>That might be correct, but it’s hard to estimate if it would be worse than e.g. <code>L1Loss</code> for depth maps.</p>

Sanjayvarma11: <p>yes sir i will try it also.Thank you so much for answering questions.</p>

mhamdan: <p>Hi,<br>
I am trying to compute the gradients of my network output (a batch of a single number) with respect to the model trainable parameters.</p>
<p>I assumed this would do the trick: outputs.backward(), but i am getting the same error as stated in this thread. Although does backward() compute the gradients w.r.t model trainable parameters? Additionally, how can I access the calculated gradients as I need to perform some operations on them?</p>
<p>Please share your thoughts on how I can accomplish the desired functionality?</p>

ptrblck: <p>The error is raised if you call <code>.backward()</code> on a tensor, which is not a scalar.<br>
In that case you should either reduce the tensor before (e.g. via <code>tensor.mean()</code>) or pass the gradients to <code>backward</code> (e.g. via <code>tensor.backward(torch.ones_like(tensor))</code>).</p>
<p>You can access the gradients after the <code>backward()</code> call by accessing them directly, e.g.:</p>
<pre><code class="lang-python">print(model.layer.weight.grad)
</code></pre>

mhamdan: <p>Thank you for your reply.</p>
<p>So, I do not wish to reduce the vector into scalar as I need gradients for each output. I do not quite follow the other method, which is passing the gradients to backward? Can you elaborate?</p>
<p>Basically, assume my network output is y and network parameters are x --&gt; i want dy/dx for each y in batch y. Then I’d like to aggregate them all together. So, when you say pass the gradients, how do I pass them when backward is actually what computes the gradients?</p>
<p>As for accessing gradients, in TF - you can get all gradients for all network parameters in a single object --&gt; grads  = tape.gradients, is not there something similar in pytorch? other than accessing them separately like this : model.layer.weight.grad</p>

ptrblck: <p>The gradient argument in <code>backward</code> can be seen as e.g. <code>dLoss/dLoss</code>, which for a scalar loss value would be <code>1</code> and is automatically set for you.<br>
However, if your loss is a tensor in a specific shape, you would have to provide <code>dLoss/dLoss</code> manually, which is shown in my example.</p>
<p>Depending on your use case, you might prefer to use <code>torch.autograd.grad</code> to compute gradients of specific parameters.</p>

Hassan_Imani: <aside class="quote no-group" data-username="ptrblck" data-post="4" data-topic="38102">
<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>or pass a <code>gradient</code> with the same shape as <code>loss</code>.</p>
</blockquote>
</aside>
<p>How can I do this?<br>
pass a <code>gradient</code> with the same shape as <code>loss</code> .</p>
<p>My loss has 128 element and I dont want to sum or mean of it.</p>

ptrblck: <p>You could use <code>loss.backward(torch.ones_like(loss))</code>.</p>