Backpropagation through List Comprehension

username: Andreas_Binder
cooked: <p>Hi everyone,<br>
I want to create tensor with shape (N*N,2) from a tensor of shape (N,1) that contains all possible combinations (with duplicates). It is part of a bigger pipeline but I realised that the gradients do not flow; this is how the code looks like:</p>
<pre><code class="lang-auto">x_graph = torch.tensor([[-1], [0], [1]], dtype=torch.float, requires_grad=True)
stacked_x = torch.stack([torch.tensor([n,i], requires_grad=True) for n in x_graph for i in x_graph])
</code></pre>
<p>This is the content of stacked_x:</p>
<pre><code class="lang-auto">tensor([[-1., -1.],
        [-1.,  0.],
        [-1.,  1.],
        [ 0., -1.],
        [ 0.,  0.],
        [ 0.,  1.],
        [ 1., -1.],
        [ 1.,  0.],
        [ 1.,  1.]], grad_fn=&lt;StackBackward0&gt;)
</code></pre>
<p>However, calling <code>torch.autograd.grad(stacked_x.sum(), x_graph)[0]</code> yields the following mistake:</p>
<pre><code class="lang-auto">RuntimeError                              Traceback (most recent call last)
/tmp/ipykernel_547127/2517417709.py in &lt;module&gt;
----&gt; 1 torch.autograd.grad(stacked_x.sum(), x_graph)[0]

~/miniconda3/envs/test_torch/lib/python3.7/site-packages/torch/autograd/__init__.py in grad(outputs, inputs, grad_outputs, retain_graph, create_graph, only_inputs, allow_unused, is_grads_batched)
    300         return Variable._execution_engine.run_backward(  # Calls into the C++ engine to run the backward pass
    301             t_outputs, grad_outputs_, retain_graph, create_graph, t_inputs,
--&gt; 302             allow_unused, accumulate_grad=False)  # Calls into the C++ engine to run the backward pass
    303 
    304 

RuntimeError: One of the differentiated Tensors appears to not have been used in the graph. Set allow_unused=True if this is the desired behavior.
</code></pre>
<p>Probably, it is a simple mistake … thank you very much!</p>
<p>UPDATE: I found a solution using <code>torch.combination</code>, however I am still curious how I can solve the original error <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=12" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"> thx!</p>

username: KFrank
cooked: <p>Hi Andreas!</p>
<aside class="quote no-group" data-username="Andreas_Binder" data-post="1" data-topic="169657" data-full="true">
<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/andreas_binder/48/56173_2.png" class="avatar"> Andreas_Binder:</div>
<blockquote>
<pre><code class="lang-auto">x_graph = torch.tensor([[-1], [0], [1]], dtype=torch.float, requires_grad=True)
stacked_x = torch.stack([torch.tensor([n,i], requires_grad=True) for n in 
</code></pre>
</blockquote>
</aside>
<p>In this line of code, <code>n</code> and <code>i</code> are indeed pytorch tensors.  However, the<br>
<code>Tensor</code> factory function, <code>torch.tensor()</code>, is expecting python scalars,<br>
so pytorch (helpfully) converts the tensors you pass in to python scalars.<br>
This “breaks the computation graph,” backpropagation fails, and adding<br>
<code>requires_grad = True</code> to your call to <code>torch.tensor()</code> doesn’t fix the<br>
problem.</p>
<p>Avoiding <code>torch.tensor()</code> works.  Here is a modified version of your code<br>
that uses <code>torch.cat()</code> to build the tensors that you then <code>stack()</code>:</p>
<pre><code class="lang-plaintext">&gt;&gt;&gt; import torch
&gt;&gt;&gt; print (torch.__version__)
1.13.0
&gt;&gt;&gt;
&gt;&gt;&gt; x_graph = torch.tensor([[-1], [0], [1]], dtype=torch.float, requires_grad=True)
&gt;&gt;&gt; stacked_x = torch.stack ([torch.cat ([x_graph[n], x_graph[i]]) for n in range (len (x_graph)) for i in range (len (x_graph))]
... )
&gt;&gt;&gt;
&gt;&gt;&gt; stacked_x
tensor([[-1., -1.],
        [-1.,  0.],
        [-1.,  1.],
        [ 0., -1.],
        [ 0.,  0.],
        [ 0.,  1.],
        [ 1., -1.],
        [ 1.,  0.],
        [ 1.,  1.]], grad_fn=&lt;StackBackward0&gt;)
&gt;&gt;&gt;
&gt;&gt;&gt; torch.autograd.grad(stacked_x.sum(), x_graph)[0]
tensor([[6.],
        [6.],
        [6.]])
</code></pre>
<p>Best.</p>
<p>K. Frank</p>