生成对抗网络(GAN)近来在研究界得到了很大的关注。在这篇文章中,Waya.ai 的创始人 Michael Dietz 介绍了 GAN 如此大有潜力的原因,并且通过 GAN 与拳击比赛的生动比较对 GAN 的工作方式进行了阐释。
生成对抗网络(GAN)由两个独立的网络组成,即生成器(generator)和判别器(discriminator)。GAN 将无监督学习问题作为这两者之间的博弈。在本文中,我们将看到为什么 GAN 有这么大的潜力,并且通过 GAN 与拳击比赛的比较来对其进行阐释。
生成对抗网络和拳击比赛没什么不同
深度学习背后的原理
深度学习源于生物学的启发,因此许多深度学习主要概念都是直观的和基于现实的。深度学习的基本原理是层次性架构——层次不仅指网络中的层,还有它们建立在彼此之上的学习到的表征。实际上,我们的现实世界也是如此:电子、质子、中子 → 原子 → 分子 →……通过层次化的方式来对层次性的世界建模是顺理成章的,这就是为什么深度学习使用简单、优雅和通用的方法就已经能够如此成功地解决非常困难的问题。
可视化由深度卷积神经网络学习的层次结构和表征
激励无监督学习
「对抗训练是有史以来最酷的东西。」
——Yann LeCun,Facebook 人工智能研究部门主管、纽约大学教授
现在让我们将这个生物学的灵感应用到目前训练网络的方法上。监督学习(supervised learning)是目前机器学习的基本方法——即对于每个数据样本,训练中都需要一个真实的注释/标签。但现实世界中大多数学习是无监督学习完成的。只要想想我们如何学习走路、谈话等……虽然有监督学习在许多任务上表现良好,但无监督学习似乎才是真正的人工智能的关键。
准确的数据标签通常是不切实际的。理想情况下,可以对无标签数据进行无监督的模型训练,然后使用足够小的标签的数据集进行微调。回到层级世界的观点,应该有可能训练人工智能了解世界的基本构建块,然后在现有的知识库之上进行开发,然后以更监督式的方式对特定用例进行微调。
无监督学习——一个具体的例子
我们通过训练数百万未标记的皮肤图像来构建一个卷积神经网络。这些图像中,一些是健康的皮肤,另一些是患病的皮肤,还有一些介于患病和健康之间。最终,神经网络将通过学习而获得对皮肤及其复杂性的深入理解。构建网络之后,就可以使用该网络处理具体的实例(如即时准确地诊断皮肤癌)。
由于该模型已经学会皮肤图像中包含的最重要信息的通用、有效的表征,因此相比于仅使用监督式方法进行训练,模型应该仅使用更小的标签数据集就能快速学习诊断皮肤癌的新任务。这是迁移学习(transfer learning)和微调(fine-tuning)的基本概念。
GAN 是无监督学习中最有希望的研究领域之一,我们将看到它们是学习大数据表征的简单且有效的方法。
理解 GAN
让我们从细节讲解 GAN 的基本组成部分:
数据:从数学上讲,我们将数据集看作是从真实数据分布抽样出的样本。这些数据可以是图像、语音、传感器读数等。
生成器(generator):将一些代码(即随机噪声)作为输入,将其转换并输出数据样本。生成器的目标是最终输出服从真实数据分布的不同数据样本。
判别器(discriminator):将数据样本作为输入,并将其分类为真实的(来自真实数据分布)或伪造的(来自生成器)。判别器的目的是能够高精度地分辨真实的和生成的图像。
标准 GAN 的整体目标是训练出能够生成服从真实数据分布的不同数据样本的生成器,使得判别器只能有 50% 的概率将图像分类为真实的/生成的。在训练这个网络的过程中,生成器和判别器都会学习源数据的强大的层次化的表征,然后可以将其迁移到各种特定任务(如分类、分割等……)和应用案例。
理解 GAN 的训练过程
下面的伪代码可能会令你感到困惑,所以我们将紧接着用一个简单的真实的对抗学习(adversarial learning)过程例子来展示它。
while equilibrium_not_reached:
# train the discriminator to classify a batch of images from our
# dataset as real and a batch of images generated by our current
# generator as fake
1.)
discriminator.train_on_batch(image_batch=real_image_batch, labels=real)
2.)
discriminator.train_on_batch(image_batch=generated_image_batch, labels=fake)
# train the generator to trick the discriminator into
# classifying a batch of generated images as real. The key here
# is that the discriminator is frozen (not trainable) in this
# step, but it's loss functions gradients are back-propagated
# through the combined network to the generator
# the generator updates its weights in the most ideal way
# possible based on these gradients
3.)
combined.train_on_batch(input=batch_of_noise, labels=real)
# where combined is a model that consists of the generator and
# discriminator joined together such that: input => generator =>
# generator_output => discriminator => classification
无论是否意识到,我们都非常熟悉 GAN 和对抗学习的一般概念。例如,试想学习在吉他上弹奏歌曲:
1. 听歌曲——弄清楚如何将歌曲映射到吉他上(上面的训练过程中的第 1 步)
2. 尝试弹奏歌曲——聆听弹奏的内容,并注意与实际歌曲的不同之处(第 2 步)
3. 再次弹奏歌曲——试图解决这些差异(第 3 步)
我们添加一些变化并重复这个过程,其中将步骤 2 和步骤 3 合并,并且将步骤 1 的结果部分储存在内存中,并在储存结果(记忆)需要改进的时候重新访问它,直到我们能够开心地弹奏出足够接近真实歌曲的声音。
因为你已经成为了一个更有技巧的吉他手,你可以学习新的歌曲,你可以仅需要一点练习就学会弹奏以前从未听过或弹奏过的歌曲(即迁移学习(transfer learning)/微调(fine-tuning))。
在这个例子中,歌曲就是数据,我们的耳朵/大脑是判别器,我们的手/大脑是生成器。这可能类似于我们如何学习行动、说话等……更进一步,想象聋哑人说话的情形——这听起来很有趣,因为他们没有判别器来促进对抗学习(也许他们可以选择其它提示(如人们的反应)来作为一种弱的判别器)。
现在我们已经对 GAN 建立了一些直观的认识,让我们来看看如何在软件中实现它们。我们需要考虑现实中的 GAN 与软件之间的相似点和差异点。举例一个差异,现实中发生的对抗学习过程在生成器和判别器之间看起来是协同的,而 GAN 的软件实现看起来是对抗性的(……就像拳击比赛)。
训练 GAN——生成器和判别器之间的拳击比赛
Creed 是判别器,Rocky 是生成器。叮……叮……开打啦!
乍一眼看上去,判别器似乎是教练,生成器是拳击手。但事实上它们都是拳击手,而真实的数据实际上是教练。唯一的不同是只有判别器可以直接访问数据。
判别器是从教练学习的拳击手(真实的数据集越大,教练越有经验),而生成器是只能从它的对手(判别器)学习的拳击手。
在上述训练过程的第 1 步中,判别器由它的教练通过沉重的沙袋训练一轮。教练指出它技术的不足并且促使判别器适应。在第 2 步中,判别器观察生成器打一轮拳击,研究生成器并相应准备其即将到来的一轮拳击比赛。
泄漏的拳击镜头画面意味着对手有更多的材料来学习和准备。
现在第 3 步,拳击比赛!生成器是来自费城的一个好斗的拳击手,它在拳击的时候放松和专注,研究判别器的每一个动作和错误并从中学习——在每轮之后适应。判别器讨厌拳击,每当它完全没有学习到任何东西的时候,它也很害怕和紧张。判别器也许比生成器更具有运动天赋(将数据分类为真实/假的比实际生成数据更容易),但是生成器的心态有助于进行比赛。即使生成器没有教练(无法访问真正的数据集),但它从判别器中学到了很多东西,因为它吸取了它的教练所教的基本特征。
持续这个过程,几轮下来后,直到最终判别器和生成器都成为全能的拳击手,并为比赛做好准备。教练已经教了它所知道的比赛的每一个重要细节,生成器和判别器在它们的拳击比赛中相互学习了很多。理想情况下,它们在训练结束时都是一样的,它们之间比赛的胜败几率是 50/50。
困难
当你深入研究 GAN 时,你会看到我们目前所面对的一个主要困难,即训练这些网络以让其较好地收敛——我们想让生成器与判别器能够达到我们所希望的平衡,但是通常都不太会实现。关于会发生怎样的错误可以参见这个网址,在里面你可以查阅很多信息与相关研究:https://www.quora.com/Do-generative-adversarial-networks-always-converge。下面这个网址提供了越来越多如何应对这些问题的信息:https://github.com/soumith/ganhacks。
以下突出强调几个最普遍的 GAN 失败的例子:
1、判别器变得过于强大、迅速,导致生成器结束训练时学不到任何东西。在我们拳击类比中,这就像是判别器变得太强以至于生成器完全在被吊打。由于判别器(相对于生成器)不会犯任何错误也不会给生成器留下任何可匹敌的空间,所以生成器无法学到任何东西。理论上这意味着,在上述训练步骤 3 中,判别器非常精准且自信地把生成的数据分类为假,以至于在对生成器所学习的判别器反向传播损失函数梯度(discriminator's back-propagated loss function gradients)中没有任何东西。
2、生成器仅会学习判别器非常特定的弱点,然后利用这些弱点来欺骗判别器以使判别器将数据分类为真,而不是学习去描绘真实的数据分布。这在理论上的解释可以参见:http://www.kdnuggets.com/2015/07/deep-learning-adversarial-examples-misconceptions.html。在我们拳击类比中,这就像是生成器仅学到了关于判别器非常有限的弱点,然后尽可能地利用那些弱点而不是去好好学习关于拳击的基础和技巧。在对阵一个没有同样缺点的对手时,生成器会变得毫无用处!并且判别器从生成器中学到的任何东西都也会变得没有用处,因为在真实的比赛中判别器的对手不会表现得像生成器这般无用。
3、生成器仅学习了真实数据分布中非常小的一个子集。在我们的拳击类比中,这就像是我们的生成器仅学会了出拳猛击和躲闪——而没有发展出任何其它工具和技巧。这将会导致判别器从生成器那里仅能学到非常少的东西,并且使得判别器过分重要地去表示这数据分布的小小的子集。在实践中发生的一个例子即:对每个可能的输入,生成器都生成同样的数据样本,并且其输出数据没有任何变化。
以上的类比是一项正在进行的实验,未来我们会添加更多相关信息。
结论
既然我们已经对 GAN 有一个基础性的了解,那么让我们现在重新审视一下其目标:从非标记的数据中学习强大的表征(例如:从原始数据中获取我们的数据,学习在一个小得多的范围中去表征其最重要的特征 →实现理想的表现所需的有标注数据更少)。
在训练一个 GAN 之后,目前大多数方法将判别器用作迁移学习基本模型以及对生产模型的微调,亦或是将生成器用作训练生产模型的数据源。在我们的拳击类比中,这意味着判别器拿到了他的拳击执照并且竞争对手生成器没有拿到。很不幸,因为生成器看起来是有潜力成为一个更好的拳手的。他要么被解雇,要么就只能作为一个生产模型的陪练。
我所无法创造的,我也无法理解。
一个训练得很好的生成器很好地学习了真实的数据分布,它可以从一个小得多的输入范围中生成属于它的样本。这意味着它发展出了极其强大的数据表征能力。能够在生产模型中直接利用生成器所学到的东西就好了,但目前似乎还没有任何能够做到这一点的方法。如果有,请评论告知。
欲知标准 GAN 清楚且简单的实现(和其它类型的 GAN,如 InfoGAN 和 ACGAN)参阅:
GAN 沙盒:基于 Keras/TensorFlow 实现的 Vanilla GAN——可实现快速实验和研究:https://github.com/wayaai/GAN-Sandbox
这里有几类可生成极为有价值生成器的 GAN,尽管它们也还是「陪练」:
SimGAN:无监督学习和自动驾驶等中的变革者:https://medium.com/intuitionmachine/simgans-applied-to-autonomous-driving-5a8c6676e36b
原文链接:http://www.kdnuggets.com/2017/03/deep-learning-gans-boxing-fundamental-understanding.html