上一节我们提到G和D由多层感知机定义。深度学习中对图像处理应用最好的模型是CNN,那么如何把CNN与GAN结合?DCGAN是这方面最好的尝试之一。源码:https://github.com/Newmu/dcgan_code 。DCGAN论文作者用theano实现的,他还放上了其他人实现的版本,本文主要讨论tensorflow版本。
TensorFlow版本的源码:https://github.com/carpedm20/DCGAN-tensorflow
DCGAN把上述的G和D换成了两个卷积神经网络(CNN)。但不是直接换就可以了,DCGAN对卷积神经网络的结构做了一些改变,以提高样本的质量和收敛的速度,这些改变有:
- 取消所有pooling层。G网络中使用转置卷积(transposed convolutional layer)进行上采样,D网络中用加入strided的卷积代替pooling。
- 在D和G中均使用batch normalization
- 去掉FC层,使网络变为全卷积网络
- G网络中使用ReLU作为激活函数,最后一层使用tanh
- D网络中使用LeakyReLU作为激活函数
(1) Allconvolutional net (Springenberg et al., 2014) 全卷积网络
Ÿ 判别模型D:使用带步长的卷积(strided convolutions)取代了的空间池化(spatial pooling),容许网络学习自己的空间下采样(spatial downsampling)。
Ÿ 生成模型G:使用微步幅卷积(fractional strided),容许它学习自己的空间上采样(spatial upsampling)
(2)在卷积特征之上消除全连接层。
Ÿ (Mordvintsev et al.)提出的全局平均池化有助于模型的稳定性,但损害收敛速度。
GAN的第一层输入:服从均匀分布的噪声向量Z,因为只有矩阵乘法,因此可以被叫做全连接层,但结果会被reshape成4维张量,作为卷积栈的开始。
对于D,最后的卷积层被flatten(把矩阵变成向量),然后使用sigmoid函数处理输出。
生成模型:输出层用Tanh函数,其它层用ReLU激活函数。
判别模型:所有层使用LeakyReLU
(3)Batch Normalization 批标准化。
解决因糟糕的初始化引起的训练问题,使得梯度能传播更深层次。稳定学习,通过归一化输入的单元,使它们平均值为0,具有单位方差。
批标准化证明了生成模型初始化的重要性,避免生成模型崩溃:生成的所有样本都在一个点上(样本相同),这是训练GANs经常遇到的失败现象。
generator:100维的均匀分布Z投影到小的空间范围卷积表示,产生许多特征图。一系列四步卷积将这个表示转换为64x64像素的图像。不用到完全连接或者池化层。
配置
Python
TensorFlow
SciPy
pillow
(可选)moviepy (https://github.com/Zulko/moviepy):用于可视化
(可选)Align&Cropped Images.zip (http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html):人脸数据集
main.py
入口程序,事先定义所需参数的值。
执行程序:
训练一个模型:
$ python main.py --dataset mnist --is_trainTrue
$ python main.py --dataset celebA --is_trainTrue --is_crop True
测试一个已存在模型:
$ python main.py --dataset mnist
$ python main.py --dataset celebA --is_cropTrue
你也可以使用自己的dataset:
$ mkdir data/DATASET_NAME
添加图片到data/DATASET_NAME ...
$ python main.py --dataset DATASET_NAME--is_train True
$ python main.py --dataset DATASET_NAME
训练出多张以假乱真的图片
源码分析
flags配置network的参数,在命令行中可以修改,比如
$pythonmain.py --image_size 96 --output_size 48 --dataset anime --is_crop True--is_train True --epoch 300
该套代码参数主要以mnist数据集为模板,如果要训练别的数据集,可以适当修改一些参数。mnist数据集可以通过download.py下载。
首先初始化model.py中的DCGAN,然后看是否需要训练(is_train)。
参数说明
c_dim:颜色通道,灰度图像设为1,彩色图像设为3
y_dim:只有训练mnist数据集时不为空
output_size:输出图像的边长,这里没有分长和宽,而是当做正方形,只设边长。
model.py
定义了DCGAN类,包括9个函数:
- __init__()
gf_dim: (optional) G的第一个卷积层的过滤器个数 [64]
df_dim: (optional) D的第一个卷积层的过滤器个数[64]
gfc_dim: (optional) 全连接层G单元的个数 [1024]
dfc_dim: (optional) 全连接层D单元的个数[1024]
其中self.d_bn2是batch标准化,见ops.py的batch_norm(object)。
然后建立模型(build_model)
- build_model()
histogram_summary:查看z的变化
self.G =self.generator(self.z):通过噪声z产生G
self.D,self.D_logits = self.discriminator(self.images):输入原始图像构建D
self.sampler = self.sampler(self.z):取样,代码和G很像,没有G训练的过程。
self.D_,self.D_logits_ = self.discriminator(self.G, reuse=True):输入G图像构建
summary这几步是关于可视化,就不管了
tf.ones_like:新建一个与给定tensor大小一致的tensor,其全部元素为1
d_loss_real:D识别出真的图片为真的
d_loss_fake:D识别出假的图片为假 G要降低这两个概率
g_loss:D识别假的图片为真的——D要降低这个概率
- train()
- generator()
反卷积的过程。s是输出图像的大小。linear()见ops.py
self.g_bn0(self.h0)调用ops.py里面的batch_norm中的__call__(self, x, train=True)
然后4次反卷积,激活函数为tanh
- discriminator():
激活函数lrelu见ops.py。四次卷积和激活。然后线性化,返回sigmoid。
load_mnist(), save(), load()
这三个加载保持等就不仔细讲了
download.py
下载数据
ops.py
- batch_norm(object)
tf.contrib.layers.batch_norm的代码见https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/layers/python/layers/layers.py
batchnormalization来自于http://arxiv.org/abs/1502.03167
加快训练。
- deconv2d()
引用tf的反卷积函数tf.nn.conv2d_transpose或tf.nn.deconv2d。以tf.nn.conv2d_transpose为例。
defconv2d_transpose(value, filter, output_shape, strides,padding="SAME", data_format="NHWC", name=None):
value: 是一个4维的tensor,格式为[batch, height, width, in_channels] 或者 [batch, in_channels,height, width]。
filter: 是一个4维的tensor,格式为[height, width, output_channels, in_channels],过滤器的in_ channels的维度要和这个匹配。
output_shape: 一维tensor,表示反卷积操作的输出shapeA
strides: 针对每个输入的tensor维度,滑动窗口的步长。
padding: “VALID”或者”SAME”,padding算法
data_format: “NHWC”或者”NCHW” ,对应value的数据格式。
name: 可选,返回的tensor名。
deconv= tf.nn.conv2d_transpose(input_, w, output_shape=output_shape,strides=[1,d_h, d_w, 1])
第一个参数是输入,即上一层的结果,
第二个参数是输出输出的特征图维数,是个4维的参数,
第三个参数卷积核的移动步长,[1, d_h, d_w, 1],其中第一个对应一次跳过batch中的多少图片,第二个d_h对应一次跳过图片中多少行,第三个d_w对应一次跳过图片中多少列,第四个对应一次跳过图像的多少个通道。这里直接设置为[1,2,2,1]。即每次反卷积后,图像的滑动步长为2,特征图会扩大缩小为原来2*2=4倍。
utils.py
可视化等函数
总结:稀里糊涂的,就这样吧。有不足之处欢迎指正。
参考:
Springenberg, Jost Tobias, Dosovitskiy, Alexey, Brox, Thomas, and Riedmiller, Martin. Striving for simplicity: The all convolutional net. arXiv preprint arXiv:1412.6806, 2014.
Mordvintsev, Alexander, Olah, Christopher, and Tyka, Mike. Inceptionism : Going deeper into neural networks.http://googleresearch.blogspot.com/2015/06/inceptionism-going-deeper-into-neural.html. Accessed: 2015-06-17.
Radford A, Metz L, Chintala S. UnsupervisedRepresentation Learning with Deep Convolutional Generative AdversarialNetworks[J]. Computer Science, 2015.
http://blog.csdn.net/nongfu_spring/article/details/54342861
http://blog.csdn.net/solomon1558/article/details/52573596