深度卷积生成对抗网络DCGAN之实现动漫头像的生成(基于keras Tensorflow2.0实现)

本文介绍了DCGAN(深度卷积生成对抗网络)的基本原理,强调了卷积和反卷积操作在解决原始GAN训练问题中的作用。通过在Keras和Tensorflow2.0上实现DCGAN,生成动漫头像。讨论了数据预处理、生成器和判别器的构建,并提供了训练策略和代码实例。文章还提及了2020年8月13日的补充,包括针对模型改进的建议。
摘要由CSDN通过智能技术生成

DCGAN简介

原始GAN在图片生成方面具有一定的缺陷:存在训练不稳定,训练过程中梯度易消失等一系列问题。

而DCGAN(Deep Convolutional Generative Adeversarial Networks)深度卷积生成对抗网络,最主要是在原始GAN的基础上加入了卷积和反卷积(上采样)的操作,而CNN卷积神经网络在处理和提取图片特征的工作中具有明显的先天优势,所以DCGAN能很大程度的提升我们生成图片的质量。

反卷积(上采样upsampling2D)

DCGAN在生成器G中加入上采样操作,对随机噪声先赋予深度后,进行不断的上采样,缩短深度,增大图片的宽度和高度,使得最后的输出与真实图片大小一致。
在这里插入图片描述

数据集

数据集来自Kaggle的tagged-anime-illustrations数据集
共包含70171个96×96的动漫头像
在这里插入图片描述
话不多说直接开冲
在这里插入图片描述

代码实战

代码整体框架和训练思路与GAN一致,变化的是生成器G和判别器D的模型构建部分。

数据导入和预处理

创建大小为(图片数量,64,64,3)的张量,将文件夹中的图片导入,依次将原始图片大小转为(64,64)以减小内存,然后进行[-1,1]上的数据归一化。

def load_image(filename):
    imgs = os.listdir(filename)
    x_train = np.empty((imgs.__len__(), 64, 64, 3), dtype='float32')

    for i in range(len(imgs)):
        img = Image.open(filename + imgs[i])
        img = img.resize((64,64))
        img_arr = np.asarray(img, dtype='float32')
        x_train[i, :, :, :] = img_arr/127.5 - 1.

    return x_train

生成器G

具体的模型结构可以看代码,这里就显示一下数据的变化吧

输入 (batch,100,1)
第一层reshape后输出 (batch,8,8,256)
第二层卷积输出 (batch,16,16,128)
第三层卷积输出 (batch,32,32,64)
第四层卷积输出 (batch,64,64,3)

这里说明一下:输出图片高度宽度可以自行根据网络结构进行调整

def build_generator(self):
    model = Sequential()
    model.add(Dense(256 * 8 * 8, activation='relu', input_dim=self.latent_dim))  # 输入维度为100
    model.add(Reshape((8, 8, 256)))
    model.add(UpSampling2D())
    model.add(Conv2D(128, kernel_size=5, padding='same'))
    model.add(BatchNormalization(momentum=0.8))
    model.add(Activation("relu"))
    model.add(UpSampling2D())
    model.add(Conv2D(64, kernel_size=5, padding="same"))
    model.add(BatchNormalization(momentum=0.8))
    model.add(Activation("relu"))
    model.add(UpSampling2D())
    model.add(Conv2D(3, kernel_size=5, padding="same"))
    model.add(Activation("tanh"))
    model.summary()  # 打印网络参数
    noise = Input(shape=(self.latent_dim,))
    img = model(noise)

    return Model(noise, img)

判别器D

判别器输出层之前采用GlobalAveragePooling(全局池化),这里简单提一下。
GlobalAveragePooling2D:相比于平均池化(在特征图上以窗口的形式滑动,去窗口内的平均值为采样值),全局平均池化不再以窗口滑动的形式取平均值,而是直接针对特征图取平均值,即每个特征图输出一个值。
通过这种方式,每个特征图都与分类概率直接联系起来,替代了全连接层的功能,并且不产生额外的训练参数,减小了过拟合的可能,但是会导致网络收敛速度变慢。

输入 (batch,100,1)
第一层卷积输出 (batch,64,64,3)
第二层卷积输出 (batch,32,32,64)
第三层卷积输出 (batch,16,16,128)
第四层卷积输出 (batch,8,8,256)
全局平均池化后输出 (batch,256)
输出 (batch,1)
def build_discriminator(self):
    model = Sequential()
    dropout = 0.5
    model.add(Conv2D(64, kernel_size=5, strides=2, input_shape=self.img_shape, padding="same"))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dropout(dropout))
    model.add(Conv2D(128, kernel_size=5, strides=2, padding="same"))
    model.add(BatchNormalization(momentum=0.8))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dropout(dropout))
    model.add(Conv2D(256, kernel_size=5, strides=2, padding="same"))
    model.add(BatchNormalization(momentum=0.8))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dropout(dropout))
    model.add(GlobalAveragePooling2D())
    model.add(Dense(1, activation='sigmoid'))
    model.summary()
    img = Input(shape=self.img_shape)
    validity = model(img)

    return Model(img, validity)

训练模块

训练过程是GAN的重要思想,DCGAN训练模式与GAN相同,下面我们着重细致的讲解一下GAN是如何训练的吧。
将数据归一化和创建好真假标签后,我们开始进行每次epoch的训练
1. 首先对判别器进行训练:
这时候输入值有2种:

一是随机噪声输入生成器产生的假图片和标签0(第一次epoch时,生成器中可训练参数只是初始化的参数值);

二是真正的图片和标签1。对这两种输入值分别经过二元交叉熵函数(binary crossentropy)计算损失值求出d_loss_real和d_loss_fake,最终判别器D的损失值为二者的平均值d_loss = 0.5 * d_loss_real + 0.5 * d_loss_fake

2. 然后训练生成器:
训练生成器的时候,停止对判别器的训练,设置self.discriminator.trainable=False,为生成器输入随机噪声,将生成器产生的图片打上真实值标签1送入在这次epoch中已经训练好的判别器中,继续通过二元交叉熵函数(binary crossentropy)做loss进行生成器的训练,这样的话生成器就会向着真实值靠近。

训练完每次epoch后生成器性能就会增强,然后回到我们的第一步继续训练判别器,再训练生成器,在这样不断地相互博弈和促进下,最终生成器会达到以假乱真的效果。

def train(self, epochs, batch_size=128, save_interval=50):
  # 载入数据
  filename = "E:/数据集/faces/"
  X_train = load_image(filename)

  # Adversarial ground truths
  valid = np
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值