Loss requires_grad is False

smu226: <p>Hello I have the following code (simplified version of my code but able to reproduce the error):</p>
<pre><code>import numpy as np
from numpy import linalg as LA
import torch
import torch.optim as optim 
import torch.nn as nn

def func(x,pars):
    a = pars[0]
    b = pars[1]
    c = pars[2]
    d = pars[3]

    x = x.int()

    H = torch.tensor([[a,b,1],[2,3,c],[4,d,7]])

    eigenvalues, eigenvectors = np.linalg.eigh(H)

    trans_freq = eigenvalues[x]

    return torch.tensor(trans_freq)

x_index = torch.tensor([1,2])
y_vals = torch.tensor([0.5,12])

params = torch.tensor([1.,2.,3.,4.])
params.requires_grad=True
opt = optim.SGD([params], lr=100)

mse_loss = nn.MSELoss()

for i in range(10):
  opt.zero_grad()
  loss = mse_loss(func(x_index,params),y_vals)
  print(x_index.requires_grad)
  print(params.requires_grad)
  print(y_vals.requires_grad)
  print(loss.requires_grad)
  loss.backward()
  opt.step() 
  print(loss)
</code></pre>
<p>The output is:</p>
<pre><code>False
True
False
False
</code></pre>
<p>and I am getting this error: <code>RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn</code> from this line: <code>loss.backward()</code>. Indeed the loss doesn’t have <code>requires_grad=True</code> but why is that the case (setting it manually in the for loop doesn’t work either). What should I do? Thank you!</p>

ptrblck: <p>You are detaching <code>trans_freq</code> from the computation graph by recreating a new tensor:</p>
<aside class="quote no-group" data-username="smu226" data-post="1" data-topic="191900">
<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/smu226/48/9063_2.png" class="avatar"> smu226:</div>
<blockquote>
<p><code>return torch.tensor(trans_freq)</code></p>
</blockquote>
</aside>
<p>Return <code>trans_freq</code> directly and remove the unnecessary tensor creation, which also will raise a warning:</p>
<pre data-code-wrap="python"><code class="lang-python">UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).
</code></pre>

smu226: <aside class="quote no-group" data-username="ptrblck" data-post="2" data-topic="191900">
<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>trans_freq</p>
</blockquote>
</aside>
<p>If I do that I am indeed not getting that error anymore, but now I get this new one: <code>TypeError: 'int' object is not callable</code>, coming from here: <code>loss = mse_loss(func(x_index,params),y_vals)</code>. Also I noticed that if I try to call <code>func(x_index,params)-y_vals</code> I am getting this error: <code>TypeError: unsupported operand type(s) for -: 'numpy.ndarray' and 'Tensor'</code>, so it seems like, unless I explicitly say <code>return torch.tensor(trans_freq)</code>, the output of <code>func(x_index,params)</code> is numpy not pytorch.</p>

ptrblck: <p>You are right and I missed your usage of numpy. This approach won’t directly work as PyTorch won’t track the <code>np.linalg.eigh</code> operation and thus won’t create a computation graph. Either use pure Pytorch methods instead of numpy or create a custom <code>autograd.Function</code> using numpy ops including the backward as described <a href="https://pytorch.org/tutorials/beginner/examples_autograd/two_layer_net_custom_function.html">here</a>.</p>

smu226: <p>Thanks for this. Why can’t that graph be computed? Matrix diagonalization requires additions and multiplications so taking the derivatives should be straightforward i.e. writing the eigenvalues in terms of the original matrix elements can be done analytically and in principle the derivatives can be taken by hand (I am genuinely curious about what makes the problem difficult computationally). Also is there a way to diagonalize matrices in Pytorch?</p>

ptrblck: <p>PyTorch does not track 3rd party library operations, so either use PyTorch operations or create the custom <code>autograd.Function</code> if you need to use numpy (or any other 3rd party library).</p>

smu226: <p>So I changed my code to this:</p>
<pre><code class="lang-auto">import torch
import torch.optim as optim 
import torch.nn as nn

def func(x,pars):
    a = pars[0]
    b = pars[1]
    c = pars[2]
    d = pars[3]

    x = x.int()

    H = torch.tensor([[a,b,1],[2,3,c],[4,d,7]])

    eigenvalues, eigenvectors = torch.linalg.eig(H)

    trans_freq = torch.real(eigenvalues[x])

    return trans_freq

x_index = torch.tensor([1.,2.])
y_vals = torch.tensor([10.,1.1])

params = torch.tensor([1.,2.,3.,4.])
params.requires_grad=True
opt = optim.SGD([params], lr=100)

mse_loss = nn.MSELoss()

for i in range(10):
  opt.zero_grad()
  loss = mse_loss(func(x_index,params),y_vals)
  loss.backward()
  opt.step() 
  print(loss)
</code></pre>
<p>Now everything is pytorch, but I am still getting the error: <code>RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn</code> for <code>loss.backward()</code>.</p>

ptrblck: <p>You are detaching <code>pars</code> by creating a new <code>tensor</code> as explained in a previous post:</p><aside class="quote quote-modified" data-post="2" data-topic="191900">
  <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">
    <a href="https://discuss.pytorch.org/t/loss-requires-grad-is-false/191900/2">Loss requires_grad is False</a> 
  </div>
  <blockquote>
    You are detaching trans_freq from the computation graph by recreating a new tensor: 

Return trans_freq directly and remove the unnecessary tensor creation, which also will raise a warning: 
UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).
  </blockquote>
</aside>

<p>Use <code>torch.cat</code> or <code>torch.stack</code> if you want to create <code>H</code> from <code>pars</code>,</p>