How back-propagation works with weights from cloned tensors

Gears_Gears: <p>Dear Community, I’m trying to understand why the following meta-learning pseudo-code works. Could you please give me some guidance?</p>
<pre><code class="lang-auto">param: dict[str, torch.Tensor]
optimizer = Adam(params=param)
def inner_loop(parameter, data):
  cloned_param = clone parameter
  calculate something with cloned_param (using data)
  get the loss from said calculation
  gradients = autograd.grad(output=that loss, input=cloned_parameter.values)
  use gradients to update cloned_param
  return: the updated cloned_param
def outer_loop(data):
  adapted_parameters = inner_loop(param, part 1 of data)
  loss = calculate(adapted_parameters, part 2 of data)
  optimizer.zero_grad()
  [Q] loss.backward()
  optimizer.step()
</code></pre>
<p>[Q] Why would this (and the optimizer) work? The loss comes from the adapted_parameters, which is cloned then updated in inner_loop, not the original parameters (‘param’)<br>
My understanding is that we need to use param itself to calculate stuff and get the loss if we want to .backward to update the param itself. It’s confusing to me that we are using loss from (virtually) a ‘future’ version of param to update param, and that it works<br>
[Q2] What would be a nice way to organize parameters besides dictionary with string names? For models with lots of layers/steps, errors from typing names (of parameter tensors) wrongly has been frustrating</p>
<p>Thanks a lot!</p>

KFrank: <p>Hi Gears!</p>
<aside class="quote no-group" data-username="Gears_Gears" data-post="1" data-topic="194392" 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>My understanding is that we need to use param itself to calculate stuff and get the loss if we want to .backward to update the param itself.</p>
</blockquote>
</aside>
<p>I have no idea what you are trying to do here, but the following comment<br>
might be helpful:</p>
<p>Backpropagation through a cloning operation works just fine.  Consider:</p>
<pre><code class="lang-plaintext">&gt;&gt;&gt; import torch
&gt;&gt;&gt; torch.__version__
'2.1.2'
&gt;&gt;&gt; param = torch.ones (1, requires_grad = True)
&gt;&gt;&gt; opt = torch.optim.SGD ([param], lr = 0.1)
&gt;&gt;&gt; pclone = param.clone()
&gt;&gt;&gt; pclone
tensor([1.], grad_fn=&lt;CloneBackward0&gt;)
&gt;&gt;&gt; loss = pclone**2
&gt;&gt;&gt; loss.backward()
&gt;&gt;&gt; param.grad
tensor([2.])
&gt;&gt;&gt; opt.step()
&gt;&gt;&gt; param
tensor([0.8000], requires_grad=True)
</code></pre>
<p>(Note if we had used <code>pclone = param.detach().clone()</code>, backpropagation<br>
back to <code>param</code> would not have occurred, <code>loss.backward()</code> would not<br>
have populated <code>param.grad</code>, and <code>opt.step()</code> would not have modified<br>
<code>param</code>.)</p>
<p>Best.</p>
<p>K. Frank</p>

Gears_Gears: <p>Thanks very much for your help K. Frank! I re-read my instructions and it turns out I misread some of it.</p>