Leaf variable has been moved into the graph interior in model definition

Eduardo_Hernandez: <p>Hello,</p>
<p>I am new to pytorch (I’m using 1.6.0), and I know that this topic or similar has a number of entries, but after studying them I can’t yet see the problem with my code, and would appreciate help with this. I define the following model:</p>
<p>import torch</p>
<p>“”" Model definition “”"</p>
<p>class NNModel( torch.nn.Module ):</p>
<pre><code>def __init__( self, nFeatures, nNeurons ):

    """
    The model consists of two hidden layers with tanh activation and a single neuron output 
    from the third layer. The input to the first layer is a tensor containing the input features
    (nFeatures); the output of the third layer is a single number.
    """

    super( NNModel, self).__init__()

    self.linear1 = torch.nn.Linear( nFeatures, nNeurons ) 
    self.activn1 = torch.nn.Tanh()
    self.linear2 = torch.nn.Linear( nNeurons, 1 ) 
    self.activn2 = torch.nn.Tanh()

def forward( self, x ):

    """
    x is a tensor containing all symmetry functions for the present configuration; therefore 
    it has dimensions (nObservations, nFeatures). The model must loop over each observation, 
    calculating the contribution of each one to the output (the sum of them).
    """

    nObservations, _ = x.shape

    z = torch.zeros( nObservations, requires_grad = True )

    for n in range( nObservations ):

        y = self.linear1( x[n,:] )
        y = self.activn1( y )
        y = self.linear2( y )
        z[n] = self.activn2( y )

    addition = z.sum()

    return addition
</code></pre>
<p>My loss functions and optimizer are:</p>
<p>lossFunction = torch.nn.MSELoss( reduction = ‘sum’ )</p>
<p>optimizer = torch.optim.SGD( model.parameters(), lr=1.0e-4 )</p>
<p>and I run this in a loop like so:</p>
<p>for t in range( 500 ):</p>
<pre><code># forward pass

for n in range( nCases ):

    y_pred[n] = model( sym[n] )

# compute and print loss

loss = lossFunction( y_pred, energy )

print( t, loss.item() )

# zero gradients, perform a backward pass and update weights

optimizer.zero_grad()
loss.backward( )
optimizer.step()
</code></pre>
<p>The first pass through the loop prints a loss value, but on the next iteration the program crashes with the known RuntimeError: leaf variable has been moved into the graph interior problem.</p>
<p>I guess this is to do with the loop over nObservations in the forward function definition, but I do not understand why nor what can I do to solve this problem. Any help would be appreciated. Thanks!</p>

albanD: <p>Hi,</p>
<p>This error has been improved on master. If you use a nightly built, it should raise an error directly at the place where the faulty inplace op is <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"><br>
This happens because you modify inplace a view of a leaf Tensor and such inplace op is not allowed. In this case I guess this is your <code>z</code>.<br>
Note that if you don’t actually need the <code>.grad</code> field on <code>z</code>, you can create it with <code>requires_grad=False</code> and that should solve the error.</p>

Eduardo_Hernandez: <p>Thank you albanD; I did install the nightly build and indeed it gives a slightly different output message, however I am still lost as to why my code doesn’t work. I will try to tinker with it some more and see if I can make some progress. Thanks for your help.</p>

albanD: <p>The updated error should point at the line that is doing an inplace operation that is not allowed.</p>
<p>But for the code above, I think changing <code>    z = torch.zeros( nObservations, requires_grad = True )</code> to <code>    z = torch.zeros( nObservations)</code> should work.</p>

Eduardo_Hernandez: <p>Thank you so much, albanD. Yes, now it appears to work fine, though I need to do more testing. However, I also need to progress in my understanding: setting the flag requires_grad = True in z appeared to me to be necessary in order to be able to compute the gradient of the value returned by forward() and thus optimize the model parameters.</p>
<p>Thanks again.</p>

albanD: <p>Since you write inplace into it a Tensor that requires gradient, it will work fine.<br>
You only need to set requires_grad=True explicitly for a Tensor if you plan to access it <code>.grad</code> field or ask for gradients for it in <code>autograd.grad</code>.</p>