在学习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()
进行更新?
TLDR:optimizer
将仅更新为其指定的参数,而backward()
call计算计算图中所有变量的梯度。因此,对于detach()
此时不需要进行梯度计算的变量很有用。
我相信答案就在于PyTorch中实现事物的方式。
tensor.detach()
创建一个张量,与张量共享tensor
不需要张量的存储。因此,有效地切断了计算图。也就是说,这样做fake_pred = d(g(noise_batch).detach())
会分离(切断)生成器的计算图。backward()
损失时,将为整个计算图计算梯度(与优化器是否使用梯度无关)。因此,切断发电机零件将避免发电机重量的梯度计算(因为不需要)。optimizer
时更新传递给特定参数的参数optimizer.step()
。因此,g_optim
只会优化传递给它的参数(您没有明确提及传递给的参数g_optim
)。同样,d_optim
仅d.parameters()
在您明确指定后才会更新。本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句