Modify an external trainable parameter manually

Prakhar_Sharma: <p>I have two external trainable parameter as follows:</p>
<pre><code class="lang-python">bc_left_coeff = torch.tensor((1.1,),  requires_grad=True,  device=device)#.to(device)
bc_right_coeff = torch.tensor((1.1,),  requires_grad=True, device=device)#.to(device)
params = list(PINN.parameters()) + [bc_left_coeff, bc_right_coeff]
</code></pre>
<p>I want to modify the <code>bc_left_coeff</code> when a certain condition is met during the training. An example would be</p>
<pre><code class="lang-python">for i in range(max_iter):
    # Normal training loss calculation
    data_loss = func1(args)
    bc_difference_loss = func2(args) 
    total_loss = data_loss + bc_difference_loss
    
    optimizer.zero_grad()    
    total_loss.backward()
    optimizer.step()
    
    # My special condition
    if bc_left_coeff &lt; 0.9:
        bc_left_coeff =  torch.tensor((1.1,),  requires_grad=True, device=device)
</code></pre>
<p>The only problem is that after setting <code>bc_left_coeff</code> to 1.1, the optimiser stops updating <code>bc_left_coeff</code>. How do I continue to update the <code>bc_left_coeff</code> with the manually modified value?</p>
<p>As a background, the problem is ill-posed with  <code>bc_left_coeff = 0</code> as a solution. I want to oscillate the value of  <code>bc_left_coeff</code> between two physically relevant values during the training. I tried <code>clamp()</code> but it gets stuck to the lower bound of the two physically relevant values, which I don’t want.</p>

KFrank: <p>Hi Prakhar!</p>
<aside class="quote no-group" data-username="Prakhar_Sharma" data-post="1" data-topic="163147" 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/prakhar_sharma/48/47007_2.png" class="avatar"> Prakhar_Sharma:</div>
<blockquote>
<pre data-code-wrap="python"><code class="lang-python">bc_left_coeff = torch.tensor((1.1,),  requires_grad=True,  device=device)#.to(device)
</code></pre>
</blockquote>
</aside>
<p>At this point <code>bc_left_coeff</code> is a python reference to an object in memory,<br>
namely the <code>Tensor</code> you just created.  Let’s call this “Object 1.”</p>
<p>Then at some point you add “Object 1” to <code>optimizer</code>’s parameter list.<br>
<code>optimizer</code> holds its own reference to “Object 1.”</p>
<aside class="quote no-group">
<blockquote>
<pre data-code-wrap="python"><code class="lang-python">    # My special condition
    if bc_left_coeff &lt; 0.9:
        bc_left_coeff =  torch.tensor((1.1,),  requires_grad=True, device=device)
</code></pre>
</blockquote>
</aside>
<p>When your “special condition” is satisfied you create a new <code>Tensor</code> that<br>
is another object in memory.  Let’s call this “Object 2.”  You then set the<br>
python reference <code>bc_left_coeff</code> to refer to “Object 2,” but doing so does<br>
not change which object the reference inside of <code>optimizer</code> refers to – it<br>
still refers to “Object 1.”  The optimizer will still update “Object 1” (which<br>
was <em>not</em> set to the new value of <code>1.1</code>), but you won’t see this by looking at<br>
<code>bc_left_coeff</code>.  Looking at <code>bc_left_coeff</code> will show you “Object 2,” which<br>
isn’t changing.</p>
<aside class="quote no-group">
<blockquote>
<p>How do I continue to update the <code>bc_left_coeff</code> with the manually modified value?</p>
</blockquote>
</aside>
<p>You need to modify the contents of “Object 1” itself rather than set<br>
<code>bc_left_coeff</code> to refer to some new <code>Tensor</code> (such as “Object 2”).<br>
You would do this as follows:</p>
<pre data-code-wrap="python"><code class="lang-python">    # My special condition
    if bc_left_coeff &lt; 0.9:
        with torch.no_grad():
            bc_left_coeff[0] = 1.1
</code></pre>
<p>Now <code>bc_left_coeff</code> still refers to “Object 1” (and <code>optimizer</code> still holds a<br>
reference to “Object 1”), but you’ve changed “Object 1’s” value.</p>
<p>Best.</p>
<p>K. Frank</p>