结合DCGAN论文,本博客旨在讲解如何探索潜在空间。
在DCGAN中,我们利用噪声
z
z
z 产生图片。我们想探索噪声对最终图片的影响,并且试图证明GAN网络并不是简单的记住了训练样本。
这个噪声 z z z 所在的空间就是所谓的潜在空间。
看到DCGAN原文的人,一定知道怎么探索,那就是利用插值的方法。**但是如何插值呢?**本博客就是手把手教你如何插值。从理论到代码。
1.怎么做插值?
随机噪声
z
1
z_1
z1 经过生成网络生成图片
G
(
z
1
)
G(z_1)
G(z1),另一个随机噪声
z
2
z_2
z2 经过生成网络生成图片
G
(
z
2
)
G(z_2)
G(z2)。
接着,我们把这两个噪声拆分一下,按照同样的方式,当然也就是分成同样的结果。比如,假如我的
z
1
z_1
z1 有100维,我们可以按照10个维度一组,把两个噪声都分成10等分,每等份都是10维。
插值过程就是用一个噪声的数据替换另一个噪声的对应位置上的数据。
指导思想就是逐渐的将随机噪声
z
1
z_1
z1 替换成 随机噪声
z
2
z_2
z2,看看对应的生成图片是否也是逐渐变化的。
那么,怎么进行逐渐替换呢?
我们先将上面划分的一份数据替换掉,然后再是二份,最后全部替换掉。
通常情况下,我们就按照顺序,先替换第一个,然后替换第一个和第二个,再是一二三个,依次类推。
虽然有其他的替换方式,但是大同小异吧。
2.这样的插值有什么作用,可以说明什么?
如果网络只是简单的记忆训练样本,那么插值可能会得到完全不同的结果,可能一个噪声对应一个结果,即使噪声之间有关系,生成的图片也只是对应到一个训练结果,而没有必然关系。
事实上,插值得到的图片是有关系的,是逐渐变化的。这说明网络并不是简单的记忆,而是学习到了一定的映射关系。
3.实际的代码
噪声1
noise_1 = torch.randn(1, nz, 1, 1, device=device)
fake = netG(noise_1)
fake = (fake + 1) / 2
output = netD(fake.detach()).view(-1)
plt.imshow(np.transpose(fake[0].detach().cpu(),(1,2,0)), animated=True)
plt.show()
噪声2
noise_2 = torch.randn(1, nz, 1, 1, device=device)
fake = netG(noise_2)
fake = (fake + 1) / 2
output = netD(fake.detach()).view(-1)
plt.imshow(np.transpose(fake[0].detach().cpu(),(1,2,0)), animated=True)
plt.show()
插值过程
noise_ = noise_1.clone()
for step in range(10):
noise_[0, 0:10*step+10, 0, 0] = noise_2[0, 0:10*step+10, 0, 0]
fake = netG(noise_)
fake = (fake + 1) / 2
plt.subplot(3, 4, step+1)
plt.axis("off")
plt.imshow(np.transpose(fake[0].detach().cpu(),(1,2,0)), animated=True)
plt.show()
plt.imshow(np.transpose(fake[0].detach().cpu(),(1,2,0)), animated=True)
s = np.transpose(fake[0].detach().cpu(),(1,2,0))
plt.imsave('save.png', s)