网站开发的高级阶段包括,工程造价信息网官网登录,黄页88网企业名录,flash可以做网站吗实验8#xff1a;生成对抗网络 一#xff1a;实验目的
1#xff1a;理解生成对抗网络的基本原理。
2#xff1a;学会构建改进的生成对抗网络#xff0c;如DCGAN、WGAN、WGAN-GP等。
3#xff1a;学习在更为真实的数据集上应用生成对抗网络的方法。 二#xff1a;实验…实验8生成对抗网络 一实验目的
1理解生成对抗网络的基本原理。
2学会构建改进的生成对抗网络如DCGAN、WGAN、WGAN-GP等。
3学习在更为真实的数据集上应用生成对抗网络的方法。 二实验要求
1理解生成对抗网络改进算法的改进内容和改进目的。
2参考课程资源中的2024年春第八次实验代码完成生成对抗网络改进算法WGAN或DCGAN网络的实现。
3在Fashion MNIST数据集上验证生成对抗网络改进算法的效果并对其进行调优。
4在玉米数据集上验证生成对抗网络改进算法在真实场景下对复杂数据集的生成结果。选做
5撰写实验报告对结果进行分析。 三实验环境
本实验所使用的环境条件如下表所示。 操作系统 UbuntuLinux 程序语言 Python3.11.4 第三方依赖 torch, torchvision, matplotlib等 四实验原理
1GAN
GAN的中文名称为生成对抗网络。GAN是一种深度学习模型由一个生成器网络和一个判别器网络组成它们相互竞争地学习生成逼真的数据样本。GAN的核心思想是通过对抗训练来使生成器生成逼真的数据样本同时训练判别器来区分真实数据样本和生成的数据样本。
【1】生成器网络
生成器网络的目标是接收一个随机噪声向量通常服从某种先验分布如均匀分布或正态分布作为输入并生成与真实数据样本相似的假数据样本。生成器网络通常由一系列反卷积层也称为转置卷积层组成用于逐渐将输入噪声向量映射到数据空间。生成器网络的输出通常通过某种激活函数如sigmoid、tanh等进行转换以确保生成的数据在合适的范围内。 生成器的训练过程如下图所示。 【2】判别器网络
判别器网络的目标是接收真实数据样本或生成的假数据样本作为输入并输出一个标量值表示输入数据是真实数据样本的概率。判别器网络通常由一系列卷积层组成用于从输入数据中提取特征并最终将这些特征映射到一个标量输出。判别器的输出通常通过sigmoid激活函数进行转换将其限制在0到1之间以表示输入数据是真实数据样本的概率。 判别器的训练过程如下图所示。 【3】对抗训练
在对抗训练中生成器和判别器网络相互竞争以改善其性能。生成器试图生成越来越逼真的假数据样本以欺骗判别器使其无法区分生成的假数据样本和真实数据样本。而判别器则试图提高其准确性以尽可能准确地区分真实数据样本和生成的假数据样本。这种竞争的动态最终导致了生成器生成逼真的数据样本。
【4】损失函数
生成对抗网络使用两个损失函数来训练生成器和判别器。对于判别器损失函数通常是二元交叉熵损失函数用于衡量判别器在真实数据样本和生成的假数据样本上的分类性能。对于生成器损失函数通常是判别器在生成的假数据样本上的输出与真实标签即1之间的二元交叉熵损失函数。通过最小化生成器和判别器的损失函数可以实现对抗训练。
2GAN的变种
目前GAN的变体主要从网络结构、条件生成网络、图像翻译、归一化和限制、损失函数、评价指标等方面进行改进。
变体的发展过程如下图所示。 其中DCGANDeep Convolutional Generative Adversarial Networks、WGANWasserstein Generative Adversarial Networks和 WGAN-GPWasserstein Generative Adversarial Networks with Gradient Penalty都是GAN的常见变体用于生成逼真的图像。
上述三种GAN变种的对比如下
【1】损失函数
DCGANDCGAN使用交叉熵损失函数来训练生成器和判别器。
WGANWGAN引入了Wasserstein距离作为生成器和判别器之间的损失函数。Wasserstein距离能够更好地衡量生成分布和真实分布之间的差异从而提高了训练的稳定性。
WGAN-GPWGAN-GP在WGAN的基础上引入了梯度惩罚项用于限制判别器的梯度从而进一步提高了训练的稳定性和生成图像的质量。
【2】训练稳定性
DCGANDCGAN在训练过程中可能会出现训练不稳定的问题例如模式崩溃mode collapse和梯度消失等。
WGANWGAN的损失函数设计使其更加稳定可以缓解训练过程中出现的模式崩溃和梯度消失等问题有助于生成更加高质量和多样化的图像。
WGAN-GPWGAN-GP进一步改进了WGAN的稳定性通过梯度惩罚项有效地限制了判别器的梯度减轻了训练过程中的梯度爆炸和梯度消失问题。 五算法流程
数据准备。准备训练所需的Fashion MNIST数据集。网络构建。利用PyTorch框架搭建不同GAN的判别器和生成器。可视化数据。导出生成器和判别器随着迭代次数所变化的损失曲线图像同时利用生成器生成图像。 六实验展示
1DCGAN在Fashion MNIST数据集上的应用
DCGAN的生成器网络构建如下图所示。 DCGAN的判别器网络构建如下图所示。 DCGAN使用的损失函数为BCE损失函数优化器使用Adam优化器的学习率为0.0002训练迭代次数为30次。
DCGAN中判别器和生成器的损失曲线如下图所示。其中橘色部分为生成器、蓝色部分为判别器。 DCGAN的生成效果如下图所示。 2WGAN在Fashion MNIST数据集上的应用 WGAN的生成器网络构建如下图所示。 WGAN的判别器网络构建如下图所示。 WGAN使用的损失函数为Wasserstein距离损失函数优化器使用RMSprop优化器的学习率为0.00005训练迭代次数为30次。
WGAN中判别器和生成器的损失曲线如下图所示。其中橘色部分为生成器、蓝色部分为判别器。 WGAN的生成效果如下图所示。 3DCGAN在大米数据集上的应用
DCGAN的超参数和训练过程与第1部分类似但是迭代次数变为了500加载数据集时将图像尺寸压缩为了28*28。 DCGAN中判别器和生成器的损失曲线如下图所示。其中橘色部分为生成器、蓝色部分为判别器。 DCGAN的生成效果如下图所示。生成的图像中包含4粒大米。 源数据集的图像样本如下。 4DCGAN在玉米数据集上的应用
DCGAN的超参数和训练过程与第1部分类似但是迭代次数变为了500加载数据集时将图像尺寸压缩为了28*28。 DCGAN中判别器和生成器的损失曲线如下图所示。其中橘色部分为生成器、蓝色部分为判别器。 DCGAN的生成效果如下图所示。生成的图像中包含4个玉米。 源数据集的图像样本如下。 七实验结论与心得
1生成对抗网络利用生成器和判别器之间的对抗训练机制能够有效地生成逼真的数据样本在图像生成、文本生成、图像转换等领域广泛应用。
2GAN的性能很大程度上受到超参数的影响如学习率、潜在空间维度、网络结构等。
3GAN相比较其他生成模型玻尔兹曼机等只用到了反向传播,不需要复杂的马尔科夫链且可以产生更加清晰、真实的样本。
4GAN采用无监督的学习方式训练可以被广泛用在无监督学习和半监督学习领域。
5如果生成器生成的样本判别器判定为真实的则说明生成器的效果是较好的因而可以用判别器来评价生成器即判别的性能越差说明生成器的性能越好。 八主要代码
1DCGAN源代码 import torch from torch import nn, optim from torchvision import datasets, transforms, utils from torch.utils.data import DataLoader import matplotlib.pyplot as plt # 设备配置 device torch.device(cuda if torch.cuda.is_available() else cpu) # 数据预处理 transform transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,)) ]) # 加载数据集 train_data datasets.FashionMNIST(root./data, trainTrue, downloadTrue, transformtransform) train_loader DataLoader(train_data, batch_size128, shuffleTrue) # 生成器 class Generator(nn.Module): def __init__(self): super(Generator, self).__init__() self.main nn.Sequential( # 输入是一个 100 维的噪声向量我们将其投射并reshape成 1x1x128 的大小 nn.Linear(100, 128*7*7), nn.BatchNorm1d(128*7*7), nn.ReLU(True), nn.Unflatten(1, (128, 7, 7)), nn.ConvTranspose2d(128, 64, 4, stride2, padding1), nn.BatchNorm2d(64), nn.ReLU(True), nn.ConvTranspose2d(64, 1, 4, stride2, padding1), nn.Tanh() ) def forward(self, x): return self.main(x) # 判别器 class Discriminator(nn.Module): def __init__(self): super(Discriminator, self).__init__() self.main nn.Sequential( nn.Conv2d(1, 64, 4, stride2, padding1), nn.LeakyReLU(0.2, inplaceTrue), nn.Conv2d(64, 128, 4, stride2, padding1), nn.BatchNorm2d(128), nn.LeakyReLU(0.2, inplaceTrue), nn.Flatten(), nn.Linear(128*7*7, 1), nn.Sigmoid() ) def forward(self, x): return self.main(x) # 实例化模型 netG Generator().to(device) netD Discriminator().to(device) # 损失函数和优化器 criterion nn.BCELoss() optimizerD optim.Adam(netD.parameters(), lr0.0002, betas(0.5, 0.999)) optimizerG optim.Adam(netG.parameters(), lr0.0002, betas(0.5, 0.999)) # 训练 num_epochs 30 lossD [] lossG [] for epoch in range(num_epochs): for i, (images, _) in enumerate(train_loader): # 更新判别器maximize log(D(x)) log(1 - D(G(z))) netD.zero_grad() real_data images.to(device) batch_size real_data.size(0) labels torch.full((batch_size,), 1, dtypetorch.float, devicedevice) output netD(real_data) labels labels.view(-1, 1) lossD_real criterion(output, labels) lossD_real.backward() noise torch.randn(batch_size, 100, devicedevice) fake_data netG(noise) labels.fill_(0) output netD(fake_data.detach()) lossD_fake criterion(output, labels) lossD_fake.backward() optimizerD.step() # 更新生成器minimize log(1 - D(G(z))) ≈ maximize log(D(G(z))) netG.zero_grad() labels.fill_(1) # fake labels are real for generator cost output netD(fake_data) loss_G criterion(output, labels) loss_G.backward() optimizerG.step() lossD.append(lossD_real.item() lossD_fake.item()) lossG.append(loss_G.item()) if (i1) % 100 0: print(fEpoch [{epoch1}/{num_epochs}], Step [{i1}/{len(train_loader)}], Loss_D: {lossD_real.item() lossD_fake.item():.4f}, Loss_G: {loss_G.item():.4f}) # 可视化一些生成的图片 noise torch.randn(64, 100, devicedevice) fake_images netG(noise) fake_images fake_images.reshape(fake_images.size(0), 1, 28, 28) fake_images (fake_images 1) / 2 # 调整像素值范围到 [0, 1] img_grid utils.make_grid(fake_images, normalizeTrue) img_grid img_grid.cpu() # 首先将张量移至 CPU plt.imshow(img_grid.permute(1, 2, 0).numpy()) plt.savefig(z.png) plt.close() # 绘制曲线 y_values1 lossD y_values2 lossG x_values range(1, len(y_values1) 1) plt.plot(x_values, y_values1, labelDiscriminator Loss) plt.plot(x_values, y_values2, labelGenerator Loss) # 添加标题和标签 plt.title(loss for discriminator and generator) plt.xlabel(Batch) plt.ylabel(Loss) plt.legend([Discriminator, Generator]) # 显示图形 plt.savefig(loss-DCGAN.png)
2WGAN源代码 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms import matplotlib.pyplot as plt # 设备配置 device torch.device(cuda if torch.cuda.is_available() else cpu) # 定义生成器网络 class Generator(nn.Module): def __init__(self, latent_dim, img_shape): super(Generator, self).__init__() self.model nn.Sequential( nn.Linear(latent_dim, 128), nn.LeakyReLU(0.2, inplaceTrue), nn.Linear(128, 256), nn.BatchNorm1d(256), nn.LeakyReLU(0.2, inplaceTrue), nn.Linear(256, img_shape), nn.Tanh() ) def forward(self, z): z z.to(next(self.parameters()).device) img self.model(z) return img # 定义判别器网络 class Discriminator(nn.Module): def __init__(self, img_shape): super(Discriminator, self).__init__() self.model nn.Sequential( nn.Linear(img_shape, 256), nn.LeakyReLU(0.2, inplaceTrue), nn.Linear(256, 128), nn.BatchNorm1d(128), nn.LeakyReLU(0.2, inplaceTrue), nn.Linear(128, 1) ) def forward(self, img): validity self.model(img) return validity # 参数 latent_dim 100 img_shape 28 * 28 batch_size 64 # 准备数据 transform transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,)) ]) train_dataset datasets.FashionMNIST(root./data, trainTrue, transformtransform, downloadTrue) train_loader torch.utils.data.DataLoader(train_dataset, batch_sizebatch_size, shuffleTrue) # 初始化网络和优化器 generator Generator(latent_dim, img_shape).to(device) discriminator Discriminator(img_shape).to(device) optimizer_G optim.RMSprop(generator.parameters(), lr0.00005) optimizer_D optim.RMSprop(discriminator.parameters(), lr0.00005) # 训练模型 lossD [] lossG [] n_epochs 30 for epoch in range(n_epochs): for i, (imgs, _) in enumerate(train_loader): # 训练判别器 optimizer_D.zero_grad() # 真实图像 real_imgs imgs.view(-1, img_shape).to(device) validity_real discriminator(real_imgs) # 生成潜在空间向量 z torch.randn(batch_size, latent_dim).to(device) fake_imgs generator(z).detach() validity_fake discriminator(fake_imgs) # 计算损失 d_loss -torch.mean(validity_real) torch.mean(validity_fake) d_loss_item d_loss.item() # 反向传播和优化 d_loss.backward() optimizer_D.step() # 限制判别器参数 for p in discriminator.parameters(): p.data.clamp_(-0.01, 0.01) # 训练生成器 optimizer_G.zero_grad() # 生成潜在空间向量 z torch.randn(batch_size, latent_dim) fake_imgs generator(z) validity discriminator(fake_imgs) # 计算损失 g_loss -torch.mean(validity) g_loss_item g_loss.item() # 反向传播和优化 g_loss.backward() optimizer_G.step() lossD.append(d_loss.item()) lossG.append(g_loss.item()) # 打印损失信息 if i % 500 0: print( [Epoch %d/%d] [Batch %d/%d] [D loss: %.4f] [G loss: %.4f] % (epoch, n_epochs, i, len(train_loader), d_loss.item(), g_loss.item()) ) # 生成图像 z torch.randn(64, latent_dim, devicedevice) generated_images generator(z) generated_images generated_images.detach().cpu().numpy() # 显示生成的图像 fig, axes plt.subplots(nrows8, ncols8, figsize(10, 10)) for i, ax in enumerate(axes.flatten()): ax.imshow(generated_images[i].reshape(28, 28), cmapgray) ax.axis(off) plt.tight_layout() plt.savefig(zz.png) plt.close() # 绘制曲线 y_values1 lossD y_values2 lossG x_values range(1, len(y_values1) 1) plt.plot(x_values, y_values1, labelDiscriminator Loss) plt.plot(x_values, y_values2, labelGenerator Loss) # 添加标题和标签 plt.title(loss for discriminator and generator) plt.xlabel(Batch) plt.ylabel(Loss) plt.legend([Discriminator, Generator]) # 显示图形 plt.savefig(loss-WGAN.png)
3玉米数据集上的DCGAN import torch from torch import nn, optim from torchvision import transforms, utils import matplotlib.pyplot as plt import os from PIL import Image from torch.utils.data import Dataset, DataLoader class CustomDataset(Dataset): def __init__(self, data_dir, transformNone): self.data_dir data_dir self.transform transform self.image_files os.listdir(data_dir) def __len__(self): return len(self.image_files) def __getitem__(self, idx): img_name os.path.join(self.data_dir, self.image_files[idx]) image Image.open(img_name).convert(RGB) # 读取图像并转换为RGB格式 if self.transform: image self.transform(image) return image # 数据集文件夹路径 data_dir r/home/ubuntu/zz-test # 设备配置 device torch.device(cuda if torch.cuda.is_available() else cpu) # 数据预处理 transform transforms.Compose([ transforms.Resize((28, 28)), # 将图像调整为28x28大小 transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,)) ]) # 加载数据集 train_data CustomDataset(data_dir, transformtransform) train_loader DataLoader(train_data, batch_size32, shuffleTrue) # 生成器 class Generator(nn.Module): def __init__(self): super(Generator, self).__init__() self.main nn.Sequential( nn.Linear(100, 128*7*7), nn.BatchNorm1d(128*7*7), nn.ReLU(True), nn.Unflatten(1, (128, 7, 7)), nn.ConvTranspose2d(128, 64, 4, stride2, padding1), nn.BatchNorm2d(64), nn.ReLU(True), nn.ConvTranspose2d(64, 3, 4, stride2, padding1), # 修改这里的输出通道数为3 nn.Tanh() ) def forward(self, x): return self.main(x) # 判别器 class Discriminator(nn.Module): def __init__(self): super(Discriminator, self).__init__() self.main nn.Sequential( nn.Conv2d(3, 64, 4, stride2, padding1), # 修改这里的输入通道数为3 nn.LeakyReLU(0.2, inplaceTrue), nn.Conv2d(64, 128, 4, stride2, padding1), nn.BatchNorm2d(128), nn.LeakyReLU(0.2, inplaceTrue), nn.Flatten(), nn.Linear(128*7*7, 1), nn.Sigmoid() ) def forward(self, x): return self.main(x) # 实例化模型 netG Generator().to(device) netD Discriminator().to(device) # 损失函数和优化器 criterion nn.BCELoss() optimizerD optim.Adam(netD.parameters(), lr0.0002, betas(0.5, 0.999)) optimizerG optim.Adam(netG.parameters(), lr0.0002, betas(0.5, 0.999)) # 训练 num_epochs 500 lossD [] lossG [] for epoch in range(num_epochs): for i, images in enumerate(train_loader): # 更新判别器maximize log(D(x)) log(1 - D(G(z))) netD.zero_grad() real_data images.to(device) batch_size real_data.size(0) labels torch.full((batch_size,), 1, dtypetorch.float, devicedevice) output netD(real_data) labels labels.view(-1, 1) lossD_real criterion(output, labels) lossD_real.backward() noise torch.randn(batch_size, 100, devicedevice) fake_data netG(noise) labels.fill_(0) output netD(fake_data.detach()) lossD_fake criterion(output, labels) lossD_fake.backward() optimizerD.step() # 更新生成器minimize log(1 - D(G(z))) ≈ maximize log(D(G(z))) netG.zero_grad() labels.fill_(1) # fake labels are real for generator cost output netD(fake_data) loss_G criterion(output, labels) loss_G.backward() optimizerG.step() lossD.append(lossD_real.item() lossD_fake.item()) lossG.append(loss_G.item()) if (i1) % 100 0: print(fEpoch [{epoch1}/{num_epochs}], Step [{i1}/{len(train_loader)}], Loss_D: {lossD_real.item() lossD_fake.item():.4f}, Loss_G: {loss_G.item():.4f}) # 保存生成的图像 noise torch.randn(4, 100, devicedevice) fake_images netG(noise) fake_images (fake_images 1) / 2 # 调整像素值范围到 [0, 1] img_grid utils.make_grid(fake_images, nrow2, normalizeTrue) # 将图像网格化并且每行显示8张图像 img_grid img_grid.permute(1, 2, 0).cpu().numpy() # 将张量转换为NumPy数组并将通道维度放到最后 plt.imshow(img_grid) plt.axis(off) # 关闭坐标轴 plt.savefig(generated_images.png) plt.close() # 绘制损失曲线 plt.plot(lossD, labelDiscriminator Loss) plt.plot(lossG, labelGenerator Loss) # 添加标题和标签 plt.title(Loss for Discriminator and Generator) plt.xlabel(Batch) plt.ylabel(Loss) plt.legend() # 保存损失曲线图 plt.savefig(loss-DCGAN.png) plt.close()