当前位置: 首页 > news >正文

AIGC实战——BicycleGAN详解与实现

AIGC实战——BicycleGAN详解与实现

    • 0. 前言
    • 1. BicycleGAN 原理
    • 2. cVAE-GAN
    • 3. cLR-GAN
    • 4. 实现 BicycleGAN
      • 4.1 将潜编码插入生成器
      • 4.2 cVAE-GAN
      • 4.3 cLR-GAN
      • 4.4 训练步骤
    • 相关链接

0. 前言

pix2pix 和 CycleGAN 是非常的流行生成对抗网络 (Generative Adversarial Network, GAN) ,不仅在学术界有许多变体,同时也有许多基于此的应用。但是,它们都有一个缺点——图像的输出看起来几乎总是相同的。例如,如果我们要执行斑马到马的转换,被转换的同一马的照片将始终具有相同的外观和色调,这是由于它学会过滤了噪声的随机性。为了进行多样化图像转换,本文详解了 BicycleGAN 如何解决此问题以生成更丰富的图像,并利用 Tensorflow2 实现 BicycleGAN

1. BicycleGAN 原理

初看之下,可能会认为 BicycleGAN 是 CycleGAN 的升级,像是增加了另一个循环(从单循环到双循环)。但其实它与 CycleGAN 无关,而是对 pix2pix 的一种改进。
pix2pix 是一对一映射,其中给定输入的输出始终相同。BicycleGAN 作者试图将噪声添加到生成器输入中,但是网络会忽略噪声,并且没有在输出图像中产生变化。因此,他们试图寻找一种方法,其中生成器不忽略噪声,而是使用噪声来生成多样化的图像,因此是一对多映射。
在以下图中,我们可以看到与 BicycleGAN 相关的模型和配置。图(a) 是推理的配置,其中图像 AAA 与输入噪声相结合以生成图像 B^\hat BB^,可以看作是 cGAN。在 cGAN 中,噪声起着主导作用,输入为具有大小为 100 的一维潜编码和作为条件的类别标签(大小为 10 的一维向量)。在 BicyleGAN 中,形状为 (256, 256, 3) 的图像 A 是条件,而从潜编码 zzz 采样的噪声为大小为 8 的一维向量。图(b)pix2pix +噪声 的训练配置,图底部的两个配置由 BicycleGAN 使用:

BicycleGAN

简而言之,BicycleGAN 的主要概念是找到潜编码 zzz 与目标图像 BBB 之间的关系,因此生成器可以在给定不同的 zzz 时学会生成不同的图像 B^\hat BB^。如上图所示,BicycleGAN 通过组合 cVAE-GANcLR-GAN 这两种方法来做到这一点。

2. cVAE-GAN

VAE-GAN 的作者认为,L1 损失并不是衡量图像视觉质量的良好指标。例如,如果图像向右移动几个像素,则人眼看起来可能没有什么不同,但会导致较大的 L1 损失。因此使用 GAN 的判别器来学习目标函数,以判断伪造的图像是否真实,并使用 VAE 作为生成器,生成的图像更清晰。如果忽略上图(c)中的图像 AAA,那就是 VAE-GAN ,由于以 AAA 为条件,其成为 cVAE-GAN 。训练步骤如下:

  1. VAE 将真实图片 BBB 编码为多元高斯分布的潜编码,然后从它们中采样以创建噪声输入,此流程是标准的 VAE 工作流程
  2. 使用图像 AAA 作为条件及从潜编码 zzz 采样的噪声用于生成伪图像B^\hat BB^

训练中的信息流为 B→z→B^B\rightarrow z\rightarrow \hat BBzB^ (图(c) 中的实线箭头),总的损失函数由三个损失组成:

  • LGANVAE\mathcal L_{GAN}^{VAE}LGANVAE:对抗损失
  • L1VAE\mathcal L_1^{VAE}L1VAEL1 重建损失
  • LKL\mathcal L_{KL}LKLKL 散度损失

3. cLR-GAN

cVAE-GAN 中,对真实图像 BBB 进行编码,以提供潜编码的真实样本并从中进行采样。但是, cLR-GAN 的处理方式有所不同,其首先使用生成器从随机噪声中生成虚假图像 B^\hat BB^ ,然后对伪图像 B^\hat BB^ 进行编码,最后计算其与输入随机噪声差异。
前向计算步骤如下:

  1. 首先,类似于 cGAN ,随机产生一些噪声,然后串联图像 AAA 以生成虚假图像 B^\hat BB^
  2. 之后,使用来自 VAE-GAN 的同一编码器将虚假图像 B^\hat BB^ 编码为潜编码
  3. 最后,从编码的潜编码中采样 z^\hat zz^ ,并用输入噪声 zzz 计算损失

数据流为 z−>B^−>z^z-> \hat B -> \hat zz>B^>z^ ( 图(d) 中的实线箭头),有两个损失:

  1. LGAN\mathcal L_{GAN}LGAN:对抗损失
  2. L1latent\mathcal L_1^{latent}L1latent:噪声 N(z)N(z)N(z) 与潜在编码之间的 L1 损失

通过组合这两个数据流,在输出和潜空间之间得到了一个双映射循环。BicycleGAN 中的 bi 来自双映射(双向单射),这是一个数学术语,简单来说其表示一对一映射,并且是可逆的。在这种情况下,BicycleGAN 将输出映射到潜空间,并且类似地从潜空间映射到输出。总损失如下:
lossBicycle=LGANVAE+LGAN+λL1VAE+λlatentL1latent+λKLloss_{Bicycle}=\mathcal L_{GAN}^{VAE}+\mathcal L_{GAN}+λ\mathcal L_1^{VAE}+λ_{latent}\mathcal L_1^{latent}+λ_{KL} lossBicycle=LGANVAE+LGAN+λL1VAE+λlatentL1latent+λKL
在默认配置中,λ=10λ = 10λ=10λlatent=0.5λ_{latent} = 0.5λlatent=0.5λlatent=0.01λ_{latent} = 0.01λlatent=0.01
我们已经了解了 BicycleGAN 架构和损失函数,接下来使用 TensorFlow 实现 BicycleGAN

4. 实现 BicycleGAN

BicycleGAN 中有三种类型的网络-生成器,判别器和编码器。随着输入图像尺寸的增大,编码器将包含更多的卷积核和更深的网络层。原始的 BicycleGAN 使用两个 PatchGAN,其有效感受野分别为 70x70140x140
为简单起见,我们将使用一个 70x70PatchGAN。为 cVAE-GANcLR-GAN 使用单独的判别器可以提高图像质量,这意味着我们总共有四个网络-生成器,编码器和两个判别器。

4.1 将潜编码插入生成器

将潜编码插入到生成器中有两种方法,一种与输入图像进行拼接,另一种将其插入到生成器的下采样路径中的其他层中,如下图所示,实验表明前者效果更好。

插入潜编码

有多种方法可以将不同形状的输入和条件结合起来。BicycleGAN 的方法是多次重复潜编码并与输入图像连接。
BicycleGAN 中,潜编码长度为 8。我们从噪声分布中提取了 8 个样本,每个样本重复 H×W 次以形成形状为 (H, W, 8) 的张量。换句话说,在 8 个通道中,其 (H, W) 特征图都是相同的。以下是 build_generator() 的代码片段,显示了潜编码的拼接和连接:

input_image = layers.Input(shape=image_shape, name='input_image')
input_z = layers.Input(shape=(self.z_dim,), name='z')
z = layers.Reshape((1,1, self.z_dim))(input_z)
z_tiles = tf.tile(z, [self.batch_size, self.input_shape[0], self.input_shape[1], self.z_dim])
x = layers.Concatenate()([input_image, z_tiles])

接下来,创建两个模型,即 cVAE-GANcLR-GAN,以合并网络并创建前向信息流。

4.2 cVAE-GAN

创建 cVAE-GAN 模型的代码,实现前向计算:

images_A_1 = layers.Input(shape=input_shape, name='ImageA_1')
images_B_1 = layers.Input(shape=input_shape, name='ImageB_1')
z_encode, self.mean_encode, self.logvar_encode = self.encoder(images_B_1)
fake_B_encode = self.generator([images_A_1, z_encode])
encode_fake = self.discriminator_1(fake_B_encode)
encode_real = self.discriminator_1(images_B_1)
kl_loss =  - 0.5 * tf.reduce_sum(1 + self.logvar_encode - \tf.square(self.mean_encode) - \
tf.exp(self.logvar_encode))
self.cvae_gan = Model(inputs=[images_A_1, images_B_1],outputs=[encode_real, encode_fake, fake_B_encode, kl_loss])

我们在模型中使用了 KL 散度损失。由于可以直接根据均值和对数方差来计算 kl_loss,而无需从训练步骤中传入外部标签,因此此方法更加简单有效。

4.3 cLR-GAN

接下来,实现 cLR-GAN

images_A_2 = layers.Input(shape=input_shape, name='ImageA_2')
images_B_2 = layers.Input(shape=input_shape, name='ImageB_2')
z_random = layers.Input(shape=(self.z_dim,), name='z')
fake_B_random = self.generator([images_A_2, z_random])
_, mean_random, _ = self.encoder(fake_B_random)
random_fake = self.discriminator_2(fake_B_random)
random_real = self.discriminator_2(images_B_2)      
self.clr_gan = Model(inputs=[images_A_2, images_B_2,   z_random],outputs=[random_real, random_fake, mean_random])

完成模型定义后,实现训练步骤。

4.4 训练步骤

两种模型一起训练,但是具有不同的图像对。因此,在每个训练步骤中,我们两次获取数据,每个模型一次。一个方法是通过创建数据管道来完成的,该数据管道将两次加载数据:

images_A_1, images_B_1 = next(data_generator)
images_A_2, images_B_2 = next(data_generator)
self.train_step(images_A_1, images_B_1, images_A_2, images_B_2)

我们可以使用两种不同的方法来执行训练步骤。一种是使用优化器和损失函数定义和编译 Keras 模型,然后调用 train_on_batch() 来执行训练步骤。这在定义明确的模型上效果很好。此外,我们也可以使用 tf.GradientTape 来更好地控制梯度和更新。BicycleGAN 有两个模型,它们共享一个生成器和一个编码器,但是我们使用损失函数的不同组合来更新它们,这使 train_on_batch 方法在不修改原始设置的情况下不可行。因此,我们将使用 tf.GradientTape 将这两个模型的生成器和判别器组合为一个训练步骤。

  1. 执行前向传递并收集两个模型的输出:
    def train_step(self, images_A_1, images_B_1, images_A_2, images_B_2):z = tf.random.normal((self.batch_size, self.z_dim))    real_labels = tf.ones((self.batch_size, self.patch_size, self.patch_size, 1))fake_labels = tf.zeros((self.batch_size, self.patch_size, self.patch_size, 1))with tf.GradientTape() as tape_e, tf.GradientTape() as tape_g, tf.GradientTape() as tape_d1, tf.GradientTape() as tape_d2:encode_real, encode_fake, fake_B_encode, kl_loss = self.cvae_gan([images_A_1,    images_B_1])random_real, random_fake, mean_random = self.clr_gan([images_A_2, images_B_2, z])
    
  2. 接下来,我们反向传播并更新判别器:
    	    self.d1_loss = self.mse(real_labels, encode_real) + self.mse(fake_labels, encode_fake)gradients_d1 = tape_d1.gradient(self.d1_loss, self.discriminator_1.trainable_variables)self.optimizer_d1.apply_gradients(zip(gradients_d1, self.discriminator_1.trainable_variables))self.d2_loss = self.mse(real_labels, random_real) + self.mse(fake_labels, random_fake)gradients_d2 = tape_d2.gradient(self.d2_loss, self.discriminator_2.trainable_variables)self.optimizer_d2.apply_gradients(zip(gradients_d2,  self.discriminator_2.trainable_variables))
    
  3. 然后,我们根据模型的输出计算损失。与 CycleGAN 相似,BicycleGAN 也使用 LSGAN 损失函数,即均方误差:
			self.LAMBDA_IMAGE = 10self.LAMBDA_LATENT = 0.5self.LAMBDA_KL = 0.01# Generator and Encoder lossself.gan_1_loss = self.mse(real_labels, encode_fake)self.gan_2_loss = self.mse(real_labels, random_fake)self.image_loss = self.LAMBDA_IMAGE * self.mae(images_B_1, fake_B_encode)self.kl_loss = self.LAMBDA_KL * kl_lossself.latent_loss = self.LAMBDA_LATENT * self.mae(z, mean_random)
  1. 最后,还有生成器和编码器权重的更新。L1 潜编码损失仅用于更新生成器,而不用于更新编码器。由于针对损失同时优化将导致它们隐藏与潜编码有关的信息,而不学习潜在编码中有意义的模式。因此,需要为生成器和编码器分别计算损失,并相应地更新权重:
            encoder_loss = self.gan_1_loss + self.gan_2_loss + self.image_loss + self.kl_lossgenerator_loss = encoder_loss + self.latent_lossgradients_generator = tape_g.gradient(generator_loss, self.generator.trainable_variables)self.optimizer_generator.apply_gradients(zip(gradients_generator, self.generator.trainable_variables))gradients_encoder = tape_e.gradient(encoder_loss, self.encoder.trainable_variables)self.optimizer_encoder.apply_gradients(zip(gradients_encoder, self.encoder.trainable_variables))

使用鞋子数据集训练 BicycleGAN,以下图像是 BicycleGAN 训练结果的展示示例。第一张图片是线稿,第二个图片是线稿对应的真实图像,右边的四个图片是生成的:
BicyleGAN效果展示BicyleGAN效果展示BicyleGAN效果展示
可以看到,由同一线稿生成的不同图片间的差异主要是颜色。

相关链接

AIGC实战——生成模型简介
AIGC实战——深度学习 (Deep Learning, DL)
AIGC实战——卷积神经网络(Convolutional Neural Network, CNN)
AIGC实战——自编码器(Autoencoder)
AIGC实战——变分自编码器(Variational Autoencoder, VAE)
AIGC实战——使用变分自编码器生成面部图像
AIGC实战——生成对抗网络(Generative Adversarial Network, GAN)
AIGC实战——WGAN(Wasserstein GAN)
AIGC实战——条件生成对抗网络(Conditional Generative Adversarial Net, CGAN)
AIGC实战——CycleGAN详解与实现
AIGC实战——自回归模型(Autoregressive Model)
AIGC实战——改进循环神经网络
AIGC实战——像素卷积神经网络(PixelCNN)
AIGC实战——归一化流模型(Normalizing Flow Model)
AIGC实战——能量模型(Energy-Based Model)
AIGC实战——扩散模型(Diffusion Model)
AIGC实战——GPT(Generative Pre-trained Transformer)
AIGC实战——Transformer模型
AIGC实战——ProGAN(Progressive Growing Generative Adversarial Network)
AIGC实战——StyleGAN(Style-Based Generative Adversarial Network)
AIGC实战——VQ-GAN(Vector Quantized Generative Adversarial Network)
AIGC实战——基于Transformer实现音乐生成
AIGC实战——MuseGAN详解与实现
AIGC实战——多模态模型DALL.E 2
AIGC实战——多模态模型Flamingo
AIGC实战——世界模型(World Model)

http://www.dtcms.com/a/398754.html

相关文章:

  • 基于Element Plus的Vue3远程搜索多选组件实现与优化
  • 网站只做静态页面安全受到影响南昌旅游集团网站建设
  • pom.xml 不在根目录,idea无法识别项目处理方案
  • 网站开发所需硬件昆明微网站搭建
  • 【第25话:路径规划】自动驾驶路径规划概念与理论介绍
  • QT多窗口跳转
  • 栈(Stack)
  • 整体设计 逻辑全链 之8 受控的自然语言-字面拼凑:正则表达式 之2
  • 攻防世界-Web-simple_php
  • 【Linux我做主】进程程序替换和exec函数族
  • 清华最新发布 | 大型推理模型的强化学习综述
  • C++异常处理的根本缺陷:隐式传播的性能陷阱与控制流断裂
  • 【东枫】USRP X310 母版 PCB
  • 山东锦华建设集团有限公司网站嘉瑞建设有限公司网站
  • 食品品牌网站策划美容行业培训网站建设
  • Amazon Timestream新用户实时分析:从零到上手完整指南
  • 淘宝联盟个人网站怎么做电商平台入驻
  • 在 Oracle SQL 中实现 `IF-ELSE` 逻辑 SQL 错误 [12704] [72000]: ORA-12704: 字符集不匹配
  • 勒索软件专攻数据库弱点:Oracle 服务器安全防线告急
  • 常用的表空间维护语句
  • MySQL笔记---数据库基础
  • 【数据迁移】:oracle 大数据上线失败复盘:【大表定义变更】不一致导致生产数据灌入失败及解决方案
  • InnoDB一致性读与锁定读全解析
  • Oracle归档及数据库存储空间查询
  • 怎么用wordpress建外贸网站华丽的网站模板
  • 如何在Linux系统里将新添加磁盘进行分区挂载
  • 公司网站案例免费域名建站
  • 抓包解析MCP协议:基于JSON-RPC的MCP host与MCP server的交互
  • 一“网”跨协议,万“设”皆可通!耐达讯自动化Modbus TCP转Profibus ,让控制无界,让能源有道。
  • 江门网站优化公司衡水seo网站建设优化排名