Modifying a Tensor with requires_grad=True in PyTorch - Maintaining Connection for Backpropagation

Yasin_K: <p><strong>Hi everyone,</strong></p>
<p>I’m encountering an issue while creating a tensor from an input matrix and performing further analysis on it in PyTorch. My code involves modifying a tensor with <code>requires_grad=True</code>, but I’m running into a <code>RuntimeError</code> about in-place operations.<br>
<br><br>
<strong>Code Snippet:</strong></p>
<pre><code class="lang-auto">import torch


def zero_dimension_Topology_computation(distance_matrix):
   
  size = distance_matrix.shape[0]

  distance = torch.zeros(int(size*(size-1)*1.5), requires_grad=True)
   
  counter = 0
  for i in range(size):
    for j in range(i+1, size):

      distance[counter] = distance_matrix[i, j]
      counter += 1
      distance[counter] = i
      counter += 1
      distance[counter] = j
      counter += 1
   
  return distance

my_distance_matrix = torch.tensor(
 [[0.,     1.1220787, 2.56805496, 3.17087232, 4.19878769, 5.28180264, 6.00723115, 7.00725978, 8.10627762, 9.00086877],
 [1.1220787, 0.,     1.48800688, 2.52166396, 3.09666062, 4.57047671, 5.06417233, 6.00301049, 7.04549262, 8.02508567],
 [2.56805496, 1.48800688, 0.,     2.82092185, 2.02773478, 4.46949128, 4.43069515, 5.16422506, 6.00762258, 7.21203433],
 [3.17087232, 2.52166396, 2.82092185, 0.,     2.51119582, 2.11094118, 3.08805856, 4.22031097, 5.51843328, 6.06739184],
 [4.19878769, 3.09666062, 2.02773478, 2.51119582, 0.,     3.14220102, 2.54342334, 3.14917369, 4.00012553, 5.19276009],
 [5.28180264, 4.57047671, 4.46949128, 2.11094118, 3.14220102, 0., 1.72659306, 2.84336824, 4.25008607, 4.29969124],
 [6.00723115, 5.06417233, 4.43069515, 3.08805856, 2.54342334, 1.72659306, 0.,     1.17321974, 2.56312249, 3.00479065],
 [7.00725978, 6.00301049, 5.16422506, 4.22031097, 3.14917369, 2.84336824, 1.17321974, 0.,     1.40677017, 2.04867891],
 [8.10627762, 7.04549262, 6.00762258, 5.51843328, 4.00012553, 4.25008607, 2.56312249, 1.40677017, 0.,     1.747742 ],
 [9.00086877, 8.02508567, 7.21203433, 6.06739184, 5.19276009, 4.29969124, 3.00479065, 2.04867891, 1.747742,  0.    ]]
, requires_grad=True)


zero_dimension_Topology_computation(my_distance_matrix)
</code></pre>
<br>
<p><strong>Error:</strong></p>
<p><code>RuntimeError: a view of a leaf Variable that requires grad is being used in an in-place operation.</code><br>
<br></p>
<p><strong>Problem:</strong></p>
<p>I want to create a tensor <code>distance</code> from <code>distance_matrix</code> while keeping <code>requires_grad=True</code> for backpropagation. However, directly assigning values to <code>distance</code> using in-place operations throws an error.<br>
<br></p>
<p><strong>Desired Outcome:</strong></p>
<ol>
<li>Create a tensor <code>distance</code> from <code>distance_matrix</code>.</li>
<li>Modify <code>distance</code> for further analysis.</li>
<li>Maintain the connection to the computation graph for backpropagation.<br>
<br></li>
</ol>
<p><strong>Question:</strong></p>
<p>How can I effectively modify a tensor with <code>requires_grad=True</code> while preserving its connection to the computation graph for backpropagation?</p>

KFrank: <p>Hi Yasin!</p>
<aside class="quote no-group quote-modified" data-username="Yasin_K" data-post="1" data-topic="200399" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/letter_avatar_proxy/v4/letter/y/8edcca/48.png" class="avatar"> Yasin_K:</div>
<blockquote>
<pre><code class="lang-auto">  distance = torch.zeros(int(size*(size-1)*1.5), requires_grad=True)
...
      distance[counter] = distance_matrix[i, j]
</code></pre>
<p><code>RuntimeError: a view of a leaf Variable that requires grad is being used in an in-place operation.</code></p>
</blockquote>
</aside>
<p>When you create <code>distance</code> you are creating a new tensor that has<br>
<code>requires_grad</code> set to <code>True</code>.  This makes it a so-called “leaf Variable<br>
that requires grad.”  You are not allowed to modify such tensors in place<br>
(as doing so messes up how autograd keeps track of what it is supposed<br>
to be computing gradients with respect to), but assigning into <code>distance</code><br>
with, say, <code>distance[counter] = distance_matrix[i, j]</code> does count<br>
as modifying it in place.  Hence the error.</p>
<aside class="quote no-group">
<blockquote>
<p>I want to create a tensor <code>distance</code> from <code>distance_matrix</code> while keeping <code>requires_grad=True</code> for backpropagation.<br>
…<br>
How can I effectively modify a tensor with <code>requires_grad=True</code> while preserving its connection to the computation graph for backpropagation?</p>
</blockquote>
</aside>
<p>Because <code>my_distance_matrix</code>, the tensor you pass into your function<br>
as its <code>distance_matrix</code> argument, carries <code>requires_grad = True</code>, the<br>
results of subsequent computations will also carry <code>requires_grad = True</code>.</p>
<p>So do not create <code>distance</code> with <code>requires_grad = True</code> – it’s not needed.</p>
<p>When you first create <code>distance</code> (without <code>requires_grad = True</code>), it will<br>
be a so-called leaf tensor, but will not have <code>requires_grad = True</code>.  So<br>
you are allowed to modify it in place.</p>
<p>With <code>distance[counter] = distance_matrix[i, j]</code>, you do modify it in<br>
place, and do so with the <code>requires_grad = True</code> tensor <code>distance_matrix</code>.<br>
This operation does preserve the connection to the computation graph and<br>
fully supports backpropagation.</p>
<p>After this operation, <code>distance</code> does carry <code>requires_grad = True</code>, but<br>
because it is no longer a leaf tensor you are allowed to further modify it<br>
in place, such as with <code>distance[counter] = i</code>.</p>
<p>If you pass into <code>zero_dimension_Topology_computation()</code> an argument<br>
that has <code>requires_grad = True</code>, the tensor it outputs will as well, and you<br>
will have a proper computation graph and will be able to backpropagate<br>
through the call to <code>zero_dimension_Topology_computation()</code>.</p>
<p>Best.</p>
<p>K. Frank</p>

Yasin_K: <p>Thank you so much.<br>
Best regards<br>
Yasin K</p>