选自towardsdatascience
作者:Nolan Kent
机器之心编译
参与:Luo Sainan、Geek AI
不能写一手好代码的工程师不是好数据科学家!本文作者 Nolan Kent 曾经是一名恶意软件分析师,具有很强的工程能力。在本文中,他编写了一个可视化工具用于观察 StyleGAN 模型中的特征图,对理解该模型起到了巨大作用。
图 1:修改单一位置的空间特征图以生成动漫人物
「写在前面」
这篇技术博客介绍了一个使用生成式对抗网络完成的项目。由于这是一个个人项目,我采用了一个在专业领域中通常不会使用的动漫人物数据集「DANBOORU2018」。
下面给出了这个数据集的链接以及使用该数据集模型的详细介绍:
https:///NVlabs/stylegan)还没有开源。StyleGAN 的结果比我接触过的其它模型要好得多,所以我想要进一步深入研究一番。
一个令我很兴奋的生成式模型的应用是:它能够为电子游戏自动生成资源。对于我来说,StyleGAN 是我复现的第一个在电子游戏上生成的结果可接受的模型,所以我的初步尝试就是让「Unity」等游戏引擎加载该模型。
为此,我制作了一个「.NET」动态链接库(DLL),它可以与模型进行交互,从理论上来讲也能够被导入到「Unity」中。为了测试这个动态链接库,我创建了一个与之交互的工具。最终,我为这个工具添加了慢慢的变多的功能,直到这个工具成为了本项目最大的组成部分之一。
以下是项目的整体架构:
图 4:从 TensorFlow python 实现到使用工具生成图像的工作流程
我喜欢使用工具来可视化「不透明」的数字对象(比如恶意软件和深度学习模型)并与之交互,所以我增加的一个功能就是对特征图的可视化及修改(见图 5,https://towardsdatascience.com/applied-deep-learning-part-4-convolutional-neural-networks-584bc134c1e2)。
观察不同图像上各层特征图最活跃的部分有助于我了解模型在做什么,并且会使对一些面部特征的自动定位变得简单。当对图片进行修改时,我注意到,对特征图特定区域的值进行加或减会产生一些有意义的变化,比如张开和合上嘴巴(见图 2)。与自动面部特征检测相结合,这可被用来在不需要标签的情况下,对所有生成的图像进行一致且有意义的修改。(见图 9、10)。
图 5:特征图可被用来识别有意义的区域(上面一行图像:眼睛,下面一行图像:人脸)。红色方块表示负激活值,绿色方块表示正激活值,白色方形表示激活值接近 0。
小结:以上是使用特征图来修改面部特征的功能,以下是本博客剩余部分内容的组织结构。
生成式模型的应用
使用工具生成动漫人物
关于代码的简要讨论
复现的细节
对数据的讨论
对训练步骤的讨论
应用
总的来说,我对生成式模型的以下几个方面很感兴趣:
更好地通过程序化的方式生成游戏资源
让艺术创作变得更容易更快
无监督学习的基本潜能与生成式因素解耦(disentaglement)相结合
更好地通过程序化的方式生成游戏资源
生成式模型有望将程序化生成推向一个新的高度,这令我十分激动。据我所知,现今的基于规则的程序化生成技术不能根据高度复杂的分布随机创造样本。例如,程序化生成的关卡的一个小节多半可以与该关卡的其余部分独立开来,并且仍然被玩家所接受。
随机生成人物肖像类的图像是更难的,因为好看的人物图片趋向于反映真实世界,而现实世界具有特别多的相互依赖性,因此每个像素都需要在其它像素的上下文中被考虑到。为了使图片看起来好看,即使非写实的图片也需要一致的光源、解剖结构、纹理、视角、风格等等。
这种依赖性也适用于音频、对话、动漫、故事情节的自动生成。我认为生成式模型是当前能够可靠地根据如此复杂的分布生成样本的最佳方式。
让艺术创作变得更容易更快
在使用生成式模型时,通过交互式工具有可能使外行人也能够创作本来需要有经验的艺术家才能创作的图像,或者让艺术家们能够更快地完成他们工作中较为常规的部分。
我并不认为生成模型会很快消除对有创意的艺术家的需求,因为生成模型(以及大多数机器学习模型)专注于对特定的分布建模。这使得生成与训练分布中任何样本都不同的高质量图像(即有创意的图像)是非常困难的。
然而,像本博客中使用的这种工具,使人们能够添加有助于生成更多独特的图片的自定义变更(尤其是如果模型已经学到了一些基本的图形概念(比如照明和透视))。
无监督学习的基本潜能与生成式因素解耦相结合
由于无标签数据的数量远超于有标签数据,并且深度学习是极其需要数据的,我认为今后无监督/半监督学习有逐渐取代有监督方法的潜力。尤其是,我们已提出了一些针对深度生成模型的方法,用来解耦数据集中的变化因素:图 7 和图 8 展示了 StyleGAN 是如何做到这一点的(至少部分做到)。
实际上,对于「解耦」并没有一个一致的的形式化定义。我的理解是,仅有有限的实验证据表明它对下游任务是有用的。然而,将「解耦」与 GAN 一起使用,让我抱有一种它是有用的乐观态度。尽管生成器不能为它未生成的图像生成内部表征,但是还有几种其它类型的生成模型可以在视觉质量上和 GAN 一较高下,并且可能更适合于下游任务。
实验结果:动漫人物
我在一个名为「Danbooru2018」的动漫数据集上训练出了自己最佳的模型(https:///nolan-dev/stylegan_reimplementation
我制作的工具:
https://github.com/nolan-dev/GANInterface
复现细节
在这一节中我将介绍复现 StyleGAN 和训练模型的技术细节。
复现 StyleGAN
在论文「A Style-based Generator Architecture for Generative Adversarial Networks」(https://arxiv.org/abs/1812.04948)发布后不久,大概是官方代码发布前的几个月,我开始复现 StyleGAN。
我将在此讨论我碰到的一些挑战和采取的应对方法(假设你熟悉 StyleGAN 和 TensorFlow)。
StyleGAN 以 PGGAN (https://arxiv.org/abs/1710.10196)(我曾经复现过)为基础。这些模型使用了「渐进增大」的训练方式,即判别器和生成器在训练期间不断增添卷积层以处理慢慢的升高的分辨率。
扩展一个模型的做法是比较罕见的——所有我复现过的其它模型在训练期间都不需要改变它们的结构。幸运的是,Tensorflow 有一些比较方便的功能,比如只为模型的一部分加载已保存的权重并随机初始化其余的权重。迁移学习中也会使用这种方法。
我非常喜欢 TensorFlow 2.0 的风格,它将模型创建为继承自「tf.keras.Model」的类。我用这种方式创建了大多数层、生成器、判别器和映射网络。我也试着在动态图执行(eager excution)和传统的基于图的执行之间能够进行切换。动态图执行使得调试更容易,我认为它是一种更好地理解程序的方法(也是一种恶意软件分析中常用的技术)。
不幸的是,现在动态图机执行比在图模式下运行慢得多,所以最终我停止了对该功能的更新。使用「tf.keras.Model」的好处之一就是它在动态图和传统的图模式下都可以工作,因此从理论上讲,再转而使用动态图执行也不会太难。与此同时,我刚刚使用了「tfdebug」命令行界面和「TensorBoard」,在这一点上我相当满意。
StyleGAN 和 PGGAN 有一些重要的区别。有一种方法在使用「自适应实例归一化」操作时,将特定图像的潜在数据作为样式(非空间属性)提供给特征图。理论上讲,这很容易根据论文中所述细节实现,但我选择用「tf.nn.moments」来计算均值和方差,这并不如官方实现的版本那样有效(官方使用较低级别的操作来计算这些值)。
我猜这是由于数值问题造成的,当时我并不想对此进行调试,因此我没有更多地研究它。通常,我很乐于深入研究此类问题,因为研究它们显然使我有机会学更多知识,但是由于这个项目只是我的爱好,因此我必须优先考虑充分的利用我的时间。
StyleGAN 也使用了一个中间潜空间,该空间假设通过增加对潜变量值范围的灵活性和依赖性促进解耦(论文中有一些实证证据)。比如说,如果我们假设人群中的男性都没有长头发,那么当对应于性别的潜向量出现在「男性」区域中时,对应于头发长度的潜向量应该永远都不可能出现在「长发」区域中。如果潜向量是独立的(在没有映射网络时会发生这种情况),我们最终将「长发」和「男性」一起采样,生成器将会生成非男性或是短发来骗过判别器。
这在某种程度上预示着即使头发长度的潜向量处在「长发」区域,当其它潜变量值在其正常范围内时,我们最终有可能生成短发图像。有必要注意一下的是,对一些解耦的定义有必要进行「轴对齐」(修改单个潜变量值会带来有意义的变化),我的理解是 StyleGAN 的映射网络促使中间潜空间成为轮流轴对齐解耦旋转之后的形式(修改潜变量会产生有意义的变化)
在我看来,使用中间潜变量值就像通过风格将信息融合到网络中一样有趣。它也很容易实现。除非另有说明,否则本系列博客中提到的潜变量值指的就是中间潜变量值。
如果起初看起来像是论文次要细节的部分变成了最难复现的部分,那就真的太令人烦恼了。StyleGAN 就遇到了这种情况——StyleGAN 和 PGGAN 之间的一个区别就是对双线性上采样(和下采样)还有 R1 regularization(https://arxiv.org/abs/1801.04406)(对判别器的梯度惩罚)的使用不同。
这两种方法都很容易单独实现,但是当我尝试将它们组合时,发现 TensorFlow 无法计算「tf.nn.depthwise_conv2d」操作的二阶导数。
Depth-wise 卷积被用来将卷积核分别应用于每个通道。在卷积神经网络中通常并不需要这样做,因为(除去一些用于移动设备的 CNN)每个卷积核都与前一层的所有通道相连。通常用于实现双线性插值的模糊卷积一次只能处理一个特征图,所以有必要进行深度卷积。如果没有实现二阶导,我将无法计算 R1 惩罚,而这需要用梯度的梯度。
当时我对自动微分还不够了解,不能自己轻易地实现二阶导。我花了一些时间尝试更好的理解自动微分,那时我已经完成了除此部分以外的所有工作,随后不久官方的代码就发布了。英伟达团队在模糊卷积中使用两个「tf.custom_gradient」函数很好地解决了这样的一个问题。
我对 StyleGAN 进行了几次实验调整,并取得了不同程度的成功。
1. 我通过将初始分辨率改为 8x4 并随后增大分辨率来测试矩形图像。
2. 我尝试用 ACGAN 和带有投影判别器的 cGan 来实现「条件 StyleGAN」。
第一个实验在矩形图像上的效果很好,用 ACGAN 和 cGan 实现的「条件 StyleGAN」效果则较差。这可能是由于我的超参数选择不够好,但是通常来说,结果比无条件训练后在潜空间中找到有意义的特征对应的向量的结果差(本文将在「训练/后处理」部分中进行讨论)。
数据
随 StyleGAN 论文一起发布的 FFHQ 数据集含有 70,000 张高分辨率图像。为了更接近生成完整任务的目标,我尝试修改英伟达提供的数据抽取脚本,按照 8:4(高:宽)的比率来提取图像。
除了提取脸部,也从脸部下方提取了相同量的数据。将高度和宽度加倍将需要原始输入尺寸提升 4 倍,而仅将高度加倍则需要将尺寸提升 2 倍。人脸下方的数据也应具有比背景数据更少的变化(差异主要来自不同的衣服),不获取背景数据意味着网络不需要为不属于人物的数据分配容量。
不幸的是,FFHQ 数据集的 70,000 张图片中只有 20,000 张在人脸以下的区域有足够的数据来按照预期的纵横比来创造图片。如图 11 所示,我并不能使用这个小数据及得到特别高质量的结果,但是仍然可能存在提高质量的方法(比如提升收录一张图片的标准)。
图 11:矩形 FFHQ 图像趋于低质量
我也对 GAN 在风格化绘画上的能力很感兴趣,我看到最近「Danbooru2018」(https:///animating-ganime-with-stylegan-part-1-4cf764578e
https://github.com/nagadomi/lbpcascade_animeface
这些工具并不总是正确地提取图像,所以我使用了「illustration2vec」(https://github.com/rezoo/illustration2vec )来过滤结果,因为那种无法检测到人的图像很可能是糟糕的。
我还创建了一个能显示大的图像网格的工具,我能够最终靠它快速手动删除坏的图片,但是这对于包含超过 30,000 张图片的数据集来说太花费时间了。我最终得到的是包含了具有各种质量和标签的图像的几个不同的数据集,图像的数量从 40,000 张到 160,000 张图像不等。完成所有这些工作后,我们得到了一个比我构建的拥有 20,000 张图像的 FFHQ 数据集好得多的一个模型。