GAN的学习 - 基础知识了解

20200818 -

0. 引言

最近看到了一些论文,是GAN在密码生成(PassGAN)、DGA检测(DeepDGA)这些论文,所以希望深入了解一下GAN的内容。之前的时候,只是知道GAN是什么东西,通过训练两个神经网络,然后相互促进来实现检测的目标,不过没有深入了解过。这里根据刚刚阅读的一篇文章[1]来记录下学习的内容。

大部分内容是文章[1]的原始内容,加上自己的理解。
(20200910 增加)
关于GAN的应用,主要是在生成模型中,一般而言,实际的数据的分布会非常复杂,无法直接模拟出相应的数学公式,所以可以采用GAN的形式来进行生成[4]。而对于GAN的研究方向,也主要来自两个方面:一是利用GAN解决领域问题,另一个是研究如何让GAN更加容易训练。[5]

1. GAN的结构

不管是什么网站,只要一介绍GAN就会告诉你:GAN由两个部分组成,一个部分是生成器,一个部分是判别器。那么具体,他们是怎么连接,生成器的输入是什么,判别器的输入又是什么呢。

1.1 判别模型与生成模型

在讲解GAN之前,需要对判别算法和生成算法有一个了解。这里首先来引用文章[1]中的一个结论:

  • 判别模型学习类之间的边界
  • 生成模型构造每个类的分布
    在以往的学习过程中,大多数都是在学习判别模型,因为平时做的主要工作就是分类过程,软件是否是恶意,域名是否是DGA算法生成等等,所以对于判别模型的理解更深入。但是,从前面的描述也可以知道,生成模型要做的工作是学习到底层每个类的分布,与判别模型恰恰相反,是从标签中学习到底层数据的分布。
    (这里有一个疑问,那么GAN输入的标签中要带有原始的Label,还是真假数据的标签呢)
    (20200910答,都可以,这种属于不同形式的GAN)

1.2 GAN如何工作

GAN(原始的)包含两个神经网络,一个叫做生成器,一个叫做判别器;生成器生成新的数据实例,而判别器用于评估生成的样本是真是假。如果是以MNIST数据集的图片为例,生成器通过生成新的图片样本,判别器要判定这个生成的样本是真实的还是伪造的。在文章[1]中列举步骤中有一点很关键。

  • 生成器输入一个随机的数值(在密码生成的文章中指出,一般使用均匀分布或者正态分布),然后返回一张图片
  • 生成的图片以及从真实数据集中提取出来的图片同时输入到判别器
  • 判别器对每个输入的图片返回一个概率,0代表是假的,1代表是真的。
    上面的步骤中,回答了两个问题:
    1)生成器的输入是什么,随机的数值,那么这个随机的数值是固定维度,还是单个呢?这个需要进一步后面看代码;(20200910答,这个输入是完全的随机分布,可以是均一分布,也可以是高斯分布)
    2)判别器的输入,包括图片和Label,从上面的描述上来看,这个Label应该是真假,那么这个时候,就需要解决另一个问题,他的类别怎么传递进去。
    (20200821更新,在文章[2]提到,训练判别器时,并且同时用标签告诉它这些样本分别来自哪里,还有,我还见过一个GAN的图,他好像将类别和真假同时训练的,所以我觉得可能这部分标签到底是什么应该还是跟他的需求相关,可能有的人就是需要真假)

生成器的目的就是生成新的数据实例,例如图片,然后能够骗过判别器。所以这里整体上有两个反馈循环:

  • 判别器利用标签来进行判断,例如图片是否是伪造的
  • 生成器利用判别器返回的数据,例如前面提到的概率来进行持续改进。

1.2.1 以MNIST数据为例

Minist的数据是手写的数字图片,使用该数据在GAN上进行实验,网络结构如下:

  • 判别器网路结构将是一个卷积神经网络,通过降采样,最终识别图片,最终将生成的图片标记为是否是伪造的,并输出一个概率。
  • 生成器是判别器反过来的过程,本来卷积神经网络是降采样,但是生成器输入一个随机噪声的向量,然后将其升采样变为一个图片。
    两个神经网络都尝试着获取最优的目标函数,具体的网络结构[1]如下。
    GAN的学习 - 基础知识了解_第1张图片

2. 具体的代码示例(生成MNIST数据集图片)

(20200821 - 学习增加)
今天看到一些文章和实例,在构造模型时,判别器的模型中还加入了数据的类别,就不仅仅是图片是真的还是假的这种标签。不过,我个人感觉,实例的具体类别标签,应该也是能加入的,可能还是要看具体的应用。下面的例子就是仅仅判定是否是真的假的过程。
文章[2]通过完整的例子,从如何定义生成器到最后怎么评估GAN的性能的一篇文章,可能这篇文章的内容也不一定准确,但是先看看这个例子具体讲了什么。具体目录(仅仅列举有用的)如下:

  1. 如何定义和训练判别器模型
  2. 如何定义和使用生成器模型
  3. 如何训练生成器模型
  4. 如何评估GAN模型的性能
  5. 如何利用最后的生成器模型来生成图片

在[3]的开头,其提到GAN,生成对抗网络是一种训练生成模型的网咯结构。如果是这样说的话,那就要具体考虑GAN的应用到底是什么了,你看这里文章[3]就是使用最后的生成器来进行图片生成。
(20200910 - 关于GAN的应用见文章[5],本质上我一直在强调这个事情,是我还没有完全将生成模型这个概念的应用给理解)

2.1 如何定义和训练判别器模型

因为处理的是minist的图片数据集,只需要加载keras库的数据即可;然后在经过一些处理,比如将数据维度扩充为三维(添加图片隧道维度),然后正则化为[0,1]范围内。还有一些其他不同的点,这里列举一下。

  • 在卷积神经网络中,没有使用池化层
  • 没有遍历整个数据集来进行训练,而是自己生成了相应的随机实例,然后输入
    下面是比较重要的内容。
    在这个过程中,就已经对GAN的判别器进行了训练,同时训练的过程中,输入的数据标签是“真”和“假”,同时因为,现在还没有相应的生成器,随意这里只是完全随机生成的一个向量,然后处理为相应维度。

那么这里总结一下大致逻辑。
1)构造一个两层的卷积神经网络的二分类网络(没有使用池化层,不过我感觉这里应该没有问题把,使用了也一样应该)
2)输入的数据,一部分类别为真的,就是从实际MNIST数据随机取出的数据,假的是自己随机生成的向量,然后转化为相应的维度
3)利用上述数据进行训练(20200822 注意这里的训练仅仅是为了进行测试示例,在最后的时候还要配合生成器来工作)

那么,在这个步骤结束之后,就能够得到一个输入是图片,然后输出这个图片是否是真假的判别器神经网络了。具体代码参考文章[3]。

2.2 如何定义和使用生成器模型

在这部分内容中,主要就是利用卷积层中的升采样来还原之前的图片大小,同时我还看到过有些直接使用了那种升维度的方式就是直接使用了dense层,所以从这个角度来看,其实内部是什么东西属于细节的地方(使用不同的模型可能导致不同的效果而已),但是并不影响整体的工作。
同时这里需要注意的是,定义了生成器模型之后,并没有使用compile方法来编译这个模型,这部分也是因为后面要将这部分模型与判别器连接起来,从而在这个混合模型中训练。

2.3 如何训练生成器模型

这部分也是耗费我耗费时间最多的部分,看了不少文章的方法,看到他们的做法都是差不多的。
首先要明白,训练生成器的过程是利用判别器的信息来反馈到生成器中,然后进行相应的权值更新。这部分内容比较关键。为了在这个过程中保证判别器的权值不会更新,就需要设置判别器的模型部分trainable=False,而且要注意这个东西的设置地点。这个部分的内容在另外一篇文章《GAN的学习 - 训练过程(冻结判别器)》中进行具体说明,这里只要知道,为了训练生成器模型,要将两个模型连接在一起,同时设置判别器不可训练。下面是设置GAN的模型。

# define the combined generator and discriminator model, for updating the generator
def define_gan(g_model, d_model):
	# make weights in the discriminator not trainable
	d_model.trainable = False
	# connect them
	model = Sequential()
	# add generator
	model.add(g_model)
	# add the discriminator
	model.add(d_model)
	# compile model
	opt = Adam(lr=0.0002, beta_1=0.5)
	model.compile(loss='binary_crossentropy', optimizer=opt)
	return model

下图是GAN的原始训练过程。
GAN的学习 - 基础知识了解_第2张图片

2.4 如何评估GAN模型的性能

在原文[3]中指出,GAN的性能是很难评估的,在本次实验中,因为使用的是MNIST图片,其图片内容比较简单,人眼就可以看出来,所以能够用主观的方式实现性能评估。但是,在其他任务中,是很难实现有针对性的性能评估的。原文内容如下:

Generally, there are no objective ways to evaluate the performance of a GAN model.
We cannot calculate this objective error score for generated images. It might be possible in the case of MNIST images because the images are so well constrained, but in general, it is not possible (yet).

针对MNIST数据集,他的评估方法包括:
1)周期性的检查判别器在区分真图片和假图片的性能
2)周期性的将生成器所生成的图片保存到硬盘,用于人眼主观检查
3)周期性的保存生成器模型

2.5 如何利用最后的生成器模型来生成图片

这部分相对来说比较简单,因为前文中提到,在GAN的训练过程中,已经周期性的保存了生成器的模型,那么就可以使用这部分保存的模型来进行图片的生成。
同时需要注意的是,这部分使用生成器进行图片生成时,需要一个随机的种子来驱动。

def generate_latent_points(latent_dim, n_samples):
	# generate points in the latent space
	x_input = randn(latent_dim * n_samples)
	# reshape into a batch of inputs for the network
	x_input = x_input.reshape(n_samples, latent_dim)
	return x_input

# load model
model = load_model('generator_model_100.h5')
# generate images
latent_points = generate_latent_points(100, 25)
# generate images
X = model.predict(latent_points)

3. 小节

通过文章[3],能够大致了解了GAN模型的构造及训练过程,其中比较关键的就是训练过程(关于具体的训练过程中的设置,见另外一篇文章);还有他这里提到了 一个比较关键性的问题,无法评估GAN的性能,这里能够评估是因为处理的数据集比较简单,同时是简单的数字图片所以可以人为的来进行评估,但是其他任务很难实现一个比较好的目标函数。

4. 后记

文章后面还包含了一些GAN与AE和VAE的区别,还有一些训练的技巧,同时还有一个GAN训练MNIST数据的代码。不过,我还是没有理解这个东西他在一些地方的实际应用是什么,最后时根据需求只要判别器或者生成器吗?这部分还是需要进一步来了解。

参考

[1]A Beginner’s Guide to Generative Adversarial Networks (GANs)
[2]教程 | 详解如何使用Keras实现Wassertein GAN
[3]How to Develop a GAN for Generating MNIST Handwritten Digits
[4]Generative Adversarial Nets in TensorFlow
[5]Wasserstein GAN implementation in TensorFlow and Pytorch

你可能感兴趣的:(深度学习,python,神经网络,人工智能)