本文主要解释pix2pix和cycleGAN背后的想法和概念,并列举一些相关的文章。
Christopher Hesse 博客: tensorflow实现的图像到图像的翻译转换
《Image-to-Image Translation in Tensorflow — Affine Layer》
Olga Liakhovich 博客:使用CycleGAN学习图像到图像的翻译转换
《Learning Image to Image Translation with CycleGANs》
Pix2Pix
pix2pix使用条件生成对抗网络(cGAN)来学习从输入图像到输出图像的映射。
数据集的一个例子是输入图像是黑白图像,目标图像是图像的彩色版本。在这种情况下,生成器generator正在尝试学习如何着色黑白图像。鉴别器discriminator正在查看生成器generator的着色尝试,并试图了解生成器generator提供的着色与数据集中提供的真彩色目标图像之间的区别。
生成器generator的结构称为“编码器 - 解码器”,在pix2pix中,编码器 - 解码器或多或少看起来像这样:
这些卷可以让您了解它们旁边的张量tensor 尺寸的形状。此示例中的输入是256x256图像,具有3个颜色通道channels(红色,绿色和蓝色,均等于黑白图像),输出相同。
生成器generator接受一些输入并试图通过一系列编码器(卷积convolution +激活函数activation function)将其减少为更小的表示。我们的想法是,通过以这种方式压缩它,我们希望在最终编码层之后具有更高级别的数据表示。解码层执行相反的操作(解卷积deconvolution +激活函数activation function)并反转编码器层的操作。
为了提高论文中图像到图像变换的性能,作者使用了“U-Net”而不是encoder-decoder。这是相同的事情,但是通过“跳过连接”将编码器层直接连接到解码器层:
跳过连接为网络提供了绕过编码/解码部分的选项,如果它没有用途的话。
这些图略有简化。例如,网络的第一层和最后一层没有batch norm layer,中间的几层有dropout单元。
鉴别器 Discriminator
Discriminator的工作是选两个图像,一个输入图像和一个未知图像(它将是来自生成器Generator的目标或输出图像),并决定第二个图像是否是由生成器Generator产生的。
该结构看起来很像生成器generator的编码器encoder部分,但工作方式略有不同。输出是30x30图像,其中每个像素值(0到1)表示未知图像的相应部分的可信度。在pix2pix实现中,来自该30x30图像的每个像素对应于输入图像的70x70 patch的可信度(patch 重叠overlap很多,因为输入图像是256x256)。该架构称为“PatchGAN”。
训练 Train
为了训练这个网络,有两个步骤:训练鉴别器Discriminator和训练生成器Generator。
为了训练鉴别器discriminator,首先生成器generator生成输出图像。鉴别器discriminator查看输入/目标对和输入/输出对,并猜测它们看起来的真实程度。然后,基于输入/输出对和输入/目标对的分类误差来调整鉴别器discriminator的权重。
然后根据鉴别器discriminator的输出以及输出和目标图像之间的差异调整生成器generator的权重。
CycleGANs
虽然PIX2PIX可以产生真正神奇的结果,但挑战在于训练数据。您想要学习翻译的两个图像空间需要预先格式化为一个X / Y图像,该图像保存两个紧密相关的图像。根据您尝试在两种图像类型之间进行转换的两种图像类型(例如,如果两个图像配置文件之间没有一对一的匹配),这可能是耗时的,不可行的,甚至是不可能的。这就是CycleGAN的用武之地。
CycleGAN背后的关键思想是它们可以建立在PIX2PIX架构的强大功能之上,但允许您将模型指向两个离散的,不成对的图像集合。例如,一组图像,组X,将充满阳光海滩照片,而组Y将是阴云密布海滩照片的集合。CycleGAN模型可以学习在这两种美学之间转换图像,而无需将紧密相关的匹配合并到一个X / Y训练图像中。
CycleGAN能够在没有明确的X / Y训练图像的情况下学习如此出色的翻译的方式涉及引入完整转换循环full translation cycle 的想法以确定整个转换系统的好坏,从而同时改进两个生成器Generators。
这种方法是CycleGAN为图像到图像翻译带来的聪明力量,以及它如何在非配对图像样式中实现更好的翻译。
最初的CycleGANs论文 “ “Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks”(使用周期一致的对抗网络进行不成对的图像到图像的翻译)由Jun-Yan Zhu等人发表。
Loss Functions 损失函数
CycleGAN的功能在于它们如何设置Loss函数,并将full cycle loss用作额外的优化目标。
作为复习:我们正在处理2个生成器Generators和2个鉴别器Discriminators。
Generator Loss 生成器损失
让我们从Generator的loss函数开始,它由两部分组成。
第1部分:如果伪造的(Generator生成的)图像非常好以至于鉴别器无法将其与真实图像区分开来,则生成器Generator是成功的。换句话说,鉴别器的伪图像输出应尽可能接近1。在TensorFlow术语中,生成器Generator希望最小化:
g_loss_G_disc = tf.reduce_mean((discY_fake - tf.ones_like(discY_fake))** 2) g_loss_F_dicr = tf.reduce_mean((discX_fake - tf.ones_like(discX_fake))** 2)
注意:上面的**符号是Python中的幂运算符。
第2部分:我们需要捕获循环损失cyclic loss:当我们使用另一个生成器generator从一个生成器generator返回到原始图像空间时,应该最小化原始图像(我们开始循环的位置)和循环图像之间的差异。
g_loss_G_cycle = tf.reduce_mean(tf.abs(real_X - genF_back))+ tf.reduce_mean(tf.abs(real_Y - genG_back)) g_loss_F_cycle = tf.reduce_mean(tf.abs(real_X - genF_back))+ tf.reduce_mean(tf .abs(real_Y - genG_back))
最后,生成器Generator的损失是这两个量的总和:
g_loss_G = g_loss_G_disc + g_loss_G_cycle
因为循环损失cyclic loss是如此重要,我们希望增加其效果。我们为这个乘数使用了L1_lambda常数(在论文中使用了值10)。
现在,生成器Generator的loss的最终结果如下:
g_loss_G = g_loss_G_disc + L1_lambda * g_loss_G_cycle g_loss_F = g_loss_F_disc + L1_lambda * g_loss_F_cycle
Discriminator Loss 鉴别器损失
Discriminator有两个抉择:
- 真实图像应标记为真实(建议应尽可能接近1)
- 鉴别器discriminator应该能够识别生成的图像,从而为假图像预测0。
DY_loss_real = tf.reduce_mean((DY - tf.ones_like(DY))** 2) DY_loss_fake = tf.reduce_mean((DY_fake_sample - tf.zeros_like(DY_fake_sample))** 2) DY_loss =(DY_loss_real + DY_loss_fake)/ 2 DX_loss_real = tf.reduce_mean((DX - tf.ones_like(DX))** 2) DX_loss_fake = tf.reduce_mean((DX_fake_sample - tf.zeros_like(DX_fake_sample))** 2) DX_loss =(DX_loss_real + DX_loss_fake)/ 2