Pytorch和DCGAN生成肖像画(下)

简介: Pytorch和DCGAN生成肖像画

生成器

我们的生成器模型将完全遵循DCGAN的完全相同的体系结构。

640.png

与生成器类似,但是相反,我们不是将图像卷积为一组特征,而是采用随机噪声输入“ z”并运行一系列反卷积以达到所需的图像形状(3,64,64 )。

classGenerator(nn.Module):
def__init__(self, channels_noise, channels_img, features_g):
super(Generator, self).__init__()
self.net=nn.Sequential(
#Input: Nxchannels_noisex1x1self._block(channels_noise, features_g*16, 4, 1, 0), #img: 4x4self._block(features_g*16, features_g*8, 4, 2, 1), #img: 8x8self._block(features_g*8, features_g*4, 4, 2, 1), #img: 16x16self._block(features_g*4, features_g*2, 4, 2, 1), #img: 32x32nn.ConvTranspose2d(
features_g*2, channels_img, kernel_size=4, stride=2, padding=1            ),
#Output: Nxchannels_imgx64x64nn.Tanh(),
        )
def_block(self, in_channels, out_channels, kernel_size, stride, padding):
returnnn.Sequential(
nn.ConvTranspose2d(
in_channels, out_channels, kernel_size, stride, padding, bias=False,
            ),
nn.BatchNorm2d(out_channels),
nn.ReLU(),
        )
defforward(self, x):
returnself.net(x)

最后,我们只需要在训练之前将initialize_weights()函数添加到两个模型即可:

definitialize_weights(model):
#InitializesweightsaccordingtotheDCGANpaperforminmodel.modules():
ifisinstance(m, (nn.Conv2d, nn.ConvTranspose2d, nn.BatchNorm2d)):
nn.init.normal_(m.weight.data, 0.0, 0.02)

训练

现在我们有了数据和模型,我们可以从train.py文件开始,在这里我们将加载数据,初始化模型并运行主训练循环。

超参数和导入

importnumpyasnpimporttorchimporttorch.nnasnnimporttorch.optimasoptimimporttorchvisionimporttorchvision.datasetsasdatasetsimporttorchvision.transformsastransformsfromtorch.utils.dataimportDatasetfromtorch.utils.dataimportDataLoaderfromtorch.utils.tensorboardimportSummaryWriterfrommodelimportDiscriminator, Generator, initialize_weightsimportrandomimportosimportnatsortfromPILimportImage, ImageOps, ImageEnhancedevice=torch.device("cuda"iftorch.cuda.is_available() else"cpu")
D_LEARNING_RATE=2e-4G_LEARNING_RATE=1e-4BATCH_SIZE=64IMAGE_SIZE=64CHANNELS_IMG=3NOISE_DIM=128NUM_EPOCHS=100FEATURES_DISC=64FEATURES_GEN=64

两个优化器可以使用相同的学习率,但是我发现对鉴别器使用稍高的学习率被证明是更有效的。在更复杂的数据集上,我发现较小的批次大小(例如16或8)可以帮助避免过度拟合。

随机增强

改善GAN训练并从数据集中获得最大收益的技术之一是应用随机图像增强。在原始论文中,它们还提供了一种在生成器端还原增强图像的机制,因为我们不希望生成器生成增强图像。但是,在这种情况下,我认为应用这些简单的增幅就足够了,而这些增幅并不会真正影响画质。如果我们试图获得照片般逼真的结果,那么使用它来进行全面实施可能是一个更好的主意。

defrandom_augmentation(img):
#randommirroring/flippingimagerand_mirror=random.randint(0,1)
#randomsaturationadjustmentrand_sat=random.uniform(0.5,1.5)
#randomsharpnessadjustmentrand_sharp=random.uniform(0.5,1.5)
converter=ImageEnhance.Color(img)
img=converter.enhance(rand_sat)
converter=ImageEnhance.Sharpness(img)
img=converter.enhance(rand_sharp)
ifrand_mirror==0:
img=ImageOps.mirror(img)
returnimg

我们对图像执行3个操作-镜像,饱和度调整和锐度调整。镜像图像对我们的图像质量没有影响,因为我们只是在翻转图像。对于饱和度和清晰度,我使用了一个较小的系数范围(0.5、1.5),以免对原始图像造成很大的影响。

数据加载器

为了应用我们之前构建的随机增强方法并加载数据,我编写了一个使用其下定义的转换的自定义数据集。

classCustomDataSet(Dataset):
def__init__(self, main_dir, transform):
self.main_dir=main_dirself.transform=transformall_imgs=os.listdir(main_dir)
self.total_imgs=natsort.natsorted(all_imgs)
def__len__(self):
returnlen(self.total_imgs)
def__getitem__(self, idx):
img_loc=os.path.join(self.main_dir, self.total_imgs[idx])
image=Image.open(img_loc).convert('RGB')
image=random_augmentation(image)
tensor_image=self.transform(image)
returntensor_imagetransforms=transforms.Compose(
    [
transforms.Resize((IMAGE_SIZE,IMAGE_SIZE)),
transforms.ToTensor(),
transforms.Normalize(
            [0.5for_inrange(CHANNELS_IMG)], [0.5for_inrange(CHANNELS_IMG)]
        ),
    ]
)
dataset=CustomDataSet("./data/128_portraits/", transform=transforms)
dataloader=DataLoader(dataset, batch_size=BATCH_SIZE, shuffle=True)

训练

最后,我们可以初始化我们的网络并开始对其进行训练。对于鉴别器训练,我使用均方误差作为损失函数。我也尝试使用二进制交叉熵,但MSELoss最有效。在训练循环之前,我们还初始化张量板编写器以在tensorboard上实时查看我们的图像。

gen=Generator(NOISE_DIM, CHANNELS_IMG, FEATURES_GEN).to(device)
disc=Discriminator(CHANNELS_IMG, FEATURES_DISC).to(device)
initialize_weights(gen)
initialize_weights(disc)
###uncommenttoworkfromsavedmodels####gen.load_state_dict(torch.load('saved_models/generator_model.pt'))
#disc.load_state_dict(torch.load('saved_models/discriminator_model.pt'))
opt_gen=optim.Adam(gen.parameters(), lr=G_LEARNING_RATE, betas=(0.5, 0.99))
opt_disc=optim.Adam(disc.parameters(), lr=D_LEARNING_RATE, betas=(0.5, 0.99))
criterion=nn.MSELoss()
fixed_noise=torch.randn(16, NOISE_DIM, 1, 1).to(device)
writer_real=SummaryWriter(f"logs/real")
writer_fake=SummaryWriter(f"logs/fake")
step=0gen.train()
disc.train()
forepochinrange(NUM_EPOCHS):
forbatch_idx, realinenumerate(dataloader):
real=real.to(device)
noise=torch.randn(BATCH_SIZE, NOISE_DIM, 1, 1).to(device)
fake=gen(noise)
###TrainDiscriminatordisc_real=disc(real).reshape(-1)
loss_disc_real=criterion(disc_real, torch.ones_like(disc_real))
disc_fake=disc(fake.detach()).reshape(-1)
loss_disc_fake=criterion(disc_fake, torch.zeros_like(disc_fake))
loss_disc= (loss_disc_real+loss_disc_fake) /2disc.zero_grad()
loss_disc.backward()
opt_disc.step()
###TrainGeneratorusingfeaturematchingoutput=disc(fake).reshape(-1)
loss_gen=criterion(output, torch.ones_like(output))
gen.zero_grad()
loss_gen.backward()
opt_gen.step()
#Printlossesoccasionallyandprinttotensorboardifbatch_idx%10==0:                
torch.save(gen.state_dict(), 'generator_model.pt')
torch.save(disc.state_dict(), 'discriminator_model.pt')
print(
f"Epoch [{epoch}/{NUM_EPOCHS}] Batch {batch_idx}/{len(dataloader)} \Loss D: {loss_disc:.4f}, loss G: {loss_gen:.4f}"            )
withtorch.no_grad():
fake=gen(fixed_noise)
img_grid_real=torchvision.utils.make_grid(
real[:16], normalize=True                )
img_grid_fake=torchvision.utils.make_grid(
fake[:16], normalize=True                )
writer_real.add_image("Real", img_grid_real, global_step=step)
writer_fake.add_image("Fake", img_grid_fake, global_step=step)
step+=1

在训练的第一部分中,我们使用MSELoss在真实图像和伪图像上训练鉴别器。之后,我们使用特征匹配来训练我们的生成器。之前,我们在鉴别器的前向传递中添加了变量“ feature_matching”,以从图像中提取感知特征。在传统的DCGAN中,您只需训练生成器以伪造的图像来欺骗鉴别器,而在这里,我们试图训练生成器以生成与真实图像的特征紧密匹配的图像。此技术通常可以提高训练的稳定性。

经过100个批次后,我获得了以下结果。我尝试对模型进行更多的迭代训练,但是图像质量没有太大改善。

640.png

结论与最终想法

本文的目的是记录我从事该项目的过程。尽管在线上有很多资源和论文探讨了这个令人兴奋的概念的不同方面,但我发现有些东西是只能通过经验学习的……与其他任何东西一样。但我希望您能在本文中找到一些可以在自己的GAN项目中应用或试验的东西。由于我们获得的结果并不完美,因此我打算应用本文中提出的EvolGAN来优化我的生成器。

目录
相关文章
|
机器学习/深度学习 数据可视化 PyTorch
PyTorch实现DCGAN(生成对抗网络)生成新的假名人照片实战(附源码和数据集)
PyTorch实现DCGAN(生成对抗网络)生成新的假名人照片实战(附源码和数据集)
235 1
|
机器学习/深度学习 PyTorch 算法框架/工具
Pytorch和DCGAN生成肖像画(上)
Pytorch和DCGAN生成肖像画
225 0
Pytorch和DCGAN生成肖像画(上)
|
机器学习/深度学习 存储 并行计算
一个快速构造GAN的教程:如何用pytorch构造DCGAN(下)
一个快速构造GAN的教程:如何用pytorch构造DCGAN
296 0
一个快速构造GAN的教程:如何用pytorch构造DCGAN(下)
|
机器学习/深度学习 存储 PyTorch
一个快速构造GAN的教程:如何用pytorch构造DCGAN(上)
一个快速构造GAN的教程:如何用pytorch构造DCGAN
299 0
一个快速构造GAN的教程:如何用pytorch构造DCGAN(上)
|
29天前
|
机器学习/深度学习 数据采集 人工智能
PyTorch学习实战:AI从数学基础到模型优化全流程精解
本文系统讲解人工智能、机器学习与深度学习的层级关系,涵盖PyTorch环境配置、张量操作、数据预处理、神经网络基础及模型训练全流程,结合数学原理与代码实践,深入浅出地介绍激活函数、反向传播等核心概念,助力快速入门深度学习。
88 1
|
5月前
|
机器学习/深度学习 PyTorch API
PyTorch量化感知训练技术:模型压缩与高精度边缘部署实践
本文深入探讨神经网络模型量化技术,重点讲解训练后量化(PTQ)与量化感知训练(QAT)两种主流方法。PTQ通过校准数据集确定量化参数,快速实现模型压缩,但精度损失较大;QAT在训练中引入伪量化操作,使模型适应低精度环境,显著提升量化后性能。文章结合PyTorch实现细节,介绍Eager模式、FX图模式及PyTorch 2导出量化等工具,并分享大语言模型Int4/Int8混合精度实践。最后总结量化最佳策略,包括逐通道量化、混合精度设置及目标硬件适配,助力高效部署深度学习模型。
729 21
PyTorch量化感知训练技术:模型压缩与高精度边缘部署实践
|
14天前
|
边缘计算 人工智能 PyTorch
130_知识蒸馏技术:温度参数与损失函数设计 - 教师-学生模型的优化策略与PyTorch实现
随着大型语言模型(LLM)的规模不断增长,部署这些模型面临着巨大的计算和资源挑战。以DeepSeek-R1为例,其671B参数的规模即使经过INT4量化后,仍需要至少6张高端GPU才能运行,这对于大多数中小型企业和研究机构来说成本过高。知识蒸馏作为一种有效的模型压缩技术,通过将大型教师模型的知识迁移到小型学生模型中,在显著降低模型复杂度的同时保留核心性能,成为解决这一问题的关键技术之一。
|
29天前
|
机器学习/深度学习 存储 PyTorch
Neural ODE原理与PyTorch实现:深度学习模型的自适应深度调节
Neural ODE将神经网络与微分方程结合,用连续思维建模数据演化,突破传统离散层的限制,实现自适应深度与高效连续学习。
75 3
Neural ODE原理与PyTorch实现:深度学习模型的自适应深度调节
|
2月前
|
PyTorch 算法框架/工具 异构计算
PyTorch 2.0性能优化实战:4种常见代码错误严重拖慢模型
我们将深入探讨图中断(graph breaks)和多图问题对性能的负面影响,并分析PyTorch模型开发中应当避免的常见错误模式。
165 9
|
7月前
|
机器学习/深度学习 JavaScript PyTorch
9个主流GAN损失函数的数学原理和Pytorch代码实现:从经典模型到现代变体
生成对抗网络(GAN)的训练效果高度依赖于损失函数的选择。本文介绍了经典GAN损失函数理论,并用PyTorch实现多种变体,包括原始GAN、LS-GAN、WGAN及WGAN-GP等。通过分析其原理与优劣,如LS-GAN提升训练稳定性、WGAN-GP改善图像质量,展示了不同场景下损失函数的设计思路。代码实现覆盖生成器与判别器的核心逻辑,为实际应用提供了重要参考。未来可探索组合优化与自适应设计以提升性能。
504 7
9个主流GAN损失函数的数学原理和Pytorch代码实现:从经典模型到现代变体

热门文章

最新文章

推荐镜像

更多