Runtime:Error:one of the variables needed for gradient computation has been modified by an inplace operation

Ashima_Kalathingal: <p>Hello,<br>
I am trying to implement a Neural ODE in pytorch and I am getting the following error. I am new to Pytorch and I am not able to understand where the error is coming from.<br>
The error is :<br>
one of the variables needed for gradient computation has been modified by an inplace operation: [torch.DoubleTensor [100, 3]] is at version 2; expected version 1 instead. Hint: the backtrace further above shows the operation that failed to compute its gradient. The variable in question was changed in there or anywhere later. Good luck!</p>
<p>This is my code snippet below.<br>
class NeuralODE(nn.Module):<br>
def <strong>init</strong>(self,x1,x2):<br>
super(NeuralODE,self).<strong>init</strong>()<br>
self.x1 = x1<br>
self.x2 = x2<br>
l = 100<br>
self.f = nn.Sequential(nn.Linear(3,l),nn.Tanh(),nn.Linear(l,1))</p>
<pre><code>  def forward(self,t,x):
      ifunc   = self.x1
      t_numpy = np.array([t.item()]) if t.dim() == 0 else t.detach().numpy()
      i       = torch.DoubleTensor([ifunc(t_numpy)]).reshape(-1,1)
      x2    = (self.x2).clone().reshape(-1,1)

      #dy/dt 
      C = 5
      dy_dt = (-1/C)*i
      S       = x[0,:].clone().reshape(-1,1) 
      T       = x[1,:].clone().reshape(-1,1) 

      
      i_S_T = torch.cat((i,S,T),dim=1)

      # dp/dt
      C1    = 0.0015397895
      C 2   = 0.020306583

      Q = self.f(i_S_T) # Finding Q through the neural network
      dp_dt = (-C1*(T-x1))+(C2*Q)

      return torch.cat((dy_dt,dp_dt),dim=0)
</code></pre>
<p>Can you please help me debug it?</p>

KFrank: <p>Hi Ashima!</p>
<aside class="quote no-group" data-username="Ashima_Kalathingal" data-post="1" data-topic="206285" 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/ashima_kalathingal/48/71421_2.png" class="avatar"> Ashima_Kalathingal:</div>
<blockquote>
<p>one of the variables needed for gradient computation has been modified by an inplace operation: [torch.DoubleTensor [100, 3]] is at version 2; expected version 1 instead.</p>
</blockquote>
</aside>
<p>The reported shape of the tensor, <code>[100, 3]</code>, can be a useful hint – see<br>
below.</p>
<p>For some explanation about how inplace-modification errors occur and<br>
some techniques to debug them, see this post:</p>
<aside class="quote quote-modified" data-post="7" data-topic="171826">
  <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/k/ecb155/48.png" class="avatar">
    <a href="https://discuss.pytorch.org/t/runtimeerror-one-of-the-variables-needed-for-gradient-computation-has-been-modified-by-an-inplace-operation-torch-floattensor-64-1-which-is-output-0-of-asstridedbackward0-is-at-version-3-expected-version-2-instead-hint-the-backtrace-further-a/171826/7">"RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.FloatTensor [64, 1]], which is output 0 of AsStridedBackward0, is at version 3; expected version 2 instead. Hint: the backtrace further a</a> <a class="badge-category__wrapper " href="/c/autograd/7"><span data-category-id="7" style="--category-badge-color: #AB9364; --category-badge-text-color: #FFFFFF;" data-drop-close="true" class="badge-category " title="A category of posts relating to the autograd engine itself."><span class="badge-category__name">autograd</span></span></a>
  </div>
  <blockquote>
    Hi Fahmyadan and Sangyoon! 

Here are some suggestions about how to track down (and maybe fix) 
inplace-modification errors.  Note that an inplace modification in the forward 
pass is not necessarily* an error – it depends on whether and how the tensor 
that was modified is used in the backward pass.  Note that inplace operations 
can be useful for saving memory – if you replace an innocent inplace operation 
with an out-of-place equivalent, your training will use more memory (and, to a 
minor e…
  </blockquote>
</aside>

<p>You can sometimes  “automatically” fix such errors by using pytorch’s<br>
<a href="https://pytorch.org/docs/2.3/autograd.html#torch.autograd.graph.allow_mutation_on_saved_tensors" rel="noopener nofollow ugc">sweep-inplace-modification-errors-under-the-rug</a> context manager, but<br>
it’s probably good practice to track down and understand the cause of<br>
the error, even if you do use this solution.</p>
<aside class="quote no-group">
<blockquote>
<pre><code>      l = 100
      self.f = nn.Sequential(nn.Linear(3,l),nn.Tanh(),nn.Linear(l,1))
</code></pre>
</blockquote>
</aside>
<p>It’s quite possible that the shape-<code>[100, 3]</code> tensor reported in the error<br>
message is <code>self.f[0].weight</code> (that is, <code>Linear (3. l).weight</code>).  You<br>
are probably training your <code>NeuralODE</code> and you should be aware that calling<br>
<code>optimizer.step()</code> on your model will modify that <code>Linear (3. l).weight</code><br>
inplace.  Are you using <code>.backward (retain_graph = True)</code> anywhere?</p>
<p>Best.</p>
<p>K. Frank</p>

Ashima_Kalathingal: <p>Hello,<br>
Thank you for your reply.</p>
<p>I am using loss.backward(retain_graph = True) to backpropogate the loss. When I try to implement just loss.backward() it shows the following error:</p>
<p>Trying to backward through the graph a second time (or directly access saved tensors after they have already been freed). Saved intermediate values of the graph are freed when you call .backward() or autograd.grad(). Specify retain_graph=True if you need to backward through the graph a second time or if you need to access saved tensors after calling backward.</p>
<p>I don’t understand how to work around this. Any help would be much appreciated.</p>
<p>Thank you again.</p>
<p>Ashima</p>

Ashima_Kalathingal: <p>I printed out the versions of the weights and biases of the neural network. It changes from 1 to 2 in the next epoch. So as my error indicates the expected version is 1</p>
<p>I modified the neural network in my code like below. I added clone to the weights. But it did not change the outcome. It is still showing the same error.</p>
<pre><code>      y1    =  torch.nn.functional.linear(i_S_T,self.lin1.weight.clone(),self.lin1.bias)
      
      y2    = self.tanh(y1)
      
      Q     = torch.nn.functional.linear(y2,self.lin2.weight.clone(),self.lin2.bias)
</code></pre>

KFrank: <p>Hi Ashima!</p>
<aside class="quote no-group" data-username="Ashima_Kalathingal" data-post="4" data-topic="206285" 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/ashima_kalathingal/48/71421_2.png" class="avatar"> Ashima_Kalathingal:</div>
<blockquote>
<p>I printed out the versions of the weights and biases of the neural network. It changes from 1 to 2 in the next epoch.</p>
</blockquote>
</aside>
<p>Just to be clear, to me “epoch” means that you have iterated over the<br>
entire training set once, but that the training set consists of many batches.</p>
<p>Typically, you would perform one optimization step for each batch:</p>
<pre data-code-wrap="python"><code class="lang-python">input, labels = get_batch (...)     # one batch, not whole training set
output = model (input)              # forward pass
loss = loss_fn (output, labels)
opt.zero_grad()
loss.backward()                     # backward pass
opt.step()                          # optimization step
</code></pre>
<p>If your error truly shows up only after an entire epoch, rather than occurring<br>
after just a single batch, then you are likely doing something incorrect at the<br>
end (or beginning) of the loop over batches that makes up an epoch.</p>
<p>(A common approach is to compute performance metrics for your validation<br>
set and maybe also for your training set after each epoch.  It would likely be<br>
an error if any such per-epoch computations contained a <code>loss.backward()</code><br>
or <code>opt.step()</code> and something like that could be causing your issue.)</p>
<p>Moving on from the question of whether your error happens within your<br>
loop over batches or only once per epoch:</p>
<p>Do you have more than one <code>loss.backward()</code> (or similar) line of code?<br>
If so, why?</p>
<p>Do you have more than one <code>opt.step()</code> (or similar) line of code, and if<br>
so, why?</p>
<aside class="quote no-group">
<blockquote>
<p>So as my error indicates the expected version is 1</p>
</blockquote>
</aside>
<p>In your original post, <code>self.f</code> is a <code>Sequential</code>.  But in the code you post<br>
below, you have <code>self.lin1</code> and <code>self.lin2</code>.  Let me use <code>lin1 and lin2</code><br>
to be concrete:</p>
<p>Please add (where <code>model</code> refers to the instance of <code>NeuralODE</code> that you<br>
are training):</p>
<pre data-code-wrap="python"><code class="lang-python">print ('model.lin1.weight._version:', 'model.lin1.weight._version)
print ('model.lin2.weight._version:', 'model.lin2.weight._version)
output = model (input)   # or whatever
print ('model.lin1.weight._version:', 'model.lin1.weight._version)
print ('model.lin2.weight._version:', 'model.lin2.weight._version)
</code></pre>
<p>around each call to <code>model (...)</code>, and, similarly:</p>
<pre data-code-wrap="python"><code class="lang-python">print ('model.lin1.weight._version:', 'model.lin1.weight._version)
print ('model.lin2.weight._version:', 'model.lin2.weight._version)
opt.step()
print ('model.lin1.weight._version:', 'model.lin1.weight._version)
print ('model.lin2.weight._version:', 'model.lin2.weight._version)
</code></pre>
<p>around each call to <code>opt.step()</code>.</p>
<p>Please post the exact code fragments where you make these calls and<br>
please post the exact output you get from the print statements.</p>
<p>Please also run with a <code>with torch.autograd.detect_anomaly():</code> context<br>
manager and post the full inplace-modification error message, including the<br>
forward-call Traceback that anomaly detection gives you.</p>
<p>If it fits within, say, ten or twenty lines, please post your exact code where<br>
you execute the equivalent of:</p>
<pre data-code-wrap="python"><code class="lang-python">output = model (input)
loss = loss_fn (output, labels)
opt.zero_grad()
loss.backward()
opt.step()
</code></pre>
<p>Also, just to double-check, please print out <code>model.lin1.shape</code> and<br>
<code>model.lin2.shape</code> at some point after you instantiate <code>model</code>.</p>
<aside class="quote no-group">
<blockquote>
<p>I modified the neural network in my code like below. I added clone to the weights. But it did not change the outcome. It is still showing the same error.</p>
<pre><code>      y1    =  torch.nn.functional.linear(i_S_T,self.lin1.weight.clone(),self.lin1.bias)
      
      y2    = self.tanh(y1)
      
      Q     = torch.nn.functional.linear(y2,self.lin2.weight.clone(),self.lin2.bias)
</code></pre>
</blockquote>
</aside>
<p>This would be a correct way to fix certain specific inplace-modification<br>
errors, but maybe your error has a somewhat different cause.</p>
<p>As an aside, please use three backticks, ```, to correctly format your code<br>
and output text.</p>
<p>(I use “```python” for code and</p>
<p>“```text” for text.)</p>
<p>Best.</p>
<p>K. Frank</p>

Ashima_Kalathingal: <p>Hello, I was able to debug my code. I made a very silly mistake. I will outline my mistake here.<br>
The code is below</p>
<pre><code class="lang-auto">loss_batch = 0
for epoch in range(50):
      optimizer.zero_grad()
      output = model(input)
      loss = loss_fn(output,labels)
      loss_batch = loss_batch+loss
      loss_batch.backward()
      optimizer.step()
</code></pre>
<p>So I put loss_batch = 0 outside my training loop which was the wrong thing to do. I corrected it and the code works fine.</p>
<p>Thanks for the help.</p>
<p>`</p>