Can not execute backward() after expand()

Young_chai_Zheng: <p>I am testing the difference between “expand()” and “repeat()”.There are some problems when executing the backward. I have a little trouble understanding this error message.</p>
<pre><code class="lang-auto">a = nn.Parameter(torch.FloatTensor(torch.ones(3,1)), requires_grad=True)
b = a.expand(3,4)
c = a.repeat(1,4)
print(a.data_ptr(),b.data_ptr(),c.data_ptr())
with torch.no_grad():
    a[0,0] = 3
print(b)
print(c)
d = torch.sum(3*b)
d.backward()
print(a.grad)
</code></pre>
<blockquote>
<p>2152330348608 2152330348608 2152301237760<br>
tensor([[3., 3., 3., 3.],<br>
[1., 1., 1., 1.],<br>
[1., 1., 1., 1.]], grad_fn=&lt;AsStridedBackward&gt;)<br>
tensor([[1., 1., 1., 1.],<br>
[1., 1., 1., 1.],<br>
[1., 1., 1., 1.]], grad_fn=&lt;RepeatBackward&gt;)<br>
Traceback (most recent call last):<br>
File “d:\Desktop\deepul-master\flow.py”, line 232, in <br>
d.backward()<br>
File “D:\App\Anaconda3\lib\site-packages\torch\tensor.py”, line 221, in backward<br>
torch.autograd.backward(self, gradient, retain_graph, create_graph)<br>
File “D:\App\Anaconda3\lib\site-packages\torch\autograd_<em>init</em>_.py”, line 132, in backward<br>
allow_unreachable=True)  # allow_unreachable flag<br>
RuntimeError: Index out of range</p>
</blockquote>

Alexey_Demyanchuk: <p>Hi. I will try to clarify as I understand it myself.</p>
<ol>
<li>It is not <code>expand</code>, there the problem is rising, if you not changing <code>a</code>, the code is working:</li>
</ol>
<pre><code class="lang-auto">a = nn.Parameter(torch.FloatTensor(torch.ones(3,1)), requires_grad=True)
b = a.expand(3,4)
c = a.repeat(1,4)
print(a.data_ptr(),b.data_ptr(),c.data_ptr())

print(b)
print(c)
d = torch.sum(3*b)
d.backward()
print(a.grad)
</code></pre>
<ol start="2">
<li>The error is giving a small clue (but clue) on what is the matter, it is about “unreachable”. And the problem is in this code <code>a[0,0] = 3</code>. You are basically making some part of <code>a</code> to not <code>requires_grad</code> and so make this part unreachable for backward computation. But if you change the code like this:<br>
<code>a.data[0,0] = 3</code>. It will change only data and not <code>requires_grad</code> and messing up with computational graph. And all the code will work as expected.</li>
</ol>
<p>I believe, I may not be 100% correct in details of my explanation but the main idea should be correct.</p>
<p>As of the difference between <code>expand</code> and <code>repeat</code>, this <a href="https://discuss.pytorch.org/t/torch-repeat-and-torch-expand-which-to-use/27969">post</a> can be of some help to you.</p>
<p>Cheers.</p>

albanD: <p>Hi,</p>
<p>Some precisions to Alexey’s message:</p>
<ol>
<li>
<p>Indeed, the problem is not with only expand, but with expand + the inplace. And in particular because expand is a view of a.  This is why you don’t see any issue if you remove the inplace or if you replace the expand with a repeat that is not a view (it allocates new memory).</p>
</li>
<li>
<p>"it is about “unreachable” I don’t think that is. And the error in an internal bug on our end I think <img src="https://discuss.pytorch.org/images/emoji/apple/confused.png?v=9" title=":confused:" class="emoji" alt=":confused:"><br>
The reason for <code>.data</code> to “fix” the issue is because it hides the inplace op from the autograd (in a bad way) and so it looks like you do only the view for the autograd.<br>
In general, you should <em>never</em> use .data! and the <code>with torch.no_grad()</code> is the right way to do this!</p>
</li>
</ol>
<p>The temporary fix here is to remove the print of <code>b</code> between the no_grad block and the line where you use it for the sum.</p>
<p>I opened an issue here that explains the exact issue and discusses how to solve it.: <a href="https://github.com/pytorch/pytorch/issues/49756" class="inline-onebox">Printing should not have (bad) autograd side effects · Issue #49756 · pytorch/pytorch · GitHub</a></p>

Young_chai_Zheng: <p>Thank you for your answer, I tried your code and it does work well. albanD’s addition to you also makes sense. Thanks again!</p>

Alexey_Demyanchuk: <p>Thanks a lot for the correction. I looked into an issue and understand the problem better now. Sorry for potentially misleading answer from my side <img src="https://discuss.pytorch.org/images/emoji/apple/slightly_frowning_face.png?v=12" title=":slightly_frowning_face:" class="emoji" alt=":slightly_frowning_face:" loading="lazy" width="20" height="20"></p>
<aside class="quote no-group" data-username="albanD" data-post="3" data-topic="106724">
<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/alband/48/215_2.png" class="avatar"> albanD:</div>
<blockquote>
<p>In general, you should <em>never</em> use .data!</p>
</blockquote>
</aside>
<p>Can you please elaborate on this a bit?</p>

albanD: <blockquote>
<p>Sorry for potentially misleading answer from my side <img src="https://discuss.pytorch.org/images/emoji/apple/slightly_frowning_face.png?v=12" title=":slightly_frowning_face:" class="emoji" alt=":slightly_frowning_face:" loading="lazy" width="20" height="20"></p>
</blockquote>
<p>No worries at all! Thanks for taking the time to look into the issue and provide a workaround!</p>
<blockquote>
<p>Can you please elaborate on this a bit?</p>
</blockquote>
<p><code>.data</code> remains from the time where we had Variable and Tensors. And in that world, it was allowing you to get the Tensor inside the Variable (so the version without any autograd info).<br>
Today where both are the same, it just creates a new Tensor with the autograd info from the original Tensor striped out.</p>
<p>The problem is that no autograd info also means no checking for inplace ops or views! So using such Tensors with other Tensors that actually do autograd can lead to silently wrong gradients!!</p>
<p>So we are in the process of removing it everywhere in our codebase to ensure that we don’t have silently wrong gradients. But users should stop using them as well and replace them with <code>.detach()</code> (that breaks the graph but keep all the essential view/inplace check) or <code>torch.no_grad()</code> to locally disable the autograd.</p>