back to index
GAN Lecture 1 (2018): Introduction

link |
整理&字幕由Amara.org社区提供
link |
整理&字幕由Amara.org社区提供
link |
在Quorra這個論壇上問說,最近在unsupervised learning的領域有什麼樣的breakthrough,然後Young Le Cong他就親自來回答了,他說adversarial training,我們今天要講的這個game的技術,是the coolest thing since sliced bread。
link |
since sliced bread是什麼意思呢?這邊你可以學到一個新的英文片,since sliced bread如果翻成中文的話,你可以翻成由始以來的意思。
link |
我Google了一下,是因為說在過去在賣這個吐司麵包的時候是沒有切片的,所以家庭主婦要買這個吐司麵包回去的時候自己切片,覺得很麻煩。
link |
後來有人就發明了切片的吐司,然後大家就覺得很高興。所以有一個好東西問世的時候,你就會說since sliced bread,可以翻譯成由始以來的意思。
link |
所以他說game這個技術是由始以來他覺得最酷的東西。
link |
這個是另外一個問題,有人問說在deep learning的領域最近有沒有什麼breakthrough,然後Young Le Cong他也親自來回答了,他說game跟它的種種變形是近十年來他覺得NL的領域最有趣的idea。
link |
所以Young Le Cong給game這個技術非常高的評價。在網絡上,你可以找到一個game的動物園,你就直接Google game加上zoom,就可以找到各式各樣相關的技術。
link |
因為現在你如果發明了一個新的跟game有關的技術,你就要在GAN前面加一些英文的字母。但是你知道英文的字母其實只有二十六個,所以很快的名字就統統都被用盡了。
link |
你會發現這個名字統統都撞在一起,比如說有兩個LS game,一個是least square game,一個是low sensitive game,完全是不一樣的東西,但是因為英文字母是有限的,很快的名字就都被用盡了。
link |
這個圖是什麼?這個圖是講說這個game的動物園裡面收錄了各種有名有姓的game,你可以自己去查查看,裡面光S game就有四個以上。
link |
它就統計了一下,到目前為止已經有接近三百種不同的game了。因為英文字母是有限的,所以甚至會發生這樣的情形,比如說這邊是variational approach for auto-encoder-generated adversarial network,按照它的名字,它應該叫做A game或者是AE game。
link |
但作者在paper裡面寫說,AE game已經被用掉了,然後看起來其他的英文字母也統統被用掉了,他只好把它叫做alpha game這樣。
link |
那在其他領域,不只是machine learning的領域,當然game是非常重要的。在其他領域,game其實也有很多的應用。
link |
我知道大家在image processing上會看到很多game的應用,但在其他和image processing沒有那麼直接相關的領域,你也可以看到很多game的應用。
link |
舉例來說,我最近才剛去了ICAS,ICAS是signal processing的conference,在ICAS裡面,我其實給了一個game的tutorial,在tutorial的開場,我就統計了一下近年ICAS跟game有關的paper。
link |
我用關鍵字看看哪些paper有包含這些關鍵字,看看哪些paper跟這些關鍵字是有關係的。
link |
我用generative這個關鍵字,你會發現說從2012年到2017年,generative有關的paper都很少,當然還是有一些啦,因為generative model不是只有game而已,它有很多其他的generative model,但是沒有非常多。
link |
如果用adversarial這個詞彙,在2013年的時候有兩篇paper,它的title有adversarial這個詞彙,不過它們跟game是完全沒有關係的。
link |
2016年這邊有一篇,它跟game其實也是沒有關係的。2017年有兩篇,它們確實是跟game有關係的,但到今年2018年就有40篇了,所以它成長的速度是20倍,所以按照這個速度,明年應該要有800篇。
link |
我其實也用了reinforcement這個詞彙當作對照組,你就會發現說其實reinforcement這個詞彙,它成長的速度就沒有adversarial它成長的速度那麼快,所以game它變成一個非常重要的技術。
link |
接下來的四週,我們都要來講game這個技術。今天我們要講的是最basic的idea,給你一個大的概念,假設你還不知道game是什麼的話,給你一個大概念,讓你知道說這個技術運作起來大概是什麼樣子。
link |
我們就先從game最基本的概念開始說起。在game裡面,我們想要讓機器做到的事情,是要讓機器來生成東西,舉例來說,讓機器生成影像,或者是假設在文字處理的領域,你會讓機器來寫詩,讓它產生句子,讓它來產生文章。
link |
那在generation這樣的process裡面,你需要做的事情,就是訓練出一個generator。那如果你要做的是影像生成,那這個generator做的事情就是,你隨便給它一個輸入,舉例來說,你random sample一個vector,你可能有一個高間distribution,你從高間distribution裡面random sample一個vector,把這個vector丟到generator裡面,generator就要產生一張image。
link |
那你丟不同的vector,它就應該產生不同的image。這個是image的generation。在文字的generation,在sentence的generation,是一樣,你丟一個vector,generator就輸出how are you,你輸入另外一個vector,它就說good morning,你再輸入另外一個vector,它就輸出good afternoon等等。
link |
好,那我們用game來達成的目標,就是要訓練出這樣子的NN的generator。那你可能會有點困惑說,輸入一個random的vector,讓它output一張image,或者是output一段詞彙,有什麼用?具體而言就是沒有什麼用這樣子。
link |
我們之後,我認為比較有用的是conditional的generation,也就是你可以輸入一些條件,比如說輸入文字,讓機器產生對應的圖片,或輸入圖片,讓機器產生另外一張對應的圖片。
link |
這個我們之後會講到,如果現在你不是輸入一個random的東西,而是輸入一個你了解那是什麼,你可以control的東西,比如說文字或者是影像,然後讓機器產生對應的東西,那這個技術就有非常多的應用。
link |
那這個我們之後再提,我們今天就只focus在讓機器吃一個隨機的項量,它就要output你想要的object,這樣子的application上。
link |
我們剛才講過說,在game裡面,我們想要訓練的東西,我們想要讓機器找出來的東西,就是一個generator,那這個generator它是一個neural network,那我們都知道說,所謂的neural network,它其實就是一個function,input一個東西,output一個東西,那在game裡面,它的input就是一個vector,如果今天是影像的生成,它的output就是一張image。
link |
或是講得更具體一點,在影像生成的話,generator的output就是一個high-dimensional的項量,generator的output是一個項量,那這個項量非常非常的長,那這個項量的每一個dimension就對應到影像中的一個pixel的顏色,那你把這個high-dimensional的項量排成一張影像的樣子,那你就可以讓generator產生一張圖片。
link |
或者是講得更具體而言,假設你今天要想要讓機器做二次元人物頭像的生成,那可能得到的結果就是這樣,你有一個generator,隨便給它一個項量,它的輸出就是一個二次元人物的頭像,那這張圖是機器真正生成的,我是用右上角這個程式生成的。
link |
而通常輸入的這個項量,它的每一個dimension會對應到圖片的某種特徵,也就是說你改變了其中一個dimension的數值,你就會發現說你產生出來的圖片的某種特徵有所改變。
link |
舉例來說,假設第一個dimension對應到的是頭髮的長度,那你把這個vector,它的第一個dimension值從0.1調到3,那generator的output就會是一個長頭髮的角色。
link |
或者說,假設這個input的vector,它的倒數第二個dimension對應到頭髮是不是藍色的,那值越大代表頭髮越藍,那你把這個值從2.4調到5.4,那你產生出來的角色就會變成藍頭髮的角色。
link |
這兩個角色看起來非常像,因為你只改了倒數第二維而已,其他維度的值是固定不變的,你只改了倒數第二維而已,所以它只改變了頭髮的顏色,那其他的特徵仍然會是很相似的。
link |
或者是說,假設最後一個維度代表的是嘴巴的大小,那本來這個值很小,所以它是無口的狀態,那你把這個值調大,然後它就笑起來了,就笑口常開這樣子。
link |
這個是generator,那在GEM裡面一個比較神奇的地方呢,就是你同時會訓練一個discriminator,那我們等一下會講說這個discriminator和generator之間有什麼樣的關係。
link |
那我先來看一下這個discriminator做的事情是什麼,這個discriminator它也是一個neural network,我們剛才有講過說neural network就是一個function,吃一個東西當作input就輸出一個東西。
link |
那discriminator它是吃一張圖片當作input,假設你今天要產生的是圖片的話,它就是吃圖片當作input,假設你今天要產生的不是圖片,是文句的話,是句子的話,那它就吃句子當作input。
link |
discriminator吃一張圖片當作input,它的輸出是一個scalar,是一個數值,這個數值代表什麼意思呢?這個數值代表說產生出來的這張圖片的quality,這個數值越大,就代表說產生出來的這張圖片的quality越高,它看起來越像是真實的圖片,它看起來越realistic。
link |
所以這一句要講的就是說,產生出來的這個數值越大,discriminator output的數值越大,就代表輸入的圖片越真實。
link |
舉例來說,假設你現在要做二次元人物頭像的生成,那你讓機器吃這張圖片,因為這個畫得很好,所以就是1.0,這個也畫得很好,所以output就1.0,我們假設1.0就是它可以輸出最大的值,或者是假設這個畫得很差,那機器可能就給它0.1分,這個也畫得很差,機器就給它0.1分,這個就是discriminator做的事情。
link |
等一下第三堂課的時候,助教會來講一下作業,我們要作業三做的就是二次元人物頭像的生成,那一樣分成三之一、三之二、三之三,那三之一就是做二次元人物的頭像生成,那等一下細節就交給助教來講。
link |
在game裡面,我們說有一個generator,有一個discriminator,那他們之間的關係就好像是獵食者跟他的獵物之間的關係,怎麼說呢?
link |
右上角這個,這是一隻枯葉蝶,這不是一個枯葉,這是一隻枯葉蝶,枯葉蝶長得跟枯葉非常的相似。那為什麼枯葉蝶可以長得跟枯葉非常的相似呢?那是因為有天擇的壓力,枯葉蝶的祖先也是彩色的。
link |
但是你知道,因為麻雀會吃枯葉蝶,所以枯葉蝶在天擇的壓力之下,牠就變成是棕色的。因為麻雀判斷一個蝴蝶能不能吃的標準就是看牠是什麼樣的顏色,如果牠是彩色的就會被吃掉,如果是棕色的就不會被吃掉,在天擇的壓力下,枯葉蝶的祖先就變成是棕色的。
link |
但是枯葉蝶的天擇也是會演化的,比如說這個東西牠是波波,然後波波進化就會變成比比鳥,如果我說錯了等一下記得修正我,還是比比鳥會進化變成波波?
link |
應該是比比鳥,我記得是對的,所以波波後來就進化成比比鳥。比比鳥判斷一個東西能不能吃的標準並不是看顏色,而是看牠有沒有葉脈的紋路,如果沒有葉脈的紋路還是會被吃掉的。
link |
所以枯葉蝶的祖先在天擇的壓力之下就產生了看起來像是葉脈的條紋,可以騙過比比鳥。其實比比鳥也會在進化,在進化可能有別的標準來判斷這個東西是不是可以吃的,枯葉蝶也會在不斷進化。
link |
所以獵食者和天敵就會在互相的結抗之中變得越來越強。而這個枯葉蝶就像是generator,而牠的天敵就像是discriminator。
link |
所以今天假設你要讓機器做二次元人物頭像的生成,首先你要準備一個database,這個database裡面有很多真實的二次元人物的頭像。
link |
接下來,一開始你的generator,我們說generator就是一個network,一開始它的參數是隨機的,所以一開始你的generator它也不知道要怎麼產生二次元人物的頭像,所以它只能夠產生看起來像是雜訊一樣的東西。
link |
那discriminator做的事情就是給它一張圖片,判斷說這張圖片像是generator生成的還是像是真實的圖片。然後接下來,generator要做的事情就是去想辦法填過第一代的discriminator。
link |
第一代discriminator可以分辨第一代generator的output和真實圖片之間的差異,舉例來說,它可能就用有沒有顏色來判斷它是真實的還是被生成的圖片。
link |
所以第二代的generator它進化了,它想要填過第一代的discriminator,所以它就會產生有色彩的圖片。但是discriminator跟著也會再進化,第一代的discriminator會被第二代generator產生的圖片填過,但是第二代的discriminator它會學著去分辨這兩種圖片之間的差異。
link |
舉例來說,它可能會發現說,如果是真實的圖片,它是有嘴巴的,如果是第二代generator產生的圖片,它是沒有嘴巴的。它就用這個標準來判斷說一張圖片是不是真正的人畫的二次元人物的頭像。
link |
generator就會跟著再進化,變成第三代的generator。第三代的generator產生出來的圖片可以填過第二代的discriminator,但是第二代的discriminator會進化成第三代的discriminator。所以這個generator和discriminator它們就會不斷地進化,所以generator產生出來的圖片就會越來越真實。
link |
因為今天這個generator和discriminator有一個對抗的關係,它們像是天敵與被獵食者之間的關係,所以用adversarial這個詞彙,adversarial就是對抗的意思,用adversarial這個詞彙來命名這個技術,叫做generative的adversarial network。
link |
有人就會問說,那爲什麽是讓兩個network互相對抗呢?爲什麽它們不能彼此合作呢?爲什麽世界不是充滿愛與和平呢?其實這個東西只是一種擬人化的說法而已。
link |
現在這個講法讓你覺得它們是在對抗的,因爲騙這個技術是Ian Goodfellow在2014年的時候提出來的。如果你看他原始的paper,它是用一個做假鈔和警察的例子,就是generator不斷地在做假鈔,它是壞人,它要做假鈔。
link |
discriminator是警察,他要去判斷說,現在這張鈔票是真鈔還是假鈔,最後generator會做的鈔票會越來越像真鈔,直到discriminator完全沒有辦法分辨爲何爲止。
link |
這個例子我其實沒有很喜歡,因爲這是一個充滿暴力與犯罪的例子。因爲你從那個例子看起來,generator跟discriminator是對抗的關係。但是你只要換一個例子,generator跟discriminator其實可以看作是合作的關係。
link |
你可以想成是,generator就是一個學生,discriminator是一個老師,是指導教授,generator要學習怎麽畫二次元人物的頭像。discriminator看過很多真人畫的二次元人物的頭像,他知道二次元人物的頭像應該長什麽樣子。
link |
所以一開始第一代generator就是一年級的學生,他不知道怎麽畫二次元人物的頭像,所以他畫出來的東西就非常的模糊、非常的奇怪。他就把這些圖片拿給老師看,那一年級的老師會給他feedback,告訴他說,
link |
你這些圖片跟真實圖片的差異是,真實的圖片有兩個圈圈,當然這只是一個擬人化的講法,等一下我們會具體地告訴你說實際上在train network的時候是怎麽樣子的。你不要以爲說他真的會講話,他不會講話,ok?
link |
他這個是一個比喻的講法,等一下會講說實際上train的時候是怎麽樣子的。discriminator發現說,這兩種圖片的差別是,這個有兩個圈圈,他都沒有圈圈。所以他就把這個資訊feedback給generator,告訴generator說,你畫的這些圖片跟真實圖片的差異是,你沒有畫兩個圈圈。
link |
那這個generator接下來就升上二年級,所以他會記得老師的教誨,他知道說在畫這個二次元人物頭像的時候,應該要把兩個圈圈點上去,然後他就把他畫出來的頭像再給二年級的老師看。
link |
他本來以爲老師會說他好棒,但其實老師只會說他好棒棒而已,因爲二年級的老師就變得更嚴格了。二年級的老師會告訴他說,你畫的跟真實的圖片仍然有很大的差異,因爲真實的圖片是彩色的,你畫的是沒有彩色的。
link |
所以generator接下來升上三年級以後,他產生的圖片就會變成是彩色的,然後generator就會不斷地進步,那discriminator會變得越來越嚴格,學生會畫得越來越好,然後老師會變得越來越嚴格,最後學生就可以畫出非常像是真的人所畫的二次元人物的頭像。
link |
在這個互動的過程中,你其實會發現有兩個問題。第一個問題是,爲什麽generator沒有辦法自己學呢?爲什麽一定要有一個discriminator介入?爲什麽generator沒有辦法直接從這些範例裏面學習怎麽產生二次元人物的頭像,爲什麽一定要透過discriminator才能學習呢?等一下我們會試著來回答這個問題。
link |
第二個更大的問題是,discriminator這麽會批評,爲什麽他不自己做呢?我相信大家都有這個困惑,對不對?老師爲什麽都不自己coding呢?老師爲什麽都只用嘴巴coding呢?等一下我們要來回答這個問題。
link |
所以這個generator跟discriminator之間的關係,他們就是寫作敵人念作朋友,寫作敵人念作朋友的意思知道嗎?就是像是塔史亮和近藤光的關係,或者像是佐助與名人的關係一樣,所以他們是朋友也是敵人。
link |
接下來我們就來正式講一下這個generator adversarial network它的演算法是怎麽運作的。我們之後會講到它的原理還有它背後的理論。
link |
我們今天先不講理論,我們就只講它操作起來,看起來像是什麽樣子。就算你對它的理論現在還沒有任何的了解,你其實從這個操作的過程,從這個演算法,你其實也可以體會到說,爲什麽它是一個有用的方法。
link |
我們有一個generator,有一個discriminator,它們都是network,那我們到train network的時候,一開始你的參數就是random initialize generator跟discriminator的network的參數。
link |
接下來你要iterative的去train這個generator和discriminator,你要跑很多的iteration,在每一個iteration裏面你要做兩件事,有兩個步驟。第一個步驟,你把generatorfix住,把generator的參數固定住,你只去調discriminator的參數,你只去traindiscriminator,把generator固定住。
link |
怎麽做呢?你有一個固定住的generator,然後你今天把一大堆的random vector丟到這個generator裏面,這個generator就會產生很多的圖片,因爲一開始這個generator它的參數是隨機的,所以它產生出來的圖片並不會特別好,可能是非常糟的。
link |
接下來你有一個database,我們剛才講過,如果你今天要讓機器產生某種東西,你要收集那種東西的範例,你要讓它產生二次元人物的頭像,你要收集很多二次元人物的頭像當作範例,你要讓機器寫詩,你要收集很多的詩詞作為範例。
link |
所以你有一個database,裏面都是二次元人物的頭像,你會從這個二次元人物的頭像database裏面sample出一些example,所以你現在有兩組圖片,一組圖片是從database裏面sample出來的,另外一組圖片是generator所生成的。
link |
那接下來你就要去訓練你的discriminator,你就要去調整你的discriminator的參數,那怎麼調discriminator的參數呢?你的目標就是,如果今天這個image是realistic的,就給它比較高的分數,如果今天這個image是generator所產生的,就給它比較低的分數。
link |
如果是從database sample出來的image就是高分,從generator產生出來的image就是低分,那你可以把它當作是一個regression的花紋,你可以把它當作是一個classification的花紋,反正不管你怎麼做,你就是要訓練這個network,
link |
讓這組圖片,就把這組圖片丟進去,output的分數就是大的,把這組圖片丟進去,output的分數就是小的。我講得更具體一點,你可能會說,你訓練的目標就是,把這四張圖片丟進去discriminator,它output的值要離1越接近越好,把這四張圖片丟到discriminator裏面,它output的值要離0越接近越好。
link |
用這個criterion去訓練你的discriminator,我相信這個在實作上對大家來說都不是問題,就跟一般訓練一個network做regression,或是訓練一個network做classification的意思是一樣的。
link |
接下來下一步,我們要固定住discriminator,我們只去調generator的參數,上來前一步是固定住generator,只調discriminator,現在discriminator訓練好了,固定住discriminator,只調generator。
link |
那怎麼調generator的參數呢?你先把一個vector丟到generator裏面,generator會產生一張圖片,接下來把這張圖片丟到discriminator裏面,discriminator會給它一個分數。
link |
那generator它訓練的目標就是要去騙過discriminator,但所謂的騙是一個擬人化的講法,實際上做的事情是,我們希望generator產生出來的圖片,discriminator可以給它比較高的分數。
link |
我們固定住discriminator的參數,只去調generator的參數,希望generator的output丟到discriminator以後,它output的值可以越大越好。
link |
那你可以想見說,剛才在前一步這裡面,我們已經把discriminator訓練好了,這個訓練好的discriminator看到好的image就會給它比較大的分數。
link |
那今天既然generator可以調整它的參數,使得它output的image,discriminator會給它高分,那顯然generator產生出來的image會是比較真實的,因為discriminator是看到真實的圖片才會給它高分。
link |
generator既然可以調整參數以後產生出來的圖片是discriminator會給高分的,那顯然generator產生出來的圖片會比較真實。
link |
實際上你在implement這個code的時候,你是怎麼做的呢?實際上你在implement的時候,你會把generator跟discriminator合起來,當作是一個巨大的network。
link |
這樣大家知道我的意思嗎?假設你的generator是五層,你的discriminator也是五層,你就是把前面的五層跟後面的五層接在一起,變成一個有十層的network。
link |
這個十層的network,input是一個vector,它的output就是一個數值。但是在這個十層的network裡面的其中一個hidden layer,它很寬,它的output就是一張image。
link |
這樣大家了解我的意思嗎?假設你這個是64x64的image,那你就會有其中一個hidden layer,它的output會output64x64的數值,它會output64x64位。
link |
你把那個hidden layer的output拿出來,你就可以把它看作是一張image。然後你在train這個network的時候,你就是固定最後幾個hidden layer,只調前面幾個hidden layer,讓它的output的值越大越好。
link |
因為我們現在是讓output越大越好,所以不是歸顛descent,歸顛descent是讓你的目標越小越好,那你做的事情其實是歸顛ascent,不過歸顛descent跟歸顛ascent其實意思是一樣的,你只是把你的objective function成一個負號而已。
link |
所以實際上在做的時候,你就是把generator跟discriminator接起來變成一個巨大的network,然後把這個巨大的network的最後幾個layerfix住,只train前面幾個layer,那目標是要讓整個network的output值越大越好。
link |
那你會發現說,因為你的目標是要讓整個network的output值越大越好,所以固定住最後幾個layer是非常有道理的。
link |
假設你不固定住最後幾個layer發生什麼事呢?因為目標是要讓output越大越好嘛,那他其實只要調最後一個layer的weight,讓他的值越大越好,馬上就可以讓最後的output爆表這樣子。
link |
但是因為最後的這幾個layer是固定住的,你只能夠調前面幾個layer,想辦法讓最後的output越大越好。
link |
好,那我們等一下講完這一頁以後,停下來問一下大家有沒有什麼問題,那我這邊更正式的把這個algorithm再講一次。
link |
我們有一個discriminator,他的參數是θD,我們有一個generator,他的參數是θG。
link |
好,那整個演算法就是這個樣子,你就call一下這個演算法,你就可以完成作業三之一了。這個演算法是這樣,對啊,就不是這樣嗎?
link |
這個database在作業三之一裡面是我們提供的,提供你一個很大的database,二次元人物頭像的database,有好幾萬張的圖片。
link |
好,那接下來呢,你從這個database裡面sample出n比example,sample出n張image,那這個n其實就是那個batch size,就像是我們train network的時候batch size,
link |
那n你要調一下,比如說32啊64啊,它是batch size。
link |
好,那同時呢,你要找一個distribution,那這個distribution其實我個人覺得沒有那麼重要,你可以在作業裡面verify一下你覺得這個distribution對你的結果有多大的影響。
link |
這個distribution可以是一個uniform distribution,可以是Gaussian distribution都可以,我們假設它是Gaussian distribution,你從Gaussian distribution裡面sample出n個vector。
link |
那至於這個vector的dimension要多少,要五維,還是十維,還是一百維,這個你自己決定,這是一個參數,你要調的,你就sample出n個vector,從一個Gaussian distribution裡面sample出n個vector。
link |
好,那接下來呢,你就根據這n個vector,你會去產生n張image,我們剛才有說generator就是吃一個vector,output一個image,那我們把generator產生出來的image用xdelta來表示。
link |
你就把這n個vector丟到generator裡面,讓它產生n張圖片,然後接下來呢,你就要去調整你的discriminator,所以前半部是在訓練你的discriminator。
link |
那怎麼調discriminator呢,底下這個式子只是一個範例,你可以用這個式子也可以用別的,那我們之後會講說,也許用別的結果會更好。
link |
但這個只是最原始的Gantt paper,它的式子是這樣寫的,它說,我們要去maximize這個objective function,這個objective function是什麼意思呢?
link |
首先呢,我們把n張真實的圖片拿出來,把它們都通過discriminator得到分數,然後呢,取一個log,再把n個圖片得到的分數通通拼平起來。
link |
那我們要讓這個objective function的值越大越好,那意味著我們要讓log d of x 越大越好,也就是我們要讓d of x 越大越好。
link |
所以這個式子告訴我們說,我們要訓練discriminator,讓它可以給這些真實的image的值越大越好。
link |
好,那這是第一項,第二項是什麼?第二項是說,把這些假的圖片,把這些generator產生出來的圖片,丟到discriminator裡面產生出一個value。
link |
那這邊你的discriminator其實會,你的那個output會先通過sigmoid,所以它的值會是介於0到1之間的,那你其實不要sigmoid也可以啦,
link |
不過這邊如果沒有sigmoid的話,你1減掉大於1的值再取log會有問題啊,所以你這邊就給一個sigmoid,所以這個d的值一定是落在0到1之間。
link |
那你可能會問說,為什麼一定要這樣?這個不一定要這樣,這樣做沒有比較好這樣子。
link |
之後我們在接下來的課程會告訴你說,這樣做其實不是最好的方法,這個只是就是最原始的方法,但你用這個方法是做得出來作業三之一的。
link |
好,那你今天呢,把這個假的generator產生出來的image丟到discriminator裡面,它還會給它一個分數,那你把1呢,減掉這個分數再取log,然後取平均值,希望這一項越大越好。
link |
希望這一項越大越好的意思就是,希望1減d of x delta的值越大越好。
link |
希望1減d of x的值越大越好的意思就是說,你希望d of x delta越小越好。
link |
你的第二項的意思是說,你希望訓練你的discriminator,這些discriminator如果把generate出來的image當作input的話,它off的值要越小越好。
link |
你有這樣一個objective function,你要去maximize這個objective function,怎麼maximize這個objective function呢?你就套一下gradient ascent,如果是gradient descent的話,這邊是減的。
link |
如果你要讓你的loss function越小越好的話,你會取gradient,然後乘這個learning rate,然後把它減掉,但是因為現在是要讓它越大越好,所以這邊是加的。
link |
你對你的objective function,取它的歸典,乘它的歸典,然後乘上learning rate,再加上原來的參數,你就得到新的參數,set of d。
link |
至於learning rate要怎麼調,你永遠可以用一些什麼addon等等進階的技術來設定這個learning rate。
link |
這邊在這個式子裡面,我們只寫說把這個set of dupdate一次參數,但至於說你要update幾次參數,其實這是另外一個hyperparameter是你要調的,你可以說在這邊,我執行這一項三次,我執行這一項五次都可以,這是一個參數你要去調它的。
link |
這個是訓練discriminator,訓練好以後,接下來我們要來訓練generator。
link |
那怎麼訓練generator呢?我們一樣去sample出n個random的vector,這n個random的vector不需要跟這n個random的vector一樣,它們可以就是另外sample n個random的vector。
link |
接下來你訓練的目標,我們剛才說generator要想辦法去騙過discriminator,如果把它的式子寫出來是什麼樣子,把它的式子寫出來就是這樣,你把這個random的vector丟到generator裡面,generator會產生一張image。
link |
這邊看起來有點複雜,log d of g of z,看起來有點複雜,但我們一個一個來看,g of z就是一張圖片,把z丟到generator裡面產生一張圖片,g of z是一張圖片。
link |
把這張圖片丟到discriminator裡面,d of g of z是一個數值,然後再把它取log,再對所有sample出來的data,一個batch裡面的data去平均。
link |
你希望這個值越大越好,也就是你的意思是說,你希望generator output出來的image丟到discriminator以後,它輸出來的值越大越好,這個是你要訓練的目標。
link |
接下來你用gradient ascent去調你的generator參數,希望它可以讓objective function的output值越大越好。
link |
那紅色的部分就是訓練generator,這兩個步驟就會反覆的執行,你訓練好discriminator,接下來訓練generator,再回頭去訓練discriminator,再訓練generator,這兩個步驟會反覆的執行。
link |
講到這邊,大家有沒有問題要問的呢?針對這個algorithm,有沒有問題要問的呢?
link |
沒有的話,我們就看一下實際上你應該要做出什麼樣的結果。
link |
這個是我實際上自己做了一下enemy-based generation的,在網路上可以找到database,連結在下面。
link |
我們在桌子裡面用的其實不是這個database,我等一下告訴你說那個database是哪來的。你就載了一個database下來,然後你就可以call一個game,你就可以開始去勸它了。
link |
這個是update一百次參數以後的結果,看起來像是這個樣子。
link |
update一千次以後,這個時候generator就知道說二次元的人物應該是有眼睛的,現在就把眼睛點出來。update兩千次以後,這個時候我發現它把嘴巴也點出來。
link |
update五千次以後,這個時候我們發現說動畫人物就是應該要有水汪汪的大眼睛,所以發現這個眼睛都變得很大,所以它們都有一個反白。
link |
接下來update一萬次以後得到的結果像是這樣,看起來有點像是水彩畫的感覺,它有很多地方都暈開了,看起來比較有二次元人物的頭像的樣子,只是感覺畫得沒有很好,是用水彩畫的,所以有一點暈開的感覺。
link |
這個是update兩萬次的結果,這個是update五萬次的結果,我就停在update五萬次的地方。
link |
我發現說這邊有很多頭像,已經看起來非常真實了,但這個其實並不是真的做得特別好的,這個是上學期同學教給我的結果,可以做到這樣,所以理論上你應該可以做到這樣。
link |
其實我們這一個學期用的是,他們其實用了自己收集的data,我們這學期用的就是他們收集的data,感謝他們提供他們收集的data給我們,所以理論上你這學期做出來應該就是要像這個樣子,所以這個看起來非常真實,比很多做畫會崩壞的動畫公司畫的都還要好了。
link |
還是有一些崩壞啦,看你可不可以做得更好一點。
link |
這個是二次元人物的生成,這個就是我們的作業三之一。當然也可以做三次元人物的生成,也可以做真實人臉的生成,這些人臉都是機器生成的。網絡上有一個名人臉的database,你載下來就可以讓機器學習產生真實的人臉。
link |
那你可能會問說,產生真實的人臉有什麼用呢?基本上沒有什麼用,因為隨便去路邊拍一個人,都會比機器產生的還要更加真實。
link |
但是有趣的地方是,機器可以產生你沒有見過的頭像。我們剛才有說,你input的vector代表了輸出圖片的特性,所以如果你input,這個只是舉例啦,實際上你這個input的vector通常不會設二維,這樣至少做個十維或者是五十維之類的,或者是一百維。
link |
假設你input 00,它output是這個人,input 0.9 0.9,它output是這個人。接下來你可以input這兩個vector之間的內差,input這兩個vector之間的interpolation,你就會得到這樣的output結果,你就會看到這兩個人臉之間的連續的變化,上面是更多的例子。
link |
我發現說,機器真的可以學到說,舉例來說,這個人臉是朝右看的,這個人臉是朝左看的。當機器要產生這個朝右看的人臉跟朝左看的人臉之間的內差的時候,它並不是把兩張臉疊起來變成一個雙面人,它自己知道說,朝右看的人臉跟朝左看的人臉如果內差的話,就是朝正面看。
link |
所以機器自己知道說,把這個人的臉轉正,然後再轉過來,這邊有更多的例子。機器要學到這件事,你完全不需要handcrafting,就並不需要給它什麼規則、物理模型,都不用,看很多真實的照片以後,它自己就可以學到這些事情了,這個是蠻神奇的。
link |
剛才講的是GEM的操作,其實如果你知道那些操作,你應該就可以做得出作業31了。接下來,我想要花一些時間從概念上講一下GEM的原理,為什麼它是這樣運作的。
link |
我們在開學的時候其實就有講過說,GEM其實可以被視為一種structured learning的技術。那什麼是structured learning呢?其實我們開學就有講過了,但我們再非常快地複習一下。
link |
所以structured learning的意思是說,我們都知道說,machine learning就是找一個function,input一個東西,output另外一個東西。
link |
但我們說,如果是regression task,machine就是output一個數值,如果是classification task,machine就是output一個class。但是如果你今天遇到的問題是更複雜的,你要機器的output不是一個數值,也不是一個class,它可能是一個sequence,它可能是一個matrix,可能是一個graph,可能是一個tree,這個時候這個任務就叫做structured learning。
link |
這個我沒講過了,舉例來說,translation是structured learning的問題,因為machine要輸出一個句子。語音辨識是structured learning的問題,machine要輸出一個句子。
link |
transfer,其實大家在作業二之二裡面已經有做了transfer,transfer其實也是一種structured learning的問題,所以也是input一個sequence,output一個sequence。那個人就想說,那我們說get是一個可以用在structured learning的技術,可不可以把get用在transfer上呢?
link |
可以這樣子,你那個sequence to sequence如果transfer起來的話,你其實可以再加上discriminator,可以讓它的回答更好這樣子,你要先把那個sequence to sequence先transfer到ok這樣子,不知道大家做得怎麼樣呢?
link |
那也可以讓機器產生一個matrix,什麼時候讓機器產生matrix呢?如果你要機器畫一張圖,那就是產生matrix。我們之前有講過說,舉例來說,你可以輸入這種圖案,讓它產生這樣子的真實的房子,或者是輸入黑白的圖片,讓它產生彩色的圖片。
link |
那你甚至可以輸入文字,讓機器產生image。所以我們在作業三之二裡面要做的事情,就是要大家輸入一些二次元人物頭像的特徵,比如說頭髮顏色、眼睛的顏色,來輸出對應的二次元人物的頭像。
link |
這個是在作業三之二要大家做的事情細節,我們就下週再公告。為什麼structured learning它是一個特別具有挑戰性的問題呢?首先我覺得structured learning它可以被視為是一個one-shot learning或者是zero-shot learning。
link |
什麼叫做one-shot learning或者是zero-shot learning呢?假設你今天有一個分類的問題,你要做分類的問題的時候,每一個類別你都要給機器一些例子。
link |
舉例來說,你要機器分別蘋果和橘子之間的差異,你要給它一百張蘋果圖片、一百張橘子圖片,它才能夠分辨說給它一個水果是蘋果還是橘子。
link |
所謂one-shot learning或者是zero-shot learning的意思是說,假設有些類別你根本沒有任何的範例或者是只有非常非常少的範例,那你能不能夠做得起來?
link |
我覺得structured learning這個問題,它可以想成是一個極端的one-shot learning或者是zero-shot learning的problem,因為在structured learning裡面,你output的東西是一個structure,比如說一個句子。
link |
那在你的整個training data裡面,從來沒有可能沒有任何句子是重複的,你的testing data跟training data,它們的句子可能也是完全沒有重疊的。
link |
假設我們把每一個不同的句子,就假設你今天做的是structured learning上讓機器output一個句子,比如說翻譯,假設你今天把各種不同可能的每一種output都視為一個class的話,
link |
那每一個class,在training data裡面每一個class,它可能就只出現一次,而testing data出現的那些class更慘,它根本在training data裡面根本就沒有出現過。
link |
所以假設我們把每一種機器可能的output視為一個class的話,那其實structured learning是一個極端的one-shot learning或者是zero-shot learning的problem,所以因為這些class,它都只會出現一次。
link |
所以在這種structured learning的task裡面,如何學到一般化,如何學著去輸出從來沒有看過的東西,就變成一個很重要的問題。
link |
那你可以想像說,要讓機器做到這件事情,要讓機器可以輸出它在training的時候從來沒有看過的東西,那這個機器是需要有一定程度的智慧的。
link |
或者是講得更擬人化一點,講得更像農場文言典的話,機器必須要學會創造,它才能夠解structured learning的問題,因為它在testing的時候,它需要輸出的正確答案很有可能是training的時候它一次也沒有看過的,那這個東西我們就可以把它視為是一種創造。
link |
如果今天機器要解決structured learning的問題,它必須要有規劃的概念,它必須要有大局觀,因為今天機器要產生一個很複雜的物件,而這個複雜的物件是由很多比較簡單的component所組成的。
link |
舉例來說,如果是影像生成的話,機器仍然是產生一個一個pixel,但是所有的pixel合起來必須要能夠變成一張人臉,那機器在產生這張圖片的時候,它一定要在心裡plan清楚說,我點這個pixel上去代表是眼睛,點這個pixel上去代表是嘴巴,才不會變成說畫三隻眼睛、畫兩張嘴巴等等。
link |
所以今天在這個structured learning裡面,真正重要的不是你產生了什麼component,而是component和component之間的關係。
link |
舉例來說,假設你今天說,我要讓機器學會畫一個數字、寫一個數字出來,那機器一開始說,那我在整張圖上面中間點一個點,那點一個點這件事情它本身是中性的,它不見得代表結果會是好的,也不見得代表結果會是不好的。
link |
假設最後機器畫出來的數字是長這樣,那結果是好的,然後畫出來的數字是長這樣,那整個就是壞掉了。
link |
文字的生成也是一樣,機器要產生的是一個完整的句子,甚至是一篇完整的文章,單看生成的一部分,你沒有辦法判斷它是好的還是不好的。
link |
這讓我想到一個可能是紀曉嵐的故事,紀曉嵐的故事是說,有一天紀曉嵐去幫翰林的老婆祝壽,然後就寫了一個詩,詩的開頭就是,這個婆娘不是人,然後大家都生氣了。
link |
還有下一句,九天玄女下凡塵,然後大家就高興了。
link |
這就告訴我們說,如果只看第一個句子,它是一個負面的句子,但是把第一個句子和第二個句子合起來,如果有大局觀的話,如果可以看整個完整的輸出的話,它就變成一個正面的句子。
link |
而這個東西,是機器在做structure learning的時候,它必須要學會的。
link |
所以,這邊想要表達的事情是,structure learning是一個有趣而又具有挑戰性的問題。
link |
我覺得gain其實是一個structure learning的solution,其實在傳統的structure learning的文獻裡面有兩套方法,一套方法是bottom-up的方法,一套方法是top-down的方法。
link |
bottom-up的方法是說,我們今天要產生一個完整的物件,機器是一個一個component分開去產生這個物件,這樣的缺點就是很容易失去大局觀。
link |
所謂top-down的方法是說,產生完一個完整的物件以後,再去從整體來看,看看說這個產生的物件好不好。
link |
這樣講有點抽象,等一下會具體地告訴大家說這件事實際上是怎麼做的。但是這邊的壞處就是,用這個方法,你很難做generation,這個我們會講到。
link |
而generator可以就視為是一個bottom-up的方法,而discriminator可以視為是一個top-down的方法。
link |
把這兩個方法結合起來,就是generator,versus,network,就是gain。
link |
好,那接下來我們想要跟大家分享的是說,我們剛才不是說有兩個問題嗎?第一個問題就是,為什麼generator不能夠自己學?
link |
我們就來看看說,generator是不是可以自己學?事實上generator是可以自己學的,我們說今天generator的學習就是input一個vector,output一個image。
link |
就假設我們現在用手寫數字當作例子,你用output一個vector,output一個數字的圖片,output不同的vector,就要產生不同的圖片。
link |
那要訓練這樣一個network的generator,訓練這樣一個NN的generator,怎麼做呢?
link |
我們知道說在傳統的supervised learning裡面,你就給networkinput跟output的pair,然後就是train下去,就得到結果了,對不對?
link |
那今天我們要generator輸入就是vector,輸出就是圖片,我們能不能夠收集這樣的pair呢?你當然可以收集這樣的pair,因為假設你有一個database,裡面都是一大堆的數字的圖片。
link |
接下來你給每一個數字assign一個vector,就結束了,因為你接下來就可以說,我train一個network,然後我們看說這個1,它的vector是0.1,0.9。
link |
所以輸入0.1,0.9,交到這個generator裡面,我就要output一張圖片,這個圖片跟它的目標,也就是這個1,越接近越好。
link |
這完全跟一般train supervised learning是一模一樣的,你就歸顛descent,train下去,就結束了,相信大家都可以秒implement這種network。
link |
那這個跟train一個classifier是一樣的,只是好像有點反過來,因為這邊是輸入一個vector,輸出一張圖片。
link |
那雖然說輸出圖片,你平常不會做輸出圖片這件事,但實際上你做的就只是輸出一個很強的向量而已,就是輸出一個很強的向量而已。
link |
那跟一般的分類就是相反的,一般的分類是輸入一個圖片,然後輸出一個向量,這個向量的每一個維度代表對應到某一個數字。
link |
所以這兩種generator training和classifier training,其實根本就可以用同樣的方式來train它。
link |
但是這邊的問題是,你怎麼產生這些數字呢?你要怎麼產生這些數字呢?
link |
當然你可以說我隨機產生,但是如果你隨機產生的話,到時候這個generator training可能會非常困難,因為這兩個1是很像的。
link |
但是如果他們input的vector非常不一樣的話,那可能很難認出一個network,input非常不一樣的東西,卻output非常像的東西。
link |
所以你可能會希望說,如果今天這兩張圖片它們有共同的特徵,它們對應到的這個vector就應該有某些相似之處。
link |
舉例來說,我在這邊assign這個vector的時候,1我都給它第一位是0.1,2的第一位給它0.2,3的第一位給它0.3,
link |
然後如果像左斜,第二位就給它負的值,像右斜,第二位就給它正的值等等。
link |
你可能會希望你input的這個vector,它跟output的東西的特徵還是有關係的。
link |
那這件事情怎麼做到呢?怎麼樣產生這樣子的vector呢?還是有辦法的,你可以認一個encoder。
link |
這個encoder是給它一張圖片,它把這個圖片的特徵用一個向量來表示,這個向量就是這邊的code。
link |
給它一個圖片,它把這個圖片的特徵用向量來表示,這個向量就是這邊的code。
link |
那怎麼train這樣的一個encoder呢?記不記得我們在講machine learning的時候,我們有講過一個技術叫做autoencoder。
link |
這個我想大家都應該記得,我只是很快很快地複習一下。
link |
autoencoder做的事情就是給一張圖片,它把它變成一個code。
link |
就autoencoder裡面有一個encoder,有一個decoder,encoder做的事情是給它一張圖片,它把這個圖片變成一個code。
link |
但是encoder本身不能夠自己train,一定要再加一個decoder才有辦法train。
link |
decoder是一個code,它會把這個code變成一張圖片。
link |
在training的時候給一張image,這張image被encoder變成一個vector,然後decoder會把這個vector解回原來的image,那你希望input跟output越接近越好。
link |
所以你今天在train一個autoencoder的時候,你就隨便選一張圖片,這張圖片變成code,這個code透過decoder變回原來的image,那你會希望input跟output越接近越好。
link |
那你仔細想想,這個decoder其實就是一個generator,我們剛才說那個generator做的事情就是給它一個code,要它產生某一張對應的圖片。
link |
那我們現在已經告訴你說,我們有一個encoder,它的工作就是產生一個圖片的code,所以這張圖片它對應的code就是這個。
link |
那decoder的學習就是看到這個code要產生那個code對應的圖片,所以這個decoder根本就是我們要學的generator。
link |
所以事實上你認好一個autoencoder以後,你把decoder拿出來,那個就是我們的generator,它就可以拿來產生image,你就可以隨便丟一些東西,它就會output你想要的image。
link |
舉例來說,你完全可以認一個數字的產生器,這個非常簡單,你回去一秒鐘就可以做出來,你認一個autoencoder,它的中間的code是兩維,
link |
然後你把那個decoder拿出來,隨便給它一個兩維的vector,它output就是一個數字。
link |
舉例來說,假設你現在給它這個是真實的例子,你給它-1.50,它就輸出這樣子的image,你給它1.50,它就輸出這樣子的image。
link |
那如果你在這一個四方形的範圍內等距的sample,你就可以看到一堆數字的連續的變化。
link |
舉例來說,第一維可能跟它有沒有圈圈有關,越往左就有圈圈,往右就是棍子。
link |
那如果是看這個縱軸的變化的話,可能跟它的方向有關,舉例來說,本來是朝左邊的,往上以後就會變成朝右邊的。
link |
那這個是autoencoder可以做的事情。
link |
那用autoencoder會有什麼樣的問題呢?你可能會遇到這樣子的一個問題,因為你的training data裡面的image是有限的。
link |
generator可能可以認到說,看到vector A產生這張圖片,看到vector B產生這張圖片,但是看到vector A跟vector B的平均,它到底會產生什麼樣的圖片呢?
link |
你可能覺得說,vector A對到的E是向左的,vector B對到的E是向右的,把這兩個東西合起來,應該產生一個是正的E。
link |
但是實際上並不一定是這個樣子,因為unknown的generator它是一個network,它是非線性的。
link |
A可以產生這個圖片,B可以產生這個圖片,把它們平均以後丟進去,未必產生出來的是數字,你可能拗不出來的東西就是noise。
link |
你實際train上看,很有可能會發生這樣子的狀況。
link |
那要怎麼解決這個問題呢?這個也是在machine learning那一門課裡面我們講過的技術,這個技術就是variational的autoencoder,也就是VAE。
link |
那在variational autoencoder裡面我們有說,encoder不只是產生一個code,這邊這個n代表它產生出來的code,它不只是產生一個code,它不只是產生一個vector,它還會產生每一個dimension的variance。
link |
接下來你從normal distribution裡面去sample一堆noise出來,把這些noise跟variance相乘,把這個noise加到你的code上面去。
link |
代表有加noise的code丟到decoder裡面,decoder要根據有noise的code還原出原來的圖片。
link |
那如果有這個技術的話,machine就會知道說,它不只看到vector A要產生數字,看到vector B也要產生數字,看到vector A加一些noise,看到vector B加一些noise,產生出來的東西也必須要是數字。
link |
所以有了variational autoencoder,你可以把你的decodertrain得更加穩定,你可以讓你的decoder,就算input的這個vector是在training的時候從來沒有看過的vector,它output的東西仍然可能是合理的option。
link |
好,那這個都是複習我們在machine learning那門課曾經講過的東西,接下來我們要講的是說,那這整套技術它少了什麼樣的東西?
link |
講到這邊不知道大家有沒有什麼問題想要問的呢?
link |
你說,那個是你自己決定的,它就跟never的參數一樣,是你要調的,但是通常這個code它會是一個low dimension的東西,因為我們通常的假設是這個樣子,假設你今天做的是image的generation,那你的decoder的output是image。
link |
那雖然image它是一個high dimensional的vector,但我們相信說這個image它在high dimensional中,它其實是一個low dimensional的metaphor,然後本質上它的分布是low dimension的。
link |
所以今天要產生這個image,你input的code不需要是high dimensional的東西,它只需要是一個low dimensional的vector就好了。
link |
但是到底dimension該多少,到底是五維、十維還是五十維,這個東西你是需要調一下的。
link |
train不起來,增加dimension會有效,但是增加dimension以後未必會得到你要的東西,因為我們今天train的是一個autoencoder,那你訓練的目標是要讓input跟output越接近越好嘛,對不對?
link |
那你要達到這個目標其實非常簡單,你把中間那個code開得跟input一樣大,那你把中間那個code開得跟input一樣大,那你其實就不會有任何loss,因為你只要學著一直copy就好了。
link |
但是這個其實並不是我們要的結果,所以今天雖然說你input的vector開得越大,你的loss可以壓得越低,但loss壓得越低並不代表你performance會越好,所以這個東西是需要調一下的。
link |
為什麼要有sigma,是嗎?你是說為什麼sigma要是train的?沒錯,所以今天假設我們沒有任何額外的constraint,我們只想要minimize reconstruction error,最後你train出來的結果,sigma就會變成0。
link |
但是實際上在training的時候還有另外一個條件,這個條件是說這些sigma的值不能夠太小,它要越接近,它其實需要在train的時候的criterion是希望這些sigma的值越接近越好。
link |
你不希望sigma太大,但是它也不可以太小,所以在這個前提之下,最後認出來的sigma並不會變成0。這樣有回答到大家的問題嗎?
link |
其實大家如果對這個東西有困惑的話,你可以去看一下machine learning的錄影,這個其實是我們在machine learning那一堂課有說過的。
link |
好,那這一部分接下來我想要講的是說,那這個autoencoder的training,它到底少了什麼樣的東西?
link |
仔細想想看,今天這個generator它在train的時候,它的目標是希望它的output跟某一張圖片越像越好。
link |
舉例來說,這個2是你input的圖片,那你就希望generator的output跟這個2越像越好。那什麼叫做越像越好呢?通常你計算的就是這兩張圖片它們pixel by pixel的差距,那通常每一個pixel它就是一個數字。
link |
所以真的在算這兩張圖片它們是不是相似的時候,你真正做的事情就是把這兩張圖片表示成兩個vector,接下來你就算這兩個vector的,比如說Euclidean distance,那這個東西就是你要去minimize的對象。
link |
這兩個vector,Euclidean distance,就代表這兩張圖片的差異的程度,那你就希望它這兩張圖片,它們的L1 distance或L2 distance越小越好。
link |
事實上,假設今天generator它確實可以完全copy你的target,那可能就沒有什麼太大的問題。但真正在training的時候,generator是會犯一些錯的,generator的capacity不會大到說它output的image一定跟它的target一模一樣。
link |
它勢必會有一些取捨,它沒有辦法完全copy這個output,它會選擇在某些地方不得不做一些妥協,沒有辦法跟它的目標一模一樣。
link |
但是這個時候,選擇在什麼地方做妥協就會變得非常的重要。舉例來說,這個是你的目標,今天有四個不同的generator,它們產生了四張這樣子的圖片。
link |
如果我們今天是看這個圖片跟這個圖片在pixel上相似的程度,你會發現說這兩張圖片差了一個pixel,這兩張圖片差了一個pixel,而下面這個圖片跟它差了六個pixel,這個圖片跟它差了六個pixel。
link |
所以對一個generator來說,假設你learning的時候是希望output圖片跟目標越像越好,那如果它今天不得不犯一些錯誤,它會傾向於產生這樣子的圖片,因為這樣子的圖片它的錯誤只有一個pixel,這樣圖片它的錯誤還有六個pixel。
link |
但事實上,假設你從人的觀點來看,你會知道說,這個是不行的,這個錯一個pixel,整個圖片看起來就不對了,整個看起來就不像是人手寫的數字,看起來就是錯的。但是下面這個case,它只是把筆劃弄得長一點而已。
link |
所以其實你是可以接受的,這個你是覺得可以的,這個你是覺得可以的。所以今天變成說,你不能夠只是單純地去讓你的output跟你的目標越像越好,單純讓你的output跟你的目標越像越好,你可能generator就會選擇產生這種圖片,而不是這種圖片。
link |
而今天在做這個structure learning的時候,我們有講過說,structure learning output就是一個比較複雜的結構,那裡面有很多很多的component,那今天component和component之間的關係是非常重要的。
link |
我們覺得,這張圖片是不行的,並不是因為這邊放了一個pixel有什麼不好,在這邊放一個pixel這件事情本身是沒有錯的,因為你如果說這邊放一個pixel,但是你可以把這邊補滿,這邊補滿,它仍然是一個像是人手寫的數字。
link |
所以並不是說,你把一個pixel在這邊塗黑是有錯的,而是把這邊塗黑以後,在相鄰的地方,你沒有把它跟著塗黑。所以今天在一個structure learning裡面,component和component之間的關係是非常重要的。
link |
但是其實在train一個generator去生成圖片的時候,你會發現說,一個network的架構其實沒有那麼容易地讓我們把component和component之間的關係放進去。舉例來說,今天假設你是做圖片的生成,那假設layer L就是整個generator的最後一個layer,就是最後一個layer,這個layer L它生出來的就是一張圖片。
link |
這個layer L的每一個neural,它顯然就對應到圖片裡的每一個pixel,它output的數值就是那個pixel塗的顏色的深淺。
link |
但是你會發現說,在這整個架構裡面,假設layer L-1的值是給定的,然後這個值是給定的,那事實上每一個layer的output,就假設你的weight已經給定了,那前面這邊的layer L-1的輸出也已經給定了,
link |
那事實上,每一個dimension的output其實是independent的,也就是說,比如說假設這個neural它產生了顏色,它希望它旁邊的人也跟著產生顏色,好產生一個看起來像是realistic的image。
link |
你會發現說,實際上這件事情是沒有辦法做到的,因為它們之間並沒有辦法互相影響,它就自己產生它自己的。它們並沒有辦法互相配合,一起去產生一個好的image。
link |
所以這個就是你單純的任一個generator困難的地方,但這個問題其實也不是沒有辦法解的,因為假設,雖然說如果只看一個dimension,你沒有辦法考慮pixel和pixel之間的correlation,但是如果你再多加幾個hidden layer,你就可以把這種correlation考慮進來。
link |
所以今天如果你不想要用discriminator,只單純用autoencoder的技術,想要做generation這件事情,根據我們的經驗,如果今天你有同樣的neural,一個是用game trend,一個是用autoencoder trend,往往就是用game的那個可以產生圖片,但是用autoencoder的那個,你需要更大的neural才能夠產生跟game接近的結果。
link |
所以今天如果你要把這個correlation考慮進去,那你其實會需要一個比較深的neural。
link |
這個是一個toy的example,這個時機要做的事情是說,我們train一個generator,而這個generator的input是一個二維的Gaussian noise,那它的output就是綠色的這些點,那它在output的時候,它的目標,我們是希望它能夠學會output這個藍色的是這個,不好意思,剛才講錯了。
link |
我剛才把這個東西講成綠色,抱歉,generator的output是藍色的這些點,綠色的是它的目標,是它學習的時候的目標,我們希望generator產生出來的,是綠色的這樣子的distribution。
link |
但實際上如果你用variation的autoencoder的技術去learn下去以後,你會發現說,你最好只能夠讓這個generator產生藍色的這些點,因為對generator來說,要考慮pixel和pixel,也就是dimension1和dimension2之間的correlation是有點困難的。
link |
它並不知道說,今天如果在x1的值很大的時候,x2如果值很大是好的,如果值很小也是好的,但如果值介於不大不小中間是不好的,它不太容易學到這件事。
link |
你就會發現說,它在這個distribution和這個distribution之間還有一大堆的點散布,在這個distribution和distribution之間有很多的點散布,而這兩個distribution,這兩個mixer,它們靠得太近了,generator根本就沒有辦法把它們分區分開了,這個是用variation的autoencoder可能會遇到的問題。
link |
我想我們在休息之前,我想給大家看一個東西,我們實際現場來關掉一些東西就可以了,一邊train還是可以一邊繼續講的。
link |
好,那接下來我們要問的第二個問題就是,為什麼discriminator它沒有辦法自己產生image呢?其實discriminator它可以自己產生image,只是它非常的卡這樣子,它非常的卡。
link |
好,所以我們來複習一下discriminator是什麼,discriminator就是輸入一個object,輸出一個分數,這個分數代表說輸入的東西有多好。那事實上呢,這個discriminator在不同的文件上,它可能有不同的名字,舉例來說,它可能叫做evaluation function,它可能叫potential function,它可能叫energy function。
link |
但是其實如果你在別的其他的領域曾經看過這些名詞function的話,比如說potential function,你想想看,它是不是也是吃一個input,然後就output一個scalar,這個scalar就決定說這個input有多好或者是多不好,所以discriminator在不同的領域其實是有不同的名字的。
link |
那我們能不能用discriminator來生成object呢?其實是可以的,那怎麼用discriminator來做generation呢?你就靠下面這個式子,不過我在講它怎麼做之前呢,我們先來講說discriminator相較於generator有什麼樣的優勢。
link |
那我們剛才有說過,generator在產生object的時候,它是每一個component一個一個獨立去生成的,所以對它來說,要考慮component和component之間的correlation是比較困難的,但對discriminator來說,要考慮component和component之間的correlation就比較容易了。
link |
對discriminator來說,因為你是產生完一張完整的image以後,再把這張image丟給discriminator,讓discriminator去給它評價,看它好還是不好。
link |
所以對discriminator來說,它可以輕易地告訴你說,這張圖片就是不好的,應該得到低分,給它這張圖片是好的,就應該拿到高分。
link |
那實際上怎麼做到這件事情呢?可能你的discriminator它也是一個componential neural network,這個componential neural network裡面有一個filter是長這樣子的filter,這個filter會去detect說有沒有isolated的pixel,有沒有pixel它周圍都沒有其他pixel,如果有這種,那就給它低分。
link |
所以對discriminator來說,當產生完一張完整的圖片以後,要檢查這張圖片裡面的component和component之間的correlation對不對,是比較容易的。在生成的時候,因為是一個一個component獨立生成,不容易考慮它們之間的關係。
link |
但是等整張圖片已經生成完以後,要再檢查這個關係對不對,是比較容易的。
link |
這個就是discriminator所佔到的優勢。那接下來我們要講說,那怎麼使用discriminator來產生東西呢?你就套用下面這個詞。
link |
假設你已經有一個discriminator,這個discriminator它確實可以鑑別說input一個x它是好的還是不好的,那怎麼拿這個discriminator來做生成呢?
link |
你就說,窮取所有可能的x,一個一個丟到discriminator裡面,看哪一個xdiscriminator會給它最高的分數或給它很高的分數,那個xdiscriminator會給它高分的x,就是生成的結果。
link |
那你可能會覺得非常的surprise說,有可能窮取所有的x,一個一個去檢查說,它丟到discriminator以後會得到高分還是低分嗎?
link |
假設你今天的x是一張image,那image就是由一堆pixel所組成的,有可能窮取所有pixel的顏色的組合,看說怎麼樣pixel顏色的組合會得到高分嗎?
link |
仔細想想,嗯,好像有一些難度,但這邊我要給你的答案就是,無視這個問題,我們先假設這一個窮取所有的x,看哪一個x可以得到高分這件事情,3號就是由某一個演算法可以做到這件事情。
link |
假設你很仔細地思考以後,也許你可以想出一個演算法來解這個ARGMax的花紋,如果你可以解這個ARGMax的花紋,你就可以用discriminator來做生成。
link |
但是這個生成是非常痛苦的,因為這個discriminator擅長的就是批評,它不擅長做有建設性的建議,它只擅長批評,就跟政論節目的名嘴一樣,你給它什麼東西,它都說這個是不好的,你叫它真的想一個好的東西,其實它是很難想出來的,這樣是很痛苦的。
link |
但是我們現在假設說它就是有辦法生成東西,接下來的問題是,在它有辦法生成東西的前提之下,我們怎麼樣訓練這個discriminator?
link |
當然我們在訓練discriminator的時候,簡單來說就是要給它很多好的example,告訴它這些好的example是高分的,給它一大堆爛的example,告訴它爛的example就是低分的,但是實際上我們手上只有好的example。
link |
我們手上真正有的,假設你是做二次元人物的生成,你手上的data是人生成的data,是人畫出來的二次元人物的頭像,這些東西通通都是好的,這些東西discriminator都應該給它高分。
link |
但是這個時候,你的discriminator只有positive example,只有正面的例子,完全沒有反面的例子。
link |
如果你只拿正面的例子去訓練你的discriminator,會發生什麼樣的問題呢?你會發現說,這個discriminator之後就會學到說,看到什麼東西,它都會覺得是正面的例子,都給它高分。
link |
因為它訓練的時候只有高分的東西,它從來沒有看過任何低分的東西,所以它就學到說,看到什麼東西,都給它高分就是對的。
link |
這個顯然不是我們要的。所以怎麼辦呢?我們需要給machine一些next example,但是從哪裡找next example這件事情就變得非常的關鍵了。
link |
如果你今天你找出來的next example非常的差,舉例來說,你就跟機器說,人畫的就是好的,就是要給高分,隨機產生一大堆的noise,這些noise就是要給它低分。
link |
對機器來說,它當然可以輕易地分辨這兩種圖片的差別,看到這種給它高分,看到這種給它低分,但之後給它這種圖片,也許畫得很差,但是它覺得說,這個其實還是比noise好很多,也會給它高分。
link |
這個不是我們要的。所以今天怎麼產生好的next example就變得很重要。
link |
假設你可以產生非常真實的next example,它這個其實還是有些錯誤,比如說這兩隻眼睛的顏色不一樣,你可以產生非常好的next example,這樣discriminator才能夠真的學會鑑別好的image跟壞的image。
link |
但是現在的問題就是,怎麼產生這些非常好的next example呢?你要產生這些好的next example,其實你也需要一個很好的process去產生這些next example,但是我們現在就是不知道要怎麼產生image,我們才要train model,這樣就變成一個雞生蛋、蛋生雞的問題。
link |
我們要有好的next example才能夠訓練discriminator,我們要有好的discriminator才能夠幫我們找出好的next example,但這樣就陷入一個雞生蛋、蛋生雞的問題。
link |
所以實際上怎麼解這個問題呢?你是用一個iterative的方法來解這個問題,所以你要怎麼訓練你的discriminator呢?這個訓練方法是這樣的。
link |
假設你有一堆positive example,假設你有一堆negative example,那一開始你的positive example是人畫的image,你的negative example是random sample出來的一堆noise。
link |
那在每一個iteration裡面,你的discriminator學會做的事情就是給這些positive example高的分數,給這些negative example低的分數。
link |
接下來,當你學會學出一個discriminator以後,你可以用這個discriminator去做generation,我們剛才說discriminator是可以做generation的,你只要會解這個argmax的problem,你就可以用這個discriminator做generation。
link |
你可以用這個discriminator,generate出一些一堆他覺得是好的image,這些image我們用xΔ來表示它,有了這些原來的discriminator覺得是好的image以後,
link |
接下來,在下一個iteration,你把原來random的image換成這些第一代的discriminator覺得是好的image,接下來再updatediscriminator參數告訴它這些是好的,這些是不好的。
link |
那你又有了新的discriminator,新的discriminator再解一次argmax的problem,因為discriminator變了,所以它可能會產生更好的image,這個process就一直反覆的循環下去。
link |
你可以只有一個discriminator,它去分辨圖片的好壞,它參數update以後,它可以去產生更好的image,然後接下來你就可以認更好的discriminator,不斷的反覆這個process。
link |
好,那這邊是一個圖示化的方式來講說,實際上這個運作看起來像是什麼樣子。
link |
這個紅色的線代表的是discriminator的value,你input一個object,這個object其實如果是image的話,它是分佈在一個很高微的空間中,那現在為了簡化起見,我們就說,假設我們的object分佈在一微的空間中,那object隨著它分佈的位置不同,discriminator會給它不同的分數。
link |
好,那你的real example,假設是落在這個地方,discriminator當然要給落在這個區域的東西高的分數,它應該要給其他的區域,就不在這個高分的區域,低的分數。
link |
但是因為實際上呢,這整個object可以分佈的space是非常巨大的,如果在一微空間裡面,你可能會覺得說,反正這個地方是高分的,那兩邊就應該給它低分的。
link |
但是如果是一個高微的空間,你很難去把高微空間裡面沒有出現real example的地方的分數都把它壓低,那所以實際上是怎麼做的呢?實際上的做法看起來像是這個樣子的。
link |
我們剛才講說discriminator在train的時候,它是iterate with the tree train的,假設一開始你的real data的分佈長這個樣子,那你有一些generate出來的data,你有一些next example,它的分佈是藍色的這個樣子。
link |
接下來呢,discriminator會去學著說,給綠色的點高分,給藍色的點低分,因為它只知道說要給這個區域高分,給這個區域低分,它可能沒有學到說到底要給這個區域多少分數。
link |
所以搞不好認完以後,這個區域的分數還比real data分數要高,這個是有可能的,因為你並沒有給機器concentrate說這個地方的分數是怎樣嘛,你只說這邊分數要高,這邊分數要低。
link |
那這個地方要怎樣,你其實是不知道的。
link |
接下來,你認出第一個discriminator以後,用這個discriminator去產生example,也就是說去找出這個discriminator的弱點。
link |
我們剛才說在這個iterative的process裡面,你認discriminator,然後接下來用discriminator去產生next example,也用discriminator去找出自己的弱點。
link |
那用discriminator產生next example的時候,我們有說怎麼讓discriminator做生成,就是看哪些圖片discriminator會給它高分,那些東西就是next example。
link |
如果是看這個例子的話,discriminator是給這些圖片高分,就如果你看這個discriminator,它其實在這邊分數是特別高的,所以它是給這些圖片高分,那這些圖片就是discriminator自己產生出來的next example。
link |
然後在下一個步驟裡面,discriminator產生出這些next example以後,它要學到說它給這些example低分,這些example高分,那discriminator的形狀就會改變,可能就變成這個樣子。
link |
然後這個process就反覆繼續下去,你就想說,這就好像是discriminator不斷去尋找它的function裡面的弱點,看看哪邊分數特別高,就某個地方如果不是real example,但它又凸起來,就在那邊sample一些next example。
link |
然後在下一個步驟,discriminator就會把那個區域的值壓下去,這樣大家聽得懂我的意思嗎?
link |
OK,那你說,這樣9不會overfit嗎?
link |
其實這個問題問得很好,這個問題其實還蠻難回答的,因為今天machine在做生成的時候,它就是看說它的real data長什麼樣子,它要產生像real data的東西。
link |
所以如果你今天你的data很少,確實有可能有overfit的狀況。如果你今天自己在勸gain的時候,你可以看看,如果你的data很少,其實你的gain也勸得起來,但是它勸出來的結果,你會發現說那些圖片就是data base裡面有的圖片。
link |
所以你會希望說你給它的圖片夠多,它可以產生一些data base裡面,它可以學到generalize的東西產生data base裡面沒有的圖片。
link |
但是這個又跟一般的training和testing不太一樣,所以今天在做gain的生成的時候,你其實很難知道說你到底有沒有overfit。
link |
OK,那其實最後你就希望訓練到說,現在對discriminator來說,在這個input space上面,只有有出現real data的地方,分數才是高的。
link |
這個時候你的next example跟positive example,它們的distribution就會重合在一起。當next example跟positive example它們的distribution重合在一起的時候,那你這個training的process就會停下來。
link |
這個是discriminator的training。假設我們今天知道說discriminator其實可以拿來做生成,你其實根本就不需要generator,你光憑藉著你的discriminator,你也可以做生成這件事。
link |
那你可以想說,有人真的拿discriminator來做生成這件事嗎?有的,其實有滿坑滿谷的work都是拿discriminator來做生成這件事。
link |
假設你熟悉整個graphical model的work的話,你仔細回去想一下,事實上我剛才講的那個trainingdiscriminator的process,其實就是general的graphical model的training,只是在不同的method裡面,講法會略有不同而已。
link |
舉例來說,我不知道大家對graphical model熟不熟,graphical model其實就是structure learning的一種,graphical model裡面又分成很多類,比如說有Bayesian network,比如說有Markov random field等等,有很多很多的技術。
link |
這邊其實並沒有列完所有和graphical model有關的技術,這邊列的其實是過去MLDS會講的東西。其實MLDS的名字是Machine Learning and Heavy Deep Structure,所以本來這一門課其實也是有一半的時間會講structure learning這個技術,只是現在後來發現,講到後來大家就不想聽了,大家都只想要聽deep learning。
link |
Structure learning那個大家不知道是什麼東西,所以大家其實是比較不想聽的,所以後來就不太講structure learning的東西,但是gen其實也可以被視為是structure learning的一種技術。
link |
而在structure learning的技術裡面,其中一個非常具有代表性的東西其實就是graphical model。
link |
如果你熟悉graphical model,比如說Markov random field或Bayesian network的話,你想想看,在Markov random field或Bayesian network裡面,你是定一個graph,然後這個graph上面有一個potential function,這個東西其實就是你的discriminator,其實那個graph就是一個discriminator。
link |
然後你輸入你的observation,然後那個graph會告訴你說,這組data產生出來的機率有多少,那個機率就是discriminator assign的分數。
link |
假設你不熟悉graphical model的話,這邊你聽不懂沒有關係,但如果你熟悉的話,你回去比較一下是不是graphical model裡面你的graph,你的potential function,你的Markov random field,你的Bayesian network,其實就是discriminator。
link |
你再回想一下,當你去train Markov random field或你train structure SVM,train種種的graphical model的時候,種種和structure learning有關的技術的時候,你是不是iterative地去train的,你做的事情是不是有positive,有next example,訓練出你的model,接下來用你的modelsample出next example,再去update model,其實就跟我剛才講的training discriminator的流程其實是一樣的,只是把同樣的事情換個名詞來講,讓你覺得不太一樣而已。
link |
你再仔細想想,它們其實就是同一回事。
link |
那這邊就講了generator跟discriminator,那我來比較一下generator和discriminator各自所遇到的問題。
link |
generator遇到的問題,generator的優勢就是它很容易做生成,因為generator在生成的時候很快,就是一個feedforward network,很快就可以生一個東西。
link |
它的缺點就是,它不容易考慮component和component之間的correlation,它在學習的時候,它只是去模仿某一個目標,所以它只學到了那個目標的表象,它沒有學到它的精神。
link |
假如講擬人化一點就是,它只學到表象,因為它只學pixel和pixel之間的相似程度,但它學不到大局,它學不到它的精神。
link |
如果我們看discriminator的話,discriminator的優勢就是,它可以考慮大局,但它的劣勢就是,你要叫discriminator生一個東西,真的是千難萬難,我們要去解一個argmax的problem。
link |
而要解那個argmax的problem,你勢必就必須要對你的discriminator model做一些假設,比如說在傳統的文獻裡面,你都必須要假設說你的discriminator model是線性的,你才有辦法解那個argmax的problem。
link |
但是你限制它是線性的,那意味著你又限制了它的能力。如果它是非線性的,你不知道要怎麼解那個argmax的problem,所以這個就是一個大問題。
link |
那過去在講structured learning的時候,講到這一段,講到要解argmax的problem,同學就會問我說,啊怎麼解呢?我通常都只能說,你就假設你可以解,然後大家聽了生氣了,所以後來就都沒有人要聽這一段這樣子。
link |
但是現在不一樣的地方就是,我們有了generator。generator做什麼事情呢?generator就是取代了這個argmax的problem。
link |
所以想像成說,我們本來要想一個algorithm來解這個argmax的problem,往往我們都不知道要怎麼解那個argmax的problem,使得整個這一套framework,假設可以解argmax的problem,聽起來沒有問題,但就是因為你不能解,所以聽起來就有很多的問題。
link |
但是現在我們用generator來產生next example,用generator來解這個argmax的problem。也就是說,我們說generator它就可以產生出x tilde,它產生出來的x tilde就是那些可以讓discriminator給它高分的image。
link |
你記不記得generator是怎麼train的?generator在training的時候,它是不是就是去學著產生一些image,這些image是discriminator會給它高分的。
link |
所以可以想成是,generator就是在學怎麼解argmax的這個problem,對不對?它在學習的過程中,它就是在學說怎麼產生discriminator會給它高分的那些image。
link |
所以過去我們是解這樣一個optimization的problem,現在比較不一樣,我們是用一個比較intelligent的方法,雖然比較intelligent,所以它是一個network,我們用network來解這個argmax的problem。
link |
所以從所謂gain有什麼好處呢?從discriminator的角度來看,過去不知道怎麼解argmax的problem,現在用generator來解argmax的problem,顯然是比這個方法更加有效,而且更容易一般化的。
link |
從對這個generator來說,它在產生object的時候,仍然是component by component的產生,但是它得到的feedback不再是什麼L1、L2的loss,不再是pixel by pixel的去算兩張圖片的相似度,它的loss將是來自於一個有大局觀的discriminator。
link |
希望透過discriminator的代理,generator可以學會產生有大局觀的結果。這個是一個用gain來產生的toy example,這個example跟剛才我們講VAE的時候看到的example其實是一模一樣的,我們只是換了一下顏色而已。
link |
剛才是藍色跟綠色,這邊換成藍色跟紅色。藍色的點是我們要generator去產生的distribution,是generator學習的目標,紅色的點是最終generator可以得到的結果。
link |
而我們這邊用的generator的架構跟前面一頁的VAE用的generator的架構是一樣的,但你發現說在學習之後有了discriminator,這邊的generator學出來的結果是比VAE的generator還要更好的。
link |
你會發現說在這個mixer和mixer之間是幾乎沒有點的。而對應到真實的應用,舉例來說,假設你要讓machine產生圖片,產生人臉,如果你用VAE,產生的人臉就會比較糊。
link |
假設說真實的人臉、清晰的人臉是一個mixer,那因為VAE會產生那種mixer和mixer之間的sample,所以它就會產生比較糊的人臉。如果你是用GaN,那你就會產生比較清晰的人臉。
link |
好,那今天這一頁是要跟大家比較一下GaN跟VAE之間的差別。這是來自於Google的一篇paper,這篇paper主要的內容其實是想要比較各種不同GaN的技術。
link |
我們之後會再提到這些名字,它比較了MM GaN、NS GaN、LS GaN、W GaN、W GaN GP、Dragon 還有BE GaN,就有各式各樣的GaN。然後它其實得到一個結論是農場文最喜歡的那一種。
link |
它得到的結論就是,所有各種不同的GaN,其實performance都差不多,之前做的事情都是白忙一場,這是農場文最喜歡的結論。
link |
那這個圖怎麼看呢?這個縱軸它是算一個FID score,這個我們之後再講。這個FID score是拿來量你產生的,這邊做的都是image的generation。
link |
FID score越小,代表說產生出來的圖片越像真實的圖片,所以這邊的值是越小越好。
link |
那對於不同的GaN,它們都試了各種不同的參數,那你知道GaN其實在training的時候是非常的sensitive的,所以往往可能只有特定某一組參數你才train得起來。
link |
所以它會發現說,GaN用不同的參數,它的performance有一個非常巨大的range。
link |
然後它們看不出說,它們做兩個不同的covers,一個是at list,一個是cypher tag,就是生成數字跟生成十種不同類別的圖案,它們做at list跟cypher tag。
link |
然後發現說,如果比較這兩個covers,不同的方法之間的差距,其實就看不出不同的GaN有什麼樣的不同,只知道說它們的range都非常大,你可以產生很好圖,也可以產生很壞的圖。
link |
那有一件事情,雖然它們payroll裡面沒有強調,但我覺得是蠻有意思的是,如果你比較VAE跟這些GaN的話,你可以發現VAE倒是明顯地跟GaN有非常大的差別。
link |
什麼樣的差別呢?首先VAE比較穩,你會發現說給它不同的參數,VAE的分佈是非常的集中的。
link |
但是假設我們比較各種不同的model,可以產生的最好的結果的話,我們剛剛講說VAE產生的圖片畢竟是比較模糊的,雖然它比較穩,但它比較難做到最好。
link |
所以你比較每一個model可以產生的最好的結果的話,你會發現VAE相較於GaN其實還是輸了一截的。
link |
主持人提出的資訊不足,請搜尋【資訊欄】。
link |
主持人提出的資訊不足,請搜尋【資訊欄】。