При изучении GAN я заметил, что примеры кода демонстрируют этот паттерн:
Дискриминатор обучен так:
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()
Генератор обучен так:
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()
Упоминается, что d(g(noise_batch).detach())
написано для дискриминатора вместо d(g(noise_batch))
, чтобы помешать d_optim.step()
обучить g
, но ничего не сказано о d(g(noise_batch))
для генератора; g_optim.step()
будет также тренироваться d
?
На самом деле, почему мы d(g(noise_batch).detach())
, если, например, d_optim = torch.optim.SGD(d.parameters(), lr=0.001)
? Разве это не указывает, что d.parameters()
, а также g.parameters()
должны быть обновлены?