Do I need loss.backward before using autograd.grad() on loss?

Gears_Gears: <p>Hi Community,</p>
<p>To compute the gradient of loss with autograd.grad(), do I need to say loss.backward() first? I need these gradients to help me update the model, but I’m doing two backward passes, so autograd is needed. I’m wondering if the additional backward pass using autograd also needs .backward().</p>
<p>Many Thanks!</p>

KFrank: <p>Hi Gears!</p>
<aside class="quote no-group" data-username="Gears_Gears" data-post="1" data-topic="194686" 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/gears_gears/48/60932_2.png" class="avatar"> Gears_Gears:</div>
<blockquote>
<p>To compute the gradient of loss with autograd.grad(), do I need to say loss.backward() first?</p>
</blockquote>
</aside>
<p>No., no need to call <code>loss.backward()</code> first.</p>
<p>The two functions do similar things:  <code>autograd.grad()</code> computes and returns<br>
gradients with respect to its <code>inputs</code> argument, while <code>loss.backward()</code><br>
computes gradients with respect to the leaf variables of the graph of which<br>
<code>loss</code> is the root and populates the <code>.grad</code> properties of those leaf variables<br>
with the computed gradients.</p>
<p>Both require that some forward pass has been performed so that a<br>
computation graph is present and neither requires that some form of<br>
<code>.backward()</code> or <code>grad()</code> be called in advance.</p>
<aside class="quote no-group">
<blockquote>
<p>I’m doing two backward passes</p>
</blockquote>
</aside>
<p>Think through carefully the logic of why you are doing two backward passes.<br>
There are legitimate use cases for doing this but they usually requires some<br>
care to get right.</p>
<p>By default, both <code>.backward()</code> and <code>autograd.grad()</code> free the computation<br>
graph, so something like:</p>
<pre data-code-wrap="python"><code class="lang-python">loss.backward()
autograd.grad (loss, inputs)
</code></pre>
<p>will fail (because the graph will be freed), while</p>
<pre data-code-wrap="python"><code class="lang-python">loss.backward (retain_graph = True)
autograd.grad (loss, inputs)
</code></pre>
<p>will work.</p>
<p>Also note that unless you arrange your forward pass carefully to avoid the<br>
problem, something like:</p>
<pre data-code-wrap="python"><code class="lang-python">loss.backward (retain_graph = True)
opt.step()
autograd.grad (loss, inputs)
</code></pre>
<p>will almost certainly fail with an inplace-modification error.  This is because<br>
<code>opt.step()</code> performs inplace modifications on the parameters it is optimizing.</p>
<p>If you’re trying to do something like this, first make sure that it is necessary<br>
and that you understand why.  Then figure out the modifications to your<br>
forward pass needed to avoid inplace-modification errors.</p>
<p>Best.</p>
<p>K. Frank</p>

Gears_Gears: <p>Thanks so much for your detailed reply K. Frank!</p>
<p>I’m doing the meta learning algorithm where a second backward pass is required. The pseudocode looks like: (<a href="https://arxiv.org/pdf/1703.03400.pdf" rel="noopener nofollow ugc">https://arxiv.org/pdf/1703.03400.pdf</a> on top of page 3)</p>
<p>for task in many_tasks:<br>
part_1_data, part_2_data = task<br>
adapted_parameter = adapted_parameter - coefficient * gradient of loss on part_1_data<br>
[1] final_parameter = original_parameter - another_coefficient * gradient loss (of adapted_parameter) on query item (with respect to original parameter).</p>
<p>In this case, calculating the gradients in [1] needs a second pass. Following your explanation, I found that using autograd.grad(inputs=loss on part_1_data, create_graph = True) works well!</p>