对抗神经网络(二)——DCGAN

article/2025/8/26 22:23:58

一、DCGAN介绍

DCGAN即使用卷积网络的对抗网络,其原理和GAN一样,只是把CNN卷积技术用于GAN模式的网络里,G(生成器)网在生成数据时,使用反卷积的重构技术来重构原始图片。D(判别器)网用卷积技术来识别图片特征,进而做出判别。同时,CDGAN中的卷积神经网络也做了一些结构的改变,以提高样本的质量和收敛速度。

DCGAN的generator网络结构图如下:

  • G网中使用ReLU作为激活函数,最后一层使用Tanh作为激活函数。
  • 去掉了FC层,使网络变为全卷积网络。

DCGAN的discriminator网络结构图如下:

  • D中取消所有的池化层,使用转置卷积(transposed convolutional layer)并且步长大于等于2进行上采样。
  • D网中也加入stride的卷积代替pooling。
  • 在D网和G网中均使用批量归一化(batch normalization),而在最后一层时通常不会使用batch normalization,这是为了保证模型能够学习到数据的正确均值和方差。
  • D网络中使用LeakyReLU作为激活函数。
  • DCGAN中换成了两个卷积神经网络(CNN)的G和D,可以刚好的学习对输入图像层次化的表示,尤其在生成器部分会有更好的模拟效果。DCGAN在训练过程中会使用Adam优化算法。

三、网络实现

以人脸数据为例

1、环境配置(Environments

  • window10
  • python3.6.4
  • TensorFlow1.13.1

2、数据准备

数据集:face-swap

数据可以从网上自行下载,或者利用自己的数据,这里对数据的没有严格要求。我是采用了网络上的数据集,这里给出数据的下载地址:https://anonfile.com/p7w3m0d5be/face-swap.zip将解压的数据分别放入文件夹A和文件夹B

3、超参数设置(Hyper-Parameters

  • Image Size = 64x64 
  • Batch Size = 64 
  • Learning Rate = 0.00005
  • Adam_beta1 = 0.5
  • z_dim = 100
  • Epoch = 500 
# 导入需要的包
from PIL import Image  # Image 用于读取影像
#from skimage import io  # io也可用于读取影响,效果比Image读取的更好一些import tensorflow as tf  # 用于构建神经网络模型
import matplotlib.pyplot as plt  # 用于绘制生成影像的结果
import numpy as np  # 读取影像
import os  # 文件夹操作
import time  # 计时# 设置相关参数
is_training = True
input_dir = "./face/"  # 原始数据的文件夹路径# 设置超参数 hyper parameters
batch_size = 64
image_width = 64
image_height = 64
image_channel = 3
data_shape = [64, 64, 3]
data_length = 64 * 64 * 3z_dim = 100
learning_rate = 0.00005
beta1 = 0.5
epoch = 500

4、读取数据并将原始数据数据resize成64*64*3的格式,原始图像大小为256*256*3

# 读取数据的函数
def prepare_data(input_dir, floder):'''函数功能:通过输入图像的路径,读取训练数据:参数 input_dir: 图像数据所在的根目录,即"./face":参数 floder: 图像数据所在的子目录, 即"./face/A":return: 返回读取好的训练数据'''# 遍历图像路径,并获取图像数量images = os.listdir(input_dir + floder)image_len = len(images)# 设置一个空data,用于存放数据data = np.empty((image_len, image_width, image_height, image_channel), dtype="float32")# 逐个图像读取for i in range(image_len):# 如果导入的是skimage.io,则读取影像应该写为img = io.imread(input_dir + images[i])img = Image.open(input_dir + floder + "/" + images[i])  # 打开图像img = img.resize((image_width, image_height))  # 将256*256变成64*64arr = np.asarray(img, dtype="float32")  # 将格式改为np.arraydata[i, :, :, :] = arr  # 将其放入data中sess = tf.Session()sess.run(tf.initialize_all_variables())data = tf.reshape(data, [-1, image_width, image_height, image_channel])train_data = data * 1.0 / 127.5 - 1.0  # 对data进行正则化train_data = tf.reshape(train_data, [-1, data_length])  # 将其拉伸成一维向量train_set = sess.run(train_data)sess.close()return train_set

5、定义生成器函数

# 定义生成器
def Generator(z, is_training, reuse):'''函数功能:输入噪声z,生成图像gen_img:param z:即输入数据,一般为噪声:param is_training:是否为训练环节:return: 返回生成影像gen_img'''# 图像的channel维度变化为100->1024->512->256->128->3depths = [1024, 512, 256, 128] + [data_shape[2]]with tf.variable_scope("Generator", reuse=reuse):# 第一层100with tf.variable_scope("g_c1", reuse=reuse):output = tf.layers.dense(z, depths[0] * 4 * 4, trainable=is_training)output = tf.reshape(output, [batch_size, 4, 4, depths[0]])output = tf.nn.relu(tf.layers.batch_normalization(output, training=is_training))# 第二层反卷积层1024with tf.variable_scope("g_dc1", reuse=reuse):output = tf.layers.conv2d_transpose(output, depths[1], [5, 5], strides=(2, 2),padding="SAME", trainable=is_training)output = tf.nn.relu(tf.layers.batch_normalization(output, training=is_training))# 第三层反卷积层512with tf.variable_scope("g_dc2", reuse=reuse):output = tf.layers.conv2d_transpose(output, depths[2], [5, 5], strides=(2, 2),padding="SAME", trainable=is_training)output = tf.nn.relu(tf.layers.batch_normalization(output, training=is_training))# 第四层反卷积层256with tf.variable_scope("g_dc3", reuse=reuse):output = tf.layers.conv2d_transpose(output, depths[3], [5, 5], strides=(2, 2),padding="SAME", trainable=is_training)output = tf.nn.relu(tf.layers.batch_normalization(output, training=is_training))# 第五层反卷积层128with tf.variable_scope("g_dc4", reuse=reuse):output = tf.layers.conv2d_transpose(output, depths[4], [5, 5], strides=(2, 2),padding="SAME", trainable=is_training)gen_img = tf.nn.tanh(output)return gen_img

6、定义判别器函数

# 定义判别器
def Discriminator(x, is_training, reuse):'''函数功能:判别输入的图像是真或假:param x: 输入数据:param is_training: 是否为训练环节:return: 判别结果'''# 判别器的channel维度变化为:3->64->128->256->512depths = [data_shape[2]] + [64, 128, 256, 512]with tf.variable_scope("Discriminator", reuse=reuse):# 第一层卷积层,注意用的是leaky_relu函数with tf.variable_scope("d_cv1", reuse=reuse):output = tf.layers.conv2d(x, depths[1], [5, 5], strides=(2, 2),padding="SAME", trainable=is_training)output = tf.nn.leaky_relu(tf.layers.batch_normalization(output, training=is_training))# 第二层卷积层,注意用的是leaky_relu函数with tf.variable_scope("d_cv2", reuse=reuse):output = tf.layers.conv2d(output, depths[2], [5, 5], strides=(2, 2),padding="SAME", trainable=is_training)output = tf.nn.leaky_relu(tf.layers.batch_normalization(output, training=is_training))# 第三层卷积层,注意用的是leaky_relu函数with tf.variable_scope("d_cv3", reuse=reuse):output = tf.layers.conv2d(output, depths[3], [5, 5], strides=(2, 2),padding="SAME", trainable=is_training)output = tf.nn.leaky_relu(tf.layers.batch_normalization(output, training=is_training))# 第四层卷积层,注意用的是leaky_relu函数with tf.variable_scope("d_cv4", reuse=reuse):output = tf.layers.conv2d(output, depths[4], [5, 5], strides=(2, 2),padding="SAME", trainable=is_training)output = tf.nn.leaky_relu(tf.layers.batch_normalization(output, training=is_training))# 第五层全链接层with tf.variable_scope("d_c1", reuse=reuse):output = tf.layers.flatten(output)disc_img = tf.layers.dense(output, 1, trainable=is_training)return disc_img

7、编写保存结果

def plot_and_save(order, images):'''函数功能:绘制生成器的结果,并保存:param order::param images::return:'''# 将一个batch_size的所有图像进行保存batch_size = len(images)n = np.int(np.sqrt(batch_size))# 读取图像大小,并生成掩模canvasimage_size = np.shape(images)[2]n_channel = np.shape(images)[3]images = np.reshape(images, [-1, image_size, image_size, n_channel])canvas = np.empty((n * image_size, n * image_size, image_channel))# 为每个掩模赋值for i in range(n):for j in range(n):canvas[i * image_size:(i + 1) * image_size, j * image_size:(j + 1) * image_size, :] = images[n * i + j].reshape(64, 64, 3)# 绘制结果,并设置坐标轴plt.figure(figsize=(8, 8))plt.imshow(canvas, cmap="gray")label = "Epoch: {0}".format(order + 1)plt.xlabel(label)# 为每个文件命名if type(order) is str:file_name = orderelse:file_name = "face_gen" + str(order)# 保存绘制的结果plt.savefig(file_name)print(os.getcwd())print("Image saved in file: ", file_name)plt.close()

8、定义训练过程

# 定义训练过程
def training():'''函数功能:实现DCGAN的训练过程'''# 准备数据。这里输入根目录,以A的影像为例进行图像生成data = prepare_data(input_dir, "A")# 构建网络结构,这是程序的核心部分---------------------------------------------x = tf.placeholder(tf.float32, shape=[None, data_length], name="Input_data")x_img = tf.reshape(x, [-1] + data_shape)z = tf.placeholder(tf.float32, shape=[None, z_dim], name="latent_var")G = Generator(z, is_training=True, reuse=False)D_fake_logits = Discriminator(G, is_training=True, reuse=False)D_true_logits = Discriminator(x_img, is_training=True, reuse=True)# 定义生成器的损失函数G_lossG_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=D_fake_logits, labels=tf.ones_like(D_fake_logits)))# 定义判别器的损失函数D_lossD_loss_1 = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=D_true_logits, labels=tf.ones_like(D_true_logits)))D_loss_2 = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=D_fake_logits, labels=tf.zeros_like(D_fake_logits)))D_loss = D_loss_1 + D_loss_2# 定义方差total_vars = tf.trainable_variables()d_vars = [var for var in total_vars if "d_" in var.name]g_vars = [var for var in total_vars if "g_" in var.name]# 定义优化方式with tf.control_dependencies(tf.get_collection(tf.GraphKeys.UPDATE_OPS)):g_optimization = tf.train.AdamOptimizer(learning_rate=learning_rate,beta1=beta1).minimize(G_loss, var_list=g_vars)d_optimization = tf.train.AdamOptimizer(learning_rate=learning_rate,beta1=beta1).minimize(D_loss, var_list=d_vars)print("we successfully make the network")# 网络模型构建结束------------------------------------------------------------# 训练模型初始化start_time = time.time()  # 计时sess = tf.Session()sess.run(tf.initialize_all_variables())# 逐个epoch训练for i in range(epoch):total_batch = int(len(data) / batch_size)d_value = 0g_value = 0# 逐个batch训练for j in range(total_batch):batch_xs = data[j * batch_size:j * batch_size + batch_size]# 训练判别器z_sampled1 = np.random.uniform(low=-1.0, high=1.0, size=[batch_size, z_dim])Op_d, d_ = sess.run([d_optimization, D_loss], feed_dict={x: batch_xs, z: z_sampled1})# 训练生成器z_sampled2 = np.random.uniform(low=-1.0, high=1.0, size=[batch_size, z_dim])Op_g, g_ = sess.run([g_optimization, G_loss], feed_dict={x: batch_xs, z: z_sampled2})# 尝试生成影像并保存images_generated = sess.run(G, feed_dict={z: z_sampled2})d_value += d_ / total_batchg_value += g_ / total_batchplot_and_save(i, images_generated)# 输出时间和损失函数losshour = int((time.time() - start_time) / 3600)min = int(((time.time() - start_time) - 3600 * hour) / 60)sec = int((time.time() - start_time) - 3600 * hour - 60 * min)print("Time: ", hour, "h", min, "min", sec, "sec", "   Epoch: ",i, "G_loss: ", g_value, "D_loss: ", d_value)

9、进行训练

if __name__ == "__main__":training()

四、结果

Epoch=1,基本什么也看不清

Epoch=100时,有了明显的纹理变化

Epoch=200时,能够明显的看到人脸轮廓

Epoch= 300时,面部特征比较清晰

 

Epoch= 400时,人脸与背景区分明显 

epoch= 500时,人脸色彩对比更加明显 ,已经能够清晰地辨别人脸。

在训练的过程中出现了模型爆炸现象,这个问题在后期的WGAN中会得到解决。下面是从原文中截取的模型爆炸原因,原文地址请参考:https://arxiv.org/pdf/1511.06434.pdf

 

参考链接:

https://blog.csdn.net/z704630835/article/details/82254193

https://github.com/HyeongminLEE/Tensorflow_DCGAN 


http://chatgpt.dhexx.cn/article/SH3QFyvs.shtml

相关文章

对抗生成网络GAN系列——DCGAN简介及人脸图像生成案例

🍊作者简介:秃头小苏,致力于用最通俗的语言描述问题 🍊往期回顾:对抗生成网络GAN系列——GAN原理及手写数字生成小案例 🍊近期目标:写好专栏的每一篇文章 🍊支持小苏:点赞…

DCGAN理论讲解及代码实现

目录 DCGAN理论讲解 DCGAN的改进: DCGAN的设计技巧 DCGAN纯代码实现 导入库 导入数据和归一化 定义生成器 定义鉴别器 初始化和 模型训练 运行结果 DCGAN理论讲解 DCGAN也叫深度卷积生成对抗网络,DCGAN就是将CNN与GAN结合在一起,生…

torch学习 (三十七):DCGAN详解

文章目录 引入1 生成器2 鉴别器3 模型训练:生成器与鉴别器的交互4 参数设置5 数据载入6 完整代码7 部分输出图像示意7.1 真实图像7.2 训练200个批次7.2 训练400个批次7.2 训练600个批次 引入 论文详解:Unsupervised representation learning with deep c…

GANs系列:DCGAN原理简介与基础GAN的区别对比

本文长期不定时更新最新知识,防止迷路记得收藏哦! 还未了解基础GAN的,可以先看下面两篇文章: GNA笔记--GAN生成式对抗网络原理以及数学表达式解剖 入门GAN实战---生成MNIST手写数据集代码实现pytorch 背景介绍 2016年&#…

Pix2Pix和CycleGAN

GAN的局限性 即便如此,传统的GAN也不是万能的,它有下面两个不足: 1. 没有**用户控制(user control)**能力 在传统的GAN里,输入一个随机噪声,就会输出一幅随机图像。 但用户是有想法滴&#xff…

PyTorch 实现Image to Image (pix2pix)

目录 一、前言 二、数据集 三、网络结构 四、代码 (一)net (二)dataset (三)train (四)test 五、结果 (一)128*128 (二)256*256 …

pix2pix、pix2pixHD 通过损失日志进行训练可视化

目录 背景 代码 结果 总结 背景 pix2pix(HD)代码在训练时会自动保存一个损失变化的txt文件,通过该文件能够对训练过程进行一个简单的可视化,代码如下。 训练的损失文件如图,对其进行可视化。 代码 #coding:utf-8 ## #author: QQ&#x…

Pix2Pix代码解析

参考链接:https://github.com/yenchenlin/pix2pix-tensorflow https://blog.csdn.net/stdcoutzyx/article/details/78820728 utils.py from __future__ import division import math import json import random import pprint import scipy.misc import numpy as…

pix2pix 与 pix2pixHD的大致分析

目录 pix2pix与pix2pixHD的生成器 判别器 PatchGAN(马尔科夫判别器) 1、pix2pix 简单粗暴的办法 如何解决模糊呢? 其他tricks 2、pix2pixHD 高分辨率图像生成 模型结构 Loss设计 使用Instance-map的图像进行训练 语义编辑 总结 …

Tensorflow2.0之Pix2pix

文章目录 Pix2pix介绍Pix2pix应用Pix2pix生成器及判别器网络结构代码实现1、导入需要的库2、下载数据包3、加载并展示数据包中的图片4、处理图片4.1 将图像调整为更大的高度和宽度4.2 随机裁剪到目标尺寸4.3 随机将图像做水平镜像处理4.4 图像归一化4.5 处理训练集图片4.6 处理…

pix2pix算法笔记

论文:Image-to-Image Translation with Conditional Adversarial Networks 论文链接:https://arxiv.org/abs/1611.07004 代码链接:https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix 这篇论文发表在CVPR2017,简称pix2pix,是将GAN应用于有监督的图像到图像翻译的经…

Pix2Pix原理解析以及代码流程

文章目录 1、网络搭建2、反向传播过程3、PatchGAN4.与CGAN的不同之处 1、网络搭建 class UnetGenerator(nn.Module):"""Create a Unet-based generator"""def __init__(self, input_nc, output_nc, num_downs, ngf64, norm_layernn.BatchNorm2d…

图像翻译网络模型Pix2Pix

Pix2pix算法(Image-to-Image Translation,图像翻译),它的核心技术有三点:基于条件GAN的损失函数,基于U-Net的生成器和基于PatchGAN的判别器。Pix2Pix能够在诸多图像翻译任务上取得令人惊艳的效果,但因为它的输入是图像对&#xff…

GAN系列之pix2pix、pix2pixHD

1. 摘要 图像处理的很多问题都是将一张输入的图片转变为一张对应的输出图片,比如灰度图、梯度图、彩色图之间的转换等。通常每一种问题都使用特定的算法(如:使用CNN来解决图像转换问题时,要根据每个问题设定一个特定的loss funct…

Pix2Pix原理解析

1.网络搭建 class UnetGenerator(nn.Module):"""Create a Unet-based generator"""def __init__(self, input_nc, output_nc, num_downs, ngf64, norm_layernn.BatchNorm2d, use_dropoutFalse):"""Construct a Unet generatorPa…

如何利用Pix2Pix将黑白图片自动变成彩色图片

实现黑白图片自动变成彩色图片 如果你有一幅黑白图片,你该如何上色让他变成彩色的呢?通常做法可能是使用PS工具来进行上色。那么,有没有什么办法进行自动上色呢?自动将黑白图片变成彩色图片?答案是有的,使用深度学习中的Pix2Pix网络就可以实现这一功能。 如图所示,我们…

Pix2Pix进一步了解

参考:Pix2Pix视频解读 一、Pix2Pix是输入图片矩阵而不是标签向量 1、生成器方面 Pix2Pix与CGAN之间的联系:CGAN生成器输入的是一个label,而我们现在要做的是把这个lable换成一个图片,如下所示。这个图片是一个建筑物的模…

CycleGAN与pix2pix训练自己的数据集-Pytorch

github:https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix 参考:https://blog.csdn.net/Gavinmiaoc/article/details/80585531 文章目录 CycleganDownload&Prerequisitesbefore your work数据集训练测试 pix2pix数据集训练测试 Cyclegan Do…

pix2pix学习系列(1):预训练模型测试pix2pix

pix2pix学习系列(1):预训练模型测试pix2pix 参考文献: [Pytorch系列-66]:生成对抗网络GAN - 图像生成开源项目pytorch-CycleGAN-and-pix2pix - 使用预训练模型测试pix2pix模型 运行环境 win 10 1、代码下载 Gith…

pix2pix简要笔记

参考(40条消息) 全文翻译&杂记《Image-to-Image Translation with Conditional Adversarial NetWorks》_Maples丶丶的博客-CSDN博客_image-to-image translation 图像到图像通常有特定方法(没有通用),但本质是像素到像素的映射问题。本文…