深度卷积对抗网络

深度卷积对抗网络简称DCGAN,这些GAN给你之前使用MNIST数据库构建差不多,但是这次的生成器和辨别器用神经网络构建,有关于DCGAN原始论文请看:https://arxiv.org/pdf/1511.06434.pdf。他的技术性不是特别强,并提供了关于这些东西训练的一些好建议。确保你在构建过程中,阅读它。

我们使用的是“街景门牌号”数据集,下图是一堆的地址图像,收集来自Google街景,他们比MNIST数据集中的图像要复杂,我们有三个颜色通道,红、绿、蓝,而且他们更大,并且图像有更多的细节。其中一些包含多个数字,那么由于这些图像比我们之前使用的,更复杂,我们需要用卷积网络来使生成器和辨别器很好的发挥作用。充分展示深度学习的神奇力量,产生一些非常酷的图像,所以基本来说,你在这里所做的和你之前在其他GAN课程中,所执行操作的唯一区别是更改生成器和辨别器。但是,训练的其余部分,像损失、优化器和输入他们基本上都一样。现在唯一的区别就在于,我们的生成器是一个卷积网络,辨别器也是一个卷积网络

 

SVHN_examples

那么一开始,我们和往常一样导入数据,导入模块

 

 导入数据:

这部分我们加载并提取SVHN数据集。

这个数据集实际上是一个.mat文件,他们通常和Matlab一起使用,但Scipy实际上有一个函数,可以将这些.mat文件,作为Numpy数组导入。那么我么们可以提取这些数组,像平常一样使用他们

这里我们可以看到数据集中的一个小的图像样本

201805271856

上面的图像样本,是我们即将传入辨别器的真实图像,也是生成器要学习重现的东西

 

你应该记得之前,我们的生成器使用一个tanh输入,来创建这些新的图像,以使输出的范围在-1到1之间。因此我们需要重新缩放所有真实图像,是他们在-1到1之间,以便在进入辨别器时匹配。上面就是缩放的代码,包含数据集的一个类,我们可以从batches这里获得取批。我们并不对这个网络进行分类,所以我们实际上不需要使用验证集,这只是你可以用于SVHN数据集的常规数据集的类。

 

网络输入

这是必不可少的。

我们有真实图像的输入,我们直接使用真图的尺寸,32*32*3(本例子的数据,你可以使用任意图像大小)。我只是将它留作一个占位符。

进入生成器本征向量input_z,他和我们之前在MNIST GAN中看到的一样。

 

生成器

这里是不同的地方,我们将在这里实现生成器和生成器的输入噪声向量z,输出也同样是一个tanh层。基本上SVHN图像输出需要匹配的大小,即32*32,但是tanh输出范围在-1到1之间。而且我们还需要匹配这些图像的深度?

我们的SVHN图像有三个颜色通道,那么他们的深度为3,即大小为32*32*3,这意味着我们具有tanh激活的输出层,也必须接受是32*32*3。这里你可以看到DCGAN论文中,使用的生成器示意图。那么(从左到右)我们取z向量,将他投射到一个全链接层,然后重塑这个全链接层,使他的大小为4*4*1024个过滤器(或者说深度),然后使用转置卷积,来减小深度并增加宽度和高度,然后在使用tanh激活。

同样在转置卷积中,使用步幅2,你会注意到这里并没有最大池化层或者类似的东西,没有全链接层。

虽然第一个使用全链接层,但是后面便全部都是卷积层,我们在转置卷积中,使用步幅2,进行所有上采样,需要注意一件事:这里最后一层在DCGAN论文中,它的大小为64*64*3,但我们的图像是32*32*3,所以他跟你应该用的架构不完全相同。但是他大致向你,展示了你应该为生成器构建的架构是什么样的。

dcgan

output是输出的深度,我们使用variable_scope进行重用,你也必须对上面的所有层进行批量归一化,除了最后一层,如果不使用批量归一化层,这个网络就无法发挥作用。典型的处理方式是,先使用转置卷积,然后是批量归一化,最后激活。

我们完成的是一个转置卷积网络。

 

辨别器

这是我们构建辨别器的地方,同样,这与你之前看到的非常相似,我们传入真实的图像,他们是32*32*3的张量,我们让他们通过一些卷积层,最后获得sigmoid输出,我们还要返回logit。用于在sigmoid交叉熵损失函数计算中使用,这跟你之前构建的卷积分类器非常像。你可以从较宽较高的层开始,但深度仅为3。下一个卷积层会更窄一些,但也会更深,像这样将卷积层堆叠起来,卷积层越往后越窄、越深。而最后一层只是一个全连接层,你将它平滑化,所以结尾将是只有一个单元的全连接层,你将它用作sigmoid输出。对于卷积层,我建议第一层以16、32、64个过滤器开始,这是层的深度。然后对于后面的每个层,深度翻倍,而宽度和高度减半。所以基本上你每添加一个新的卷积层,就给深度乘以2,而给宽度和高度除以2 。此外,你还会需要对每一个卷积层使用leaky ReLU激活和批量归一化,要确保你不对第一层使用,批量归一化,其他层都可以。

 

模型损失

 

优化器

 

 

构建模型

这里是一些用于构建模型的代码,这一次我基本上是将损失和优化器放入上面这些函数内,使这个构建过程更容易一些,这是一个叫作 GAN 的类。我们基本上在它里面构建整个模型,我们调用这些函数,构建输入,进行计算,获得损失和优化器。
我们可以用这些来实际训练网络,像这样将它打包在一个对象里,以更容易地传递数据和进行构建。

 

这是用于展示正在生成的图像的一个函数,我们可以在训练过程中用它,查看进展如何。也可以在训练完成后使用它,看看是否要从生成器生成新的图像,我们可以使用此函数实际看到生成的图像。

这个函数很明显是用来训练网络,我们只需传入网络net和数据dataset给它一些超参数,它会帮我们训练数据或训练网络。

 

超参

这里是你设置超参数和实际训练网络的地方,GAN 的训练稍有点复杂,因为它们对超参数非常敏感,人们不断通过各种实验,来找到最佳类型的参数,或者不是最佳的,但至少是有用的超参数。那么接下来发生的是–生成器和辨别器它们在互相玩游戏。而你必须设置超参数,以使生成器和辨别器,不会互相压制。生成器能够生成图像,而辨别器能够区分图像,确定图像是真是假。
但同时 如果辨别器的区分能力太好,生成器就无法学习。
所以你在这里要做的是尝试一些你自己的超参数,或者参阅这里的 DCGAN 论文,看看什么比较有用。我发现他们的参数对此数据库的确非常有效。但不会总是这样,当你在使用不同的数据库时,最好尝试不同的超参数。我发现的一点是,当超参数设置正确时,辨别器损失通常在 0.3 左右。这意味着:辨别器正确区分图像真假的概率为 50%,这基本上正是你想要的 对吧?
因为你想要–你的辨别器– 或你希望生成器能生成看起来逼真的图像。然后对于辨别器,如果它无法确定是真是假,则它正确的概率将是 50%,基本就像掷硬币一样。所以这就是你在设置超参数时的目标。

而且我也从我的生成器损失看到他通常在2或3之类的左右,我是说当辨别器在0.3或者0.3左右时,你可以尝试下面这些超参数。想起个好头或者一次作对,请参阅 DCGAN 论文

 

在他训练时就一边训练一边打印,图像和生成器和辨别器损失。从一堆噪声,到可以学习颜色,到显示一些斑点,到生成类似的数字,21个echop后,可以清晰的看清出数字了,

201806272050

这是生成器和辨别器在训练步长中的损失图,可以看到蓝色时辨别器损失他比较低,大概在0.5左右。

 

201806272051

201806272052

201806272053

上面时我们在训练中从生成器获得的最终图像。产生了一些不错的图像,有些能清晰的看清数字。

你也可以做一些改进,这需要从Ian Goodfellow和其他人的论文中了解。