Loss not updating in PyTorch?

johnny69: <p>I’m trying to create a collaborative filtering model to generate recommendations for patient/psychologist pairs. Here’s my model so far:</p>
<pre><code class="lang-auto">class Recommender(nn.Module):
  def __init__(self, patients, psychologists):
    super().__init__()
    self.patient_params = nn.ParameterDict({patient.name: nn.Parameter(torch.randn(10, requires_grad=True, dtype=torch.float)) for patient in patients})
    self.psych_params = nn.ParameterDict({psych.name: nn.Parameter(torch.randn(10, requires_grad=True, dtype=torch.float)) for psych in psychologists})
  def forward(self, matches):
    output = []
    for psych_match in matches:
      patient = psych_match[0]
      psych = psych_match[1]
      patient_params = self.patient_params[patient.name]
      psych_params = self.psych_params[psych.name]
      output.append(patient_params @ psych_params.T)
    return torch.tensor(output, requires_grad=True)
</code></pre>
<p>I’m able to make predictions with this model, and run through the training loop, <em>but</em> my loss and weights don’t update.</p>
<pre><code class="lang-auto">model = Recommender(patients, psychologists)
loss_fn = nn.MSELoss()
optimizer = torch.optim.SGD(params=model.parameters(), lr=0.01)
for epoch in range(50):
  model.train()
  y_preds = model(X)
  loss = loss_fn(y_preds, y)
  optimizer.zero_grad()
  loss.backward() 
  optimizer.step()
  if epoch % 10 == 0:
    print(f"Epoch: {epoch} | Loss: {loss}")
</code></pre>
<p>And the output is:</p>
<pre><code class="lang-auto">Epoch: 0 | Loss: 20.708234786987305
Epoch: 10 | Loss: 20.708234786987305
Epoch: 20 | Loss: 20.708234786987305
Epoch: 30 | Loss: 20.708234786987305
Epoch: 40 | Loss: 20.708234786987305
</code></pre>
<p>For simplicity’s sake, I’ve made the y values numerical, so I’d assume that MSELoss would be work fine here.</p>
<p>Any idea what might be going wrong or how to fix it?</p>

ConvolutionalAtom: <p>If you look at the link below:<br>
<a href="https://pytorch.org/docs/stable/generated/torch.tensor.html" class="onebox" target="_blank" rel="noopener nofollow ugc">https://pytorch.org/docs/stable/generated/torch.tensor.html</a></p>
<p>It says torch.tensor does not preserve autograd history, hence no grad value is preserved.<br>
In you last step of forward function,you use this function, which I think leads to destruction of computation graph</p>
<p>I think it may be not necessary to turn into tensor with require grad in the last step since it already has grad as it originates from param.Parametere</p>

J_Johnson: <pre><code class="lang-auto">class Recommender(nn.Module):
  def __init__(self, patients, psychologists):
    super().__init__()
    self.patient_params = nn.ParameterDict({patient.name: nn.Parameter(torch.randn(10, requires_grad=True, dtype=torch.float)) for patient in patients})
    self.psych_params = nn.ParameterDict({psych.name: nn.Parameter(torch.randn(10, requires_grad=True, dtype=torch.float)) for psych in psychologists})
  def forward(self, matches):
    output = []
    for psych_match in matches:
      patient = psych_match[0]
      psych = psych_match[1]
      patient_params = self.patient_params[patient.name]
      psych_params = self.psych_params[psych.name]
      output.append(patient_params @ psych_params.T)
    return torch.tensor(output, requires_grad=True)
</code></pre>
<p>As <a class="mention" href="/u/convolutionalatom">@ConvolutionalAtom</a> noted, your model isn’t maintaining the gradients graph all the way through, given the way you currently have structured the forward pass.</p>
<p>You could try something like:</p>
<pre><code class="lang-auto">  def forward(self, matches):
    output = torch.empty(0,1)
    for psych_match in matches:
      patient = psych_match[0]
      psych = psych_match[1]
      patient_params = self.patient_params[patient.name]
      psych_params = self.psych_params[psych.name]
      output=torch.cat([output,(patient_params @ psych_params.T).view(1,-1)])
    return output
</code></pre>

johnny69: <p>Perfect, now it’s working as expected. Thanks!</p>