课程打卡凭证
CycleGAN模型
CycleGAN(Cycle-Consistent Generative Adversarial Network),即循环一致生成对抗网络,它能够在没有成对训练样本的情况下,能够实现两个不同领域(或风格、类型)之间的图像转换。详见论文https://arxiv.org/abs/1703.10593。
什么是GAN
GAN,即生成对抗网络,它主要是由生成器(Generator)和判别器(Discriminator)两部分组成。其中生成器用于生成尽可能接近真实数据的假数据,而判别器则用于区分输入数据是真实的还是由前者生成的。
CycleGAN的组成
CycleGAN本质上是由两个镜像对称的GAN组成,因此它两个生成器和两个判别器,其中两个生成器的作用分别是将图像从域A转换到域B以及将图像从域B转换回域A,两个判别器的作用分别是判断图像是否属于域A以及判断图像是否属于域B。具体过程如图所示。
循环一致性损失
如图所示,CycleGAN的核心思想是引入了循环一致性损失(Cycle Consistency Loss),确保图像在通过两个生成器转换后能够恢复到原始状态。即,图像从域X转换到域Y,再转换回域X,应与原始域X的图像尽可能相似。
训练过程
数据加载与处理
本次实验的数据集来自ImageNet,只使用了其中的苹果和橘子部分。
实验用到的数据集如图所示。实验的目的是将苹果图像与橘子图像的风格互换。
模型构建
构建生成器
使用MindSpore框架定义CycleGAN中的生成器,生成器主要由几个部分组成:卷积块(ConvNormReLU)、残差块(ResidualBlock)和残差网络生成器(ResNetGenerator)。
导入必要的库和模块,定义初始权重。
ConvNormReLU的功能是根据传入的参数决定是否使用卷积转置(transpose)以及使用哪种归一化(BatchNorm或InstanceNorm)。如果需要填充(padding),则使用指定的填充模式(pad_mode)。
ResidualBlock中包含两个ConvNormReLU模块,它能将输入与输出相加以形成残差连接。
ResNetGenerator是CycleGAN中的生成器,使用残差网络结构,它包含输入卷积层、两层下采样卷积层、多个残差块、两层上采样卷积层以及输出卷积层。它的输出使用tanh激活函数,可以将输出值限制在[-1, 1]之间。
分别实例化两个生成器net_rg_a和net_rg_b,并更新它们的参数名称以便于区分。
构建判别器
这里定义了一个判别器网络,使用多层卷积层和LeakyReLU激活函数,使用卷积层和归一化层(BatchNorm或InstanceNorm),通过多个卷积层逐渐增加特征图的数量。最后使用一个卷积层将特征图映射到单通道输出,表示判别结果。
分别实例化两个生成器net_d_a和net_d_b,并更新它们的参数名称以便于区分。
优化器和损失函数
使用了Adam优化器来优化生成器和判别器的参数,构建四个优化器,分别对应四个生成器。在损失函数中,使用均方误差损失(MSELoss)来计算生成的图像与目标图像之间的误差。使用L1损失来计算生成图像与真实图像之间的绝对差异,定义gan_loss函数来于计算GAN的损失。
前向计算
导入mindspore库。
生成器前向计算,过程如下:输入图像img_a和img_b分别经过生成器net_rg_a和net_rg_b得到假图像fake_a和fake_b,假图像再通过生成器还原得到重建图像rec_a和rec_b,输入图像也直接通过生成器得到身份图像indentity_a和indentity_b。
生成器损失计算,包括GAN损失、循环一致性损失和身份损失。
生成器梯度计算,计算生成器的总损失loss_g。
判别器损失计算,包括对假图像和真实图像的判别损失。
保留一个图像缓冲区,用来存储之前创建的50个图像。每次调用时随机返回新图像或池中的图像。
计算梯度和反向传播
使用mindspore中的value_and_gard函数来计算生成器和判别器的梯度。value_and_gard函数返回两个值:前向计算的损失值和反向传播计算的梯度。
在生成器训练过程中,冻结判别器的梯度计算,前向计算生成器的损失,并计算其梯度,然后使用优化器更新生成器的参数。
在判别器训练过程中,启用判别器的梯度计算,前向计算判别器的损失,并计算其梯度,然后使用优化器更新判别器的参数。
模型训练
导入必要的库,设置模型的默认参数。
开始训练模型,打印每个epoch的平均损失和训练时间,并保存模型检查点。
训练结果如图所示。
模型推理
导入必要的库。
加载模型训练中保存的权重文件。
根据训练的模型,进行图片推理。
推理结果如图所示。