如何使用 Keras 开发信息最大化 GAN (InfoGAN)

生成对抗网络(GAN)是一种用于训练深度卷积模型以生成合成图像的架构。

尽管效果显著,但默认的 GAN 无法控制所生成图像的类型。信息最大化生成对抗网络(简称 InfoGAN)是对 GAN 架构的扩展,它引入了由架构自动学习的控制变量,可以控制生成图像的属性,例如手写数字图像的样式、粗细和类型。

在本教程中,您将了解如何从头开始实现信息最大化生成对抗网络模型。

完成本教程后,您将了解:

  • InfoGAN 的动机是解耦和控制生成图像中的属性。
  • InfoGAN 包含添加控制变量以生成辅助模型,该模型通过互信息损失函数预测控制变量。
  • 如何从头开始开发和训练 InfoGAN 模型,并使用控制变量来控制模型生成的数字。

通过我的新书《Python 生成对抗网络》开始您的项目,其中包括分步教程和所有示例的Python 源代码文件。

让我们开始吧。

  • 2019 年 10 月更新:修正了互信息损失解释中的拼写错误。
  • 2021 年 1 月更新:更新以使层冻结与批标准化一起工作。
How to Develop an Information Maximizing Generative Adversarial Network (InfoGAN) in Keras

如何在 Keras 中开发信息最大化生成对抗网络 (InfoGAN)
照片由 Irol Trasmonte 拍摄,部分权利保留。

教程概述

本教程分为四个部分;它们是

  1. 什么是信息最大化生成对抗网络
  2. 如何实现 InfoGAN 损失函数
  3. 如何为 MNIST 开发 InfoGAN
  4. 如何使用训练好的 InfoGAN 模型进行控制代码

什么是信息最大化生成对抗网络

生成对抗网络(简称 GAN)是一种用于训练生成模型(如生成合成图像的模型)的架构。

它涉及同时训练用于生成图像的生成器模型和学习将图像分类为真实(来自训练数据集)或虚假(生成)的判别器模型。这两种模型在一个零和博弈中竞争,使得训练过程的收敛涉及在生成器生成逼真图像的能力与判别器检测它们的能力之间找到平衡。

生成器模型以潜在空间中的一个随机点作为输入,通常是 50 到 100 个随机高斯变量。生成器通过训练为潜在空间中的点赋予独特的含义,并将点映射到特定的输出合成图像。这意味着,尽管潜在空间由生成器模型构建,但无法控制生成的图像。

GAN 公式使用简单的因子化连续输入噪声向量 z,同时不对生成器可能使用此噪声的方式施加任何限制。因此,噪声可能被生成器以高度纠缠的方式使用,导致 z 的各个维度不对应数据的语义特征。

InfoGAN:通过信息最大化生成对抗网络学习可解释的表示,2016。

可以探索潜在空间并比较生成的图像,以尝试理解生成器模型已学习的映射。或者,可以通过类标签等条件来控制生成过程,以便按需创建特定类型的图像。这是条件生成对抗网络(CGAN 或 cGAN)的基础。

另一种方法是将控制变量作为输入与潜在空间中的点(噪声)一起提供给生成器。生成器可以被训练为使用控制变量来影响生成图像的特定属性。这就是信息最大化生成对抗网络(简称 InfoGAN)所采用的方法。

InfoGAN,是对生成对抗网络的一种信息论扩展,能够以完全无监督的方式学习解耦的表示。

InfoGAN:通过信息最大化生成对抗网络学习可解释的表示,2016。

生成器在训练过程中学习到的结构化映射在某种程度上是随机的。尽管生成器模型学会了在潜在空间中空间上分离生成图像的属性,但无法进行控制。这些属性是纠缠的。InfoGAN 的动机是解耦生成图像的属性。

例如,在人脸生成的情况下,生成人脸的属性可以解耦和控制,例如脸型、发色、发型等。

例如,对于包含人脸的数据集,一个有用的解耦表示可能为以下每个属性分配一组单独的维度:面部表情、眼睛颜色、发型、是否存在眼镜以及相应的人的身份。

InfoGAN:通过信息最大化生成对抗网络学习可解释的表示,2016。

控制变量与噪声一起作为输入提供给生成器,并通过互信息损失函数训练模型。

……我们提出了一种对生成对抗网络目标函数的简单修改,该修改可以鼓励它学习可解释且有意义的表示。我们通过最大化 GAN 的一小部分固定噪声变量与观测值之间的互信息来实现这一点,这相对来说很直接。

InfoGAN:通过信息最大化生成对抗网络学习可解释的表示,2016。

互信息指的是通过了解另一个变量来了解一个变量的信息量。在这种情况下,我们感兴趣的是通过使用噪声和控制变量生成的图像来了解控制变量的信息。

在信息论中,X 和 Y 之间的互信息 I(X; Y) 衡量了从对随机变量 Y 的了解中获得的关于另一个随机变量 X 的“信息量”。

互信息 (MI) 的计算方式为:由生成器 (G) 从噪声 (z) 和控制变量 (c) 生成的图像(创建的图像)给定控制变量 (c) 的条件熵,减去控制变量 (c) 的边际熵;例如

  • MI = Entropy(c) – Entropy(c ; G(z,c))

在实践中,计算真实互信息通常是不可行的,尽管论文中采用了简化方法,称为变分信息最大化,并且控制代码的熵保持恒定。有关互信息的更多信息,请参阅教程

通过互信息训练生成器是通过使用一种称为 Q 或辅助模型的新模型来实现的。新模型与判别器模型共享所有相同的权重,用于解释输入图像,但与预测图像是真实还是虚假的判别器模型不同,辅助模型预测了用于生成图像的控制代码。

这两种模型都用于更新生成器模型,首先是为了提高生成欺骗判别器模型的图像的可能性,其次是为了提高用于生成图像的控制代码与辅助模型对控制代码的预测之间的互信息。

结果是生成器模型通过互信息损失进行正则化,使得控制代码捕获生成图像的关键属性,反过来,这些属性可用于控制图像生成过程。

……每当我们有兴趣学习一个从给定输入 X 到保留原始输入信息的更高层表示 Y 的参数化映射时,就可以利用互信息。 […] 表明最大化互信息的任务本质上等同于训练一个自编码器来最小化重构误差。

理解互信息及其在 InfoGAN 中的应用, 2016。

想从零开始开发GAN吗?

立即参加我为期7天的免费电子邮件速成课程(附示例代码)。

点击注册,同时获得该课程的免费PDF电子书版本。

如何实现 InfoGAN 损失函数

一旦熟悉了模型的输入和输出,InfoGAN 的实现就相当直接。

可能唯一的障碍是互信息损失函数,尤其是如果您没有像大多数开发人员那样扎实的数学背景。

InfoGan 使用的控制变量主要有两种:分类变量和连续变量,连续变量可能有不同的数据分布,这会影响互损失的计算方式。可以根据变量类型计算并对所有控制变量求和互损失,这是 OpenAI 为 TensorFlow 发布的原版 InfoGAN 实现所采用的方法。

在 Keras 中,简化控制变量为分类变量和高斯或均匀连续变量可能更容易,并在辅助模型上为每种控制变量类型设置单独的输出。这样就可以使用不同的损失函数,大大简化了实现。

有关此部分建议的更多背景信息,请参阅“进一步阅读”部分中的论文和文章。

分类控制变量

分类变量可用于控制生成图像的类型或类别。

这被实现为一个独热编码向量。也就是说,如果类别有 10 个值,那么控制代码将是一个类别,例如 6,并且输入到生成器模型的分类控制向量将是一个包含所有零值的 10 个元素的向量,其中类别 6 的值为 1,例如 [0, 0, 0, 0, 0, 0, 1, 0, 0]。

我们在训练模型时不需要选择分类控制变量;相反,它们是随机生成的,例如,每个样本以均匀概率选择。

……在潜在代码 c ∼ Cat(K = 10, p = 0.1) 上进行均匀分类分布

InfoGAN:通过信息最大化生成对抗网络学习可解释的表示,2016。

在辅助模型中,分类变量的输出层也将是独热编码向量,以匹配输入控制代码,并使用 softmax 激活函数。

对于分类潜在代码 ci,我们使用自然选择的 softmax 非线性来表示 Q(ci |x)。

InfoGAN:通过信息最大化生成对抗网络学习可解释的表示,2016。

回想一下,互信息是通过控制变量的条件熵和辅助模型的输出减去输入变量提供的控制变量的熵来计算的。我们可以直接实现这一点,但没有必要。

控制变量的熵是一个常数,并且非常接近零;因此,我们可以从计算中将其删除。条件熵可以直接计算为控制变量输入与辅助模型输出之间的交叉熵。因此,可以使用分类交叉熵损失函数,就像我们在任何多类分类问题上所做的那样。

使用超参数 lambda 来缩放互信息损失函数,并设置为 1,因此可以忽略。

尽管 InfoGAN 引入了一个额外的超参数 λ,但它很容易调整,并且对于离散潜在代码,将其设置为 1 就足够了。

InfoGAN:通过信息最大化生成对抗网络学习可解释的表示,2016。

连续控制变量

连续控制变量可用于控制图像的样式。

连续变量从均匀分布(例如 -1 到 1 之间)采样,并作为输入提供给生成器模型。

……连续代码可以捕获本质上连续的变化:c2, c3 ∼ Unif(−1, 1)

InfoGAN:通过信息最大化生成对抗网络学习可解释的表示,2016。

辅助模型可以通过高斯分布实现连续控制变量的预测,其中输出层配置为具有一个节点(均值)和一个节点(高斯标准差),例如,每个连续控制变量需要两个输出。

对于连续潜在代码 cj,根据真实的后验 P(cj |x) 有更多选项。在我们的实验中,我们发现将 Q(cj |x) 简单地视为因子化高斯就足够了。

InfoGAN:通过信息最大化生成对抗网络学习可解释的表示,2016。

输出均值的节点可以使用线性激活函数,而输出标准差的节点必须产生正值,因此可以使用 sigmoid 等激活函数来创建 0 到 1 之间的值。

对于连续潜在代码,我们通过对角高斯分布来参数化近似后验,并且识别网络输出其均值和标准差,其中标准差通过网络输出的指数变换进行参数化以确保正性。

InfoGAN:通过信息最大化生成对抗网络学习可解释的表示,2016。

损失函数必须计算为高斯控制变量的互信息,这意味着它们必须在计算损失之前从均值和标准差重构。计算高斯分布变量的熵和条件熵可以直接实现,但不是必需的。相反,可以使用均方误差损失。

或者,可以将输出分布简化为每个控制变量的均匀分布,辅助模型中每个变量使用一个输出节点,并具有线性激活,模型可以使用均方误差损失函数。

如何为 MNIST 开发 InfoGAN

在本节中,我们将仔细研究生成器 (g)、判别器 (d) 和辅助模型 (q),以及如何在 Keras 中实现它们。

我们将开发一个适用于 MNIST 数据集的 InfoGAN 实现,这与 InfoGAN 论文中的做法相同。

该论文探讨了两个版本;第一个版本仅使用分类控制代码,并允许模型将一个分类变量映射到大约一个数字(尽管数字没有按分类变量排序)。

Example of Varying Generated Digit By Value of Categorical Control Code

通过分类控制代码的值改变生成数字的示例。
取自 InfoGan 论文。

该论文还探讨了 InfoGAN 架构的一个版本,其中包含独热编码的分类变量 (c1) 和两个连续控制变量 (c2 和 c3)。

第一个连续变量被发现控制数字的旋转,第二个控制数字的粗细。

Example of Varying Generated Digit Slant and Thickness Using Continuous Control Code

使用连续控制代码改变生成数字倾斜和粗细的示例。
取自 InfoGan 论文。

我们将重点关注使用具有 10 个值的分类控制变量的更简单情况,并鼓励模型学会让此变量控制生成的数字。您可能希望通过更改分类控制变量的基数或添加连续控制变量来扩展此示例。

用于在 MNIST 数据集上训练的 GAN 模型配置已在论文的附录中提供,并在下面转载。我们将使用列出的配置作为开发我们自己的生成器 (g)、判别器 (d) 和辅助 (q) 模型的一个起点。

Summary of Generator, Discriminator and Auxiliary Model Configurations for the InfoGAN for Training MNIST

InfoGAN 训练 MNIST 的生成器、判别器和辅助模型配置摘要。
取自 InfoGan 论文。

让我们从开发生成器模型作为深度卷积神经网络(例如 DCGAN)开始。

模型可以接受噪声向量 (z) 和控制向量 (c) 作为单独的输入,并将它们连接起来,然后将它们用作生成图像的基础。或者,可以将向量预先连接起来并提供给模型中的单个输入层。这两种方法是等效的,在本例中我们将使用后者来简化模型。

下面的 `define_generator()` 函数定义了生成器模型,并接受输入向量的大小作为参数。

一个全连接层接收输入向量并生成足够的激活量,以创建 512 个 7x7 的特征图,然后从中重塑激活。然后,这些激活通过具有 1x1 步长的常规卷积层,然后通过两个后续的上采样转置卷积层,其步长为 2x2,首先生成 14x14 的特征图,然后通过 tanh 激活函数生成所需的 1 通道 28x28 的特征图输出,像素值在 [-1,-1] 范围内。

良好的生成器配置启发式方法包括:随机高斯权重初始化、隐藏层使用ReLU 激活以及使用批标准化。

接下来,我们可以定义判别器和辅助模型。

判别器模型按照正常 GAN 的方式独立训练,用于真实和虚假的图像。生成器和辅助模型都不会被直接拟合;相反,它们作为复合模型的一部分被拟合。

判别器和辅助模型共享相同的输入和特征提取层,但输出层不同。因此,同时定义它们是有意义的。

同样,这个架构可以通过多种方式实现,但首先将判别器和辅助模型定义为独立的模型,可以让我们稍后通过函数式 API 将它们直接组合成一个更大的 GAN 模型。

下面的 `define_discriminator()` 函数定义了判别器和辅助模型,并接受分类变量的基数(例如,值的数量,如 10)作为输入。输入图像的形状也作为函数参数进行参数化,并设置为 MNIST 图像大小的默认值。

特征提取层包括两个下采样层,作为最佳实践,用于替代池化层。同样遵循 DCGAN 模型的最佳实践,我们使用 LeakyReLU 激活和批标准化

判别器模型 (d) 有一个单一的输出节点,并通过 sigmoid 激活函数预测输入图像为真实的概率。该模型被编译,因为它将以独立方式使用,通过随机梯度下降的Adam 版本和最佳实践学习率和动量来优化二元交叉熵函数

辅助模型 (q) 为分类变量的每个值有一个节点输出,并使用 softmax 激活函数。在特征提取层和输出层之间添加了一个全连接层,这与 InfoGAN 论文中的使用相同。该模型未被编译,因为它不是独立使用。

接下来,我们可以定义复合 GAN 模型。

此模型使用了所有子模型,并且是训练生成器模型权重的基石。

下面的 `define_gan()` 函数实现了这一点,它接收三个子模型作为输入,然后定义并返回该模型。

如前所述,判别器以独立方式进行训练,因此判别器的所有权重都被设置为不可训练(仅在此上下文中)。生成器模型的输出连接到判别器模型的输入,以及辅助模型的输入。

这将创建一个新的复合模型,该模型以 [噪声 + 控制] 向量作为输入,然后通过生成器生成图像。图像随后通过判别器模型进行分类,并通过辅助模型预测控制变量。

该模型有两个输出层,需要使用不同的损失函数进行训练。判别器输出使用二元交叉熵损失,正如我们在为独立使用编译判别器时所做的那样;辅助模型使用互信息损失,在本例中,可以直接实现为分类交叉熵,并达到预期结果。

为了使 GAN 模型架构更清晰,我们可以创建模型和复合模型的图。

完整的示例如下所示。

运行示例会创建所有三个模型,然后创建复合 GAN 模型并保存模型架构的图。

注意:创建此图假定已安装 pydot 和 graphviz 库。如果这是一个问题,您可以注释掉 import 语句和 `plot_model()` 函数的调用。

该图显示了生成器模型的所有细节以及判别器和辅助模型的压缩描述。重要的是,请注意判别器的输出形状,它是用于预测图像真实性或伪造性的单个节点,以及用于辅助模型预测分类控制码的 10 个节点。

请记住,此复合模型仅用于更新生成器和辅助模型的模型权重,并且判别器模型中的所有权重将保持不可训练,即仅在更新独立判别器模型时更新。

Plot of the Composite InfoGAN Model for training the Generator and Auxiliary Models

用于训练生成器和辅助模型的复合 InfoGAN 模型的图

接下来,我们将为生成器开发输入。

每个输入将是一个由噪声和控制代码组成的向量。具体来说,是一个 [ 高斯随机数 ] 向量和一个一次热编码的随机选择的分类值。

下面的 `generate_latent_points()` 函数实现了这一点,它将潜在空间的大小、分类值的数量和要生成的样本数量作为参数。该函数返回连接的输入向量作为生成器模型的输入,以及独立的控制代码。在通过复合 GAN 模型更新生成器和辅助模型时,将需要独立的控制代码,特别是用于计算辅助模型的互信息损失。

接下来,我们可以生成真实和虚假的样本。

可以加载 MNIST 数据集,将其转换为 3D 输入(通过为灰度图像添加额外的维度),并 将所有像素值缩放到 [-1,1] 范围,以匹配生成器模型的输出。这在下面的 `load_real_samples()` 函数中实现。

通过随机选择数据集的一个子集,我们可以检索训练判别器所需的真实样本批次。这在下面的 `generate_real_samples()` 函数中实现,该函数返回图像和类别标签 1,表示判别器它们是真实的图像。

判别器还需要通过生成器生成的虚假样本批次,使用 `generate_latent_points()` 函数的向量作为输入。下面的 `generate_fake_samples()` 函数实现了这一点,返回生成的图像以及类别标签 0,表示判别器它们是虚假的图像。

接下来,我们需要跟踪生成图像的质量。

我们将定期使用生成器生成图像样本,并将生成器和复合模型保存到文件。然后,我们可以在训练结束时查看生成的图像,以选择最终的生成器模型,并加载模型开始使用它来生成图像。

下面的 `summarize_performance()` 函数实现了这一点,首先生成 100 张图像,将它们的像素值缩放回 [0,1] 范围,并将它们保存为 10x10 方形图像的图。

生成器和复合 GAN 模型也会被保存到文件,文件名基于训练迭代次数而唯一。

最后,我们可以训练 InfoGAN。

这在下面的 `train()` 函数中实现,该函数接收定义的模型和配置作为参数,并运行训练过程。

模型训练 100 个 epoch,每个 batch 使用 64 个样本。MNIST 训练数据集有 60,000 张图像,因此一个 epoch 涉及 60,000/64,即 937 个 batches 或训练迭代。将其乘以 epoch 数量(100),意味着总共将有 93,700 次总训练迭代。

每次训练迭代包括首先用一半真实样本和一半虚假样本更新判别器,形成一个 batch 的权重更新,或每次迭代 64 个。接下来,复合 GAN 模型会根据一个 batch 的噪声和控制代码输入进行更新。每次训练迭代都会报告判别器在真实和虚假图像上的损失,以及生成器和辅助模型的损失。

然后,我们可以配置并创建模型,然后运行训练过程。

我们将为单个分类变量使用 10 个值,以匹配 MNIST 数据集中的 10 个已知类别。我们将使用具有 64 个维度的潜在空间,以匹配 InfoGAN 论文,这意味着在此情况下,生成器模型的每个输入向量将是 64 个(随机高斯变量)+ 10 个(一次热编码的控制变量),即长度为 72 个元素。

总而言之,在 MNIST 数据集上使用单个分类变量训练 InfoGAN 模型的完整示例列在下面。

运行示例可能需要一些时间,建议使用GPU硬件,但并非必需。

注意:由于算法或评估程序的随机性质,或者数值精度的差异,您的 结果可能会有所不同。考虑运行该示例几次并比较平均结果。

每次训练迭代都会报告模型之间的损失。如果判别器的损失保持在 0.0 或长时间停留在 0.0,这可能是一个训练失败的迹象,您可能需要重新启动训练过程。判别器损失可能从 0.0 开始,但很可能会上升,正如在本例中那样。

辅助模型的损失很可能会趋于零,因为它完美地预测了分类变量。生成器和判别器模型的损失最终可能会在 1.0 附近徘徊,以展示稳定的训练过程或两个模型训练之间的平衡。

图和模型每 10 个 epoch 或每 9,370 次训练迭代保存一次。

查看图表应显示早期 epoch 的图像质量较差,后期 epoch 的图像质量有所提高且稳定。

例如,下面显示了前 10 个 epoch 后保存的图像图,显示了低质量的生成图像。

Plot of 100 Random Images Generated by the InfoGAN after 10 Training Epochs

10 个训练 epoch 后 InfoGAN 生成的 100 张随机图像的图

更多的 epoch 并不意味着更好的质量,这意味着最高质量的图像可能不是来自训练结束时保存的最终模型。

查看图表并选择具有最佳图像质量的最终模型。在此案例中,我们将使用在 100 个 epoch 或 93,700 次训练迭代后保存的模型。

Plot of 100 Random Images Generated by the InfoGAN after 100 Training Epochs

100 个训练 epoch 后 InfoGAN 生成的 100 张随机图像的图

如何使用训练好的 InfoGAN 模型进行控制代码

现在我们已经训练了 InfoGAN 模型,我们可以探索如何使用它。

首先,我们可以加载模型并像在训练期间那样使用它来生成随机图像。

完整的示例如下所示。

将模型文件名更改为与您训练期间生成最佳图像的模型文件名匹配。

运行此示例将加载已保存的生成器模型,并使用它生成 100 张随机图像,并将这些图像绘制在 10×10 的网格上。

Plot of 100 Random Images Created by Loading the Saved InfoGAN Generator Model

加载已保存的 InfoGAN 生成器模型创建的 100 张随机图像图

接下来,我们可以更新示例,测试我们的控制变量能提供多大的控制力。

我们可以更新 `generate_latent_points()` 函数,使其接受一个类别值参数(范围在 [0,9] 之间),对其进行编码,并将其与噪声向量一起用作输入。

我们可以通过生成一个 25 张图像的网格,并将类别值设置为 1 来测试这一点。

完整的示例如下所示。

结果是一个由 25 张生成的图像组成的网格,这些图像是在将类别代码设置为 1 的情况下生成的。

注意:由于算法或评估程序的随机性质,或者数值精度的差异,您的 结果可能会有所不同。考虑运行该示例几次并比较平均结果。

控制代码的值预计会影响生成的图像;特别是,它们预计会影响数字的类型。但是,它们不一定是排序的,例如,控制代码为 1、2 和 3 来创建这些数字。

尽管如此,在本例中,值为 1 的控制代码已生成看起来像 1 的图像。

Plot of 25 Images Generated by the InfoGAN Model With the Categorical Control Code Set to 1

InfoGAN 模型使用类别控制代码设置为 1 生成的 25 张图像图

尝试不同的数字,并回顾一下该值具体控制图像的哪个部分。

例如,在这种情况下将值设置为 5(digit = 5)会生成看起来像数字“*8*”的图像。

Plot of 25 Images Generated by the InfoGAN Model With the Categorical Control Code Set to 5

InfoGAN 模型使用类别控制代码设置为 5 生成的 25 张图像图

扩展

本节列出了一些您可能希望探索的扩展本教程的想法。

  • 更改基数。更新示例以使用不同基数的类别控制变量(例如,更多或更少的值),并回顾其对训练过程和生成图像控制的影响。
  • 均匀控制变量。更新示例并将两个均匀连续控制变量添加到辅助模型中,并回顾其对训练过程和生成图像控制的影响。
  • 高斯控制变量。更新示例并将两个高斯连续控制变量添加到辅助模型中,并回顾其对训练过程和生成图像控制的影响。

如果您探索了这些扩展中的任何一个,我很想知道。
请在下面的评论中发布您的发现。

进一步阅读

如果您想深入了解,本节提供了更多关于该主题的资源。

论文

API

项目

文章

总结

在本教程中,您将学习如何从头开始实现信息最大化生成对抗网络模型。

具体来说,你学到了:

  • InfoGAN 的动机是解耦和控制生成图像中的属性。
  • InfoGAN 包含添加控制变量以生成辅助模型,该模型通过互信息损失函数预测控制变量。
  • 如何从头开始开发和训练 InfoGAN 模型,并使用控制变量来控制模型生成的数字。

你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。

立即开发生成对抗网络!

Generative Adversarial Networks with Python

在几分钟内开发您的GAN模型

...只需几行python代码

在我的新电子书中探索如何实现
使用 Python 构建生成对抗网络

它提供了关于以下内容的自学教程端到端项目
DCGAN条件GAN图像翻译Pix2PixCycleGAN
以及更多...

最终将GAN模型引入您的视觉项目

跳过学术理论。只看结果。

查看内容

如何使用 Keras 开发信息最大化生成对抗网络 (InfoGAN) 的 48 条回复

  1. Rjpg 2019 年 7 月 22 日 9:39 am #

    不错。这和 AC-GAN 一样对吧?(辅助分类 GAN)

    我有这个实现:https://raw.githubusercontent.com/rjpg/bftensor/master/Autoencoder/src/ac-gan2.py

    为了控制要生成的类别,我将噪声(潜在)乘以类的编号。也称为“给噪声上色”。效果很好。

    但您的实现非常优雅,干得好。

  2. Darren Jones 2019 年 8 月 8 日 9:04 am #

    嗨,Jason,

    我能得到一些关于如何实现连续控制变量的代码片段吗?

    谢谢,
    Darren

    • Jason Brownlee 2019 年 8 月 8 日 2:18 pm #

      是的,我尝试了大约 10 分钟,效果很差。我建议使用论文中的方法,而不是我糟糕的方法。

      尽管如此,为了完整起见,这里仍然提供。

      如果您能找到实现此目标并获得良好结果的方法,请告诉我。

    • Caterina 2019 年 12 月 11 日 4:37 pm #

      你好 Darren,
      你成功了吗?
      我正在尝试,并且我的模型与 Jason 在下面发布的模型类似……但无法使其正常工作。
      我实际上正在尝试将连续变量实现到 ACGAN 中。

      提前感谢,
      Caterina

  3. David 2019 年 9 月 4 日 10:11 pm #

    Jason,非常感谢您的工作。

    是否可以构建 InfoGAN 以及一个分类器?我明白 InfoGAN 可以使用控制变量生成所需类别的图像,但同时,我想输入一个未见的 MNIST 数据,看看模型是否能正确地对它们进行分类。

    谢谢

    • Jason Brownlee 2019 年 9 月 5 日 6:55 am #

      通常 GAN 是为图像合成设计的,而不是分类。

      如果您需要一个分类模型,请参阅这篇帖子
      https://machinelearning.org.cn/how-to-develop-a-convolutional-neural-network-from-scratch-for-mnist-handwritten-digit-classification/

      • David 2019 年 9 月 5 日 8:47 pm #

        是的,我使用了您的代码构建了一个 InfoGAN 模型。但现在我想做的是将一个未见的 MNIST 图像反向输入生成器,看看它在学习到的潜在空间中的位置。基本上,我希望可视化模型学习到的潜在空间,以便在新数据输入时,它首先被分类,然后在潜在空间中显示。这可能吗?

        • Jason Brownlee 2019 年 9 月 6 日 4:57 am #

          听起来很有趣。

          抱歉,我没有这方面的例子,需要做一些实验/原型设计才能弄清楚。如果您有进展,请告诉我。

        • TheJag 2020 年 8 月 31 日 4:53 am #

          您能否保存模型的权重,构建一个“反向”模型,然后逐层加载权重?

        • Boris 2020 年 9 月 2 日 4:44 pm #

          David,神经网络是连续操作的应用,例如仿射变换 Wx + b 和激活函数。如果所有这些都是可逆的(权重矩阵 W 通常是),那么整个操作就是可逆的。

          在此特定代码中,使用了“relu”激活函数,它不是可逆的,因为它有一半的时间将某些东西乘以 0。LeakyReLU 是可逆的,以及一些其他激活函数。

          但是,您可以采用不同的路径,尝试构建一个自动编码器网络,其中解码器部分是您已经训练过的生成器函数。您可以通过冻结解码器并为输入和输出提供相同的图像来训练它,训练数据可以来自预训练的生成器网络。

          结果应该是一个编码器+解码器的组合,当输入图像时,编码器会生成潜在变量,而这些潜在变量在输入到 GAN 生成器(解码器)时会生成相同的图像。

  4. Claire 2019 年 10 月 12 日 6:22 pm #

    你好 David,我也在研究您提出的问题,您是否找到了对未见过的 MNIST 数据进行分类的方法?

  5. lei 2019 年 12 月 24 日 3:12 pm #

    Jason,感谢您的文章。

    但实际上,无论运行 100 个 epoch 还是 1000 个 epoch,我生成的图像都不好。
    我认为是 q_net 的训练过程导致了这个问题。
    也许我们可以尝试将 q_net 的独立部分从 Discriminator 中分离出来,然后设置共享部分 q_model.trainable=False。这样可以生成出色的图像。

    • Jason Brownlee 2019 年 12 月 24 日 4:59 pm #

      说得有理。

    • Farhod 2020 年 3 月 12 日 2:38 pm #

      你好 lei!

      我有点困惑。你的意思是
      – 像本教程中那样定义 d_net 和 q_net。
      – 使 q_net 的 d_net 部分不可训练。
      – 使用真实数据(带有相应标签的真实图像)训练 q_net。

      我的理解正确吗?

      提前感谢你

  6. SARVANI CH 2020 年 1 月 22 日 5:12 pm #

    Jason,感谢 InfoGAN 代码。
    info gen 的损失函数如下:
    min max V(D, G)= V (D, G) − λI(c; G(z, c))
    G D
    您考虑了 λ=1,但是 q_model 上的“交叉熵损失”如何等于 c 和 G(z,c) 之间的互信息????

    • Jason Brownlee 2020 年 1 月 23 日 6:27 am #

      我相信我们在“如何实现 InfoGAN 损失函数”部分对此进行了讨论。

      • SARVANI CH 2020 年 1 月 23 日 6:19 pm #

        是的,解释得很清楚。非常感谢。

  7. Ali 2020 年 8 月 15 日 11:25 am #

    你好!很棒的教程。
    请问,为什么您要将 Q 模型与 G 模型一起训练?
    为什么不使用 CNN 作为 Q 模型,并像 D 模型一样单独训练它?

    • Jason Brownlee 2020 年 8 月 15 日 1:27 pm #

      我的实现是为了匹配论文的意图。

      • Ali 2020 年 8 月 15 日 10:27 pm #

        我明白了,但您认为进行这些更改是否合理,并且可能会奏效?
        我已经在尝试应用此模型,但我正在尝试检查我的逻辑和思维方式是否正确。
        以下是我正在进行的更改列表
        – 将 Q 模型更改为 CNN 模型。
        – 单独训练 Q 模型。
        谢谢你的帮助。

        • Jason Brownlee 2020 年 8 月 16 日 5:52 am #

          很难说,也许可以尝试一下看看。

          • Ali 2020年8月16日上午9:39 #

            当然,非常感谢!

          • Jason Brownlee 2020年8月17日上午5:43 #

            不客气。

  8. Ali 2020年8月18日上午11:45 #

    你好!
    我用你在 Google Colab 上发布的模型进行了训练,我看到了这个
    > 49943, d[0.000,0.000], g[0.000] q[0.000]
    这是第40或50个 epoch,损失是0!?
    除此之外,生成的图像也很糟糕。有什么原因吗?

    • Ali 2020年8月18日上午11:47 #

      抱歉,我的意思是,我在 Google Colab 上运行了您在这篇文章中分享的代码。

    • Jason Brownlee 2020年8月18日下午1:26 #

      损失为零表明模式失败。
      https://machinelearning.org.cn/practical-guide-to-gan-failure-modes/

      也许可以尝试重新训练模型。

      • Ali 2020年8月20日上午5:05 #

        我尝试了几个改动,不知何故,删除批量归一化解决了我的问题。
        我尝试将批量归一化添加到 vanilla DCGAN (用于 MNIST),结果也一样。
        看起来批量归一化不是 GAN 的好选择,但我总是看到有人建议添加它。我感到很困惑。
        您遇到过同样的情况吗?

        • Jason Brownlee 2020年8月20日上午6:53 #

          干得好!

          这确实取决于具体的数据和模型。对于简单的 dcgan,通常不需要批量归一化。

          • Ali 2020年8月20日上午7:52 #

            我同意。非常感谢您,先生!

          • Jason Brownlee 2020年8月20日上午7:53 #

            不客气。

  9. Ali 2020年8月23日下午1:22 #

    大家好!
    经过一些实验,连续控制变量模型奏效了。
    我使用了两个控制变量模型,就像您一样,我也删除了批量归一化。
    但我注意到,带有额外变量(分类或连续)的模型更容易生成错误的数字。另外,两个连续变量具有厚度和宽度效果。不知何故,宽度较小的数字会变成“1”,所以也许他并没有生成错误的数字,很难说……
    抱歉语言不通顺,我还是太激动了。

    以下是保存模型的链接:https://drive.google.com/drive/folders/1Gv3fyAi8oypC3JhTdCmc6CxOIdqHJKeA?usp=sharing

    这是我的 Colab 游乐场链接
    https://colab.research.google.com/drive/13B4COwR-UktpQ7pTQntORri2jwn13BuQ?usp=sharing

    此外,我将相同的概念应用到了 CelebFaces 数据集上,我选择了一个具有两个类别的分类变量(男性和女性),我认为模型会学习这些特征,而随机噪声会塑造面部的细节。不幸的是,这没有奏效,我每次都得到了两种类型的面孔,呈绿色,但不是我想要的,这是模型和结果
    https://drive.google.com/drive/folders/1GMom1tIltHbph-Rr4Qdt1Vg9wal4rWJ3?usp=sharing

    所以我的问题是,您会如何制作一个用于人脸的人脸 InfoGAN,您会使用哪些变量?
    谢谢你。

    • Jason Brownlee 2020年8月24日上午6:12 #

      你的实验做得很好!

      是的,像 InfoGAN 这样的条件 GAN 是生成男性/女性面孔的不错方法。可以使用分类变量,并且生成器必须足够好/大才能生成逼真的面孔。

      也许可以借鉴一个已经擅长生成人脸的模型中的生成器架构。

  10. BZ 2021年1月4日下午12:01 #

    嗨,Jason,
    如果我错了,请纠正我。
    i) 在实现中,您是否生成了两个假批次,一个用于更新判别器,一个用于更新辅助网络?
    ii) 在原始 InfoGAN 实现中,似乎判别器在更新辅助网络时没有被冻结?
    谢谢!

    • Jason Brownlee 2021年1月4日下午1:41 #

      判别器使用真实和虚假图像进行更新。

      判别器权重未被冻结,只有在更新生成器时才不进行更新——例如,对于 GAN 更新来说是典型的。

      如果您不熟悉 GAN 训练实现,这可能会有所帮助。
      https://machinelearning.org.cn/how-to-code-the-generative-adversarial-network-training-algorithm-and-loss-functions/

      • BZ 2021年1月4日下午5:46 #

        谢谢你。
        我知道 GAN 中的生成器和判别器是如何更新的。

        i) 在您的代码中,您首先通过真实和虚假图像更新了判别器和 q 模型

        # 获取随机选择的“真实”样本
        X_real, y_real = generate_real_samples(dataset, half_batch)
        # 更新判别器和 q 模型权重
        d_loss1 = d_model.train_on_batch(X_real, y_real)
        # 生成“虚假”示例
        X_fake, y_fake = generate_fake_samples(g_model, latent_dim, n_cat, n_con, half_batch)
        # 更新判别器模型权重
        d_loss2 = d_model.train_on_batch(X_fake, y_fake)

        然后,您似乎使用另一批新生成的虚假数据更新了您的复合 GAN 模型(生成器和 q 模型)(如果我错了请纠正我)

        z_input, cat_codes, con_codes = generate_latent_points(latent_dim, n_cat, n_con, n_batch)
        # 为虚假样本创建反转标签
        y_gan = ones((n_batch, 1))
        # 通过 d 和 q 误差更新 g
        _,g_1,g_2,g3 = gan_model.train_on_batch(z_input, [y_gan, cat_codes, con_codes])

        ii) 我不熟悉 Keras,所以我不知道当您使判别器参数不可训练时,与 Q 模型共享的层是否也变得不可训练(换句话说,判别器和 Q 模型是否保留了共享层的单独副本)。我认为原始 InfoGAN 的意图是共享层可由 D 和 Q 更新(只有一份副本被 D 和 Q 访问和更新)。当您更新生成器(肯定会固定判别器)并更新 Q 模型时,会发生两种情况
        i. 如果我猜对了,共享层在更新 Q 模型时不会被更新,那么这与原始论文的意图不符。
        ii. 如果我猜错了,共享层在更新 Q 模型时实际上会被更新,那么您的实现是正确的。
        请告知,谢谢!
        祝好

  11. Daniel Hackney 2022年11月6日下午5:07 #

    此教程提供的代码使用了哪个版本的 TensorFlow?我无法在 2.8 或 2.6 版本中使其正常工作。

    • James Carmichael 2022年11月7日上午10:05 #

      你好 Daniel……你遇到了什么错误信息或问题?

  12. Daniel Hackney 2022年11月11日上午4:26 #

    我最终在 TensorFlow 2.5.0 版本中成功了。现在我正在尝试添加更多的控制变量——例如宽度/角度的变量。有什么资源/技巧可以参考吗?

Leave a Reply

Machine Learning Mastery 是 Guiding Tech Media 的一部分,Guiding Tech Media 是一家领先的数字媒体出版商,专注于帮助人们了解技术。访问我们的公司网站以了解更多关于我们的使命和团队的信息。