NOT SOLVED: retain_graph=True problem

alepeak: <p>So, I am working with a generator and a discriminator in my network.<br>
I wanted to add a new type of loss, which is computed given the features of every layer of the discriminator (these features are computed in the <code>forward()</code> of the discriminator), but contributes to the generator loss.<br>
Let’s call this loss <strong>gen_feat_loss</strong>.</p>
<p>Therefore what I do is:</p>
<ol>
<li>call the <code>forward</code> of the discriminator, that returns a list of every discriminator layer output.</li>
<li>compute the discriminator loss with the last element of the list returned by the <code>forward</code>.</li>
<li>compute the <code>gen_feat_loss</code>.</li>
<li>call the <code>forward</code> of the generator, compute all the other losses.</li>
<li>call <code>discriminator.zero_grad()</code>
</li>
<li><code>discriminator_loss.backward()</code></li>
<li><code>opt_discriminator.step()</code></li>
<li><code>call generator.zero_grad()</code></li>
<li><code>generator_loss = loss1 + loss2 + ... +  gen_feat_loss</code></li>
<li><code>generator_loss.zero_grad()</code></li>
<li><code>generator_loss.backward()</code></li>
<li><code>opt_generator.step()</code></li>
</ol>
<p>However, when I run the code, I see the following error:<br>
<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></p>
<p>I tried to change the order of the computations.<br>
I tried to put the <strong>generator backward</strong> before, and the <strong>discriminator backward</strong> after.<br>
I then tried to use <code>retain_graph=True</code> as the error suggests, but the RAM finishes.<br>
Do you have any idea of what I am doing wrong?<br>
It must be a problem of the backward of the generator, that tried to compute the gradients on the <code>gen_feat_loss</code> that were, for the last step, already computed by the discriminator.</p>

Dwight_Foster: <p>When you inputted the fake image into the discriminator did you detach it by using</p>
<pre><code class="lang-auto">image.detach()
</code></pre>
<p>?</p>

alepeak: <p>Yes, I used these lines of code:</p>
<pre><code class="lang-auto">fake_list_features, _ = self.run_discriminator(discriminator, fake.detach())
fake_labels = fake_list_features[-1]
fake_loss += self.compute_loss(fake_labels, self.zeros_like(fake_labels))
</code></pre>
<p>where <code>run_discriminator</code> calls the forward of the discriminator</p>

Dwight_Foster: <p>Ok can you show the line where you define discriminator loss.</p>

alepeak: <p>So I use three times the discriminator, because I am using a multi-scale implementation with 3 different scaled inputs. therefore I do:</p>
<pre><code class="lang-auto">for i in range(0,num_discriminators):
   if(i != 0):
       fake = self.downsample(fake)
       true = self.downsample(true)

   fake_list_features, _ = self.run_discriminator(discriminator, fake.detach())
   fake_labels = fake_list_features[-1]
   fake_loss += self.compute_loss(fake_labels, self.zeros_like(fake_labels)) 
   true_list_features, _ = self.run_discriminator(discriminator, true)
   true_labels = true_list_features[-1]
   true_loss += self.compute_loss(true_labels, self.zeros_like(true_labels))

discriminator_loss = true_loss + fake_loss
</code></pre>

Dwight_Foster: <p>Ok how about the generator loss in the first post you only show part of it.</p>

alepeak: <p>for the generator, firstly I compute the gen_feat_loss as I said with the features from the discriminator:<br>
<code>genFeatLoss += self.compute_genFeatLoss(fake_list_features, true_list_features, discriminator.n_layers, num_discriminators)</code></p>
<p>Then, after computing perceptual and other losses, I sum them like this in the <code>train</code> method:</p>
<pre><code class="lang-auto">for epoch in range(epochs):
      for i, batch in enumerate(self.train_loader): 
                ...
                # train discriminator
                self.opt_discriminator.zero_grad()
                discriminator_loss, genFeat_loss = self.compute_discriminator(generator, discriminator, 
                batch)
                discriminator_loss.backward()
                self.opt_discriminator.step()

                # train generator
                self.opt_generator.zero_grad()
                loss_1, loss_2, loss_3, _ = self.compute_generator_loss(generator, 
                discriminator, batch)

                generator_loss = loss_1 + loss_2 + loss_2 + genFeat_loss
                generator_loss.backward()
                self.opt_generator.step()
</code></pre>

Dwight_Foster: <p>Ok I think in either the compute generator loss or the computer discriminator loss functions you have not detach the input images or detach the losses. Can you send those two functions too.</p>

alepeak: <p>The function<br>
compute_discriminator is the one I wrote before the loop for the training.</p>
<p>The function compute_generator_loss is independent, as the error occurs only when I add genFeat_loss into the sum<br>
<code>                generator_loss = loss_1 + loss_2 + loss_2 + genFeat_loss</code><br>
If I remove this from the sum, I don’t get any error.<br>
The function <code>self.compute_genFeatLoss</code> is a simple mathematical formula</p>
<pre><code class="lang-auto">loss_G_GAN_Feat = 0
for j in range(len(fake_features)):
      loss_G_GAN_Feat += self.computeL1Loss(fake_features[j], true_features[j].detach())
</code></pre>

Dwight_Foster: <p>ok try to detach fake_features too.</p>

alepeak: <p>But why?<br>
I want the generator to learn to imitate the true images.<br>
If I use detach, in both, that means I am not computing the gradient on that loss, no?</p>
<p>Indeed, I tried and I don’t get the error anymore, but if I train I get increasing losses for the generator.</p>

Dwight_Foster: <p>Yes that is true but it still should train. I don’t have any other ideas. Maybe you could that variable in the discriminator loss and that could help your generator.</p>

alepeak: <p>Thanks for trying to help!<br>
But I think it’s not a solution, as I need that loss to train the generator.<br>
If I put .detach to everything, then I am not training with that loss… There must be another error somewhere</p>

Dwight_Foster: <p>Ya sorry I couldn’t help I had the same problem with my gan a little bit ago and this is what I did and the gan trains fine. I looked it up everywhere but that was the only answer I could fine. Hope you find a better solution because that could help me too. Sorry again. Also you might want to ask this question again cuz people will see replies and won’t answer it.</p>