用CNN实现深度生成对抗网络GAN

GAN

生成对抗网络(Generative Adversarial Network,GAN)是近几年很热门的一种深度学习神经网络模型,是目前在复杂分布上进行无监督学习最前沿的模型之一,这个概念由Ian Goodfellow和Yoshua Bengio等人在2014年提出,GAN的核心思想源自博弈论,它通过构造生成器(Generator)和判别器(Discriminator)在训练过程中互相博弈学习,最终得到理想的结果。其中生成器的目的在于生成虚假的样本分布,判别器的目的在于判别出输入的样本是否真实。由于GAN模型“博弈”的这一特点,它已经开始被应用到语音和语言处理、电脑病毒监测、棋类比赛程序等问题的研究当中。另外,GAN最常用的领域还是图像处理和计算机视觉,进行图像生成,构成各种逼真的室内外场景。

GAN的基本模型

avatar

CNN实现GAN

GAN提出的是一种对抗模型的思想,而要实现它,目前流行的是使用感知器或者多层神经网络。而用CNN来实现,可以大大解决GAN难以训练和不够稳定的问题,并且可以提高生成样本的质量、收敛速度,以及拓展维度。
CNN实现的改进:

  • 去掉了G和D中的池化层(pooling layer),并用微步幅卷积替代,能够分别使得G和D的下采样和上采样效率更高。
  • 在G和D中使用批量规范化(Batch Normalization),通过将输入的每个样本单元标准化为0均值和单位方差来稳定学习,这有助于处理初始化不良导致的训练问题,也有助于梯度流向更深的网络层。
  • 去掉最后一层卷积层后面的全连接层(fully layer),将生成器和判别器直接相连,能够有效提高模型收敛速率。
  • 生成器中除了输出层采用Tanh激活函数,其余所有层都采用ReLU激活函数。
  • 判别器中所有层都采用Leaky ReLU激活函数。

模型设计

生成器模型

生成器的网络由4层卷积层构成

  • 第1层:卷积核大小为5”×” 5,步长2,“same”填充,深度512,输出样本尺寸8”×” 8,生成函数ReLU
  • 第2层:卷积核大小为5”×” 5,步长2,“same”填充,深度256,输出样本尺寸16”×” 16,生成函数ReLU
  • 第3层:卷积核大小为5”×” 5,步长2,“same”填充,深度128,输出样本尺寸32”×” 32,生成函数ReLU
  • 第4层:卷积核大小为5”×” 5,步长2,“same”填充,深度3,输出样本尺寸64”×” 64,生成函数Tanh

判别器模型

判别器的4层卷积层具体如下:

  • 第1层:卷积核大小为5”×” 5,步长2,“same”填充,深度64,输出样本尺寸32”×” 32,生成函数Leaky ReLU。
  • 第2层:卷积核大小为5”×” 5,步长2,“same”填充,深度128,输出样本尺寸16”×” 16,生成函数Leaky ReLU。
  • 第3层:卷积核大小为5”×” 5,步长2,“same”填充,深度256,输出样本尺寸8”×” 8,生成函数Leaky ReLU。
  • 第4层:卷积核大小为5”×” 5,步长2,“same”填充,深度512,输出样本尺寸4”×” 4,生成函数Sigmoid。

构建模型

  • 构建生成器模型

    def generator(self, z):
    self.z_, self.h0_w, self.h0_b = linear(z, self.gf_dim84*4,

                                         'g_h0_lin', with_w=True)
    

    self.h0 = tf.reshape(self.z_, [-1, 4, 4, self.gf_dim * 8])
    h0 = tf.nn.relu(self.g_bn0(self.h0))

//第1层微步幅卷积层
self.h1, self.h1_w, self.h1_b = conv2d_transpose(h0,[self.batch_size, 8, 8, self.gf_dim*4], name=’g_h1’, with_w=True)
h1 = tf.nn.relu(self.g_bn1(self.h1))

//第2层微步幅卷积层
h2, self.h2_w, self.h2_b = conv2d_transpose(h1,
[self.batch_size, 16, 16, self.gf_dim*2], name=’g_h2’, with_w=True)
h2 = tf.nn.relu(self.g_bn2(h2))

//第3层微步幅卷积层
h3, self.h3_w, self.h3_b = conv2d_transpose(h2,
[self.batch_size, 32, 32, self.gf_dim*1], name=’g_h3’, with_w=True)
h3 = tf.nn.relu(self.g_bn3(h3))

//第4层微步幅卷积层,4层微步幅卷积后,矩阵维度变为(64, 64, 3)
h4, self.h4_w, self.h4_b = conv2d_transpose(h3,
[self.batch_size, 64, 64, 3], name=’g_h4’, with_w=True)
return tf.nn.tanh(h4)

  • 构建判别器模型

    def discriminator(self, image, reuse=False):
    //第1层卷积
    h0 = lrelu(conv2d(image, self.df_dim, name=’d_h0_conv’))

//第2层卷积
h1 = lrelu(self.d_bn1(conv2d(h0, self.df_dim*2, name=’d_h1_conv’)))

//第3层卷积
h2 = lrelu(self.d_bn2(conv2d(h1, self.df_dim*4, name=’d_h2_conv’)))

//第4层卷积
h3 = lrelu(self.d_bn3(conv2d(h2, self.df_dim*8, name=’d_h3_conv’)))
h4 = linear(tf.reshape(h3, [-1, 8192]), 1, ‘d_h3_lin’)
return tf.nn.sigmoid(h4), h4

  • 构建优化器

    //判别器优化器,最小化损失函数
    d_optim = tf.train.AdamOptimizer(config.learning_rate, beta1=config.beta1) \
                  .minimize(self.d_loss, var_list=self.d_vars)
    
    //判别器优化器,最小化损失函数
    g_optim = tf.train.AdamOptimizer(config.learning_rate, beta1=config.beta1) \
                  .minimize(self.g_loss, var_list=self.g_vars)