你就是不能那样做。正如您所说,您的网络需要 100 维输入,通常从标准正态分布中采样:

所以生成器的工作就是获取这个随机向量并生成与真实图像无法区分的 3x64x64 图像。输入是从标准正态分布中采样的随机 100 维向量。在不修改架构和重新训练新模型的情况下,我看不到任何将图像输入到当前网络的方法。如果你想尝试一个新模型,你可以将输入更改为被遮挡的图像,应用一些 conv。/ 线性层将维度减少到 100,然后保持网络的其余部分相同。这样,网络将尝试学习生成图像,而不是从潜在向量,而是从被遮挡图像中提取的特征向量。它可能会也可能不会起作用。
编辑我决定试一试,看看网络是否可以使用这种类型的条件输入向量而不是潜在向量来学习。我使用了您链接的教程示例并添加了一些更改。首先是一个用于接收输入并将其减少到 100 维的新网络:
class ImageTransformer(nn.Module):
def __init__(self):
super(ImageTransformer, self).__init__()
self.main = nn.Sequential(
nn.Conv2d(3, 1, 4, 2, 1, bias=False),
nn.LeakyReLU(0.2, inplace=True)
)
self.linear = nn.Linear(32*32, 100)
def forward(self, input):
out = self.main(input).view(input.shape[0], -1)
return self.linear(out).view(-1, 100, 1, 1)
只需一个简单的卷积层 + relu + 线性层即可在输出端映射到 100 维。请注意,您可以在这里尝试一个更好的网络作为更好的特征提取器,我只是想做一个简单的测试。
fixed_input = next(iter(dataloader))[0][0:64, :, : ,:]
fixed_input[:, :, 20:44, 20:44] = torch.tensor(np.zeros((24,24), dtype = np.float32))
fixed_input = fixed_input.to(device)
这就是我修改张量以在输入上添加黑色补丁的方式。只需采样一批以创建固定输入来跟踪过程,就像在教程中使用随机向量完成的那样。
# Create the generator
netG = Generator().to(device)
netD = Discriminator().to(device)
netT = ImageTransformer().to(device)
# Apply the weights_init function to randomly initialize all weights
# to mean=0, stdev=0.2.
netG.apply(weights_init)
netD.apply(weights_init)
netT.apply(weights_init)
# Print the model
print(netG)
print(netD)
print(netT)
大多数步骤是相同的,只是创建了新变压器网络的一个实例。最后,对训练循环稍作修改,其中生成器不被馈送随机向量,而是给定新变压器网络的输出。
img_list = []
G_losses = []
D_losses = []
iters = 0
for epoch in range(num_epochs):
for i, data in enumerate(dataloader, 0):
############################
# (1) Update D network: maximize log(D(x)) + log(1 - D(G(z)))
###########################
## Train with all-real batch
netD.zero_grad()
transformed = data[0].detach().clone()
transformed[:, :, 20:44, 20:44] = torch.tensor(np.zeros((24,24), dtype = np.float32))
transformed = transformed.to(device)
real_cpu = data[0].to(device)
b_size = real_cpu.size(0)
label = torch.full((b_size,), real_label, dtype=torch.float, device=device)
output = netD(real_cpu).view(-1)
errD_real = criterion(output, label)
errD_real.backward()
D_x = output.mean().item()
## Train with all-fake batch
fake = netT(transformed)
fake = netG(fake)
label.fill_(fake_label)
output = netD(fake.detach()).view(-1)
errD_fake = criterion(output, label)
errD_fake.backward()
D_G_z1 = output.mean().item()
errD = errD_real + errD_fake
optimizerD.step()
############################
# (2) Update G network: maximize log(D(G(z)))
###########################
netG.zero_grad()
label.fill_(real_label)
output = netD(fake).view(-1)
errG = criterion(output, label)
errG.backward()
D_G_z2 = output.mean().item()
optimizerG.step()
# Output training stats
if i % 50 == 0:
print('[%d/%d][%d/%d]\tLoss_D: %.4f\tLoss_G: %.4f\tD(x): %.4f\tD(G(z)): %.4f / %.4f'
% (epoch, num_epochs, i, len(dataloader),
errD.item(), errG.item(), D_x, D_G_z1, D_G_z2))
# Save Losses for plotting later
G_losses.append(errG.item())
D_losses.append(errD.item())
# Check how the generator is doing by saving G's output on fixed_noise
if (iters % 500 == 0) or ((epoch == num_epochs-1) and (i == len(dataloader)-1)):
with torch.no_grad():
fake = netT(fixed_input)
fake = netG(fake).detach().cpu()
img_list.append(vutils.make_grid(fake, padding=2, normalize=True))
iters += 1
训练在减少损失等方面还可以。最后这是我在 5 次训练后得到的结果:


那么这个结果告诉我们什么?由于生成器的输入不是从正态分布中随机获取的,因此生成器无法学习人脸的分布来创建不同范围的输出人脸。而且由于输入是条件特征向量,输出图像的范围是有限的。所以总而言之,生成器需要随机输入,即使它学会了删除补丁:)