打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
数据嗨客 | 深度学习第7期:生成对抗网络GAN

生成模型

机器学习的模型大体分为两类,判别模型(Discriminative Model)与生成模型(Generative Model)。判别模型是用来预测或判断输入的类别的。例如给我们一张动物的图片,让我们的分类器判断这个图片里的动物是不是牛,或者判断图片里的动物是什么,这都属于判别模型;而生成模型则是用来随机产生观测数据(或者根据某些随机生成的噪声来生成观测数据)。例如当我们给定一系列牛的图片,然后让我们的生成器根据这类图片再生成一张牛的图片。如果从数学的角度看,判别模型相当于学习一个条件分布P(y|x),而生成模型则相当于在学习一个概率分布P(x)。

在前面几篇科普文中,我们介绍的模型大多是以判别模型举例的。例如对于图片判断类别(Classification)、检测物体的位置与分类(Object Detection)或是分割(Segmentation),都是针对输入的图片进行某些信息的判断的。事实上,目前机器学习领域主要的工作也都集中在判别模型的领域。其中一个原因是因为判别模型目前应用的领域比较广泛,而另一个原因则是因为判别模型的训练要相对简单。

我们之前说过,神经网络的本质是一个万能的函数拟合器,其训练的方式是优化某一函数。当我们训练判别模型的时候,假设输入为x,其对应的label为y,而我们的模型为f(x,w),其中w为参数。则我们训练即优化loss(y,f(x,w))。无论选取何种损失函数,例如平方损失或交叉熵等等,其含义都十分清楚。并且最重要的一点是,将这些各个样本上的损失加和起来,其和Σloss(yi,f(xi,w))仍然是具有清晰含义的。

而对于生成模型而言,其损失函数的定义则十分不清晰。如果我们采取欧式距离,例如将生成图片与训练集的图片的欧式距离作为loss,则这个loss含义并不清晰。更重要的是,这种欧式距离是不适应叠加的。比方说,我有100张牛的图片,你用一个强大优化算法求出一张图片,使得该图片与那100张牛的图片的距离总和严格最小,找不到其他图片能够使得这个总距离最小。可是当你仔细看这张图片的时候,你可能完全看不出牛的样子(这张图片或许会是一片混乱的涂鸦,让人看不出任何有价值的信息)。正是由于生成模型的损失相对难以定义,所以其发展要比判别模型更加艰难。

如果换一个说法理解,我们可以认为判别模型能对一个高维输入给出一个低维输出(例如分类问题),或者对一个高维输入给出高维输出(例如分割问题)。而生成模型则是能对一个低维的输入或是一个高维的随机噪音输入,去生成一个有意义的高维输出。从这一点来看,也不难理解生成模型比起判别模型要更加复杂。

我们考虑一个基本的问题。当我们拥有一个包含10000张牛的图片的数据集时,如何建立一个生成器,使得其能够生成出一张全新的牛的图片? 当然,图片的生成不可能是凭空的。所以一般而言,我们建立的生成模型要接受一个随机的噪声为输入,然后输出一个牛的图片。这个噪声可以理解为牛的“随机种子”。对于更高级一些的模型,我们可以输入一些对于图片的具体要求,例如牛的大小、牛的颜色等等。模型接受这些人为设定的参数与一定的随机噪声,然后输出一个满足我们要求的图片。

目前,能够利用深度学习相关技术实现较好的生成模型的主要方法有三种,第一种是自回归类的方法,例如Pixel CNN等;第二类是自编码类的方法,例如VAE等;第三种则是对抗生成模型(GAN)。我们首先来简要介绍下前两种方法的主要思路,然后再开始详细介绍第三种,也即我们今天的主题GAN。

自回归类的算法基于一个基本的假设——我们要生成的数据在因果关系上是顺序的。在这个顺序的结构中,前面的元素决定了后面元素的概率分布。也就是说,对于所有的i,我们由模型得到P(xi|x1,x2,,xi1),并从中生成出xi。然后,我们再根据x1,x2,,xi去生成xi 1,并以此类推生成整个序列。

在目前的自然语言处理领域,例如“生成讲话”、“生成同人文”等一类应用中,最常见的生成模型都相当于在使用RNN(例如LSTM或GRU等)进行自回归。其首先学习给定数据集,学习语言的条件概率分布。然后再在随机初始化之后,根据学到的语言概率分布去生成序列。例如下面是一个生成讲话的例子:

在图片生成的领域,我们可以假定各个像素之间也是根据一定顺序排列而成的,并且像素之间也有因果的决定关系。例如,我们可以将图片中最左上角的像素命名为1号像素,将它紧邻右边的一个像素命名为2号像素,剩下的根据先从左到右,再从上到下的顺序排列好。然后,我们可以先随机初始化1号像素,接着根据1号像素生成2号像素,根据1、2号像素生成3号,根据1、2、3号像素生成4号。以此类推,生成整个图片。

Pixel-CNN大体上就是根据这种原理设计而成的。Pixel-CNN包含两个方向上的卷积网络,垂直的和水平的。垂直的网络可以看到所有需要预测的像素上方的像素 (在下图中微蓝色区域),而水平的网络可以看到所有该像素左边的像素(图中对应左边区域)。在训练过程中,为了避免看到“后面”的像素,它使用了带有掩膜的卷积;在生成图片时,需要从随机化的初始点开始,从左到右从上到下地一个个像素地生成图片。每一个像素由其左边与上面的像素决定。其示意图如下所示:

除了图像与自然语言的领域外,还有类似的自回归结构运用在别的领域也取得了成功。例如WaveNet在音频生成上取得了重大成功等。不过要注意的是,与语言、语音这种天然具有序列型的结构相比,将图像中的像素强行组织成这种顺序结构,从逻辑上是有一定不足的。这也导致虽然Pixel-CNN与WaveNet结构几乎差不多,但是目前Pixel-CNN在图片生成的领域远远不具有WaveNet在音频生成领域那样的地位。

第二种主要的生成模型是基于自编码(Auto Encoder)的方法。在之前的文章中,我们介绍过自编码是一种非线性降维的方法。它可以帮助我们找出将高维的信息编码成低维表示,并且解码恢复原有信息的方法。在自编码中,我们力图要优化的目标是重建损失。即假设我们原有的图片是X,编码器将X编码为z,解码器将z解码为X’,则我们要通过优化使得X与X’之间的差异(重建损失)尽量小。我们可以想象,这里的z是一种对于高维数据的稀疏表示。从这个意义上而言,人脑对于图片的记忆也是一个编码的过程——当我们看了一张高维的图片之后,我们不可能将其按照像素记忆,而是将其记忆为一些稀疏的信息。而解码则是根据这些稀疏的信息重新想象出原来图片的过程。

我们期望自编码技术可以达到人类智能一般强大的能力——将高维X编码为我们能够理解且含义清晰的稀疏信息z,例如牛有多大之类的。但是事实上,目前的自编码技术远远不具备这种能力。我们对X编码出来的z往往十分复杂,它是服从某个分布的隐含变量,并且我们并不知道如何显式地了解它与图片的关系。当我们随意生成一个z,将其交给解码器解码后,往往效果不好,甚至会得到混乱的涂鸦。这正是z是本身具有某种分布的随机变量导致的。所以,我们有两种方法利用自编码技术来建造生成模型。

其一是使用普通的自编码技术,接着用其它的生成模型来学习编码z的分布。然后,根据学习到的z的分布来生成一个全新的z’,再根据这个z’解码得到生成的图片。由于从X编码为z的过程已经进行了充分的降维,所以学习z的分布比学习X的分布要更加简单。我们用一些传统的生成模型即可做到这一点。但是现实中人们采取这种做法的并不多。

其二是一种被称为变分自编码(Variational AutoEncoder,简称VAE)的方法,这也是利用自编码技术做生成模型的主流。它与一般的自编码稍有不同。我们在使用VAE建立编码器与解码器的时候,不但像一般的自编码器一样考虑让解码后的重建损失尽量小,我们同时还要考虑让编码尽量接近正态分布。在VAE中,我们一般用交叉熵(KL散度)来衡量z的分布与正态分布的差异,KL散度越大则意味着z与正态分布的差异越大,反之则z越接近正态分布。故而在VAE中,我们要优化的损失是一个重建损失与KL散度的和。当VAE优化完成后,我们就得到了一个编码器,可以将我们手头的图片都编码成某个正态分布。而当我们根据该正态分布生成一个新的z时,将其放入我们的解码器进行解码,即可得到生成的图片。如下图所示:

我们已经介绍了自回归与VAE这两种常见的生成模型的思想。我们想象图片是一个高维数据(x1,x2,,xn),我们要求的是其联合分布P(x1,x2,,xn)。自回归的方法相当于将这个联合分布分解为一系列条件分布的连乘,即:


而VAE的方法则相当于将这个联合分布分解为隐变量的分布与关于隐变量的条件分布的乘积,即:


而GAN与上述二者不同。它相当于是“直接”解出联合分布P(x1,x2,,xn)。与上述二者相比,它在数学上的含义是更加模糊的。但是目前,它的效果是最好的。


生成对抗模型GAN

下面,我们来介绍GAN的基本结构。

我们有许多牛的图片,而我们希望利用深度学习技术来造这样一个生成模型——当我们输入一个随机产生的噪声图片,它通过我们的网络后,就能够变成一个“像模像样”的牛。 然而,深度学习技术本身是一种优化的技术。如果我们有一个“标准图片”,我们可以衡量输出与标准图片的距离,作为需要优化的损失。这样,经过多次训练之后,我们网络就可以把噪声输入给变得接近于标准图片一样输出。但是,在前面我们也已经说过了,上述的“标准图片”是不存在的。我们不知道何种损失才能衡量“是否像一头牛”。 GAN的想法是,既然我们不明白如何定义一个损失去衡量“是否像一头牛”,我们不妨将其想象成一个极其复杂的函数。既然是一个复杂的函数,则我们就可以用另外一个神经网络去拟合它。如果我们有一个完美的神经网络,判断一个图片“是否像一头牛”,则我们就可以根据这个网络提供的损失优化我们的生成网络。这事实上就是GAN的主要思想。 GAN的设计如下:它同时训练一个生成网络G与一个判别网络D。G的作用是接受随机的高维噪音作为输入,输出一个尽量像牛的图片。而我们将G网络输出的、企图伪装为牛的图片,增加一个“假”的标签,而将训练集里的牛的图片增加一个“真”的标签。将这一组混合了“真牛”与“假牛”的图片交给D网络,令其学习如何分别一个图片是否是真的牛。训练的过程就好像是一个对抗的过程,D是“火眼金睛”的警察,努力想辨别出G“造假”的图片;而G则是“以假乱真”的骗子,努力打磨自己的技术,企图有一天能够骗过D的眼睛,造出和训练集一模一样的图片。其示意图如下:

对于D而言,其训练是相对简单的。它的训练集是许多有标记的数据集,包括被标记为“真”的现实中牛的图片与被标记为“假”的G造出来的图片。我们可以建立一个CNN,其输入为图片,输出为一个经过压缩函数(Sigmoid或tanh)压缩到0与1之间的数,表示其为真的概率;也可以让其输出两个数,经过softmax之后,得到其为真的概率与为假的概率。总之,这可以做为一个二分类问题,或是一个回归问题,比较简单。

而对于G而言,其训练相对复杂。它的输入是高维噪声z,输出是造假的图片G(z)。在监督学习问题中,我们有一个标签L,我们的目的是让损失(LG(z))2尽量接近0。而这里,我们没有标签L,我们只有判断输出是否为真的函数D。所以此处我们的目的是让D(G(z))尽量接近1。通过回传损失log(1-D(G(z)))可以达到目的。

Goodfellow创立GAN的第一篇论文《Generative Adversarial Nets》中明确了其严格的数学定义:

理论上而言,GAN的训练是一个min-max的过程,即训练最终要优化的目标是:

这意味着,我们要在D做到最好的情况下,来优化G——这是合乎情理的——因为我们对G的训练是为了让它能够迎合D的判断。如果D的判断能力完全和人眼一模一样,而你让G去努力迎合D的判断,就是让G往正确的方向学习;而如果D完全是瞎判断,则你让G去迎合D的判断,起不到任何效果。一般来说,D越好的时候你让G去学习迎合它的判断就越有意义。这就仿佛是面对强大的对手时候,才能有效地提升自己。而面对太弱小的对手时,即使熟练地学会了击败他的方法,也毫无意义。

但是另一方面,如果D太强大而G太弱,也是无法训练的。因为D会将G(z)及其邻域都判断为0,导致G找不到更新的方向。这就好像遇到了强大的对手,你如何微调自己的技巧,都没有使得自己获胜的希望增加一点。这也是对于提升自己不利的。

所以,在GAN的训练过程中,为了求出上述的min-max点,我们一般同时、交替地训练两个网络。对D网络进行梯度上升,对G网络进行梯度下降。这样一来,两个网络就可以同时成长、同时提高。每个阶段他们都可以从与自己同等水平的对手进行对抗。训练初期,不太强大的G在努力学习造假,以骗过不太强大的D的眼睛;而不太强大的D则在努力学习辨认,企图找出不太强大的G造的赝品;等到了训练末期,强大的G已经可以造出以假乱真的图片,而强大的D也火眼金睛地能够察觉赝品中不起眼的细节。由于训练的过程充满了对抗性,所以被称为Generative Adversarial Nets,这也是GAN名字的由来。 具体而言,其训练方法如下:

在上述的图中,我们可以看到,我们要对D进行k步的梯度上升,然后才对G进行一次梯度下降,然后再对D进行k步梯度上升,再对G进行梯度下降……这是因为初代的GAN训练时候很不稳定。我们希望让D具有一定的判别能力后,再让G去学习迎合他。所以,我们总是期待D要比G更强一些。实验也证明了这样的方法效果比较好。

此外,在实际训练中,一般采用log(D(G(z)))来代替log(1D(G(z)))。这样可以加大梯度的信息,以便于训练。 对于GAN的训练过程,Goodfellow在其论文中给出了一个简单的图示:

在上图中,蓝色的虚线代表D对于模型为真的概率的判断——越高表示越有可能为真;黑色的虚线表示真实x的密度函数;绿色的实线表示G生成的“伪造品”的密度。

在训练的初始阶段,均匀的z全部被映射到了右边,形成了绿色实线的分布。它与黑色虚线代表的真实数据分布有所出入。而蓝色虚线此起彼伏,表示D的判断很随性,不能正确地分辨真假。

在训练的第二个阶段,D被训练得性能提高了。它知道真品的均值比较靠左,而赝品的均值比较靠右,所以它判断靠左的x都比较有可能为真,靠右的x都比较困难为假。

在训练的第三个阶段,由于D性能的提升,G也要努力学习迎合D。它知道D更有可能将靠左的x判别为真,所以它也竭力将不同的z生成的x靠左。而D也在根据G的提升做出相应的变化。

在训练的最终阶段,G的性能提升到了极致——它能生成完全与真实x密度一样的数据。而这时候D为了其性能最优,也只能将所有输入的x视为0.5为真,0.5为假了。此时,我们的目的便达到了。由于D成为了常数,所以D(G(z))也无法再进行更新,训练结束。

以下是GAN在MINIST(手写数字)数据集上训练的结果。其一开始生成的是一片混乱的噪音。随着训练,其逐渐能够写出一些有模有样的数字。到最后,GAN几乎能够生成与人类手写数字一模一样的数字。如下图所示:


GAN的变体

在GAN中,我们输入的是随机的噪音,我们也不能人为调整输入获得我们想要的输出,我们也不知道输入与输出之间的关系。例如对于用MINIST数据集训练好的GAN来说,我们只是随机地输入一个高维正态噪音z,输出一个手写数字。我们无法人为控制输出的手写数字是6还是9。

因此,我们会很自然地想到能否用一个有意义的数据作为输入,得到相应的输出。我们希望达到的理想的情况是我们能人为地调整输出,使得输出也相应发生调整。针对这种思想,Mehdi Mirza与Simon Osindero发明了CGAN(Conditional Generative Adversarial Nets)。

同样对于MINIST数据集的数字字体生成,CGAN尝试比普通的GAN更进一步。它希望能够接受一个人为指定的数字作为输入,然后输出对应的字体。

CGAN比起GAN而言,训练方式基本没有太大的变化,唯一的变化就是从GAN的无监督学习变成了有监督学习。(不过这和传统的图像分类这样的任务正好相反——图像分类是输入图片,然后对图像进行分类,而这里是输入分类,要反过来输出图像。这显然要比传统的图像分类问题更难) 我们让G网络的输入在z的基础上再额外连接一个输入y,然后在D网络的输入在x的基础上也连接一个y。这里的y是一个10维的one-hot向量,表示各个手写数字。例如(1,0,0,0,0,0,0,0,0,0)表示0而(0,0,0,0,0,1,0,0,0,0)表示5。然后,再将连接好的数据集放入网络中进行训练。其示意图如下:

相应地,我们将优化的目标改为:


可以看到,我们在CGAN中的优化目标由GAN的概率变成了条件概率。这也是其得名Conditional GAN的原因。与GAN类似,我们仍然交替训练两个网络,对D网络的参数进行梯度上升,对G网络的参数进行梯度下降。

利用CGAN训练MINIST数据集,做出的效果如下所示(其中每一行代表一种输入对应的输出):

在CGAN中,人们实现了人为调整输入,以获得所需输出这样的功能。但是,这毕竟还是一个有监督学习的过程,我们需要人为地对训练数据加上标签,才能实现这一点。因此,我们自然地想到,能否用一个无监督学习过程,让GAN自己学习特征?这就是Info-GAN的主要思路。

在Info-GAN中,我们将G网络的输入类似CGAN一样,在z上拼接一个c变量。不过这个c变量不是有监督的标签,并且神经网络也不知道它是什么含义。但是,在训练过程中我们希望c与G网络输出的x之间的互信息(mutual information)最大化,也就是让c不同的时候,整个输出的图片x尽可能强烈地发生变化。 同样是利用MINIST数据集进行训练,作者定义了10个one-hot变量,与2个连续变量,并且在训练过程中增大其与图片的互信息。很快,10个one-hot变量就学会了分别代表不同的手写数字,因为只有这样,其与图片的互信息才会足够大。

训练完毕后,我们尝试调节固定one-hot变量的前提下调整另外两个连续变量,得到如下的输出:

可见,由于训练过程中我们不断增大变量c与输出图片x的互信息,所以网络分别学会了两个最快地增大互信息的办法,那就是让两个c分别代表字体的倾斜度与粗细程度。当网络学习完毕之后,我们可以手动地设定数字、倾斜度与粗细程度的参数,输入网络,得到符合我们要求的输出。不得不说这是十分强大的功能。

要注意的是,上述的训练是在无监督学习下完成的,也就是说我们从来没有人为指定两个变量代表字体的倾斜程度与粗细程度,也没有人为地为此添加标签。我们完全只是利用互信息的概念,尝试在训练过程中增大c与x的互信息,这就导致c自动地学会了倾斜度与粗细程度的这两个属性。不得不说,这是一件十分神奇的事情。

在Goodfellow发明了基础版的GAN之后,许多人对其进行了改进。其中比较有代表性的改进除了CGAN、Info-GAN外,还有LAPGAN、DCGAN、GRAN、VAEGAN等等,有兴趣的同学们可以自己去查阅有关的论文。

这里我们再展示几个用GAN及其变体可以达到的神奇效果。例如生成的卧室图片:

例如用包含戴眼镜的男人、不带眼镜的男人,以及不戴眼镜的女人,生成戴眼镜的女人的图片:

例如根据客户给的涂鸦,生成一张风景图:

可见,GAN能有许多十分神奇的用处。

小结

本文中,我们主要介绍了生成模型。生成模型是为了学习一个分布,而判别模型是为了学习一个条件分布;生成模型一般接受低维输入,输出高维的结果,而判别模型一般接受高维输入,输出低维的结果。从各个角度来看,生成模型都比判别模型要更难。这也是目前针对生成模型的研究少于判别模型的主要原因。但是随着技术的发展,越来越多研究者开始将目光聚焦于生成模型的领域。

目前主要有三种利用深度学习的生成模型。第一种是自回归的模型,例如生成文字的LSTM、生成图片的Pixel-CNN,以及生成音频的WaveNet等等。它试图将一个联合分布拆开成为一系列条件分布的乘积,加以学习;第二种是VAE,它企图将联合分布拆开为隐含变量的分布以及数据关于隐含变量的分布,利用自编码的技术加以学习;第三种即是我们重点介绍的GAN,它企图直接学习整个数据的联合分布,是一种最接近于深度学习思维的算法。具体而言,它用一个D网络来学习数据联合分布的密度,用一个G网络来学习将低维噪声往数据联合分布的映射方式。它让二者同时训练、相互对抗、共同进步,使得最后G网络能够很好地生成以假乱真的数据。

GAN有许多变体,而我们主要介绍了CGAN与Info-GAN两种。它们都试图让输入的数据具有一定的意义,以实现通过人为调节输入来控制输出。具体而言,CGAN采取的是有监督学习的策略,需要将数据人为标注上人们能够理解的的数据特性;而Info-GAN则采取的是无监督学习的策略,希望网络可以自己学习到数据的一些特性。当Info-GAN学习完毕后,我们也常常能够看得出来其自主学习到的数据特性是什么,这正是其神奇之处。如果同学们想了解更多有关GAN的内容,可以自行查阅有关资料。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【百战GAN】新手如何开始你的第一个生成对抗网络(GAN)任务
生成式对抗网络模型综述:一文看懂各种GAN模型原理
「每周CV论文推荐」 初学GAN必须要读的文章
给图片悄悄加上像素级水印:防止AI「抄袭」艺术作品的方法找到了
生成对抗网络(GAN)的发展史
【仿真科普】什么是生成式人工智能?
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服