【问题标题】:How does PyTorch's loss.backward() work when "retain_graph=True" is specified?当指定“retain_graph=True”时,PyTorch 的 loss.backward() 是如何工作的?
【发布时间】:2020-09-19 20:14:27
【问题描述】:

我是 PyTorch 和对抗网络的新手。我试图在 PyTorch 文档以及 PyTorch 和 StackOverflow 论坛中的先前讨论中寻找答案,但我找不到任何有用的东西。

我正在尝试使用生成器和判别器训练 GAN,但我无法理解整个过程是否正常。就我而言,我应该首先训练生成器,然后更新鉴别器的权重(类似于this)。我更新两个模型权重的代码是:

# computing loss_g and loss_d...
optim_g.zero_grad()
loss_g.backward()
optim_g.step()

optim_d.zero_grad()
loss_d.backward()
optim_d.step()

其中loss_g 是生成器损失,loss_d 是判别器损失,optim_g 是参考生成器参数的优化器,optim_d 是判别器优化器。 如果我像这样运行代码,我会得到一个错误:

RuntimeError: Trying to backward through the graph a second time, but the buffers have already been freed. Specify retain_graph=True when calling backward the first time.

所以我指定了loss_g.backward(retain_graph=True),我的疑问出现了:如果有两个具有两个不同图的网络,我为什么要指定retain_graph=True?我是不是搞错了?

【问题讨论】:

    标签: python python-3.x pytorch torchvision


    【解决方案1】:

    拥有两个不同的网络并不一定意味着计算图不同。计算图只跟踪从输入到输出执行的操作,并且操作发生在哪里并不重要。换句话说,如果您在第二个模型中使用第一个模型的输出(例如model2(model1(input))),您将拥有相同的顺序操作,就好像它们是同一模型的一部分一样。事实上,这与模型的不同部分(例如多个卷积)一个接一个地应用没有什么不同。

    您得到的错误表明您正试图通过生成器从鉴别器反向传播,这意味着鉴别器的输出直接调整生成器的参数以使鉴别器成功。在你想要避免的对抗环境中,它们应该彼此独立。通过设置retrain_graph=True,您错误地隐藏了这个错误。在几乎所有情况下,retain_graph=True 都不是解决方案,应该避免使用。

    要解决该问题,需要使这两个模型相互独立。当您使用生成器输出作为鉴别器时,两个模型之间会发生交叉,因为它应该决定这是真的还是假的。大致如下:

    fake = generator(noise)
    
    real_prediction = discriminator(real)
    # Using the output of the generator, continues the graph.
    fake_prediction = discriminator(fake)
    

    虽然fake来自生成器,但就判别器而言,它只是另一个输入,就像real一样。因此fake 应该被视为与real 相同,它不附加到任何计算图。这可以通过 torch.Tensor.detach 轻松完成,它将张量与图形解耦。

    fake = generator(noise)
    
    real_prediction = discriminator(real)
    # Detach to make it independent of the generator
    fake_prediction = discriminator(fake.detach())
    

    这也在您引用的代码中完成,来自erikqu/EnhanceNet-PyTorch - train.py

    hr_imgs = torch.cat([discriminator(hr), discriminator(generated_hr.detach())], dim=0)
    

    【讨论】:

      猜你喜欢
      • 2021-01-28
      • 2020-10-06
      • 1970-01-01
      • 2019-02-27
      • 2017-10-27
      • 1970-01-01
      • 2019-05-27
      • 2018-12-24
      • 2012-08-03
      相关资源
      最近更新 更多