作者:Marco Pasini
编译:ronghuaiyang
导读
训练生成对抗网络是很难的:我们来想办法变得简单一点。
介绍
一年前,我决定开始我的旅程,进入生成对抗网络(GANs)的世界。自从我对深度学习产生兴趣以来,我就一直对它们很感兴趣,主要是因为它们能产生难以置信的结果。当我想到人工智能这个词的时候,GAN是我脑海中最先出现的一个词。
但直到我第一次开始训练它们时,我才发现这种有趣算法的两面性:训练极其困难。是的,在我尝试之前,我从报纸上和其他人的尝试中了解到这一点,但我一直认为他们夸大了一个本来很小但很容易克服的问题。
我错了。
当我尝试生成一些与传统MNIST示例不同的东西时,我发现了影响GANs的巨大不稳定问题,并且随着花在寻找解决方案上的时间的增加,变得非常烦人。
现在,在花了无数天的时间研究已知的解决方案并尝试提出新的解决方案之后,我终于可以说,在我的GAN项目中,我至少对收敛的稳定性有了更多的控制,你也可以。我不会承诺你一个10分钟的解决方案来对每个项目都实现完美的收敛 (或用博弈论的话说,纳什均衡),但我想给你一些可以跟着做的技巧和技术,这样你训练GAN的旅程会更简单,耗时少,最重要的是,更少的烦人。
目前GANs的状态
自生成对抗网络及其稳定性问题产生以来,进行了大量的研究。目前已有大量的文献提出了稳定收敛的方法,除此之外,还有大量的数学证明。此外,一些实用的技巧和启发方法也出现在了深度学习领域:我注意到,这些未经证实的技巧往往没有数学思维的支持,却出奇地有效,绝不能被抛弃。
随着稳定性的提高,生成的图像真实感也出现了重大飞跃。你只需要看看来自英伟达的StyleGAN和来自谷歌的BigGAN的结果就能真正理解GANs已经走了多远。
在阅读并尝试了文献和实践中的许多技巧之后,我整理了一个列表,列出了在训练GANs时应该考虑和不应该考虑的技巧,希望能让你对这个复杂且有时单调乏味的主题有进一步的了解。
1. 稳定性和容量
当我开始我的第一个独立的GAN项目时,我注意到在训练过程的早期,识别器的对抗损失总是趋于零,而生成器的损失却非常高。我立即得出结论,一个网络没有足够的“容量”(或参数数量)来跟上另一个网络,因此我匆忙更改生成器的架构,在卷积层上添加更多的过滤器,但令我惊讶的是,什么也没有改变。
在进一步探究网络容量变化对训练稳定性的影响后,我没有发现任何明显的相关性。两者之间肯定存在某种联系,但它并不像你刚开始想象的那么重要。
因此,如果你发现自己的训练过程不平衡,而且你没有任何明显超过对方的网络能力,我不建议你添加或删除过滤器作为主要解决方案。
当然,如果你对自己的网络容量非常不确定,你可以在线查看一些用于类似场景的架构示例。
2. 提前停止
在GANs训练中,你可能会遇到的另一个常见错误是,当你看到生成器或鉴别器损失突然增加或减少时,立即停止训练。我自己也这么做过无数次:在看到损失增加之后,我立刻想到整个训练都完蛋了,而责任在于某个调得不完美的超参数。
直到后来,我才意识到,通常损失的上升或下降几乎是随机的,这没有什么错。我取得了一些很好的实验 的结果,而生成器的损失远高于鉴别器的损失,这是完全正常的。因此,当你在训练过程中遇到突然的不稳定时,我建议你多训练一会儿,在训练过程中注意生成图像的质量,因为视觉理解通常比一些损失数字更有意义。
3. 损失函数的选择
在选择用于训练GAN的损失函数时,我们应该选择哪一个?
最近的一篇论文解决了这个问题(https://arxiv.org/abs/1811.09567),其中对所有不同的损失函数进行了基准测试和比较:出现了一些非常有趣的结果。显然,选择哪个损失函数并不重要,没有哪个函数绝对优于其他函数,GAN能够在每个不同的情况下学习。
因此,我的建议是从最简单的损失函数开始,留下一个更具体和“最先进的”选项作为可能的最后一步,正如我们从文献中了解到的,你很可能会得到一个更糟的结果。
4. 平衡生成器和鉴别器的权重更新
在许多GAN论文中,特别是一些早期的论文中,在实现部分中经常可以看到,作者每更新生成器两次或三次才更新一次识别器。
在我的第一次尝试中,我注意到在不平衡训练的情况下,几乎每次鉴别器网络会压过另一个(损失大大减少)。因此,当我读到即使是著名论文的作者也有类似的问题,并实施了一个极其简单的解决方案来克服它时,我对自己所做的一切充满信心。
不幸的是,在我看来,通过不同的网络权重更新来平衡训练是一个非常短视的解决方案。最终,稳定我训练的解决方案是几乎不改变生成器更新其权重的频率:它有时可以推迟“不稳定”,但永远无法解决它,直到收敛。当我注意到这种技术的无效时,我甚至试图使它更加动态,根据两个网络损失的当前状态改变权值update schedule,直到后来我才发现,我并不是唯一一个试图走这条路的人,和其他许多人一样,我也没有成功地克服不稳定性。
我后来才明白,其他技术,在本文后面的解释中,在提高训练稳定性方面有更大的作用。
5. 模式坍塌和学习率
如果你正在处理GANs,你肯定知道什么是模式坍塌。它包含在生成器“坍塌”中,并且总是为输入的每个可能的潜向量生成同一个图像。在GAN训练中,这是一个相当常见的障碍,在某些情况下,它会变得非常烦人。
如果您发现自己处于这种情况,我建议您使用最直接的解决方案是尝试调整GAN的学习率,因为根据我的个人经验,我总是能够克服这个障碍,改变这个特定的超参数。根据经验,当处理模式坍塌时,尝试使用一个较低的学习率并从头开始训练。
学习速度是最重要的超参数之一,即使不是最重要的超参数,因为即使是很小的变化也会导致在训练过程中发生根本性的变化。通常,当使用更大的批处理大小时,你可以允许更高的学习率,但是在我的经验中,处于保守的一边几乎总是一个安全的选择。
还有其他方法可以对抗模式坍塌,比如Feature Matching和Minibatch Discrimination,我从来没有在自己的代码中实现过,因为我总能找到另一种方法来避免这种特别的麻烦,但是如果需要的话,可以给予它们一些关注。
6. 加噪声
众所周知,增加鉴别器的训练难度有利于提高系统的整体稳定性。增加鉴别器训练复杂度的最著名的方法之一是在真实数据和合成数据(例如由生成器生成的图像)中添加噪声,在数学世界中,这应该是可行的,因为它有助于为两个相互竞争的网络的数据分布提供一定的稳定性。它确实是一个简单的解决方案,我建议您尝试一下,因为它在实践中可以很好地工作(即使它不能神奇地解决您可能遇到的任何不稳定问题),同时只需要很少的设置工作。话虽如此,我开始的时候使用这种技术,但过了一段时间后就放弃了,而是更喜欢其他一些在我看来更有效的技术。
7. 标签平滑
实现相同目标的另一种方法是标签平滑,这更容易理解和实现:如果真实图像的标签设置为1,我们将它更改为一个较低的值,比如0.9。这个解决方案不鼓励鉴别器对其分类过于自信,或者换句话说,不依赖非常有限的一组特征来判断图像是真还是假。我完全赞同这个小技巧,因为它在实践中表现得非常好,并且只需要更改代码中的一两个地方。
8. 多尺度梯度
当处理不是太小的图像(如MNIST中的图像)时,你必须查看多尺度梯度。这是一个特殊的GAN实现,由于两个网络之间有多个跳过连接,使得梯度流从鉴别器到生成器,类似于传统用于语义分割的U-Net中所发生的情况。
多尺度梯度论文的作者能够训练GAN直接生成高清晰度 1024x1024图像,没有任何特定的障碍(模式坍塌等),而以前只有progressively growing GANs(英伟达ProGAN)才有可能。我已经在我的项目中实施了它,我注意到这是一个更稳定的训练和具有令人信服的结果。
9. TTUR
当我说Two Time-Scale Update Rule,或者TTUR的时候,你可能会认为我指的是GAN训练中使用的一种复杂的技术,你可能完全错了。它只包含为生成器和鉴别器选择不同的学习率,仅此而已。在首次引入TTUR的论文中,作者提供了一个收敛于Nash均衡的数学证明,并证明了使用不同的学习率实现著名的GANs (DCGAN, WGAN-GP)可以获得最先进的结果。
但是当我说“使用不同的学习速度”时,我在实践中真正的意思是什么呢?一般来说,我建议为鉴别器选择更高的学习速度,而为生成器选择更低的学习速度:这样一来,生成器就必须采取更小的步骤来欺骗鉴别器,并且不会选择快速、不精确和不现实的解决方案来赢得对弈。为了给出一个实际的例子,我经常为discriminator选择0.0004,为generator选择0.0001,我发现这些值在我的一些项目中运行得很好。请记住,在使用TTUR时,你可能会注意到生成器的具有更好的损失。
10. 谱归一化
在一些文献中,如介绍SAGAN(或Self - Attention GAN)的文献中,表明谱归一化是应用于卷积核上的一种特殊的归一化,可以极大地提高训练的稳定性。它最初只在鉴别器中使用,后来被证明是有效的,如果也用于生成器的卷积层,我可以完全赞同这个决定!
我几乎能说的发现和实现光谱归一化改变了我的GAN旅程方向,我坦率地说没有看到任何理由不使用它,我几乎可以保证它会把你带到一个更好的结果以及更稳定的训练,从而让可以你关注其他更有趣的方面。
结论
许多其他技巧、更复杂的技术和体系结构有望解决GANs的训练问题:在本文中,我想告诉你我个人发现并实现了哪些方法来克服我遇到的障碍。
因此,如果你在了解这里介绍的每种方法和技巧时发现自己陷入了困境,那么还有更多的资料需要研究。我只能说,在花了无数个小时学习和尝试所有可能的解决GAN相关问题的方法之后,我对我的项目更加自信了,我真的希望你们也能这样做。
英文原文:https://towardsdatascience.com/10-lessons-i-learned-training-generative-adversarial-networks-gans-for-a-year-c9071159628