Difference between computing grad with torch.autograd.grad() and .backward + .grad

ateixeira: <p>Hi all, Im having difficults to do a differential machine learning model, because it seems im having problem in the training part, more specially in the loss part.</p>
<p>The differential ML model has this loss:</p>
<p>loss = 0.5 * self.criterion(output, label) + 0.5 * self.criterion(gradients * self.lambda_j, dydx_batch * self.lambda_j)</p>
<p>While the stantard ML model has this one:</p>
<p>loss = self.criterion(output, label)</p>
<p>In the diff one, when I use:</p>
<pre><code>                gradients = torch.autograd.grad(outputs=output,
                                                inputs=input,
                                                grad_outputs=output.data.new(output.shape).**fill_(0)**,
                                                create_graph=True,
                                                retain_graph=True,
                                                allow_unused=True)[0]
</code></pre>
<p>i have the same result of the standard model, and the same result if i calculate the gradients as:</p>
<p>output.sum().backward(retain_graph=True)<br>
gradients = input.grad</p>
<p>In the other hand, when i do:</p>
<pre><code>                gradients = torch.autograd.grad(outputs=output,
                                                inputs=input,
                                                grad_outputs=output.data.new(output.shape).**fill_(1)**,
                                                create_graph=True,
                                                retain_graph=True,
                                                allow_unused=True)[0]
</code></pre>
<p>the result is different but the prevision is a little bit worst…</p>
<p>So, whats the reason to use fill_(1), because i tested other values, for example, 2 or .-1, and the results where even worst?</p>
<p>And the other doubt: whats the difference using one way to calculate gradients and the other?</p>

ptrblck: <aside class="quote no-group" data-username="ateixeira" data-post="1" data-topic="203390">
<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/a/8edcca/48.png" class="avatar"> ateixeira:</div>
<blockquote>
<p>i have the same result of the standard model, and the same result if i calculate the gradients as:</p>
</blockquote>
</aside>
<p>This is expected since passing a zero gradient as <code>grad_outputs</code> will create a <code>gradients</code> output containing zeros, too.</p>
<aside class="quote no-group" data-username="ateixeira" data-post="1" data-topic="203390">
<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/a/8edcca/48.png" class="avatar"> ateixeira:</div>
<blockquote>
<p>So, whats the reason to use fill_(1), because i tested other values, for example, 2 or .-1, and the results where even worst?</p>
</blockquote>
</aside>
<p>The <code>grad_outputs</code> define the passed in gradient, which is a <code>1.</code> implicitly set in the <code>backward</code> call for scalar tensors.</p>
<aside class="quote no-group" data-username="ateixeira" data-post="1" data-topic="203390">
<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/a/8edcca/48.png" class="avatar"> ateixeira:</div>
<blockquote>
<p>And the other doubt: whats the difference using one way to calculate gradients and the other?</p>
</blockquote>
</aside>
<p>The <code>torch.autograd.grad</code> call computes the specified gradients explicitly instead of the full backward pass and avoid unnecessary computations (e.g. it won’t compute the weight gradients unless specified in the <code>inputs</code>).</p>