文章目录

  • 1 导包
  • 2 数据准备
  • 3 定义生成器
  • 4 定义判别器
  • 5 定义损失函数和优化器
  • 6 定义训练批次函数
  • 7 定义可视化训练结果函数
  • 8 定义训练主函数
  • 9 训练
  • 10 结果
  • 11 使用生成器

DCGAN(深度卷积生成对抗网络Deep Convolutional GAN)的论文地址: 论文地址

生成对抗网络系列
【生成对抗网络】GAN入门与代码实现(一)
【生成对抗网络】GAN入门与代码实现(二)
【生成对抗网络】基于DCGAN的二次元人物头像生成(TensorFlow2)
【生成对抗网络】ACGAN的代码实现

1 导包

tensorflow版本为2.6.2

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import numpy as np
import os
import glob # 用于读取
import matplotlib.pyplot as plt
%matplotlib inline

2 数据准备

数据下载地址:kaggle anime-faces数据集,共21551张人物头像,每张图片size为64*64。

image_path = glob.glob(r"../input/anime-faces/data/*.png") # 数据读取

原数据介绍:

This is a dataset consisting of 21551 anime faces scraped from www.getchu.com, which are then cropped using the anime face detection algorithm in https://github.com/nagadomi/lbpcascade_animeface. All images are resized to 64 * 64 for the sake of convenience. Please also cite the two sources when using this dataset.

数据预处理:

def load_preprosess_image(path): # 定义每张图片的处理函数image = tf.io.read_file(path) # 读取路径文件image = tf.image.decode_png(image,channels=3) # 解码png图片,通道为3image = tf.cast(image,tf.float32) # 转换为float类型image = (image/127.5) - 1 # -1至1之间return image
image_ds = tf.data.Dataset.from_tensor_slices(image_path) # 创建Dataset对象
AUTOTUNE = tf.data.experimental.AUTOTUNE # 让TensorFlow自动选择合适的数值,充分利用计算机资源
image_ds = image_ds.map(load_preprosess_image,num_parallel_calls = AUTOTUNE) # 对于每张图片应用load_preprosess_image函数进行处理

设置Batch大小,定义图片总数

BATCH_SIZE = 64
image_count = len(image_path) # 21551
image_ds = image_ds.shuffle(image_count).batch(BATCH_SIZE) # 打乱图片顺序,设置batch大小
image_ds = image_ds.prefetch(AUTOTUNE) # 在GPU进行训练的同时 CPU进行数据预加载,提高训练效率

image_ds为<PrefetchDataset shapes: (None, None, None, 3), types: tf.float32>

其中每个batch的shape为(64, 64, 64, 3)

3 定义生成器

输入为100维的noise,输出维度为(64,64,3)

def generator_model():model = tf.keras.Sequential()model.add(layers.Dense(8*8*256, use_bias=False, input_shape=(100,)))model.add(layers.BatchNormalization())model.add(layers.LeakyReLU())model.add( layers.Reshape((8,8,256)) )  # 输出8*8*256# 反卷积model.add(layers.Conv2DTranspose(128,(5,5),strides=(1,1),padding='same',use_bias='false'))model.add(layers.BatchNormalization())model.add(layers.LeakyReLU())      # 输出8*8*128model.add(layers.Conv2DTranspose(64,(5,5),strides=(2,2),padding='same',use_bias='false'))model.add(layers.BatchNormalization())model.add(layers.LeakyReLU())      # 输出16*16*64model.add(layers.Conv2DTranspose(32,(5,5),strides=(2,2),padding='same',use_bias='false'))model.add(layers.BatchNormalization())model.add(layers.LeakyReLU())      # 输出32*32*32model.add(layers.Conv2DTranspose(3,(5,5),strides=(2,2),padding='same',use_bias=False,activation='tanh'))  # 输出64*64*3return model

4 定义判别器

输入维度(64,64,3),输出1维判定结果

def discriminator_model():# 第一层 不用BatchNormalizationmodel = tf.keras.Sequential()model.add(layers.Conv2D(32,(5,5),strides = (2,2),padding='same',input_shape=(64,64,3))) # 输入为64*64*3model.add(layers.LeakyReLU())model.add(layers.Dropout(0.3)) # 32*32*32model.add(layers.Conv2D(64,(5,5),strides = (2,2),padding='same')) model.add(layers.BatchNormalization())model.add(layers.LeakyReLU())model.add(layers.Dropout(0.3)) # 16*16*64model.add(layers.Conv2D(128,(5,5),strides = (2,2),padding='same')) model.add(layers.BatchNormalization())model.add(layers.LeakyReLU())model.add(layers.Dropout(0.3)) # 8*8*128model.add(layers.Conv2D(256,(5,5),strides = (2,2),padding='same')) model.add(layers.BatchNormalization())model.add(layers.LeakyReLU())   # 4*4*256model.add(layers.GlobalAveragePooling2D())# Global Average Pooling(简称GAP,全局池化层),被认为是可以替代全连接层的一种新技术model.add(layers.Dense(1024))model.add(layers.BatchNormalization())model.add(layers.LeakyReLU())model.add(layers.Dense(1)) return model

为了避免训练震荡和模型的不稳定,生成器的输出层和判别器的输入层不使用BatchNormalization()

5 定义损失函数和优化器

判别器损失:

  • 将判别器中对于真实图像的判别结果与1进行比较,求交叉熵损失
  • 将判别器中对于生成图像的判别结果与0进行比较,求交叉熵损失
  • 两者相加即为判别器损失

生成器损失:

  • 将判别器中对于生成图像结果与0进行比较,求交叉熵损失
cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True) # 因为判别器最后没有使用激活 所以我们添加from_logits=True
# 求判别器损失的函数
def discriminator_loss(real_out,fake_out):real_loss = cross_entropy(tf.ones_like(real_out),real_out) # 真实图片的输出与1比较fake_loss = cross_entropy(tf.zeros_like(fake_out),fake_out) # 生成图片的输出与0比较return real_loss + fake_loss
# 求生成器损失的函数
def generator_loss(fake_out):fake_loss = cross_entropy(tf.ones_like(fake_out),fake_out)return fake_loss

优化器:

# 优化器
generator_opt = keras.optimizers.Adam(1e-5)
discriminator_opt = keras.optimizers.Adam(1e-5)

定义损失评价指标,用于损失绘图

epoch_loss_avg_gen = tf.keras.metrics.Mean('g_loss')
epoch_loss_avg_disc = tf.keras.metrics.Mean('d_loss')
g_loss_results = []
d_loss_results = []

6 定义训练批次函数

EPOCHS = 500
noise_dim = 100 # 随机数的维度num_example_to_generate = 6 # 用于绘图过程中生成图片的数量seed = tf.random.normal([num_example_to_generate,noise_dim]) # 生成6个长度为100的随机向量

获取生成器模型和判别器模型

generator = generator_model() # 获取生成器模型
discriminator = discriminator_model() # 获取判别器模型

利用自动求导机制定义模型参数更新函数

# 接收一个批次的图片,对其进行训练
@tf.function
def train_step(images):noise = tf.random.normal([BATCH_SIZE,noise_dim]) # 生成BTATH_SIZE个长度为100的随机向量# images 是真实图片的输入# noise 是噪声输入with tf.GradientTape() as gen_tape,tf.GradientTape() as disc_tape:real_out = discriminator(images,training = True)gen_image = generator(noise,training = True)fake_out = discriminator(gen_image,training = True)# 通过损失函数计算损失gen_loss = generator_loss(fake_out)disc_loss = discriminator_loss(real_out,fake_out)# 自动计算机损失函数关于自变量(模型参数)的梯度    gradient_gen = gen_tape.gradient(gen_loss,generator.trainable_variables)gradient_disc = disc_tape.gradient(disc_loss,discriminator.trainable_variables)# 根据梯度更新参数generator_opt.apply_gradients(zip(gradient_gen,generator.trainable_variables))discriminator_opt.apply_gradients(zip(gradient_disc,discriminator.trainable_variables))return gen_loss, disc_loss

7 定义可视化训练结果函数

使用固定的一个noise再训练的过程中来测试生成器生成的人物头像效果

# 画图函数
def generate_plot_image(gen_model,test_noise):pre_image = gen_model(test_noise,training = False)print(pre_image.shape)fig = plt.figure(figsize=(16,3)) # figsize:指定figure的宽和高,单位为英寸for i in range(pre_image.shape[0]):   # pre_image的shape的第一个维度就是个数,这里是6plt.subplot(1,6,i+1) # 几行几列的 第i+1个图片(从1开始)plt.imshow((pre_image[i,:,:,:] + 1)/2) # 加1除2: 将生成的-1~1的图片弄到0-1之间,plt.axis('off') # 不要坐标plt.show()

8 定义训练主函数

在每个epoch中循环取出一个batch大小真实图像进行生成器与判别器训练,同时记录每次的loss信息

def train(dataset,epochs):  for epoch in range(1,epochs+1): # 总共训练epochs次print("\n epoch:",epoch)for image_batch in dataset: # 从数据集中遍历所有batchgen_loss, disc_loss = train_step(image_batch)# 训练一个batchepoch_loss_avg_gen(gen_loss)epoch_loss_avg_disc(disc_loss)print(".",end="")g_loss_results.append(epoch_loss_avg_gen.result())d_loss_results.append(epoch_loss_avg_disc.result())epoch_loss_avg_gen.reset_states()epoch_loss_avg_disc.reset_states()if epoch%10 == 0: # 每10个epoch绘图一次generate_plot_image(generator,seed) # 绘图,用随机数seed在生成器generate_plot_image(generator,seed) # 绘图,用随机数seed在生成器

9 训练

train(image_ds,EPOCHS)
# 绘制loss变化图
plt.plot(range(1, len(g_loss_results)+1), g_loss_results, label='g_loss')
plt.plot(range(1, len(d_loss_results)+1), d_loss_results, label='d_loss')
plt.legend()

10 结果

epoch 10:

epoch 20:

epoch 30:

epoch 100:

epoch 200:


epoch 500:

11 使用生成器

seed2 = tf.random.normal([30,noise_dim]) # 生成30个长度为100的随机向量
a = seed2.numpy()
pre = generator.predict(a)
print(pre[0].shape) # 查看输出的第一个图片的shape为(64, 64, 3)
plt.imshow((pre[0] + 1)/2, cmap = 'gray')


如上是600epoch效果,还是有些糊啦

代码下载(GitHub):DCGAN-anime-faces

【生成对抗网络】基于DCGAN的二次元人物头像生成(TensorFlow2)相关推荐

  1. 深度学习100例-生成对抗网络(DCGAN)手写数字生成 | 第19天

    文章目录 深度卷积生成对抗网络(DCGAN) 一.前言 二.什么是生成对抗网络? 1. 设置GPU 2. 加载和准备数据集 三.创建模型 1. 生成器 2. 判别器 四.定义损失函数和优化器 1. 判 ...

  2. Pytorch 使用GAN实现二次元人物头像生成 保姆级教程(数据集+实现代码+数学原理)

    Pytorch 使用DCGAN实现二次元人物头像生成(实现代码+公式推导) GAN介绍   算法主体   推导证明(之后将补全完整过程)   随机梯度下降训练D,G   DCGAN介绍及相关原理 Py ...

  3. 深度卷积生成对抗网络(DCGAN)原理与实现(采用Tensorflow2.x)

    深度卷积生成对抗网络(DCGAN)原理与实现(采用Tensorflow2.x) GAN直观理解 DCGAN网络结构 GAN训练目标 DCGAN实现 数据加载 网络 鉴别网络 生成网络 网络训练 定义损 ...

  4. 生成对抗网络简介,深度卷积生成对抗网络(DCGAN)简介

    本博客是个人学习的笔记,讲述的是生成对抗网络(generate adversarial network ) 的一种架构:深度生成对抗网络 的简单介绍,下一节将使用 tensorflow 搭建 DCGA ...

  5. 基于DCGAN的动漫头像生成

    基于DCGAN的动漫头像生成 数据 数据集:动漫图库爬虫获得,经过数据清洗,裁剪得到动漫头像.分辨率为3 * 96 * 96,共5万多张动漫头像的图片,从知乎用户何之源处下载. 生成器:输入为随机噪声 ...

  6. 使用残差网络与wgan制作二次元人物头像

    使用残差网络与wgan制作二次元人物头像 ref:https://blog.csdn.net/qq_41103479/article/details/119352714 我复现的项目链接:https: ...

  7. 深度学习100例-生成对抗网络(DCGAN)生成动漫人物 | 第20天

    文章目录 一.前言 二.什么是生成对抗网络? 1. 设置GPU 2. 加载和准备数据集 三.创建模型 1. 生成器 2. 判别器 四.定义损失函数和优化器 1. 判别器损失 2. 生成器损失 五.保存 ...

  8. 生成对抗网络gan原理_必读!TOP10生成对抗网络GAN论文(附链接)

    来源:新智元 本文约2200字,建议阅读7分钟. 本文所选论文提供了一个易读的对GAN的介绍,帮助你理解GAN技术的基础. [ 导读 ]生成对抗网络 (GAN) 是深度学习中最有趣.最受欢迎的应用之一 ...

  9. 生成对抗网络的损失函数如何设计_理解生成对抗网络,一步一步推理得到GANs(一)...

    作者:Joseph Rocca 编译:ronghuaiyang 导读 GANs在2014年提出,然后就在图像生成领域取得了巨大的成功,但是其背后的原理却不是那么好理解,这篇文章带你从最基础的随机变量开 ...

最新文章

  1. 关于目标检测你必须知道的……
  2. java map key是否存在_java中如何判断map集合中是否存在key
  3. Cocos2d—声音API
  4. 一、NLTK工具包使用
  5. 让预训练模型学习知识:使用多学习器增强知识建模能力
  6. 2018数据技术嘉年华-金融峰会·重庆站即将起航!
  7. Linux常用到的指令汇总
  8. java.lang.NumberFormatException: For input string: 0.7
  9. Unity3D 场景编辑器扩展学习笔记-Editor
  10. PowerDesigner 生成数据字典
  11. 各种材料衣服的保养 全面知识分享
  12. 逻辑回归(Logistic Regression)详解
  13. oracle打印awr报告,oracle生成awr报告
  14. Activiti实现流程定义的控制与修改
  15. 实现div半透明效果
  16. IP 地址以 0 开头会降维成八进制
  17. Mac运行exe的几种方法,欢迎补充!
  18. 5G 与 MEC 边缘计算
  19. 奇瑞新能源的小车为何备受市场青睐?鲍思语这样解释
  20. 计算机毕业设计Java企业员工考勤系统的设计与实现(源码+系统+mysql数据库+lw文档)

热门文章

  1. 机器学习 K-均值聚类算法(K-Means)
  2. 划片机在测高过程中发生异常如何自查
  3. 【学习笔记】医学图像文件存储的格式及Python中的读取方式
  4. java cst gmt_技术分享:CST和GMT时间的区别
  5. 《30岁前别结婚》读后感
  6. RFID/NFC双标签产品防伪溯源方案
  7. 【SIXUN】思迅软件软锁更换硬锁
  8. 如何结合 Scrum 和 Kanban
  9. 程序员如何进化成架构师?
  10. springboot使用qq邮箱进行注册登录