StyleGAN 混合多风格 - 生成模型 GAN 网络 | 莫烦Python

StyleGAN 混合多风格

作者: 莫烦 编辑: 莫烦 2021-04-09

学习资料:

怎么了

StyleGAN 最大的不同是它的生成器有着完全不同的结构,作者对于 GAN 有了另一种定义。 以前的 GAN 我们都认为是将一个随机想法,变成一张图片。而 StyleGAN 认为另一种模式可能更棒, 那就是我有一个随机想法,这个想法不会突然变成一张图片,而是通过这个想法其改动原本的一张图片,将图片中的鼻子改大一点,眼镜改小一点。 这里的想法控制的是原照片当中的风格 Style,所以它也被称为 StyleGAN。

用一句话来概述 StyleGAN:我要做一个黏土花瓶,黏土已经有了,我的想法只负责把黏土捏成不同的样子,而不是创造黏土。 以前的算法都是去创造黏土花瓶,而 StyleGAN 不创造黏土,它只想着怎么改黏土的样子。

clay

所以如果沿着这个思路,StyleGAN 就是一种控制风格的 GAN,而不是单纯的生成模型。所以我们可以拿着它做下面这种风格混合实验, 这也是我们今天要用 mnist 做的练习了。风格可以分层,底层/中层/高层等。下面的例子中顶上黑色的数字控制着一层风格,右边黑色的控制这另一层风格。 将这两层糅合起来,就变成了中间白色的数字了。

results

在数字的例子中,我也说不上来这到底是怎么个糅合的,但是如果你看看论文中的图,它用人脸来糅合,这效果就更明显了。 左边不同层级的风格控制,生成出不一样的融合脸。

paper

想看看它如何动态变化的?没问题,给你看。

dymatic change

怎么训练

这个训练过程真的像上面的那个黏土捏瓶子图。如果说这个瓶子是一个竖着放的CNN,GAN的随机噪点控制的就是你捏瓶子的手,哪里力道要轻点,哪里力道要重点。 随机噪点只管控制这种风格力道,最后这瓶子也就被捏成了特别的样子。天哪,我觉得我的比喻太生动,太形象了。

clay compare

在把paper中的网络结构图简化一下,先给你看看我简化的样子,然后再给你放一张paper里的样子,你做一下对比,应该能很容易理解具体的结构属性。 在下面的图中,我们有一个 Mapping Net 用来将随机想法转变成 CNN 不同层的力道,如果没有 Mapping Net 提供的力道,那么这个 CNN 每次都会生成一样的图片。 只要控制不同的力道,做一下整形手术,图片中的内容风格就不一样了。StyleGAN 把手伸进了 CNN 的结构中,和 CNN 做着偷鸡摸狗的勾当。

g struct

在论文里,它的示意图是下面这样。Mapping net 将随机噪点 z 转换成一个 w,由 w 经过 A 加工,通过 AdaIN 的结构来控制 g CNN 输出特征图的风格。 论文里还加上了一些额外的 Noise,从 B 的口子灌入到 gSynthesis net),负责给CNN再提供一点随机性。

g struct

StyleGAN 目前有两篇论文,第二版在结构上进行一些修改与简化,使之更有效率,不过在这个教学中,我们专注在第一版中,我觉得第一版的代码好写一点。

  1. 第一版 A Style-Based Generator Architecture for Generative Adversarial Networks
  2. 第二版 Analyzing and Improving the Image Quality of StyleGAN

在来看看论文里的动图吧,实验结果还是挺有趣的。如果你操纵 CNN 中不同 level 的 A,它是如何影响生成效果的?

style layer control

如果你操控不同 B 的随机噪声,它又是如何影响生成的?

noise control

接下来我们来看看,为什么要加入 Mapping net, 他的作用是什么?如果用白话描述就是:我的世界和你的世界不一样,我们需要一个桥梁来联通两个世界。 具体再解释一下的话,在我的世界里我还没发现有胡子的女人,所以我给他留白了一份探索空间(类似下图a)。而你的世界里,你压根就没想过女人会不会有胡子的问题, 所以你并没有留白任何探索空间(图b)。那么 Mapping net 构建了一个桥梁,将你的世界转化成了我的世界的模式(图b到图c)。这样,我们两个世界就能对接啦。

mapping net w

为什么图b是一个圆形的呢?因为我们通常用正太分布来 sample 随机噪声,所以一般来说,都需要从正太分布的空间,转移到其他不规则空间分布。唯有这样, 噪声空间的数据分布才能比较好的映射的真实数据的空间分布。

normal distribution

最后,论文图里面的那个 AdaIN 是啥?简单来说,这是一种 Mapping net 把手伸进 CNN 特征图的过程,操作特征图的过程。 里面的 y 是通过 Mapping net 的 w 结果变换而来,里面的 x 就是特征图,AdaIN 用一种 re-normalization 的方式, 将特征图重新放大,平移了,变成了新的特征图,或者你可以认为,特征图的风格被改变了。

adain

正式对每一张特征图的风格变换,才导致了最后生成的图片变化。注:在 StyleGAN2, 它不操控特征图了,转而操控生成特征图的卷积核,真是一种聪明的办法。

秀代码

如果想直接看全部代码, 请点击这里去往我的Github. 因为代码太长,我在这里说一下代码当中的重点部分。我的代码采用的架构是 StyleGAN2 中的这张图的(c)结构, 因为这张图比 StyleGAN 原版的图要清楚,代码比较好组织。

architecture

A 操控特征图,调整后的特征图在进入卷积,卷积出来的新特征图过一遍 norm,在加一些 B 噪声,一个 block 就这样完成了。所以下面我会先创建这个 block, 作为 StyleGAN 的核心模块。

在这其中有三个我定义的小插件,分别是 AdaNorm, AdaMod, AddNoise, 这三者都是 Synthesis net 的组件。用来控制风格的。 AdaNorm 就是图c当中的 norm 部分,用来重新将特征图拉回原来的正太分布。

AdaMod 则是把 Mapping net 出来的 w 加工成两个 y 用来控制特征图 x 的缩放平移变化。 所有在这里我们需需要将 w 通过举证运算,转化成 y 使之可以匹配特征图的格式。

AddNoise 则是添加随机噪点的方式,这里其实还可以有其他方式去添加, 我为了简化在这里传入的 inputs 的 noise,将它设定成每一层 CNN 特征图都可以用的 noise,所以每层CNN传递的noise都一样。 但是我会对这个 noise 选取不同的长宽大小,来匹配上当前特征图的长宽。

在组合这些插件的 StyleGAN 中,我重点说说 Generator 的写法,因为 Discriminator 和以前的网络没什么差别。 在 Generator 中,定义一个 const 作为基础图像,由接下来的 Style 层不断给它转换风格。最后变成不一样的图片。

其中的 Mapping net 就比较简单了,就是几层全连接层。但是有意思的是,如果我在 Mapping net 的全连接层加上激活函数,做一些非线性的话, 生成结果就要差很多。我不明白其中的道理,因为安理来说,非线性是 mapping 的核心概念,就是要转换空间分布的,可是为什么这个试验中,反而有坏处呢? 有想法的同学可以在下面讨论一下。

我的训练结果展示的是风格融合的结果, 具体代码见我的Github. 在 styleGAN 中,你可以将两种不同的 mapping w 嵌入到不同的 Synthesis net 层中,这里我嵌入了2中不同的 z 噪声。 而且这两种不同的 z 噪声在训练时每次都被插入到不同的 CNN 层中。方式如下。

训练出来的效果如下,下图展示的是最后一个训练 epoch 的结果。从结果看出,还是有些融合的效果,但是用数字做例子总还不是那么合适,总感觉怪怪的。 不过我在下面还做了些其他实验,你可以看看人脸和卡通脸的效果,这就稍微好点了。

res

延伸

很多学GAN的人心里面都有一个小小二次元愿望,比如用GAN来生成老婆。我其实还好,只是恰好有这些二次元的数据,我就拿着试了试。上面用 mnist 手写数字的 StyleGAN 总感觉哪里怪怪的,但是当我们用二次元人脸数据时,情况就好很多,而且也能看出来明显的风格混合了。 这个项目的详情,请看我的 Github anime-StyleGAN

anime

明星脸我也尝试了一下,效果还可以~ 具体项目 Github celebA-styleGAN

CelebA

总结

哈哈,终于开始有点意思了,作者在 StyleGAN 中提出了一个非常新颖的方法来做 Generator,就是从特征图的改变做起。 其实 StyleGAN 的表现还是挺好的,但是我总觉得操控特征图有点效率不高,这可能也是为什么在 StyleGAN2 的版本中, 作者换成了操控卷积核了。


降低知识传递的门槛

莫烦很常从互联网上学习知识,开源分享的人是我学习的榜样。 他们的行为也改变了我对教育的态度: 降低知识传递的门槛免费 奉献我的所学正是受这种态度的影响。 通过 【赞助莫烦】 能让我感到认同,我也更有理由坚持下去。