我在尝试设置一个简单的GAN训练循环,但遇到了以下错误:
RuntimeError: 尝试第二次反向传播图(或者在已释放的保存变量后直接访问它们)。当你调用.backward()或autograd.grad()时,图的保存中间值会被释放。如果你需要第二次反向传播图或在调用backward后需要访问保存的变量,请指定retain_graph=True。
for epoch in range(N_EPOCHS): # 获取生成器的数据 for i, batch in enumerate(dataloader, 0): # 将目标图像传递给判别器 global_disc.zero_grad() output_disc = global_disc(batch.to(device)) error_target = loss(output_disc, torch.ones(output_disc.shape).cuda()) error_target.backward() # 对图像应用掩码 batch = apply_mask(batch) # 将假图像传递给判别器 global_output, local_output = gen(batch.to(device)) output_disc = global_disc(global_output.detach()) error_fake = loss(output_disc, torch.zeros(output_disc.shape).to(device)) error_fake.backward() # 合并错误 error_total = error_target + error_fake optimizer_disc.step() # 更新生成器 gen.zero_grad() error_gen = loss(output_disc, torch.ones(output_disc.shape).to(device)) error_gen.backward() optimizer_gen.step() break break
据我所知,我已经按照正确的顺序操作了,我清零了梯度,并且在将生成器的输出送入判别器之前进行了分离。
这篇文章很有帮助,但我在一些我不理解的地方仍然遇到了问题。
回答:
我想到了两个重要点:
-
你应该用噪声而不是真实输入来馈送你的生成器:
global_output, local_output = gen(noise.to(device))
上面的noise
应该具有适当的形状(它是你的生成器的输入)。
-
为了优化生成器,你需要重新计算判别器的输出,因为它已经被反向传播过了。只需添加这一行来重新计算
output_disc
:# 更新生成器gen.zero_grad()output_disc = global_disc(global_output)# ...
请参考PyTorch提供的这个教程以获取完整的演练。