While learning about GANs, I noticed that the code examples exhibit this pattern:
The discriminator is trained like this:
d_optim.zero_grad()
real_pred = d(real_batch)
d_loss = d_loss_fn(real_pred, torch.ones(real_batch_size, 1))
d_loss.backward()
fake_pred = d(g(noise_batch).detach())
d_loss = d_loss_fn(fake_pred, torch.zeros(noise_batch_size, 1))
d_loss.backward()
d_optim.step()
The generator is trained like this:
g_optim.zero_grad()
fake_pred = d(g(noise_batch))
g_loss = g_loss_fn(fake_pred, torch.ones(noise_batch_size, 1))
g_loss.backward()
g_optim.step()
It is mentioned that d(g(noise_batch).detach()) is written for the discriminator instead of d(g(noise_batch)) to prevent d_optim.step() from training g, but nothing is said about d(g(noise_batch)) for the generator; would g_optim.step() also train d?
In fact, why do we d(g(noise_batch).detach()) if, for example, d_optim = torch.optim.SGD(d.parameters(), lr=0.001)? Does this not specify that d.parameters() and not also g.parameters() are to be updated?