【生成对抗网络】基于DCGAN的二次元人物头像生成(TensorFlow2)
文章目录
- 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)相关推荐
- 深度学习100例-生成对抗网络(DCGAN)手写数字生成 | 第19天
文章目录 深度卷积生成对抗网络(DCGAN) 一.前言 二.什么是生成对抗网络? 1. 设置GPU 2. 加载和准备数据集 三.创建模型 1. 生成器 2. 判别器 四.定义损失函数和优化器 1. 判 ...
- Pytorch 使用GAN实现二次元人物头像生成 保姆级教程(数据集+实现代码+数学原理)
Pytorch 使用DCGAN实现二次元人物头像生成(实现代码+公式推导) GAN介绍 算法主体 推导证明(之后将补全完整过程) 随机梯度下降训练D,G DCGAN介绍及相关原理 Py ...
- 深度卷积生成对抗网络(DCGAN)原理与实现(采用Tensorflow2.x)
深度卷积生成对抗网络(DCGAN)原理与实现(采用Tensorflow2.x) GAN直观理解 DCGAN网络结构 GAN训练目标 DCGAN实现 数据加载 网络 鉴别网络 生成网络 网络训练 定义损 ...
- 生成对抗网络简介,深度卷积生成对抗网络(DCGAN)简介
本博客是个人学习的笔记,讲述的是生成对抗网络(generate adversarial network ) 的一种架构:深度生成对抗网络 的简单介绍,下一节将使用 tensorflow 搭建 DCGA ...
- 基于DCGAN的动漫头像生成
基于DCGAN的动漫头像生成 数据 数据集:动漫图库爬虫获得,经过数据清洗,裁剪得到动漫头像.分辨率为3 * 96 * 96,共5万多张动漫头像的图片,从知乎用户何之源处下载. 生成器:输入为随机噪声 ...
- 使用残差网络与wgan制作二次元人物头像
使用残差网络与wgan制作二次元人物头像 ref:https://blog.csdn.net/qq_41103479/article/details/119352714 我复现的项目链接:https: ...
- 深度学习100例-生成对抗网络(DCGAN)生成动漫人物 | 第20天
文章目录 一.前言 二.什么是生成对抗网络? 1. 设置GPU 2. 加载和准备数据集 三.创建模型 1. 生成器 2. 判别器 四.定义损失函数和优化器 1. 判别器损失 2. 生成器损失 五.保存 ...
- 生成对抗网络gan原理_必读!TOP10生成对抗网络GAN论文(附链接)
来源:新智元 本文约2200字,建议阅读7分钟. 本文所选论文提供了一个易读的对GAN的介绍,帮助你理解GAN技术的基础. [ 导读 ]生成对抗网络 (GAN) 是深度学习中最有趣.最受欢迎的应用之一 ...
- 生成对抗网络的损失函数如何设计_理解生成对抗网络,一步一步推理得到GANs(一)...
作者:Joseph Rocca 编译:ronghuaiyang 导读 GANs在2014年提出,然后就在图像生成领域取得了巨大的成功,但是其背后的原理却不是那么好理解,这篇文章带你从最基础的随机变量开 ...
最新文章
- 关于目标检测你必须知道的……
- java map key是否存在_java中如何判断map集合中是否存在key
- Cocos2d—声音API
- 一、NLTK工具包使用
- 让预训练模型学习知识:使用多学习器增强知识建模能力
- 2018数据技术嘉年华-金融峰会·重庆站即将起航!
- Linux常用到的指令汇总
- java.lang.NumberFormatException: For input string: 0.7
- Unity3D 场景编辑器扩展学习笔记-Editor
- PowerDesigner 生成数据字典
- 各种材料衣服的保养 全面知识分享
- 逻辑回归(Logistic Regression)详解
- oracle打印awr报告,oracle生成awr报告
- Activiti实现流程定义的控制与修改
- 实现div半透明效果
- IP 地址以 0 开头会降维成八进制
- Mac运行exe的几种方法,欢迎补充!
- 5G 与 MEC 边缘计算
- 奇瑞新能源的小车为何备受市场青睐?鲍思语这样解释
- 计算机毕业设计Java企业员工考勤系统的设计与实现(源码+系统+mysql数据库+lw文档)