Backward on loss function; the parameter doesn't update

username: ElleryL
cooked: <p>Hi; I’m playing around with this toy exmaple</p>
<pre><code class="lang-auto">from torch import nn, optim
net1 = torch.nn.Linear(1,2)
net2 = torch.nn.Linear(1,1)

x = torch.Tensor([[1.]])
z = torch.Tensor([[2.]])

x.requires_grad=True
z.requires_grad=True

optimizer = optim.Adam(net1.parameters(), lr=1e-3)
Loss = []
for _ in range(50):
    optimizer.zero_grad()

    y = net1(x) # get the output from first neural network

    net2.weight.data = y[0][0].reshape(-1,1) # using the output from first net as parameter to second net
    net2.bias.data = y[0][1].reshape(-1,1)
    pred = net2(z)

    ## above can also be written as pred = y[0][0].reshape(-1,1) @ z + y[0][1].reshape(-1,1) ## which I think can work
    loss = (pred - 2).pow(2).sum()


    loss.backward()
    print(loss.grad) # prints None value for either approach above
    optimizer.step()
    
    Loss.append(loss.item())
plt.plot(Loss)
</code></pre>
<p>Above method is simply <code>pred = [z,1] @ (W1*x + b1)</code> where @ is dot product of two vector; and I try to make the network to output <code>2</code>.</p>
<p>But clearly; the <code>loss.backward()</code> doesn’t give proper value with first approach. How do I fix it ? I kind of want to make it work for <code>nn.Conv2d</code> so I can avoid manually compute the convolutionary layer</p>

username: albanD
cooked: <p>Hi,</p>
<p><code>loss.grad</code> is expected to remain <code>None</code> as only the gradients for leaf variables are saved in the <code>.grad</code> field.</p>
<p>These two lines</p>
<pre><code class="lang-auto">net2.weight.data = y[0][0].reshape(-1,1) # using the output from first net as parameter to second net2.bias.data = y[0][1].reshape(-1,1)    
</code></pre>
<p>Use <code>.data</code> and thus break the computational graph. Meaning that no gradients will flow back to n1.</p>
<p>If you want to set these weights, the right way to do this is to delete the existing parameters with <code>del net2.weight</code> and then set the field to the tensor that you want: <code>net2.weight = y[0][0].reshape(-1,1)</code>.</p>

username: ElleryL
cooked: <p>Hi I use <code>net2.weight = y[0][0].reshape(-1,1)</code> raises Error say <code> cannot assign 'torch.FloatTensor' as parameter 'weight' (torch.nn.Parameter or None expected)</code></p>
<p>So I switch to <code>net2.weight = torch.nn.Parameter(y[0][0].reshape(-1,1))</code> but still doesn’t update the value <img src="https://discuss.pytorch.org/images/emoji/apple/frowning.png?v=9" title=":frowning:" class="emoji" alt=":frowning:"></p>

username: albanD
cooked: <p>The second one does not update because the call to <code>nn.Parameter()</code> breaks the graph as well.</p>
<p>Re-read my answer: you need to <code>del net2.weigh</code> before-hand (just after creating the model) and then you will be able to assign it a Tensor that requires gradients.</p>

username: ElleryL
cooked: <aside class="quote no-group" data-username="albanD" data-post="4" data-topic="58973">
<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/alband/48/215_2.png" class="avatar"> albanD:</div>
<blockquote>
<p>del net2.weigh</p>
</blockquote>
</aside>
<p>Thanks; I wasn’t too careful when reading and missing the delete part. Thanks for the help ! <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=12" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>