Use of auxiliary function when computing loss

username: the-dharma-bum
cooked: <p>Hi,<br>
I’m having troubles computing gradients, here’s my setup:<br>
I have a parametric function <code>f</code> that I wan to optimize (e.g. a MLP), but the loss computation involves an auxiliary function <code>g</code>:</p>
<pre><code class="lang-auto">y = f(x)
loss = g(y)
</code></pre>
<p>And I’d like to compute d loss / df.<br>
I’m sure using .detach() or autograd.grad() this should be easy but I’m not sure how to do it.<br>
Thanks a lot !</p>

username: srishti-git1110
cooked: <p>Hi, could you please elaborate what your auxiliary function looks like.<br>
Nonetheless, since loss is a function of y which in turn means it is a function of the parameters of f, you should be fine creating an optimizer with f’s parameters and using the loss to backpropagate the errors.</p>
<p>Does that make sense?</p>
<p>Also, could you please show some concrete code (rather than pseudo)?</p>

username: the-dharma-bum
cooked: <p>Thanks for the reply !<br>
I’m working with a frozen autoencoder. Basically what I’m doing is</p>
<ol>
<li>translate a latent vector</li>
<li>decode the translated vector</li>
<li>rotate the decoded signal by many angles</li>
<li>encode back each rotated object</li>
<li>each latent vector obtained contributes to the loss of the translation function</li>
</ol>
<p>So things look like that</p>
<pre><code class="lang-python">z_new = model(z_current, Z_gt)  # function to optimize
x = decode(z_new) # decoder should be frozen
X = torch.stack([rotate(x, a) for a in theta])
Z = self.encode(X) # encoder should be frozen
loss = some_distance_function(Z, Z_gt)
</code></pre>
<p>What you said definitely makes sense, but I’m not sure how to freeze the autoencoder: if I use <code>with torch.no_grad()</code> then <code>Z</code> and thus the loss ends up being grad less. So could I simply iterate over the AE parameters and set <code>requires_grad = False</code>   ?</p>

username: srishti-git1110
cooked: <p>Looping over a layer’s parameters and setting their <code>requires_grad=False</code> is one way like you mentioned and has worked fine for me in the past.</p>
<p>I think you should be fine using it.<br>
Any specific errors you anticipate or encounter with this?</p>

username: the-dharma-bum
cooked: <p>Yeah I tried and it works, thank you !<br>
I initially encountered the <code>RuntimeError: Trying to backward through the graph a second time</code>, because I kept the variable while looping the optimization, but as I can discard the gradients between steps, I got away with:</p>
<pre><code class="lang-python">z = z.detach().requires_grad_()
</code></pre>
<p>Thanks again !</p>

username: srishti-git1110
cooked: <p>Good to know it’s solved.</p>
<p>Regarding the error:<br>
Was it something like z was a part of some graph that you’d already backward propagated through, and you then were trying to backward propagate through another graph that also had z as part (which would essentially mean there’s no another graph, it got built as a part of the already existing graph)?</p>

username: the-dharma-bum
cooked: <p>Yes that’s right, I’m updating z at each optimisation step so that’s what happend. But as I said I can discard the graph from one step to the other.</p>