Loss.backward() does not update

Sitaraman: <p>Hi,<br>
Here is my code, on training the logits dont seem to change at all.  What could be the reason?<br>
from dgl.nn import GraphConv, SAGEConv</p>
<p>class GCN(nn.Module):<br>
def <strong>init</strong>(self, in_feats, h_feats, num_classes):<br>
super(GCN, self).<strong>init</strong>()<br>
<span class="hashtag">#self</span>.conv1 = GraphConv(in_feats, h_feats, allow_zero_in_degree=True)<br>
<span class="hashtag">#self</span>.conv2 = GraphConv(h_feats, num_classes, allow_zero_in_degree=True)<br>
‘’’<br>
self.conv1 = SAGEConv(in_feats, 1024, ‘pool’)<br>
self.conv2 = SAGEConv(1024, 512 , ‘pool’)<br>
self.conv3 = SAGEConv(512, 256, ‘pool’)<br>
self.conv4 = SAGEConv(256,num_classes, ‘pool’)<br>
‘’’</p>
<pre><code>    self.conv1 = SAGEConv(in_feats, 64, 'pool')
    self.conv2 = SAGEConv(64, 64 , 'pool')
    self.conv3 = SAGEConv(64, 32, 'pool')
    self.conv4 = SAGEConv(32,num_classes, 'pool')
def forward(self, g, in_feat):
    h = self.conv1(g, in_feat)
    h = F.relu(h)
    h = self.conv2(g, h)
    h = F.relu(h)
    h = self.conv3(g, h)
    h = F.relu(h)
    h = self.conv4(g, h)
    h = F.sigmoid(h)
    return h
</code></pre>
<h1>
<a name="create-the-model-with-given-dimensions-1" class="anchor" href="#create-the-model-with-given-dimensions-1"></a>Create the model with given dimensions</h1>
<p><span class="hashtag">#model</span> = GCN(g.ndata[‘feat’].shape[1], 16, dataset.num_classes)</p>
<p>def train(g, model):<br>
for param in model.parameters():<br>
param.requires_grad = True<br>
loss_fn = nn.MSELoss()<br>
<span class="hashtag">#optimizer</span> = torch.optim.Adam(model.parameters(), lr=0.01)<br>
optimizer = torch.optim.Adam(<br>
[{“params”: model.parameters()}, {“params”: loss_fn.parameters()}], lr=0.001<br>
)<br>
best_val_acc = 0<br>
best_test_acc = 0<br>
model = model.double()<br>
features = g.ndata[‘feature’]<br>
labels = g.ndata[‘label’]<br>
train_mask = g.ndata[‘train_mask’]<br>
val_mask = g.ndata[‘val_mask’]<br>
test_mask = g.ndata[‘test_mask’]</p>
<pre><code>for e in range(100000):
    for param in model.parameters():
        param.requires_grad = True
    # Forward
    #optimizer.zero_grad()
    logits = model(g, features)

    # Compute prediction
    #pred = logits.argmax(1)

    # Compute loss
    # Note that you should only compute the losses of the nodes in the training set.
    
    #loss = F.binary_cross_entropy(logits[train_mask].double(), labels[train_mask].double())
    loss = F.mse_loss(logits[train_mask].double(), labels[train_mask].double())
    #loss_fn = nn.MSELoss()
    #logits = Variable(logits[train_mask].float(), requires_grad = True)
    #labels = Variable(labels[train_mask].float(), requires_grad = True)
    logits.requires_grad = True
    labels.requires_grad = True
    #logits.is_leaf = True
    #labels.is_leaf = True
    #loss = loss_fn(logits, labels)
    loss = Variable(loss, requires_grad = True)
    
    #loss = ((logits[train_mask] - labels[train_mask])**2).mean()
    
    #loss.is_leaf = True
    '''
    # Compute accuracy on training/validation/test
    #print(pred[train_mask].shape, labels[train_mask].shape)
    train_acc = (pred[train_mask] == labels[train_mask]).float().mean()
    val_acc = (pred[val_mask] == labels[val_mask]).float().mean()
    test_acc = (pred[test_mask] == labels[test_mask]).float().mean()

    '''
    # Compute accuracy on training/validation/test
    #print(pred[train_mask].shape, labels[train_mask].shape)
    train_acc = (logits[train_mask].argmax(1) == labels[train_mask].argmax(1)).float().mean()
    val_acc = (logits[val_mask].argmax(1) == labels[val_mask].argmax(1)).float().mean()
    test_acc = (logits[test_mask].argmax(1) == labels[test_mask].argmax(1)).float().mean()
    print("logits", logits[0])
    print("label", labels[0])

    # Save the best validation accuracy and the corresponding test accuracy.
    if best_val_acc &lt; val_acc:
        best_val_acc = val_acc
        best_test_acc = test_acc

    # Backward
    optimizer.zero_grad()
    loss.requres_grad = True
    print(loss.is_leaf)
    loss.backward()
    optimizer.step()

    if e % 10 == 0:
        print('In epoch {}, loss: {:.3f}, val acc: {:.3f} (best {:.3f}), test acc: {:.3f} (best {:.3f})'.format(
            e, loss, val_acc, best_val_acc, test_acc, best_test_acc))
</code></pre>
<p>In epoch 0, loss: 0.248, val acc: 0.044 (best 0.044), test acc: 0.044 (best 0.044)<br>
logits tensor([0.3738, 0.4152, 0.6884, 0.6958, 0.7550, 0.4365, 0.2546, 0.3509, 0.1485,<br>
0.5741, 0.8709, 0.8646, 0.4125, 0.4890, 0.1682, 0.6156, 0.0968, 0.1036,<br>
0.2117, 0.4285, 0.8276], dtype=torch.float64, requires_grad=True)<br>
label tensor([1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,<br>
0., 0., 0.], dtype=torch.float64, requires_grad=True)</p>
<p>…<br>
…<br>
In epoch 1760, loss: 0.248, val acc: 0.044 (best 0.044), test acc: 0.044 (best 0.044)<br>
logits tensor([0.3738, 0.4152, 0.6884, 0.6958, 0.7550, 0.4365, 0.2546, 0.3509, 0.1485,<br>
0.5741, 0.8709, 0.8646, 0.4125, 0.4890, 0.1682, 0.6156, 0.0968, 0.1036,<br>
0.2117, 0.4285, 0.8276], dtype=torch.float64, requires_grad=True)<br>
label tensor([1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,<br>
0., 0., 0.], dtype=torch.float64, requires_grad=True)<br>
True</p>

KFrank: <p>Hi Vilayannur!</p>
<aside class="quote no-group" data-username="Sitaraman" data-post="1" data-topic="129991" data-full="true">
<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/s/e95f7d/48.png" class="avatar"> Sitaraman:</div>
<blockquote>
<p>on training the logits dont seem to change at all.</p>
</blockquote>
</aside>
<p>I haven’t looked at your code in any detail, however:</p>
<aside class="quote no-group">
<blockquote>
<pre><code class="lang-auto">        loss = F.mse_loss(logits[train_mask].double(), labels[train_mask].double())
        ...
        loss = Variable(loss, requires_grad = True)
</code></pre>
</blockquote>
</aside>
<p>“breaks the computation graph” because<br>
<code>Variable(loss, requires_grad = True)</code> creates a new tensor<br>
(that also happens to be called <code>loss</code>), and (by design) gradients<br>
backpropagated to the new <code>loss</code> don’t get further backpropagated<br>
through the old <code>loss</code>.  (And creating the new <code>loss</code> with<br>
<code>requires_grad = True</code> doesn’t fix this.)</p>
<p>(As an aside, <code>Variable</code> has been deprecated for some time now.<br>
You should just use regular pytorch tensors.)</p>
<aside class="quote no-group">
<blockquote>
<pre><code class="lang-auto">    #logits = Variable(logits[train_mask].float(), requires_grad = True)
    #labels = Variable(labels[train_mask].float(), requires_grad = True)
    logits.requires_grad = True
    labels.requires_grad = True
    #logits.is_leaf = True
    #labels.is_leaf = True
</code></pre>
</blockquote>
</aside>
<p>This suggests that you’ve been trying to fix things by turning various<br>
tensor properties on and off.  It might make sense to review some of<br>
the basics of pytorch, in particular <a href="https://pytorch.org/tutorials/beginner/basics/autogradqs_tutorial.html" rel="noopener nofollow ugc">torch.autograd</a>.</p>
<p>Best.</p>
<p>K. Frank</p>