Multiple loss functions/networks (Pytorch 1.5+ and inplace operation error)

username: inigo-val
cooked: <p>Hi</p>
<p>I am building a VAE-GAN (<a href="https://miro.medium.com/max/2992/0*KEmfTtghsCDu6UTb.png" rel="noopener nofollow ugc">https://miro.medium.com/max/2992/0*KEmfTtghsCDu6UTb.png</a>). It has 3 different loss functions for each part of the network (encoder, decoder, discriminator) and each loss function is a function of outputs/network weights of the different networks.</p>
<p>Pytorch throws this error <code>RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation</code> when calling the second backward pass.</p>
<p>I think it is because the gradients of the network are being used to calculate the loss functions after they have already been updated. I have tried freezing the network gradients and then backpropping but to no avail.</p>
<p>What is best practise for dealing with this kind of issue?</p>
<p>My code looks like this</p>
<pre><code class="lang-auto">for data in trainLoader:
		i += 1
		X, _ = data
		X = X.view(-1, 28*28)
		X = X.cuda()

		# zero gradients from last step
		enc_opt.zero_grad()
		dec_opt.zero_grad()
		disc_opt.zero_grad()

		mu, std = enc(X) # encode data; mu = E[z]

		X_tilde = dec(mu) # reconstructed image from training data

		_, disc_1_real, disc_2_real = disc(X)
		_, disc_1_fake, disc_2_fake = disc(X_tilde)


		Z = z_sample(mu.clone().detach(), std.clone().detach()) # sample z using reparameterisation trick
		X_p = dec(Z.detach())# randomly generated image

		# define losses
		L_llike =  mse_loss(disc_1_fake, disc_1_real) + mse_loss(disc_2_fake, disc_2_real)# disc featurewise error
		# L_llike = mse_loss(X_tilde, X)
		L_GAN = GAN_loss(X, X_tilde, X_p, disc)
		L_prior = KL_loss(mu, std) # regularization loss


		# define network losses
		L_enc = L_prior + L_llike
		L_dec = gamma*L_llike.clone() - L_GAN
		L_disc = L_GAN.clone()

		set_requires_grad(enc, True)
		set_requires_grad(dec, False)
		set_requires_grad(disc, False)

		# train encoder
		L_enc.backward(retain_graph=True)
		enc_opt.step()

		set_requires_grad(enc, False)
		set_requires_grad(dec, True)
		set_requires_grad(disc, False)

		# train decoder
		L_dec.backward(retain_graph=True)
		dec_opt.step()

		set_requires_grad(enc, False)
		set_requires_grad(dec, False)
		set_requires_grad(disc, True)

		# train discriminator
		L_disc.backward()
		disc_opt.step()#
</code></pre>

username: ptrblck
cooked: <aside class="quote no-group" data-username="inigo-val" data-post="1" data-topic="99921">
<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/inigo-val/48/30023_2.png" class="avatar"> inigo-val:</div>
<blockquote>
<p>I think it is because the gradients of the network are being used to calculate the loss functions after they have already been updated.</p>
</blockquote>
</aside>
<p>Yes, this would be most likely the issue. The error might be raised, e.g. if you are using different forward passes, calculate the gradients of one loss w.r.t. the parameters, update the parameters via <code>optimizer.step()</code>, and try to call <code>backward()</code> on the second loss.<br>
Since the parameters were already updated, the gradient calculation would be wrong and thus the error is raised.</p>
<p>Based on your code it seems that <code>L_llike</code> is computed by all three models (<code>enc</code>, <code>dec</code>, <code>disc</code>), so I guess freezing the parameters might not work, if some earlier model might need the gradient calculation.</p>