我正在查看此示例-https://github.com/pytorch/examples/blob/master/dcgan/main.py,我有一个基本问题。
fake = netG(noise)
label = Variable(label.fill_(fake_label))
output = netD(fake.detach()) # detach to avoid training G on these labels
errD_fake = criterion(output, label)
errD_fake.backward()
D_G_z1 = output.data.mean()
errD = errD_real + errD_fake
optimizerD.step()
我知道为什么我们要调用detach()
variable fake
,以便不为Generator参数计算梯度。我的问题是,这是否重要,因为optimizerD.step()
仅更新与鉴别器相关的参数?
OptimizerD定义为: optimizerD = optim.Adam(netD.parameters(), lr=opt.lr, betas=(opt.beta1, 0.999))
此外,在下一步中,当我们更新Generator的参数时,在此之前,我们将调用netG.zero_grad()
最终删除所有先前计算的梯度。此外,当我们更新G网络的参数时,我们执行- output = netD(fake)
。在这里,我们不使用分离。为什么?
那么,为什么在上面的代码中必须分离变量(第3行)?
原始答案(错误/不完整)
没错,调用之前optimizerD
仅使用更新netD
和渐变,因此分离是不必要的,它仅节省时间,因为您无需为生成器计算渐变。netG
netG.zero_grad()
基本上,您也可以自己回答其他问题,fake
因为您特别希望计算渐变netG
以更新其参数,所以您不会在第二个步骤中感到困惑。
请注意,在第二个块中real_label
如何将其用作的相应标签fake
,因此,如果鉴别器发现虚假输入是真实的,则最终损失很小,反之亦然,这恰恰是生成器想要的。不知道这是不是让您感到困惑,但这实际上是与对鉴别器进行假输入训练相比的唯一区别。
编辑
请参阅FatPanda的评论!我原来的回答实际上是不正确的。当.backward()
调用时,Pytorch销毁了计算图(的一部分)。如果没有之前分离errD_fake.backward()
的errG.backward()
通话以后会无法backprop到发生器,因为所需图形不再可用(除非您指定retain_graph=True
)。我松了一口气,Soumith犯了同样的错误:D
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句