最近对生成模型的兴趣有了很大的复兴(参见这篇博客例如OpenAI)。这些模型可以学习创建与我们提供的数据相似的数据。这背后的直觉是,如果我们能得到一个模型来写高质量的新闻文章,那么它一定也学习了很多一般的新闻文章。或者换句话说,模型也应该有一个好的内部表示的新闻文章。然后,我们就有希望使用这种表示来帮助我们完成其他相关任务,比如按主题对新闻文章进行分类。实际上,训练模型来创建这样的数据并不容易,但近年来,一些方法已经开始相当有效。其中一个很有前途的方法是使用生成对抗网络(GANs)。Facebook著名的深度学习研究员、人工智能研究总监扬·勒丘恩最近表示引用GANs作为深度学习领域最重要的新发展之一:

“深度学习领域最近有许多有趣的进展……在我看来,最重要的是对抗训练(也称为GAN,即生成对抗网络)。在我看来,这和现在正在被提出的变化是过去10年ML中最有趣的想法。”- - -Yann勒存

这篇文章的其余部分将更详细地描述GAN的公式,并提供一个使用GAN解决一个玩具问题的简短示例(使用TensorFlow中的代码)。

区别式与生成式模型

在看GANs之前,让我们简单回顾一下生成和辨别模型之间的区别:

  • 一个区别的模型学习映射输入数据(x)到一些所需的输出类标签(y).在概率方面,他们直接学习条件分布P (y | x)
  • 一个生成模型试图同时学习输入数据和标签的联合概率,即。P (x, y).这可以转换为P (y | x)通过贝叶斯规则进行分类,但生成能力也可以用于其他事情,比如创造可能的新事物(x, y)样本。

这两种类型的模型都很有用,但是生成模型比鉴别模型有一个有趣的优势——即使没有标签,生成模型也有可能理解和解释输入数据的底层结构。在处理真实世界中的数据建模问题时,这是非常可取的,因为没有标签的数据当然是大量的,但获得有标签的数据通常在最好的情况下是昂贵的,在最坏的情况下是不切实际的。

生成对抗的网络

甘斯是一个有趣的想法吗首先介绍了由Ian Goodfellow(现就职于OpenAI)领导的蒙特利尔大学的一组研究人员于2014年完成。GAN背后的主要思想是有两个相互竞争的神经网络模型。一种将噪声作为输入并生成样本(因此称为生成器)。另一个模型(称为鉴别器)同时接收来自生成器和训练数据的样本,并且必须能够区分这两个来源。这两个网络进行了一个持续的博弈,其中生成器正在学习生成越来越多的真实样本,而鉴别器正在学习越来越善于将生成的数据与真实数据区分开来。这两个网络是同时训练的,希望通过竞争可以使生成的样本与真实数据难以区分。氮化镓

氮化镓概述。来源:https://ishmaelbelghazi.github.io/ALI

这里经常使用的类比是,生成器就像一个试图制造一些伪造材料的造假者,而鉴别器就像试图检测伪造物品的警察。这种设置似乎也有点让人想起强化学习,其中生成器从鉴别器接收奖励信号,让它知道所生成的数据是否准确。然而,与GANs的关键区别在于,我们可以将梯度信息从鉴别器反向传播回生成器网络,因此生成器知道如何调整其参数,以产生可以欺骗鉴别器的输出数据。

到目前为止,GANs主要应用于自然图像建模。他们现在正在生产出色完成图像生成任务,生成的图像比使用基于最大似然训练目标的其他领先生成方法训练的图像清晰得多。以下是一些由GANs生成的图像示例:

gan-samples-1

生成的卧室。来源:“无监督表示学习与深度卷积生成对抗网络”https://arxiv.org/abs/1511.06434v2

gan-samples-2

生成CIFAR-10样本。来源:“训练GANs的改进技术”https://arxiv.org/abs/1606.03498

近似一维高斯分布

为了更好地理解这一切是如何工作的,我们将使用GAN来解决TensorFlow中的一个玩具问题——学习近似一维高斯分布。这是基于a博客Eric Jang也有类似的目标。我们的演示的完整源代码可以在Github (https://github.com/AYLIEN/gan-intro),这里我们将只关注代码中一些更有趣的部分。首先,我们创建“真实”数据分布,即平均值为4、标准差为0.5的简单高斯分布。它有一个样本函数,从分布中返回给定数量的样本(按值排序)。

类DataDistribution(对象):def __init__(self): self。= 4 self。sigma = 0.5 def sample(self, N):亩,自我。sigma, N) samples.sort()返回样本

我们要学习的数据分布是这样的:数据

我们还定义了发生器输入噪声分布(使用类似的样本函数)。Eric张成泽的后例子,我们也用a分层抽样发生器输入噪声的方法-首先在指定范围内均匀地生成样本,然后随机扰动。

类GeneratorDistribution(对象):def __init__(self, range): self。返回N .linspace(-self, N)。范围内,自我。N) + np.random.random(N) * 0.01

我们的发生器和鉴别器网络非常简单。生成器是一个经过非线性(软加函数)的线性变换,然后是另一个线性变换。

Def生成器(input, hidden_size): h0 = tf.nn。Softplus (linear(input, hidden_size, 'g0')) h1 = linear(h0, 1, 'g1')返回h1

在这种情况下,我们发现确保鉴别器比生成器更强大是很重要的,否则它就没有足够的能力来学习准确区分生成的和真实的样本。所以我们做了一个更深入的神经网络,拥有更大的维度。它在所有层中都使用了tanh非线性,除了最后一层,它是一个sigmoid(它的输出可以解释为概率)。

Def鉴别器(input, hidden_size): h0 = tf。Tanh (linear(input, hidden_size * 2, 'd0')) h1 = tf。Tanh (linear(h0, hidden_size * 2, 'd1')) h2 = tf。Tanh (linear(h1, hidden_size * 2, 'd2')) h3 = tf。Sigmoid (linear(h2, 1, 'd3'))返回h3

然后我们可以将这些片段连接到一个TensorFlow图中。我们还为每个网络定义损失函数,生成器的目标只是简单地欺骗鉴别器。

with tf.variable_scope('G'): z = tf.placeholder(tf. placeholder)float32, shape=(None, 1)) G = generator(z, hidden_size),使用tf.variable_scope('D')作为作用域:float32, shape=(None, 1)) D1 = discriminator(x, hidden_size) scope.reuse_variables() D2 = discriminator(G, hidden_size) loss_d = tf.reduce_mean(-tf.log(D1) -tf.log(1 - D2)) loss_g = tf.reduce_mean(-tf.log(D2))

我们使用TensorFlow中普通的GradientDescentOptimizer为每个网络创建优化器,具有指数学习率衰减。我们还应该注意,在这里找到好的优化参数确实需要一些调优。

def优化器(loss, var_list): initial_learning_rate = 0.005 decay = 0.95 num_decay_steps = 150 batch = tf.Variable(0) learning_rate = tf.train.exponential_decay(initial_learning_rate, batch, num_decay_steps, decay, staircase=True)优化器= GradientDescentOptimizer(learning_rate)。最小化(loss, global_step=batch, var_list=var_list) return optimizer vars = tf.trainable_variables() d_params = [v for v in vars if v.name.startswith('D/')] g_params = [v for v in vars if v.name.startswith('G/')] opt_d = optimizer(loss_d, g_params)

为了训练模型,我们从数据分布和噪声分布中提取样本,并在优化鉴别器和发生器的参数之间交替进行。

使用tf.Session()作为会话:tf.initialize_all_variables().run() for step in xrange(num_steps): # update discriminator x = data.sample(batch_size) z = gen.sample(batch_size) session.run([loss_d, opt_d], {x: np。重塑(x, (batch_size, 1)), z: np。重塑(z, (batch_size, 1))})# update generator z = gen.sample(batch_size) session.run([loss_g, opt_g], { z: np.reshape(z, (batch_size, 1)) })

下面的动画展示了生成器如何在训练过程中学习近似数据分布:

我们可以看到,在训练过程的开始,生成器产生了一个与真实数据非常不同的分布。它最终学会了非常接近它的近似(大约在第750帧左右),然后收敛到一个聚焦于输入分布均值的更窄的分布。训练之后,两个分布看起来像这样:

gan-trained-1

这在直觉上是有道理的。鉴别器从真实数据和生成器中查看单个样本。在这个简单的例子中,如果生成器只产生真实数据的平均值,那么它很可能会欺骗鉴别器。

这个问题有很多可能的解决方案。在这种情况下,我们可以添加某种早期停止准则,当两个分布之间达到某种相似阈值时暂停训练。然而,我们还不完全清楚如何将其推广到更大的问题中,即使是在简单的情况下,我们也很难保证我们的发电机分配总能达到一个提前停止有意义的点。一个更有吸引力的解决方案是,通过给予鉴别器一次检查多个示例的能力,直接解决问题。

提高样本的多样性

发电机崩溃到一个参数设置,输出非常狭窄的点分布的问题是GANs的“主要故障模式之一”最近的一篇论文由Tim Salimans和OpenAI的合作者完成。值得庆幸的是,他们还提出了一个解决方案:允许鉴别器同时查看多个样本,他们称之为一种技术minibatch歧视.在本文中,将小批鉴别定义为任何方法,其中鉴别器能够查看整个批次的样本,以决定它们是来自生成器还是来自真实数据。他们还提出了一种更具体的算法,该算法通过模拟给定样本与同一批次中所有其他样本之间的距离来工作。然后将这些距离与原始样本结合,并通过鉴别器,因此在分类过程中,它可以选择使用距离度量和样本值。该方法大致可以总结如下:

  • 取鉴别器的某个中间层的输出。
  • 将其乘以一个3D张量就得到了一个矩阵(大小为num_kernels x kernel_dim,如下面的代码所示)。
  • 在批处理的所有样本中计算矩阵中行之间的l1距离,然后应用一个负指数。
  • 样本的小批特征是这些指数距离的和。
  • 将原始输入与新创建的小批处理特性连接到小批处理层(前一个鉴别器层的输出),并将此作为输入传递到鉴别器的下一层。

在TensorFlow中,它可以翻译成这样:

Def小批处理(input, num_kernels=5, kernel_dim=3): x =线性(input, num_kernels * kernel_dim)激活= tf。重塑(x, (-1, num_kernels, kernel_dim))Expand_dims(激活,3)- tf. Expand_dims (tf. Expand_dims)。转(激活,[1,2,0]),0)abs_diffs = tf.reduce_sum(tf.abs(diffs), 2) minibatch_features = tf.reduce_sum(tf.exp(-abs_diffs), 2)返回tf.reduce_sum(tf.exp(-abs_diffs), 2)concat([输入,minibatch_features])

我们实现了提议的小批识别技术,看看它是否有助于解决我们的示例中的生成器输出分布崩溃问题。发电机网络在训练过程中的新行为如下所示。

在本例中,很明显,添加小批区分会使生成器保持原始数据分布的大部分宽度(尽管它仍然不完美)。收敛后的分布是这样的:

gan-trained-2

关于区分小批的最后一点是,它使得批大小作为超参数更加重要。在我们的玩具例子中,我们必须保持相当小的批次(少于16个左右),以便训练收敛。也许仅仅限制用于每个距离测量的样本数量就足够了,而不是使用整个批处理,但这又是一个需要调优的参数。

最终的想法

生成对抗网络是一个有趣的发展,为我们提供了一种进行无监督学习的新方法。大多数GANs的成功应用都在计算机视觉领域,但在Aylien,我们正在研究将这些技术应用于自然语言处理的方法。如果你们有相同的想法,想要交换意见,那么请与我们联系。这一领域的一个悬而未决的大问题是如何最好地评估这些类型的模型。在图像域中,至少可以很容易地查看生成的样本,尽管这显然不是一个令人满意的解决方案。在文本领域,这就更没用了(除非你的目标是生成散文)。使用基于最大似然训练的生成模型,我们通常可以根据未见测试数据的似然(或似然的某个下界)生成一些度量,但在这里不适用。一些GAN论文给出了基于核密度估计但这种技术在高维空间中似乎失效了。另一种解决方案是只评估某些下游任务(如分类)。如果你有任何其他建议,我们很乐意听到你的意见。

更多的信息

如果你想了解更多关于GANs的知识,我们建议从以下出版物开始:

请随意重用GAN代码,当然也要留意我们的博客.欢迎评论、更正和反馈。 开始免费试用

消息灵通

我们会不时地通过电子邮件与您联系我们的产品和服务。