原创:岐山凤鸣,转载请注明本站域名

理解可能有偏差,有错误请指出~

参考:

[1] Image2StyleGAN: How to Embed Images Into the StyleGAN Latent Space?

[2] A Style-Based Generator Architecture for Generative Adversarial Networks

前言:这篇StyleGAN的follow文章很有点意思,也是19年ICCV的Oral论文,是对StyleGAN进行的更多的理解和分析,而正是这些理解和分析,让StyleGAN有了超越仅仅生成高清图像的领域,进而对GAN有了更多的理解也有了更多的操作空间。什么是对GAN的理解?GAN本质是根据一个空间的分布(如512d向量空间),得到另一个空间的分布(如1024x1024x3的人脸空间),如果对这个有更多理解后,对原空间进行一些操作,从而让目标空间根据你想要的结果发生变化,这是非常awesome的。

理解StyleGAN

先放一张用烂的神图:

这图直接表明了StyleGAN的网络结构,很直观有两部分组成,一部分是左边的mapping网络和右边的Synthesis网络。

先明确输入,输入是一段随机分布latent,记为zz,首先zz经过Norm后,直接由多个串联的FC进行映射,映射到latent space ω\omega,关于这个的中文说法,有的说是"潜空间"或者"隐空间",总之我认为这个就是一个编码空间,每段编码经过仿射变换意味着一个 style,之后将style进行合成就能形成人脸。

那么原始输入latent映射到了latent space之后,假如原始latent的shape是[512],那当前映射后的shape还是是[ 512],再经过一些变换,得到n个[512]输入上图的A即仿射变换后得到n个style,其中每个style的编码是(2)的向量,即为(ys,i,yb,i)(y_{s,i}, y_{b,i}),i表示第几层。这里在代码实现的时候,直接将向量经过多个个FC后,broadcast到n个layer后经过updating moving average + style mixing regularization + truncation trick后即可,可直接输入(n,512)的编码dlatent。

这里知道了A的输出是什么之后,再看最右边,是n个高斯噪音输入,这个是直接对特征图作用的,关于GAN中加噪音的原因可以参考别的资料,这里基本就是引入随机的细节。接下来是右边网络的细节部分,看下两图:

这是一个自顶向下的结构,最顶上的输入是一个const的比如4x4x512的矩阵,层层会进行传递,每层都包括style的输入和噪音的输入,输出是一个[res, res, channel]的矩阵,跨层的时候需要降采样,层内传递需要一个AdaIN模块和3x3的conv,最底层输出的是[1024,1024,3]的生成图像。AdaIN的模块公式上面给了,意思很简单,对特征图进行标准化后,和两个style值进行平移和缩放,然后一起经过conv。这个操作很像BN,但不同的是两个style值是根据编码来的,而不是特征图,这里对理解来说很重要,理解了BN也就能理解这个AdaIN模块的重要性。

简略的说,从代码层面考虑,整个过程很简单,就这样:

  1. 输入一个随机向量z,shape=(512,1)
  2. 多个FC对随机向量直接进行变换,得到zlatentz_{latent},shape=(512,1)
  3. 复制n层zlatentz_{latent},n表示右边结构的层数,shape=(n,512),经过uodating moving average + style mixing regularization + truncation后,得到dlatent,shape=(n,512)
  4. 先得到一个初始const图,往下进行输入
  5. 进行每层结构的计算,结构开始需要一个降采样,比如(4,4,512)降采样到(8,8,512),给feature_map加点高斯噪音,然后标准化。对输入的512的latent进行放射变换得到两个y,根据两个y对标准化的feature_map进行放缩和平移,之后输入conv进行channel变化
  6. 将n个结构都跑完,前几个结构都是4x4,8x8这种小的,主要是学的轮廓啊,头发在哪啊这些玩意,中间的几个结构比如32x32,64x64这种大一点的,主要是学的更多的人脸表情啊,眼睛啊什么的,最后几个更大的比如256x256,512x512,1024x1024学的就是超细节的比如毛发啊,颜色啊什么的。
  7. 输出最后的1024x1024x3

所以可以看到这个过程并不难,有兴趣的同学可以去读源码,读源码的话,一个完整的链是这样的:

  1. 302行的G_style是完整的生成器流程
  2. 334行定义synthesis网络,即440行的G_synthesis,同时了解总层数这些信息,dlatent的shape即是(n_layers,512)这种
  3. 338行定义mapping网络,即384行的G_mapping
  4. 根据随机的latent生成dlatent,四个步骤嘛,分别是345行的mapping,然后是348行的update,然后是356行的style mixing,然后是369行的truncation,最后得到dlatent
  5. 378行直接将dlatent输入syntheis网络即可,噪音均在中间生成。

只有上述过程全部了解,才能开始下面的内容,所以要理解如何进行嵌入和编辑,必须对StyleGAN有很完整的理解。

到底什么东西在控制人脸生成?

一句话,dlatent,其shape=(n_layers, 512)。

这到底是什么东西?

刚刚已经说了,它的前面几层在做什么?前面几层是4x4,8x8这种小图,前面几层的风格即是脑袋轮廓,头发位置这些显而易见的宏观风格。

所以它的中间几层,不断的一点点放大,去学的细节就会越来越多,n_layers越多,给的细节就越丰富,细节程度是自顶向下的那种,最顶部的细节是粗糙的,最底部的细节是最精细的。

每一个结构里,输入的dlatent 512编码,都仿射变换到了两个数y,然后带噪声的特征图通过标准化后用这两个y进行平移和放缩(AdaIN),所以实际控制风格的只有y,y来自于dlatent,这即表示输入当前层的dlatent即包含风格。

举个很简单的例子,比如你最后要输出256x256x3的清晰图像。那么整个res的变化是:

(4,4) -> (8,8) -> (16,16) -> (32,32) -> (64,64) -> (128,128) -> (256,256)

这一共是7个要变化的res,也就是需要7个结构,每个结构是包含两层的(一层欠采样,一层正常变换),所以一共14层,那么原始的z编码后是得到(14, 512)的编码,分别输入这14层。

第一层之前首先先init了一个(4,4,512)的东西,这时候还不是图像,然后加个噪音后标准化,将dlatent的第一个(512)提出来放射变换到y1,y2后对标准化后的图进行控制平移和放缩,然后一层层的输入。

所以就是这么简单,(14,512)的编码,一层层逐级的在控制人脸的生成。如果你改变(14,512)的前两三层,可能这个人的脑袋就变了,如果改了最后两三层,可能这个人的肤色什么的,毛孔什么的会发生变化。

如何控制人脸的特征生成?

既然了解了什么在控制人脸生成后,我们要进行控制,就变得很简单,只需要控制这个dlatent即可了。

那么到底如何控制?比如我现在有一张照片I,里面描述的是一个人严肃的表情,我想让他笑起来怎么办?

那么首先,先预训练上述的StyleGAN,得到了G,其中输入(14,512)的编码,会通过G得到一张256,256的图,这时候需要做一个类似AE结构的训练,训练什么?

我们得训练一个编码器,输入I后,得到人脸识别的emb前一层的feature_map,然后用这个feature_map经过一个编码结构,得到(14,512)的编码,然后输入参数冻结的G,得到了假图I',再通过一个预训练的人脸识别网络N(I, I')增加一个损失L给整个编码器,训练编码器。

这到底在干嘛?很简单,我们希望能够得到I这张照片的编码而已,也就是希望控制预训练且参数冻结的G生成出I这张照片。这样我们才能得到I的dlatent,得到dlatent后,通过控制dlatent才能编辑I这个人脸的特征,比如发色什么的。

到这步,我们手上得到了两个东西,生成器G,编码器E,要让I笑起来,怎么办?

这时候需要得到一组人脸数据对(I1,I2)(I_1, I_2),满足一个条件,前者是严肃不笑的照片,后者是笑的照片,都进入E后得到一组两个编码(E1,E2)(E_1,E_2),根据之前的理论,很明显啊,这一组从E1>E2E_1 -> E_2的方向向量,即是控制人脸笑起来的关键因素,当然这个方向向量也是(14,512)的shape。所以现在唯一要做的,就是求解出这个方向向量,然后作用到E(I)上,那么G(E(I)+w)G(E(I) + \vec{w})就是让I笑起来的图了。

其他的例如表情迁移(哭->笑)、特征迁移(白发->黑发)这些都用类似的操作就可以很容易的实现。关于求解这个向量,这个问题下节进行详述。