我目前正在Wasserstein GAN(https://arxiv.org/pdf/1701.07875.pdf)上的pytorch中从事一个项目。
在Wasserstain GAN中,使用wasserstein距离将新的目标函数定义为:
这会导致以下算法训练GAN:
我的问题是:
在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()
很抱歉,我的问题很长,我试图尽可能清楚地解释我的疑问。谢谢大家。
答案 0 :(得分:0)
我注意到在实施鉴别器培训协议时出现了一些错误。您会两次调用向后函数,真实和虚假值损失都会在不同的时间步长反向传播。
从技术上讲,使用此方案的实现是可能的,但高度可读。您的errD_real
犯了一个错误,即您的输出将变为正值,而不是作为最佳D(G(z))>0
的负值,因此您将其作为正确的值加以惩罚。总体而言,只需为所有输入预测D(x)<0
,模型就可以收敛。
要解决此问题,请勿致电您的errD_readl.backward()
或errD_fake.backward()
。在定义errD.backward()
之后简单地使用errD
就可以很好地工作。否则,您的生成器似乎是正确的。