Wasserstein GAN在pytorch中的实现。如何实现亏损?

时间:2020-04-23 14:52:05

标签: deep-learning pytorch generative-adversarial-network

我目前正在Wasserstein GAN(https://arxiv.org/pdf/1701.07875.pdf)上的pytorch中从事一个项目。

在Wasserstain GAN中,使用wasserstein距离将新的目标函数定义为: enter image description here

这会导致以下算法训练GAN:

enter image description here

我的问题是:

在pytorch中实现算法的第5行和第6行时,我应该乘以损失-1吗?就像在我的代码中一样(我将RMSprop用作生成器和评论器的优化器):

############################
  # (1) Update D network: maximize (D(x)) + (D(G(x)))
  ###########################
  for n in range(n_critic):


    D.zero_grad()

    real_cpu = data[0].to(device)
    b_size = real_cpu.size(0)


    output = D(real_cpu)

    #errD_real = -criterion(output, label) #DCGAN
    errD_real = torch.mean(output)

    # Calculate gradients for D in backward pass
    errD_real.backward()
    D_x = output.mean().item()

    ## Train with all-fake batch
    # Generate batch of latent vectors
    noise = torch.randn(b_size, 100, device=device) #Careful here we changed shape of input (original : torch.randn(4, 100, 1, 1, device=device))

    # Generate fake image batch with G
    fake = G(noise)

    # Classify all fake batch with D
    output = D(fake.detach())


    # Calculate D's loss on the all-fake batch
    errD_fake = torch.mean(output)

    # Calculate the gradients for this batch
    errD_fake.backward()
    D_G_z1 = output.mean().item()

    # Add the gradients from the all-real and all-fake batches
    errD = -(errD_real - errD_fake)

    # Update D
    optimizerD.step()

    #Clipping weights
    for p in D.parameters():
      p.data.clamp_(-0.01, 0.01)

如您所见,我执行errD =-(errD_real-errD_fake)操作,其中errD_real和errD_fake分别是评论者对真实样本和假样本的预测的平均值。

据我所知,RMSprop应该通过以下方式优化评论家的权重:

w <-w-alpha * gradient(w)

(alpha是学习率除以平方梯度的加权移动平均值的平方根)

由于优化问题需要在与梯度相同的方向上“移动”,因此在优化权重之前,应该要求将梯度(w)乘以-1。

您认为我的推理正确吗?

程序运行了,但是我的结果很差。

对于发生器的权重,我遵循相同的逻辑,但是这次是为了沿梯度的相反方向前进:

      ############################
  # (2) Update G network: minimize -D(G(x))
  ###########################
  G.zero_grad()

  noise = torch.randn(b_size, 100, device=device)
  fake = G(noise)

  #label.fill_(fake_label)  # fake labels are real for generator cost

  # Since we just updated D, perform another forward pass of all-fake batch through D
  output = D(fake).view(-1)

  # Calculate G's loss based on this output

  #errG = criterion(output, label) #DCGAN
  errG = -torch.mean(output)

  # Calculate gradients for G
  errG.backward()
  D_G_z2 = output.mean().item()

  # Update G
  optimizerG.step()

很抱歉,我的问题很长,我试图尽可能清楚地解释我的疑问。谢谢大家。

1 个答案:

答案 0 :(得分:0)

我注意到在实施鉴别器培训协议时出现了一些错误。您会两次调用向后函数,真实和虚假值损失都会在不同的时间步长反向传播。

从技术上讲,使用此方案的实现是可能的,但高度可读。您的errD_real犯了一个错误,即您的输出将变为正值,而不是作为最佳D(G(z))>0的负值,因此您将其作为正确的值加以惩罚。总体而言,只需为所有输入预测D(x)<0,模型就可以收敛。

要解决此问题,请勿致电您的errD_readl.backward()errD_fake.backward()。在定义errD.backward()之后简单地使用errD就可以很好地工作。否则,您的生成器似乎是正确的。