Loss increasing and decreasing randomly. Where am i suppose to be backward the loss?

username: stuck
cooked: <p>I am implementing a dependency parsing model using PyTorch and little bit confused about the situation that I explained below.<br>
When calculating loss and backward the model; I tried different things.</p>
<ul>
<li>When I use the code below exactly, and make batch size 1 (1 batch in iteration):
<ul>
<li>Loss looks like decreasing, however the predictions are not getting well after 20 epochs.</li>
</ul>
</li>
<li>When I use the code below exactly, and make batch size 100(0):
<ul>
<li>I get an error: <code>RuntimeError: Trying to backward through the graph a second time, but the buffers have already been freed. Specify retain_graph=True when calling backward the first time.</code>
</li>
<li>As the error message said, when I use inside_loss.backward(retain_graph=True) instead of inside_loss.backward(), the execution tooks too long. And the loss is both <strong>increasing</strong> and <strong>decreasing</strong> randomly.</li>
</ul>
</li>
<li>When I comment out the inside_loss and uncomment the lines after the for loop:
<ul>
<li>The loss is not changing.</li>
</ul>
</li>
</ul>
<p>The code is here:</p>
<pre><code>def forward(self, x,):
# x is the scores of my vocab. It has grad so cannot change its values.
# So take the clone
x_prime = x.clone()

# loss = Variable(torch.zeros(1), requires_grad=True)
loss_v = torch.zeros(1)

for i in range(x_prime.size(0)):

    # Some operations that changes x_prime's values
    # Calculate sentence_probs and sentence_scores from x_prime's values

    eisner_values = eisner_torch(sentence_probs)

    # Changed x_prime above; so update the x
    x = x_prime

    # Get the gold dependencies
    gold_deps = return_gold_deps(i, sentence_to_dependencies)

    if gold_deps is None:
        continue

    mask = np.greater(np.asarray(eisner_values), -1)

    # Calculate hinge loss
    inside_loss = hinge(sentence_scores, eisner_values, gold_deps, mask, 1)

    # Calculate total loss in the batch
    loss_v += inside_loss.data

    inside_loss.backward()

    # Optimizer step
    if self.opt is not None:
        self.opt.step()
        self.opt.optimizer.zero_grad()

# loss.data = loss_v.data
# loss.backward()
# Optimizer Step
return loss_v
</code></pre>
<p>I use the Adam optimizer for this task:</p>
<pre><code>model_opt = NoamOpt(model_size=d_model, factor=1, warmup=200,
                    torch.optim.Adam(model.parameters(), lr=0, betas=(0.9, 0.98), eps=1e-9))
</code></pre>
<p>What are the problems in here?<br>
How can I solve that issue?</p>
<p>Thanks in advance.</p>

username: ptrblck
cooked: <p>I’m not sure, how your code works exactly, but the usage of <code>loss</code> is wrong.<br>
<code>Variables</code> are deprecated since PyTorch <code>0.4.0</code>, so you can now use tensors.<br>
However, you don’t need to initialize the <code>loss</code> tensor with <code>requires_grad=True</code>, since the loss is usually an output of your criterion and will require gradients, if you don’t detach the computation graph at some point.<br>
The usage of <code>.data</code> is dangerous and you are manipulating the underlying data at the moment without Autograd tracking any of these operations.</p>
<p>It seems you are calculating the <code>inside_loss</code> in a loop, which should explain the “backward a second time” error.<br>
E.g. if you feed some outputs from the initial loop as inputs to the next iteration, these tensors will still be connected to the computation graph. The next backward call will thus try to compute the gradients for the complete computation graph, which would result in both iterations.<br>
Depending on your use case, you could <code>.detach()</code> the tensors to stop the backward pass at this point.</p>

username: stuck
cooked: <p>Hİ <a class="mention" href="/u/ptrblck">@ptrblck</a>, thank you for your answer. I have a few followup questions about what you say.</p>
<ul>
<li>
<p>The inside_loss parameter requries gradient however inside the batch, I am summing that inside_loss values and create the “loss” variable. So, the loss not requires any gradient. Because of that I used that one and then commented out it. What should I do?</p>
</li>
<li>
<p>You are saying that “<em>The usage of <code>.data</code> is dangerous</em>”, however I am using a code like <code>x = x_prime</code>; is it dangerous too?</p>
</li>
<li>
<p>And the last one; yes the “backward a second time” is meaningful; however if I “detach” the tensor inside_loss; how can I took the backward of it? It means “take the inside_loss out of the graph”, isn’t it?</p>
</li>
</ul>
<p>Thank you for your answers;</p>
<p>Have a nice day.</p>