前言
大家好,筆者将在本文介紹一種基于UGATIT的圖像翻譯網絡,并且DIY,加入兩項額外的trick,使UATIT能支援漸進式的域遷移,即能實作A域的圖像樣本是如何逐漸向B域遷移的。我們叫該DIY模型為Morph-UGATIT。筆者在該項目的主要工作有:
- 首先基于UGATIT官方tensorflow源代碼,用PyTorch 1:1完美還原,包括網絡模型,訓練代碼,超參數。
- 在生成器(G)的loss中引入額外的一項:identity preserving loss。
- 在生成器(G)中,增加MLP,沿用StyleGAN利用w+空間的方式,代替UGATIT生成beta和gamma的方式。
- 将UGATIT的兩個生成器,整合為一個生成器。判别器依然使用兩個,分别判别A域和B域的真假。
Note:寫在前面,筆者的改進思路,并非完全原創,其借鑒了Eccv2020的一篇論文。文中也會提及。全部代碼已經開源,位址在:
https://github.com/shoutOutYangJie/Morph-UGATIT
複制
預備知識
我們先簡單回顧一下UGATIT,作為一個Cycle-base圖像翻譯方法,它和cycleGAN的主要差別在于:
- 提出CAM loss,CAM loss在G和D中起到的作用也不一樣。
- 提出AdaLIN,自适應改變LN和IN的比例。
https://github.com/taki0112/UGATIT
複制
由于以上兩個差別不會導緻和CycleGAN framework的巨大差異,為了友善我以下的描述,筆者直接沿用cycleGAN的framework進行描述。CycleGAN的framework大緻如下,僅畫了從A域向B域遷移的過程,黃色虛線是計算loss,省略了identity loss:
cycle-base GAN (方向:AtoB)
A域的真實樣本經過G_A得到假的B域樣本fakeB,fakeB經過G_B又從B域向A域遷移,為了是建立cycle consistency loss。優化cycle consistency loss,使得A和B域之間的各個屬性mapping能一一對齊,這樣就解決了unpair的圖像翻譯。
同時,A域的樣本經過B,直接得到了B域的樣本,各位煉丹師們是無法得知,樣本是如何從A域變換到B域的。
接下來簡單介紹筆者借鑒的另一篇論文。
https://github.com/royorel/Lifespan_Age_Transformation_Synthesis
複制
lifespan age synthesis
該論文是一個unpair multi-domain transfer的圖像翻譯方法。作者将年齡分成6個段,作為單獨的6個域,能實作一個樣本在這6個域的連續漸變遷移。巧妙的地方在于,不同于其他face aging(人臉年齡編輯)的cgan方式,作者使用了一個mlp編碼年齡向量z,進入到一個隐空間。
不同年齡段的latent code進行插值,用插值之後的latent code生成圖像,則圖像的效果就介于兩個域之間。比如說,該論文選擇face aging這個方向實驗。資料集中各個年齡被化分為幾個段:{0:6},{16:30},...。如果我們想得到{7:15}歲的人臉,則将{0:6}和{16:30}這兩個區間對應的latent code進行按比例插值即可。
大家要注意,如果沒有這個mlp,現存的方式的做法是,z将會被視作condition,直接送入G中。但是,如果直接在z空間插值,得到z',z'是無法直接起到作用的。因為在訓練階段,G就沒有見過z'這種資料分布。在隐空間插值,繞過了這個問題。
這樣的話,筆者已經介紹完畢所需要的預備知識。
方法
Morph-UGATIT
overview:Morph-UGATIT直接使用一個生成器完成2個域的遷移。X是生成器的輸入,接收來自兩個域的樣本。Z空間也是兩個域分别對應一個随機z向量。如果Z空間輸入的是z1,則代表,生成器要生成B域圖像;
反之亦然。有兩個判别器,分别對生成的A域真or假樣本以及B域真or假樣本進行判别。同時生成的樣本X`,也會在經過一個E,和原始輸入X對應的E(X),計算L1 loss,作為identity presevering loss,即希望生成的樣本和原始樣本的細節接近一緻。
Z空間的初始化是依賴于生成器想生成哪個域的樣本,如果想生成B域樣本,則輸入z1;反之亦然。z1和z2的初始化方式也不一樣。Z向量是一個64維向量,其初始化方式為:
z1和z2的初始化方式,僅僅在于加1的位置不同,z1在前zdim個位置都加上1,z2則在後zdim個位置上加1。z_dim的值是Z長度的一半,即32(在筆者的實驗中)。
看到這裡大家也許就明白為何不能在Z空間插值了。因為插值出來的新z‘,不屬于兩種分布之一,G沒有在訓練中接收到這種分布,自然沒法在測試階段起到作用。
将兩個域用一個生成器實作,以及MLP的應用,都是遵從論文“Lifespan Age Transformation Synthesis”的做法。
筆者認為,原作者首先将Z單獨使用,由Z決定生成器要往哪個域上遷移,有助于Encoder(E)學習到A域和B域共同屬性的特征,再加上identity preserving loss的作用,進一步限制兩個域的相似。
下面以從A域向B域遷移為例子:
- 初始化一個向量z1,用屬于方向"AtoB"的方式建立一個z1。(兩個方向,初始化z的方式不一樣),送入生成器中。
- x經過Generator,得到E(x), x', cam_ab;cam_ab是為了計算cam loss,屬于ugatiti論文的做法,不再多說明
- 重新初始化一個向量z2,把x'和z2都送進生成器,得到x''。
- 計算對抗loss,恒等映射loss(identity loss),cam loss,cycle consistency loss,以及identity preserving loss。G和D交替優化。
更相似的過程可以參考筆者開源的代碼:
https://github.com/shoutOutYangJie/Morph-UGATIT
複制
實驗
筆者設定了3組模型。分别在{成人臉,娃娃臉}和{真實人臉,動漫人臉}兩種資料集探究Morph-UGATIT的能力。
- config-A: 使用筆者自己用pytorch複現的UGATIT訓練
- config-B:在config-A的基礎上,增加identity preserving loss
- config-C: 在config-B的基礎上,增加MLP學習隐空間
資料集來源:
- {成人臉,娃娃臉}:來自G-lab開放下載下傳的,由StyleGAN2生成的萌娃資料集,以及StyleGAN生成的成人資料集。(沒錯,用的生成的假資料訓練的。實在沒有好的資料來源。)所幸這批資料大部分樣本還是很逼真,有些樣本的背景包括發尾,頸部以下會失真。
http://www.seeprettyface.com/mydataset.html#adult
複制
- {真實人臉, 動漫人臉}:來自UGATIT開源的代碼中提供的資料集,大家可以自行尋找。目前這個實驗正在做,還沒有做完。
首先看一下在成人臉向娃娃臉(AtoB)轉化,在訓練集上的表現。
以下圖像按照原圖(第一列),config-A(第二列,UGATIT),config-C(第三列,Morph-UGATIT)。因為config-B的視覺效果和config-A差不多,故此省略。
第3列的樣本,morph-ugatit生成的臉更像輸入人臉
config-A和config-C總體上差不多,也說明UGATIT自身的強大。
受樣本分布影響,黑人基本上都轉成了白人娃娃
總體來看,在訓練集上,config-{A,B,C}差不多,且都存在bad case。config-C在細節的保留上略微好了一丢丢。這裡面有兩個點需要探讨:
- 如果不在訓練集上測試,config-{A,B,C}的差距會不會拉大。畢竟訓練集是做了針對性優化的
- config-C的CAM如果去除,會不會提升其視覺效果,進一步拉開與config-{A,B}的差距。(筆者木有時間做了)
筆者在網絡上搜集了一些名人明星的照片,作為測試集。因為時間及精力有限,僅搜集了幾張。這些照片均使用FFHQ規則進行align。
四列按照 原圖,config-A, config-B,config-C的排列。
接下來看看在{真實人臉,動漫人臉}資料集上的效果。筆者在UGATIT論文提供的資料集“selfie2anime”上的訓練集訓練,在測試集測試。由于時間關系,筆者僅僅做了config-A的實驗(即筆者自己用pytorch實作的UGATIT)。
消融讨論(ablation discussion)
1.Morph-UGATIT的Encoder是否可以學習到公共的屬性,能如筆者所想?
在筆者的實驗過程中,意外的發現,cam loss的曲線異常,這算是一個實驗的驚喜。筆者搭建的morph-ugatit,是在筆者自己複現的ugatit的基礎上完成的,自然保留了CAM這個子產品以及對應的loss。
起初筆者并沒有思考,在自己DIY的基礎上,還需不需要CAM,而是選擇直接保留。于是就看到了這樣的CAM loss 曲線。
config-C(第一行)和config-B(第二行)的CAM loss曲線。
這裡簡單回顧一下生成器的CAM loss:
在UGATIT原文中,G中的CAM負責找出最不像目标域的區域,并使用cam的方式強調該區域。CAM loss則優化從源域到目标域得到的置信機率,以及目标域到目标域(恒等映射)得到的置信機率的距離。
CAM loss可以簡單了解為:讓兩個不同域的樣本進入相同的Encoder,特征分布要有所區分。我們從上面的曲線圖可以看出,config-B的CAM loss都優化都到了接近0的位置。而config-C的CAM loss優化到1300多,就已經要收斂了!!!
這提供了一個事實依據:Morph-UGATIT能夠解耦出AB域共同的特征屬性。因為config-C的cam loss很早就陷入了拉鋸戰:一個相同的分布,如何讓它被分到兩個類别上去?自然無法做到,是以cam loss一直很高,無法下降。
2. 在AB域插值,檢視其漸變遷移效果如何。
很遺憾,在{成人臉,娃娃臉}資料集上,AB域的轉換非常不平滑。沒有論文“lift age transformation synthesis”中的那麼好。這裡面存在的可能原因将在Extension.3中提及。
A域向B域漸進遷移(從右向左)
在A域逐漸向B域遷移的過程中,可以看出,遷移效果并不穩定。一些中間結果出現了artifacts。遷移的變化,主要展現在面部臉盤變大,發型開始變化,面部細節的變換很生硬,基本是直接跳過去的。
筆者認為,如果A域B域的關鍵因素(比如年齡)的間隔如果小一些,可能遷移會更加平滑,正如論文“lift age transformation synthesis”展示的效果那樣。
另外如果在訓練過程中,設定一個新的判别器,用來判别用mix W空間隐向量生成的樣本的真僞,在輔助identity preserving loss,以及content loss,push生成結果更加真實,也許能在該資料集上,做到比較真實且平滑的大人臉到娃娃臉之間的遷移。
Extension
1. 在希望編碼公共屬性的同時,也許我們留出某些通道,去挖掘AB域的不同點,剩下的通道學習AB域的公共屬性,讓CAM loss隻去優化挖掘不同點對應的權重,也許會有更好的視覺效果。
2. 筆者雖然引入了Z空間,但Z空間的作用隻為了滿足兩個域的轉換所需要的分布。這導緻z的不同并不能生成基于原始A域樣本人物的多樣性B域樣本。如何能讓z的變化,帶來domain transfer上的變化,也是一個不錯的探索方向。
3. AB域的漸進變化,并不平滑。這裡可能是因為{成人臉,娃娃臉}年齡相差太大導緻。也可能是因為decoder沒有完全采用論文“Lifespan_Age_Transformation_Synthesis”中的style-based decoder。
4. 由于用的是L1 loss進行恒定映射,是以導緻A域到A域的映射會輸出一張模糊的照片,這是L1,L2loss自身的局限性。但因為cycle-base訓練方式需要恒定映射,而L1 loss也是最簡單的做法。
如果想生成更真的恒定映射結果,或許可以用content loss(vgg loss)以及将恒等映射的結果也送到判别器,參與訓練,說不定可以解決該問題。同理,cycle loss需要的recA,recB也是可以用同樣的做法。
5. 在訓練過程中,設定一個新的判别器,用來判别用mix W空間隐向量生成的樣本的真僞,在輔以identity preserving loss,以及content loss,以此來push生成結果更加真實,也許能在{大人臉,娃娃臉}上,做到比較真實且平滑的大人臉到娃娃臉之間的遷移。
總結
- cycle-based的domain transfer,還是盡量對齊資料集的分布,就拿人臉資料集來說,男性女性分開,前景背景分離,以及側臉正臉區分,都是有助于模型的收斂。我在實驗的時候發現,對于側臉的情況以及帶眼睛(墨鏡)的情況,生成器傾向于生成正臉,但臉部的邊緣又有側臉情況的重影(導緻視覺效果假),墨鏡則被完全移除。
- identity preserving loss的一個副作用,就是讓生成器過度關注人臉面部,而忽略的其他細節的合理性:比如假樣本娃娃域的耳朵實在是太大了(哈哈)
- identity preserving loss并不是讓Encoder學習公共屬性的關鍵,而是引入MLP,将域的轉換依賴于Z空間分布,并且讓Encoder接收來自不同域的樣本,迫使encoder學習公共屬性。因為config-B也使用了identity preserving loss,但是CAM loss 一樣優化到了很低.
- Morph-UGATIT中,生成器的CAM loss雖然經過實驗得知,沒有必要保留,但筆者開源的代碼中還是留存了;筆者也不會再去花費時間驗證去除G中CAM loss的效果。但如果去除掉CAM,會不會有視覺效果的提升呢?
- 男性轉化的難度比女性大。