- Generative Adversarial Network(生成性对抗网络)
- Conditional Generation by GAN
二十八、Generative Adversarial Network(生成性对抗网络)
到目前为止已经有300种不同的GAN。
Outline
- Basic Idea of GAN
- GAN as structured learning
- Can Generator learn by itself?
- Can Discriminator generate?
- A little bit theory
(一)Basic Idea of GAN
1、介绍
在GAN中我们想要机器做到的事情就是让机器生成东西。举例来说来机器生成图片或者产生文章。在Generation这个process里面需要做的事情就是训练出一个Generator。如果你要做的是影像生成,这个Generator做的事情就是你随便给它一个输入,Generator就要产生一张image,丢不同的vector,产生不同的image。
比较有用的是Conditional Generation。
在GAN里面我们想要找出来的东西就是一个Generator,这个Generator是一个neural network(or a function),在GAN中它的input就是一个vector,output就是一张image(假设这里是影像生成,output也可以是一个high dimension vector)。
具体而言,假设想要机器做二次元人物的生成,随便给它一个向量,它的输入就是一个二次元人物。通常输入的这个向量的每一个dimension对应到图片的某种特征,也就是说你改变其中一个dimension的数值,你就会发现你产生出来的图片的某种特征有所改变,举例来说:
在GAN中有一个比较神奇的地方就是同时会训练一个Discriminator,这个Discriminator也是一个neural network(or a function),输入一张图片(假设这里是影像生成),输出是一个scalar,这个scalar代表产生的这张图片的quality,这个scalar越大,就代表产生这张图片的quality越高。
假设一张图片画的很好给它1.0分,画的很差给它0.1分(假设1.0最高):
举例:假设要让机器做二次元人物头像生成,首先你要准备一个database,这个database里面有很多真实的二次元人物的头像,加下来,一开始的Generator的参数是随机的,只能产生看起来像是杂讯的东西,Discriminator要做的就是给它一张图片判断这张图片像是Generator生成的,还是真实的图片。接下来Generator要做的事情就是想办法骗过第一代的Discriminator,第一代的Discriminator可以分辨第一代的Generator生成的图片和真实图片之间的差异,举例来说它可能以有没有颜色来判断它们;
所以第二代Generator想要骗过第一代的Discriminator,就要产生有颜色的图片,但是Discriminator也会跟着进化,第二代的Discriminator会学着分辨这两种图片之间的差异,举例来说它可能会发现真实的图片是有嘴巴的;
Generator就会跟着再进化变成第三代的Generator,第三代Generator产生出来的图片骗过第二代的Discriminator,第二代的Discriminator再进化成第三代的Discriminator…它们之间不断进化产生的图片就会越来越真实。Generator和Discriminator就像是天敌与被狩猎的关系,所以它们是“adversarial”(对抗的)。
2、算法
(1)初始化generator和discriminator
(2)在每个training iteration中:**Step1、固定住generator G,并且update discriminator D;**举例:有一个固定住的generator,然后把一大堆random的vector丢进去,然后会产生很多图片,接下来你有一个database,你会从中sample一些example,因此就会有两组图片,一组图片是generator产生的,一组图片是database中的。接下来去训练discriminator参数,如果是generator产生的就给它很低的分数,如果image是database中的就给它很高的分数。
**Step2、固定住discriminator D,并且update generator G;**举例:先把一个vector丢到generator里面,产生一张图片,再把这张图片丢到discriminator里面,discriminator会给它一个分数,generator训练的目标就是要骗过discriminator,discriminator给出比较高的分数。在前一步骤里面已经把discriminator D训练好了,它看到好的image就会给它比较大的分数。在实际中,会把generator和discriminator合起来当成一个巨大的network,这个network其中的hidden layer的output就是一张image。在train这个network时,固定最后几个hidden layer,只调前面几个hidden layer,让network的output值越大越好,这件事是Gradient Ascent。
算法步骤:
举例:三次元人物的生成:机器可以产生你没有见过的头像。假设input一个vector产生一张人物的image,input另一个vector产生另一个人物的image,接下来你可以input这两个vector之间的内差得到:
(二)GAN as structured learning
GAN其中可以被视为一种structured learning,structured learning的解释如下:
有哪些是structured learning的问题:
为什么structured learning是一个特别具有挑战性的问题?
首先,structured learning被视为one-shot learning/zero-shot learning,one-shot learning/zero-shot learning:假设今天有一个分类的问题,每一个类别都要给机器一些例子。假设有些类别根本没有任何的范例或者是只有非常少的范例,你能不能够做的起来。假设把每一个可能的输出当成是一个“class”,那么structured learning就是极端的one-shot learning/zero-shot learning的问题。从而如何学到一般化,如何学着去输出从来没有看到过的东西就变成一个很重要的问题。
如果今天机器要解决structured learning的问题,它必须要有规划的概念,必须要有大局观。比如,影像生成,机器每次产生一个pixel,但是所有pixel合起来能够变成一张人脸,机器在产生这张图片的时候能够清楚哪里是眼睛,哪里是头发。所以今天在这个structured learning里面,真正重要的不是产生什么component,而是component和component之间的关系。
Structured Learning Approach:两套方法–Bottom Up、Top Down。Bottom Up就是产生一个完整的物件需要一个一个component分开去产生,缺点是容易失去大局观;Top Down就是产生一个完整的物件以后,再去从整体来看产生的物件好不好,缺点是很难去做generation。Generator可以视为一个Bottom Up方法;Discriminator可以视为一个Top Down方法。
(三) Can Generator learn by itself?
事实上,generator 是可以自己学的,generator的学习就是input一个vector,output一个image。假设现在用手写数字当作例子,input不同的vector产生不同的图片。训练这样一个network的generator:在传统的supervised learning里面,就给network的input和output,然后train下去就可以得到结果。假设你有一个database,里面都是一大堆的数字的图片,接下来你给每个数字图片转换成vector。然后train一个network。这个和train一个classifier刚好是反过来的。
那么上面将图片转换成vector怎么实现呢?
可以learn一个encoder,这个encoder给它一张图片,它把这个图片的特征用一个向量来表示,这里的向量就是上面的code。
怎么train这个encoder呢?在Auto-encoder中,encoder本身没办法train,要再加一个decoder才能train起来。
仔细想想这里的decoder就是一个generator。
使用Auto-encoder会有什么样的问题?因为training data里面的image是有限的,generator可能可以做到,看到vector a产生一张图片,看到vector b产生另一张图片,那么看到vector a和vector b的平均会产生什么样的图片呢?
怎么解决这个问题呢?–Variational Auto-encoder(VAE)(变分自动编码器):
encoder不只是产生一个code,它还会产生每一个dimension的Variance。接下来从normal distribution去sample一堆noise出来,把这个noise和Variance相乘,把这个noise加到你的code上去,然后丢到decoder里面,然后deocder要根据有noise的code还原出原来的图片。如果有这个技术,machine就会知道它不止看到vector a要产生数字,看到vector b要产生数字,看到vector a加一些noise,看到vector b加一些noise,产生出来的东西也必须要是数字。
这整套技术(auto-encoder的training)少了什么东西?
真正在train的时候,generator会犯一些错,不会让产生的image和它的target一模一样,它会选择在某一些地方不得不做一些妥协。选择在什么地方做妥协就会变得非常重要:
component之间的关系至关重要,虽然highly correlated,但它们不能相互影响。但是在train一个generator去生成图片时你会发现一个network架构其实没有那么容易让文法component和component之间的关系放进去。
举例来说,假设你是做图片的生成,Layer L就是整个generator的最后一个layer,这个Layer L生出来的就是一张图片,这个Layer L的每一个neuron显然就对应到图片里的每一个pixel,它output的数值就是那个pixel涂的颜色的深浅。但是你会发现在这整个架构里面,假设layer L-1的值是给定的,那么layer L的每一个dimension的output是independent的。
每一个dimension之间无法相互配合一起去产生一个好的image,这就是单纯地learn一个generator困难的地方。但是问题还是可以解决的,如果多加几个hidden layer,就可以把这个correlation考虑进来。所以如果今天不想用discriminator,只单纯地用auto-encoder的技术想要做generator这件事情,同一个network,一个用GAN去train,一个用Auto-encoder去train,往往使用GAN的可以产生图片,而Auto-encoder需要更大的network才能产生和GAN接近的结果。
(四)Can Discriminator generate?
事实上,Discriminator可以自己产生image,只是会非常卡。
Discriminator相较于generator有什么样的优势?
generator在产生object时每一个component都独立去生成,所以对它来说要考虑component和component之间的correlation是比较困难的。但是对Discriminator来说要考虑component和component之间的correlation就比较容易了。对Discriminator来说是产生一张完整的image后再把这张image丢给Discriminator去评分,所以对Discriminator来说它可以轻易地告诉你这张图片好不好。
怎么做到这件事情呢?可能你的Discriminatory也是一个CNN,它的CNN filter可能长上图那样,如果有长成这样的pixel就给它低分。所以对Discriminator来说,去检查component和component之间的关系是比较容易的。
那么怎么使用Discriminator来产生东西呢?
假设你已经有一个Discriminator,这个Discriminator确实可以鉴别input x是好的还是不好的,那么怎么使用这个Discriminator来做生成呢?–穷举所有可能的x,一个一个丢到Discriminator里面,看哪个x,Discriminator会给它很高的分数,那么这个x就是生成的结果。
怎样去训练Discriminator?
给它很多好的example,告诉它是高分;给它一大堆烂的example,告诉它是低分。实际上,我们手上只有好的example,这个时候Discriminator只有正面的例子 ,没有反面的例子,拿正面的例子去train Discriminator会发生什么问题呢?会让Discriminator看到什么东西都给它正面的例子。
所以我们需要给machine 一些negative example,但是从哪里找呢?
如果今天给机器的negative example非常地差,比如人画的就是好的,随机产生一大堆noise,就是要给低分,那对机器来说当然可以轻易地分辨两种图片的差别,但之后给它不太好的图片,机器会觉得比noise好而给高分。
所以今天怎么产生好的negative example就变得很重要。假设你可以产生非常真实的negative example,这样Discriminator才能真正学会鉴别好的image和坏的image。所以怎么产生好的negative example?
是用迭代的方法来解这个问题的,这个训练的步骤是:
(1)假设有一堆positive example,随机产生一堆negative example
(2)in each iteration:1、Discriminator给positive example高的分数;给negative example低的分数。2、当你学出一个Discriminator以后,你可以用这个Discriminator做generation,你用这个Discriminator generate一些它觉得是好的image,这些image用
x
~
\tilde{x}
x~ 来表示:
有了这些原来的Discriminator 觉得是好的image之后在下一个iteration,把它替换到随机生成的negative example上:
以下用一个图示化的方式来展示Discriminator training的过程:
上图红色的线代表Discriminator的value,input一个object,随着这个object分布的位置的不同,Discriminator会给它不同的分数,它会给落在real example的区域高的分数,其它的区域低的分数。图示为一个一维空间,但在高维空间很难把real example没有出现的地方的分数都把它压低。
实际上的做法是:一开始real example和generated的分布如下图
接下来,Discriminator会学着说给绿色的点高分,给蓝色的点低分,但是没有学到给没有real example 和generated的区域多少分:
接下来,learn出第一个Discriminator以后,用这个Discriminator去产生example,也就是说去找出这个Discriminator的弱点,把原本第一个Discriminator觉得分数高的区域的分数压低:
这个过程反复进行下去。
对Discriminator来说,在这个input space上面,有出现real data的地方分数才是高的,这个时候你的negative example跟positive example它们的distribution就会重合在一起,当negative example跟positive example它们的distribution重合在一起的时候那这个training 的process就会停下来。
比较generator和discriminator:
generator取代了discriminator中discriminator自己产生negative example的问题:
GAN的好处:
(1)从discriminator来看,过去不知道怎么解agr max的problem,现在用generator来解这个problem:
(2)从generator的角度来看,产生object的时候仍然是component-by-component的,但是它得到的loss将是一个来自于有大局观的discriminator。
二十九、Conditional Generation by GAN
1、介绍
之前的GAN是随机输入一个vector然后产生一张image,Conditional Generation GAN就是你可以输入一个比如文字,然后产生对应那个文字的图片,也就是你可以操控你要输出的结果。那我们举的例子就是text-to-image:输入文字,产生对应的图片。
text-to-image这件事情可以当作一个单纯的supervised learning problem:需要一大堆图片,每张图片要对应的文字的描述,然后套用一个传统的supervised的方法:
但是光是这样做有什么问题呢?比如,火车对应的图片其实是有很多张的,现在如果要让你的network的output去产生一张train的image,出来的结果会是多张image的平均,那么就会是模糊的(因为图片分很多角度):
所以需要用到GAN的方法:
在原来的GAN里面,你的generator吃一个从normal distribution里面产生的
z
z
z,根据这个
z
z
z产生一张image
x
x
x,但在conditional generation里面,你的generator不是只吃
z
z
z,它同时也吃了另外一个东西–conditional text
c
c
c,根据这两个输入产生generative 的结果。
接下来,train一个discriminator,在原来的GAN里面discriminator只吃一张image
x
x
x,然后它告诉你这个
x
x
x 它的quality好不好。如果是real images就给它一分,如果是generated images就给它 0分。但是光这么做是不够的,假设你是用之前看到的方式来train discriminator的话,会发现generator在产生image的时候,它完全无视 input 的condition,它只要产生 high quality的图片就好了。
这个显然不是我们要的,我们希望机器是按照我们输入的condition产生不同的图片。所以要注意在做conditional GAN的时候你的discriminator不可以只看generator的输出,它要同时看generator的输入跟输出。这个时候你的discriminator有两个任务,discriminator吃一个condition跟吃一个object,然后产生一个scalar,这个scalar对应到两件事情,第一件事情是
x
x
x 是不是真实的;第二件事情是
c
c
c 和
x
x
x 合起来是不是应该凑成一对的。这两个东西加起来就是discriminator的output。
我们今天在train这种discriminator的时候,什么样的组合能给它高分呢?–一段文字加对应的image,合起来要给它高分。什么样的状况应该给它0分?–如果是正确的文字,跟generated的image要给低分;随机的文字加real image就要给低分。
2、Conditional GAN - Discriminator
在discriminator的network的架构上,常见的设计是:
input一个object,通过一个network把它变成一个embedding,condition也通过一个network也变成一个embedding,组合起来丢到network里面,然后network output一个scalar,这个scalar代表了两件事:一件事是input
x
x
x 有多好,同时又代表了
x
x
x 跟
c
c
c 合起来凑成一个pair有多合适。
但是有另外一种discriminator的架构,这种discriminator的架构在文献上看起来它的performance是不错的:有一个object进来,object先通过一个network就output一个分数,接下来这个network也吐出一个embedding,这个embedding跟condition结合起来丢到另外一个network中,吐出一个分数。现在吐出两个分数,一个只看object,它代表这个object是realistic还是不是realistic;另一个同时看了object和condition,代表这两个是不是应该被match在一起的。
下面这种架构performance更好。
Stack GAN:
先产生小张的图,根据小张的图再产生大张的图:
3、image-to-image
以上的例子都是text-to-image,也可以image-to-image:把黑白图转换成彩色的图;把白天转成夜晚;
要train这种network,首先要有training data,假设现在要做把图形转换成真实的房屋的样子,需要搜集很多简单的图形跟真实的房屋,然后去train一个network。
可以用supervised 方法来解这个问题,但是缺点是产生的图片比较模糊:
所以要引入GAN的概念:在GAN里面你的generator吃一个简单的图(condition)和noise
z
z
z产生一张对应的图片。然后discriminator吃generator的输入和输出的pair,它会给它一个分数,那么产生的图就会清晰很多。缺点是会产生一些奇奇怪怪的东西,如果今天给它下额外的constraint,希望generator的output跟training data里面目标的那个image同时也要越靠越近越好,那么对于generator来说有两个目标:一是要产生够清晰的图去骗过discriminator,二是generator产生的output不要跟原来的目标相差太多。
在image-to-image那篇paper里面,它的discriminator有稍微经过设计:如果今天产生出来的image非常大张,你的discriminator如果是吃整张image当作input的话,你的结果很容易坏掉。(图片太大,你的discriminator需要的参数也要很多,train的过程会坏掉)。所以在这个paper里面,它的discriminator每次只检查图片里面的一小块而已。检查多大的区域需要去调整。
4、GAN应用在语音
举例:可以用GAN这个技术应用在speech enhancement上:你有一段声音讯号,它被杂讯干扰,加了很多背景,你希望机器可以自动把背景去掉,通常有两个作用,一个是提高语音辨识的正确率,一个是让人听得更清楚。
如果是一般的speech enhancement,train的方式是找很多声音,把这些声音加上一些杂讯,接下来train一个generator,input一段有杂讯的声音,希望output没有杂讯的声音:
直接train generator产生的结果会比较模糊,所以要加入GAN的概念,不只要train generator,你还要train一个discriminator:
5、GAN应用在video generation
给generator看一段影片,然后让它预测接下来会发生什么样的事情,需要一个discriminator,同时看generator的input和output,把它们接在一起变成一段完整的影片,然后让discriminator分辨它是否是合理的:
本文是对blibli上李宏毅机器学习2020的总结,如有侵权会立马删除。