Example for One of the differentiated Tensors appears to not have been used in the graph

Sudarshan_VB: <p>Can anyone please give an example of this scenario, I am struggling to understand why this could even happen</p>

albanD: <p>Hi,</p>
<p>Here is an example:</p>
<pre><code class="lang-auto">a = torch.rand(10, requires_grad=True)
b = torch.rand(10, requires_grad=True)

output = (2 * a).sum()

torch.autograd.grad(output, (a, b))
</code></pre>

Sudarshan_VB: <p>Thank you !! yeah it makes sense now</p>

muammar: <p>Is there any way to add the <code>b</code> to the graph so that the derivative can be computed?</p>

albanD: <p>Well if <code>b</code> is not in the graph then the derivative is just <code>0</code> everywhere. You don’t need to add it to the graph to get the derivatives.</p>

muammar: <p>Thanks for your reply. I asked that because of the following (I hope you could shed some light): I have a model that forward-propagates using features <strong>a</strong> that were calculated as a function of another vector <strong>c</strong> without pytorch  – I used numpy and then converted <strong>a</strong> to tensor (that’s why they are not part of the graph, I guess). The output of the model I am working on, a scalar, can be differentiated with respect to <strong>c</strong>. However, because <strong>c</strong> is nowhere registered in the computational graph, it will not be possible to compute the derivative of the output with respect to it. Is this correct? And there is no way to compute that gradient with autograd unless <strong>c</strong> is used somewhere and registered.</p>

albanD: <p>Hi,</p>
<p>You are right that if you don’t use pytorch for some things, you won’t be able to use autograd.<br>
The way to get around this is to create a custom Function (see <a href="https://pytorch.org/docs/stable/notes/extending.html">here</a> how to) that specifies how to compute the backward for a given op. That way, you can wrap the code that the autograd cannot handle in the forward and write the backward by hand there. And then you will be able to use this as any differentiable function in the autograd.</p>

muammar: <p>Thanks for your reply. The link seems very helpful. Hopefully I can extend the functionality as I need. <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"></p>

Sahar_Nasser: <p>Thank you for the clarification.so this will give an error unless we set “allow_unused=True”. My question when we have huge number of parameters and some of them are not used in the graph how can we just ignore them instead of using  “allow_unused=True” ?<br>
because getting None after using “allow_unused=True” will cause another problem.</p>

albanD: <p>If you already know that these parameters are not used, you can filter the out and not give them to <code>autograd.grad()</code> in the first place. That way, you won’t have to give allow_unused=True.</p>

Sahar_Nasser: <p>I did that, thank you <img src="https://discuss.pytorch.org/images/emoji/apple/blush.png?v=9" title=":blush:" class="emoji" alt=":blush:"></p>

Tony_Gracious: <p>Do you know why this block of code giving the error “One of the differentiated Tensors appears to not have been used in the graph”?</p>
<pre><code class="lang-auto">a = torch.rand(10, requires_grad=True)

output = (2 * a).sum()

torch.autograd.grad(output, a[0])
</code></pre>

albanD: <p>Hi,</p>
<p>This is because <code>a[0]</code> is a different Tensor from <code>a</code>. And that Tensor (that you just created) has not been used to compute the <code>output</code>.<br>
You will have to do:</p>
<pre><code class="lang-python">grad_a, = torch.autograd.grad(output, a)
grad_a_0 = grad_a[0]

</code></pre>

Tony_Gracious: <p>Since a[0] is part of a, why is it considered as a different tensor? Could you also point out some reference materials regarding this?</p>

albanD: <blockquote>
<p>Since a[0] is part of a</p>
</blockquote>
<p>Well it is not. It is the same as doing <code>a.select(0, 0)</code>. And it just returns a new Tensor that shares memory.</p>
<p>You can check our doc about Tensor views for more details: <a href="https://pytorch.org/docs/stable/tensor_view.html?highlight=view" class="inline-onebox">Tensor Views — PyTorch 2.1 documentation</a></p>

Ellun: <p>Hi <a class="mention" href="/u/alband">@albanD</a>,</p>
<p>Based on Tony’s code, suppose we have a batch of data x, and we need to calculate the grad one by one like:</p>
<pre><code class="lang-auto">output[i] = fn(x[i])
grad = torch.autograd.grad(output[i], x[i])
</code></pre>
<p>Considering the explanations you provided, either we can do</p>
<pre><code class="lang-auto">grad_x, = torch.autograd.grad(output[i], x)
grad_x_i = grad_x[i]
</code></pre>
<p>or we can do</p>
<pre><code class="lang-auto">u = x[i]
output = fn(u)
grad_x_i = torch.autograd.grad(output, u)
grad_x[i] = grad_x_i 
</code></pre>
<p>Will the latter way be faster than the former one? Since now it seems we need to calculate the input one by one, can the calculation be accelerated if in GPU? Thank you for your time in advance!</p>

albanD: <p>Hi,</p>
<p>Yes both will give the same result.<br>
And indeed the second will be a bit more efficient as you only evaluate on the part of the input you want.</p>

s_mkb: <p>Hello. I have the same error, and I described my question in detail here:<a href="https://discuss.pytorch.org/t/calculating-loss-with-autograd-one-of-the-differentiated-tensors-appears-to-not-have-been-used-in-the-graph/121795" class="inline-onebox">Calculating loss with autograd: One of the differentiated Tensors appears to not have been used in the graph</a></p>
<p>Is this happening because I need to create a custom pytorch function for the curl?</p>

Griffin_Tabor: <p>If it shares memory, then clearly the value of a[0] does have a gradient with respect to output. If I changed a[0] and then recalled loss it would be updated, we could then measure that update with respect to how much I changed a[0]. <strong>The very definition of the gradient</strong></p>
<pre><code class="lang-auto">import torch
a = torch.rand(10, requires_grad=True)

output = (2 * a).sum()

print(output)
a[0] +=1
output2 = (2 * a).sum()
print(output2)
</code></pre>
<pre><code class="lang-auto">
tensor(11.2303, grad_fn=&lt;SumBackward0&gt;)
tensor(13.2303, grad_fn=&lt;SumBackward0&gt;)
</code></pre>

Griffin_Tabor: <p>I guess my example code above does not actually work in a more up to date version of pytorch. It throws an error instead…</p>
<p>Which admittedly weakens my argument that its clear there is a gradient between a[0] and output; but does not seem to satisfy me. If I wanted to know the cost/gradient if a was shifted in a single dimension I would want the above code to work.</p>