Вы просто не можете этого сделать. Как вы сказали, ваша сеть ожидает 100-мерный ввод, который обычно выбирается из стандартного нормального распределения:
![введите здесь описание изображения](https://i.stack.imgur.com/KE5NH.png)
Таким образом, работа генератора состоит в том, чтобы взять этот случайный вектор и сгенерировать изображение размером 3x64x64, неотличимое от реального изображения. Входные данные представляют собой случайный 100-мерный вектор, выбранный из стандартного нормального распределения. Я не вижу способа ввести ваше изображение в текущую сеть без изменения архитектуры и переобучения новой модели. Если вы хотите попробовать новую модель, вы можете изменить ввод на закрытые изображения, применить некоторые конв. / linear Layers, чтобы уменьшить размеры до 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-ти эпохальной тренировки:
а>
а>
Так что же говорит нам этот результат? Поскольку входные данные генератора не были взяты случайным образом из нормального распределения, генератор не смог изучить распределение лиц, чтобы создать различный диапазон выходных лиц. А поскольку вход представляет собой условный вектор признаков, диапазон выходных изображений ограничен. Таким образом, для генератора требуются случайные входные данные, хотя он научился удалять патчи :)
person
yutasrobot
schedule
24.03.2021