生成式对抗网络(GAN)(李宏毅2022)

到目前為止大家学到的network,都是一个function,你给他一个X就可以输出一个Y

我们已经学到各式各样的,network架构,可以处理不同的X 不同的Y

我们学到输入的X

  • 如果是一张图片的时候怎麼办
  • 如果是一个sequence的时候怎麼办

我们也学到输出的Y, 可以是一个数值、类别、sequence

目前讲过的network架构已经可以涵盖多数问题,

接下来我们要进入一个新的主题,把network当作一个generator来用,

特别的地方是,现在network的输入会加上一个random variable Z,

这个Z,是从某一个distribution, sample出来的,所以现在network它不是只看一个固定的X得到输出,它是同时看X跟Z得到输出

network怎麼同时看X跟Z,有很多不同的做法,就看你怎样设计你的network架构

  • 你可以说X是个向量,Z是个向量 两个向量直接接起来,变成一个比较长的向量,就当作network的input
  • 或者是你的X跟Z正好长度一模一样,把它们相加以后,当做network的input
  • 等等

Z特别的地方是 它是不固定的,每一次我们用这个network的时候,都会随机生成一个Z,所以Z每次都不一样,它是从一个distribution裡面,sample出来的

这个distribution,这边有一个限制是,它必须够简单,够简单的意思是,我们知道它的式子长什麼样子,我们可以从这个distribution,去做sample

 

举例来说这个distribution,可以是高斯分布和均匀分布(uniform distribution)。比如 你知道Gaussian distribution的式子,你知道怎麼从,gaussian distribution做sample

,所以这一个distribution,的形状你自己决定,但你只要记得说它是简单的,你能够sample它 就可以

【不用擔心這個 input 是一個 normal distribution、會不會對 output 來說有很大的限制 其實不會、因為通過一個 generator 以後、可以把一個單純的 normal distribution 凹成各式各樣複雜的形狀

所以每次今天,有一个X进来的时候,你都从这个distribution,裡面做一个sample,然后得到一个output,随著你sample到的Z不同,Y的输出也就不一样,所以这个时候我们的network输出,不再是单一一个固定的东西,而变成了一个复杂的distribution,同样的X作為输入,我们这边每次sample到,不一样的东西,通过一个复杂的network转换以后,它就会变成一个复杂的分布,你的network的输出,就变成了一个distribution

 那这种可以输出,一个distribution的network,我们就叫它generator

接下来我们要讲怎么训练出这种generator

Why distribution

在此之前,我们第一个要回答的问题是,為什麼我们需要generator输出是一个分布?输入X输出Y,这样固定的输入跟输出关係不好吗?為什麼需要输出是一个分布呢?

这边举的例子,是video prediction,就是给机器一段的影片,然后它要预测接下来会发生什麼事情

video prediction,那你就给你的network过去的游戏画面,然后它的输出就是新的游戏画面,下一秒的下一个时间点的游戏画面

有人可能会问说怎麼输出一张图片?

这个一张图片就是一个很长的向量,所以你只要让你的network,可以输出一个很长的向量,然后这个向量整理成图片以后,跟你的目标越接近越好

其实在这个github裡面,它不是直接把整个画面当做输入,它是从画面裡面只切一小块当做输入,就它把这整个画面切成很多块,然后分开来处理,不过我们这边為了简化说明,就当作network是一次,输入一整个这样的画面

如果你用我们学过的network training的方法,Supervise learning train下去,你得到的结果可能会是这个样子,这个是机器预测出来的结果(第三部分 Non-Adversarial)

有点模模糊糊的,而且中间还会变换角色,神奇的是那个小精灵,走著走著 居然就分裂了,它走到转角的时候,就分裂成两隻了,有时候走著走著还会消失

因為今天对这个network而言,在训练资料裡面同样的输入,同样的转角

  • 有时候小精灵是往左转
  • 有时候小精灵是往右转,

两种可能性,同时存在你的训练资料裡面

所以你的network,学到的就是两面讨好,

 所以你的network,它就会得到一个错误的结果,向左转是对的 向右转也是对的,但是同时向左向右转 反而是不对的,

那有什麼样的可能性,可以处理这个问题,一个可能性就是,让机器的输出是有机率的,让它不再是输出单一的输出,让它输出一个机率的分佈

当我们给这个network input,加上一个distribution Z的时候,它的输出就变成了一个distribution,它的输出就不再是固定的

我们希望训练一个network,它可以知道说它的输出的这个分佈,包含了向左转的可能,也包含向右转的可能

举例来说假设你选择你的Z,是一个比如说,binary的random variable,它就只有0跟1 那可能各佔50%,也许你的network就可以学到说,Z sample到1的时候就向左转,Z sample到0的时候就向右转,就可以解决,这个世界有很多不可预测的东西,的状况

那什麼时候我们会特别需要,处理这种问题,什麼时候,我们会特别需要这种,generator的model,当我们的任务需要一点创造力的时候

任务需要一点创造力这件事情,是比较拟人化的讲法,更具体一点的讲法就是,我们想要找一个function,但是同样的输入多种可能的输出,而这些不同的输出都是对的,

同样的输入有多种不同的输出,每个人都可以各自发挥,就算是人来处理这个问题,可能每个人的答案也都不一样,

举例来说,画图这件事情,可能就需要一些创造力

举例来说假设叫一个人,画一个红眼睛的角色,那每个人可能画出来,或者心裡想的动画人物可能都不一样,有哪些角色是红眼睛的

那这个时候,我们就需要让机器能够,让我们的model,能够output一个distribution

那还有什麼样的例子,会需要用到创造力,举例来说 对话这件事情

 

Generative Adversarial Network (GAN)

generative的model,其中一个非常知名的,就是generative adversarial network,它的缩写 是GAN,那我们这一堂课主要就是介绍,GAN

它其实有很多各式各样的变形,你可以在网路上找到,一个GAN的动物园,找到一个GAN的zoo

 那个GAN的动物园裡面,收集了超过五百种以上的GAN,每次有人发明了,一个新的GAN的时候,他就会在前面加一个英文的字母,但是英文的字母是有限的,很快的英文的字母就被用尽了

举例来说在GAN的动物园裡面,至少就有六种的SGAN,它们都是不同的东西,但它们通通被叫做SGAN,甚至还发生了的状况,有一篇paper他提出来的叫做,“Variational auto-encoding GAN”,照理说应该所写成,AEGAN或者是AGAN,但是作者加了一个註解说,哎呀AEGAN被别人用了,所有的英文字母,看起来都被别人用了,我只好叫做α-GAN

Anime Face Generation

我们现在要举的例子,就是要让机器生成二次元人物的脸,我们举的例子是Unconditional的generation,,就是我们这边先把X拿掉,所以我们的generator它输入就是Z,它的输出就是Y

 那之后我们在讲到conditional,generation的时候,我们会再把X加回来,

那输入的这个Z是什麼,我们等一下都假设Z是从一个normal distribution里sample出来的向量,那这个向量通常会是一个,low-dimensional的向量,它的维度其实是你自订的,你自己决定的,那通常你就订个50啊100啊,的大小,它是你自己决定的

 好你从这边 normal distribution Z,裡面sample一个向量以后,丢到generator裡面,Generator就给你一个对应的输出,那我们希望对应的输出,就是一个二次元人物的脸

那到底generator要输出,怎麼样的东西,才会变成一个二次元人物的人脸,其实这个问题没有你想像的那麼困难

一张图片就是一个非常高维的向量,所以generator实际上做的事情,就是產生一个非常高维的向量,举例来说 假设这是一个64X64, 彩色的图片,那你的generator输出就是64X64X3,那麼长的向量 把那个向量整理一下,就变成一张二次元人物,这个就是generator要做的事情

当你输入的向量不同的时候,你的输出就会跟著改变,所以你从这个,normal distribution裡面, Sample到不同的Z,那你输出来的Y都不一样,那我们希望说不管你这边sample到什麼Z,输出来的都是动画人物的脸

那讲到这边可能有同学会问说,这边為什麼是,normal distribution?

可以是别的,这边选别的你其实也会问同样的问题,就是了,那我(李宏毅本人)的经验是不同的distribution之间的差异,可能并没有真的非常大,不过你还是可以找到一些文献,试著去探讨不同的distribution之间,有没有差异

但是这边其实你只要选一个,够简单的distribution就行,因為你的generator会想办法,把这个简单的distribution,对应到一个复杂的distribution,所以你可以把选择,distribution这件事情,交给你的generator来处理,那这边我们在等一下的讨论裡面,都假设是一个,normal distribution

Discriminator

在GAN裡面,一个特别的地方就是,除了generator以外,我们要多训练一个东西,叫做discriminator

discriminator它的作用是,它会拿一张图片作為输入,它的输出是一个数值scalar,这个discriminator本身,也是一个neural network,它就是一个function.,输出的scalar越大就代表说,现在输入的这张图片,越像是真实的二次元人物的图像

至於discriminator的,neural network的架构啊,这也完全是你自己设计的,所以generator,它是个neural network,Discriminator,也是个neural network,他们的架构长什麼样子,你完全可以自己设计,你可以用CNN 你可以用,transformer 都可以,只要你能够產生出你要的输入输出,就可以了

那在这个例子裡面,像discriminator,因為输入是一张图片,你很显然会选择CNN对不对,CNN在处理影像上有非常大的优势,既然输入是一张图片,那你的discriminator很有可能,裡面会有大量的CNN的架构,那至於实际上要用什麼样的架构,完全可以自己决定

Basic Idea of GAN

為什麼要多一个discriminator,这边就讲一个故事,这个故事跟演化是有关的

 那这个是演化的故事,对应到GAN 枯叶蝶就是generator,那它的天敌就是discriminator,

那现在我们generator要做的事情,是画出二次元的人物,那generator怎麼学习画出二次元的人物,它学习的过程是这样子

 第一代generator它的参数几乎是,它的参数完全是随机的,所以它根本就不知道,要怎麼画二次元的人物,所以它画出来的东西就是一些,莫名其妙的杂讯

discriminator接下来,它学习的目标是,要分辨generator的输出,跟真正的图片的不同,那在这个例子裡面可能非常的容易,对discriminator来说它只要看说,图片裡面有没有两个黑黑的圆球,就是眼睛,有眼睛就是真正的二次元人物,没有眼睛就是generator,產生出来的东西

接下来generator就调整它的裡面的参数,Generator就进化了,它调整它裡面的参数 它调整的目标,是為了要骗过discriminator,假设discriminator,判断一张图片是不是真实的依据,看的是有没有眼睛,那generator就產生眼睛出来,给discriminator看

所以generator產生眼睛出来,然后他可以骗过第一代的,discriminator,但是discriminator也是会进化的,所以第一代的discriminator,就变成第二代的discriminator,第二代的discriminator,会试图分辨这一组图片,跟真实图片之间的差异,它会试图去找出这两者之间的差异

它发现说,这边產生的图片都是比较简单的,举例来说都没有头髮也没有嘴巴,那这些图片是有头髮的也有嘴巴

 接下来第三代的generator,就会想办法,去骗过第二代的discriminator,既然第二代的discriminator是看,有没有嘴巴来判断是不是真正的,二次元人物,那第三代的generator就会把嘴巴加上去

那discriminator也会逐渐的进步,它会越来越严苛,然后期待discriminator越来越严苛,Generator產生出来的图片,就可以越来越像二次元的人物,那因為这边有一个generator,有一个discriminator,它们彼此之间是会互动

最早这个GAN是,Ian Goodfellow propose的,14年这个GAN的paper,是发表在14年的arvix,那最早在这个GAN的原始的,paper裡面,把generator跟discriminator,当作是敌人

如果你有看很多网路文章的话,它都会举例说,啊generator是假钞的啊,然后discriminator是警察啊,警察要抓做假钞的人啊,假钞就会越来越像,警察就会越来越厉害等等

因為觉得generator,跟discriminator中间有一个,对抗的关係,所以就用了一个,adversarial这个字眼,Adversarial就是对抗的意思,但是至於generator跟discriminator,他们是不是真的在对抗,这只是一个拟人化的说法而已,

所以generator,跟discriminator的关係啊,用动画来说就是写作敌人唸做朋友,就跟进藤光还有塔矢亮一样,或者是跟Naruto跟Sasuke一样

 

Algorithm

以下就是正式来讲一下, generator跟discriminator是如何运作的,

这个演算法实际上是长什麼样子,generator跟discriminator,他们就是两个network

network在训练前,你要先初始化它的参数,所以我们这边就假设说,generator跟discriminator,它们的参数 都已经被初始化了

Step 1: Fix generator G, and update discriminator D

初始化完以后,接下来训练的第一步是,定住你的generator,只train你的discriminator

一开始,generator的参数,是随机初始化的,那如果你又固定住你的generator,那它根本就什麼事都没有做啊,它的参数都是随机的啊,產生出来的就很像是电视机坏掉的,那一种杂讯

database里有很多二次元人物的头像,去爬个图库就有了,不难收集

接下来你就拿真正的二次元人物头像,跟generator產生出来的结果,去训练你的discriminator,discriminator它训练的目标是要分辨,真正的二次元人物,跟generator產生出来的二次元人物,它们之间的差异

讲得更具体一点啊,你实际上的操作是这个样子,你可能会把这些真正的人物都标1,Generator產生出来的图片都标0

接下来对於discriminator来说,这就是一个分类的问题,或者是regression的问题

  • 如果是分类的问题,你就把真正的人脸当作类别1,Generator產生出来的,这些图片当作类别2,然后训练一个classifier就结束了
  • 或者是有人会把它当作,regression的问题,那你就教你的discriminator说,看到这些图片你就输出1,看到这些图片你就输出0,都可以 总之discriminator就学著,去分辨这个real的image,跟產生出来的image之间的差异

Step 2: Fix discriminator D, and update generator G

我们训练完,discriminator以后,接下来定住discriminator改成训练generator,怎麼训练generator呢

拟人化的讲法是,我们就让generator想办法去骗过discriminator,因為刚才discriminator,已经学会分辨,真图跟假图的差异,真图跟生成的图片的差异,Generator如果可以骗过,discriminator它可以產生一些图片,Discriminator觉得,是真正的图片的话,那generator產生出来的图片,可能就可以以假乱真

它实际上的操作方法是这样子,你有一个generator,generator吃一个从gaussian distribution sample,出来的向量作為输入,然后產生一个图片

接下来我们把这个图片丢到,Discriminator裡面,Discriminator会给这个图片,一个分数,那generator它训练的目标,就Discriminator参数是固定的,我们只会调整generator的参数

Generator训练的目标,:generator调整参数之后,输出来的图片Discriminator,会给予高分,那意味著generator產生出来的图片,是比较真实的

 得更具体一点,实际上你的操作是这个样子,Generator是一个network裡面有好几层,Discriminator也是一个,network裡面有好几层,我们把generator跟Discriminator直接接起来,当做一个比较大的network来看待

举例来说generator,如果是五层的network,Discriminator如果是五层的network,把它们接起来我们就把它当作是一个,十层的network来看待

而这个十层的network裡面,某一个hidden layer它的输出很宽,它的输出的这个dimension呢,就跟图片裡面pixel的数目,乘三是一样的,你把这个hidden layer的输出呢,做一下整理以后 就会变成一张图片,所以这整个大的network裡面,其中某一层的输出就是代表一张图片

我们要做的事情是,整个巨大的network啊,它会吃一个向量作為输入,然后他会输出一个分数,那我们希望调整这个network,让输出的分数越大越好

但是要注意一下 我们不会去调,对应到Discriminator的部分,我们不会去调这个巨大,network的最后几层,(Discriminator)

我们只调generator的参数,好那这边呢,至於怎麼调Generator的参数呢,这个训练的方法啊,跟我们之前训练一般的network,是没有什麼不同的

我们之前说训练network的时候就是,定一个loss啊 然后你用gradient descent,让loss越小越好,那这边呢 你也有一个目标,只是这个目标呢不是越小越好,而是越大越好,那当然你也可以把这个目标,Discriminator output成一个负号,就当作loss。然后generator训练的目标,就是让loss越小越好

或者你也可以说,我们就是要让Discriminator output,的值越大越好,然后我们用gradient ascent,不是gradient descent,gradient descent是,让loss越小越好,gradient ascent会让你的目标函数,越大越好,我们会用gradient ascent去调generator,让Discriminator的输出越大越好

这是同一件事,这边训练generator的方法,也是用gradient descent base的方法,跟我们之前在训练一个,一般network的时候,是没有什麼差异的

所以现在讲了两个步骤

  • 第一个步骤 固定generator,训练discriminator
  • 第二个步骤,固定discriminator训练generator

接下来就是反覆的训练,discriminator跟generator,

所以你是训练一阵子discriminator,训练一阵子generator,训练一阵子discriminator,再训练一阵子generator,Generator跟discriminator,它们是反覆的去进行训练,当其中一种进行训练的时候,另外一个就固定住,那你期待discriminator跟generator,都可以做得越来越好,

助教是学生时做的:

 如果有很好的资料库,也许可以做出非常好的结果,

 

 用GAN可以产生没有看过的人脸,

不止可以输入一个向量,输出一个图片。 还可以把输入的向量做内插, 会看到两张图片间连续的变化,

 机器可以自己学到 往左看的人脸和往右看的人脸,内插会得到往正面看的人脸。

14年第一次听到可以产生图片,

 

 

 机器有时候也会产生一些幻想中的角色。。。网球狗。。。。

Theory behind GAN

前面用了一堆比喻说明GAN 的操作是怎麼进行的 接下来,我们告诉你说实际上,為什麼这个 Generator 跟 Discriminator 的互动,可以让我们的 Generator產生像是真正的人脸的图片,那这背后的互动在做的,到底是什麼样的事情

那我们先来弄清楚,我们今天的训练的目标到底是什麼?

我们在训练 Network 的时候,你就是要

  • 定一个 Loss Function
  • 定完以后用 Gradient Descent 去调你的参数
  • 去 Minimize 那个 Loss Function 就结束了

在这个 Generation 的问题裡面,我们要 Minimize,或者是 Maximize 什麼样的东西,我们要把这些事弄清楚,才能够做接下来的事情

我们想要 Minimize 的东西是这个样子的,我们有一个 Generator

  • 给它一大堆的 Vector,给它从 Normal Distribution Sample 出来的东西
  • 丢进这个 Generator 以后,会產生一个比较复杂的 Distribution,这个复杂 Distribution,我们叫它 P_G
  • 然后 我们有一堆的 Data,这
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值