Manually calculate gradients for model parameters using autograd.grad()

username: Muhammad_Usman_Qadee
cooked: <p>I want to do this</p>
<pre><code class="lang-auto">grads = grad(loss, model.parameters())
</code></pre>
<p>But I am using nn.Module to define my model. It runs backward() function automatically but I want backward() function not to calculate any grads and want to compute grads myself.</p>
<p>How can I omit backward() function and can prevent to perform any gradient calculation when I call my model?</p>

username: albanD
cooked: <blockquote>
<p>I was wondering if it were at all possible to implement a backward of backward method in an autograd function?</p>
</blockquote>
<p>Hi, plain <code>nn.Module</code> don’t call backward by themselves.<br>
You might need to update the library you’re using on top of pytorch to stop doing that.<br>
Then you can use <code>autograd.grad()</code> to do what you want.</p>

username: Muhammad_Usman_Qadee
cooked: <p>I am using version 1.6 of pytorch. And I am getting this error for using grad manually</p>
<p>“RuntimeError: Trying to backward through the graph a second time, but the saved intermediate results have already been freed. Specify retain_graph=True when calling backward the first time.”</p>

username: albanD
cooked: <p>As mentioned, if you want to backward through the graph multiple times, you have to specify <code>retain_graph=True</code> for all but the last call.<br>
Note that this can happen as well if you do some computations before your training loop and you re-use part of the graph for all the iterations. you should recompute all the graph at every iteration!</p>

username: Muhammad_Usman_Qadee
cooked: <p>So here is what I am doing</p>
<ol>
<li>Defined the model class (myModel) using nn.Module<br>
Now in training</li>
<li>called my model as <code>outputs = myModel(inputs)</code>
</li>
<li>calculating  loss as <code>loss = Crossentropy(outputs, targets)</code>
</li>
<li>Now I am not calling loss.backward(). I use: <code>grads = grad(loss, model.paramaters())</code>
</li>
</ol>
<p>I am getting the error that I mentioned above which means that somehow it is calling backward() function already. I want to prevent that automatic first call of backward().</p>

username: albanD
cooked: <p>Hi,</p>
<p>There is no automatic call to backward. And this can also be a previous call to <code>autograd.grad</code>.</p>
<p>Can you share the code around your main training loop. Or a small code sample (30-40 lines) that can reproduce the error if you can do so?</p>

username: Muhammad_Usman_Qadee
cooked: <p>I am using LSTM for PENN TreeBank problem.<br>
Also I have one doubt that came across mind. For LSTMs, do I have to initialize hidden states in every loop or just at the start?</p>
<pre><code class="lang-auto">def train_loss(data, target, ht, ct):
    out, (ht, ct) = myModel(data, ht, ct)
    loss = F.cross_entropy(out, target)
    return loss, (ht, ct)
</code></pre>
<pre><code class="lang-auto">for epoch in range(EPOCHS):
    trainloss = 0.0
    
    t0 = time.time()
    for batch in train_loader:
        data, target = batch.text.t(), batch.target.t(), 
        loss, (ht, ct)  = train_loss(data, target.reshape(-1), ht, ct)

        grads = grad(loss, Ws)
        
        trainloss += loss
..........................
</code></pre>

username: albanD
cooked: <p>You do have to either re-initialize it or at least <code>.detach()</code> it. Otherwise, you will try to backprop through all the previous iterations of your model.<br>
And this causes the error you see as you already backproped in that model before.</p>

username: Muhammad_Usman_Qadee
cooked: <p>Yes, Right</p>
<p>The problem is solved by using</p>
<pre><code class="lang-auto">ht = ht.clone().detach()
ct = ct.clone().detach()
</code></pre>
<p>solved the problem.<br>
Thank you.</p>