生成人脸时如何探索 GAN 潜在空间

如何使用插值和向量算术来探索GAN的潜在空间。

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

GAN架构中的生成模型学习将潜在空间中的点映射到生成的图像。潜在空间除了通过生成模型赋予的含义外,本身没有其他意义。然而,潜在空间具有可以探索的结构,例如通过在点之间进行插值以及在潜在空间中的点之间执行向量算术,这些操作对生成的图像具有有意义的、有针对性的影响。

在本教程中,您将学习如何开发用于人脸生成的生成对抗网络,并探索潜在空间的结构以及对生成人脸的影响。

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

  • 如何开发用于生成人脸的生成对抗网络。
  • 如何对潜在空间中的点进行插值,并生成从一张脸到另一张脸的变形图像。
  • 如何在潜在空间中执行向量算术,并在结果生成的面部中实现有针对性的效果。

用我新书Python生成对抗网络开启您的项目,其中包括分步教程以及所有示例的Python源代码文件。

让我们开始吧。

  • 2019 年 11 月更新: 已更新至 TensorFlow v2.0 和 MTCNN v0.1.0。
How to Interpolate and Perform Vector Arithmetic With Faces Using a Generative Adversarial Network

如何使用生成对抗网络对人脸进行插值和向量算术。
照片由Intermountain Forest Service拍摄,部分权利保留。

教程概述

本教程分为五个部分;它们是:

  1. 潜在空间中的向量算术
  2. 大规模CelebFaces数据集(CelebA)
  3. 如何准备CelebA人脸数据集
  4. 如何开发生成对抗网络
  5. 如何探索生成人脸的潜在空间

潜在空间中的向量算术

GAN架构中的生成器模型以潜在空间中的一个点作为输入,并生成一张新图像。

潜在空间本身没有意义。通常,它是一个100维的超球体,每个变量从均值为零、标准差为一的高斯分布中抽取。通过训练,生成器学会将潜在空间中的点映射到特定的输出图像,并且这种映射在模型每次训练时都会有所不同。

当被生成器模型解释时,潜在空间具有结构,并且对于给定的模型,这种结构可以被查询和导航。

通常,使用潜在空间中的随机点来生成新图像。更进一步,可以构造潜在空间中的点(例如,全0、全0.5或全1),并将其用作输入或查询以生成特定图像。

可以在潜在空间中两个点之间的线性路径上创建一系列点,例如两个生成的图像。这些点可用于生成一系列图像,显示两个生成图像之间的过渡。

最后,可以保留潜在空间中的点,并用于简单的向量算术以创建新的潜在空间点,这些点又可用于生成图像。这是一个有趣的想法,因为它允许直观且有针对性地生成图像。

Alec Radford等人在2015年发表的重要论文“使用深度卷积生成对抗网络进行无监督表示学习”介绍了一种稳定的模型配置,用于在GAN架构中训练深度卷积神经网络模型。

在论文中,作者们探索了在多个不同训练数据集上训练的GAN的潜在空间,尤其是名人脸部数据集。他们展示了两个有趣的方面。

第一个是人脸的向量算术。例如,一张微笑女性的脸减去一张中性女性的脸再加上一张中性男性的脸,结果是一张微笑男性的脸。

具体来说,算术运算是针对生成人脸的潜在空间中的点进行的。实际上是对具有给定特征的多个面部的平均值进行运算,以提供更稳健的结果。

Example of Vector Arithmetic on Points in the Latent Space for Generating Faces with a GAN

使用GAN生成人脸的潜在空间点向量算术示例。
摘自“使用深度卷积生成对抗网络进行无监督表示学习”。

第二个演示是两个生成人脸之间的过渡,具体方法是创建生成两个人脸的点之间的潜在维度线性路径,然后生成路径上所有点的所有面部。

Example of Faces on a Path Between Two GAN Generated Faces

两个GAN生成人脸之间路径上人脸示例。
摘自“使用深度卷积生成对抗网络进行无监督表示学习”。

探索GAN模型的潜在空间结构,对于问题领域来说既有趣,也有助于培养对生成器模型所学内容的直观理解。

在本教程中,我们将开发一个用于生成人脸照片的GAN,然后通过向量算术来探索模型的潜在空间。

想从零开始开发GAN吗?

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

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

大规模CelebFaces数据集(CelebA)

第一步是选择一个面部数据集。

在本教程中,我们将使用大规模CelebFaces属性数据集,简称CelebA。该数据集由Ziwei Liu等人为其2015年论文“从面部部件响应到人脸检测:深度学习方法”开发和发布。

该数据集提供了约20万张名人面部照片,以及对照片中出现的物品的标注,例如眼镜、脸型、帽子、发型等。作为数据集的一部分,作者提供了每张照片的居中人脸版本,并裁剪为肖像,尺寸在150像素宽和200像素高之间。我们将以此为基础来开发我们的GAN模型。

可以从Kaggle网页轻松下载该数据集。注意:这可能需要Kaggle账户。

具体来说,下载文件“img_align_celeba.zip”,该文件大小约为1.3 GB。为此,请在Kaggle网站上点击文件名,然后点击下载图标。

下载速度可能需要一些时间,具体取决于您的互联网连接速度。

下载完成后,解压存档。

这将创建一个名为“img_align_celeba”的新目录,其中包含所有图像,文件名类似202599.jpg202598.jpg

接下来,我们可以准备原始图像以供建模。

如何准备CelebA人脸数据集

第一步是开发加载图像的代码。

我们可以使用Pillow库加载给定的图像文件,将其转换为RGB格式(如果需要),然后返回像素数据数组。下面的load_image()函数实现了这一点。

接下来,我们可以枚举图像目录,依次将每个图像加载为像素数组,然后返回包含所有图像的数组。

数据集中有20万张图像,这可能比我们需要的多,所以我们也可以通过参数限制加载的图像数量。下面的load_faces()函数实现了这一点。

最后,一旦图像被加载,我们就可以使用matplotlib库的imshow()函数来绘制它们。

下面的plot_faces()函数执行此操作,将图像绘制成正方形排列。

将这些结合起来,完整的示例列在下面。

运行该示例将从目录加载总共25张图像,然后总结返回数组的大小。

最后,将25张图像绘制在5x5的方格中。

Plot of a Sample of 25 Faces from the Celebrity Faces Dataset

名人面部数据集的25张面部样本图

在使用GAN时,如果所有图像都小且呈方形,则更容易对数据集进行建模。

此外,由于我们只对照片中的人脸感兴趣,而不是背景,我们可以执行人脸检测,只提取人脸,然后再将结果缩放到固定大小。

人脸检测有很多方法。在这种情况下,我们将使用预训练的多任务级联卷积神经网络(MTCNN)。这是一个最先进的人脸检测深度学习模型,在2016年的论文“使用多任务级联卷积网络进行联合人脸检测和对齐”中有描述。

我们将使用Iván de Paz Centeno在ipazc/mtcnn项目中提供的实现。该库可以通过pip安装,如下所示

我们可以通过导入库并打印版本来确认库是否正确安装;例如

运行示例会打印库的当前版本。

MTCNN模型非常易于使用。

首先,创建一个MTCNN模型实例,然后可以调用detect_faces()函数,传入一张图像的像素数据。结果是检测到的人脸列表,其中包含以像素偏移值定义的边界框。

我们可以更新我们的示例,从每张加载的照片中提取人脸,并将提取的人脸像素调整为固定大小。在这种情况下,我们将使用80x80像素的方形。

下面的extract_face()函数实现了这一点,它将MTCNN模型和单个照片的像素值作为参数,并返回一个80x80x3的像素值数组,其中只包含人脸,或者如果未检测到人脸则返回None(这种情况很少见)。

我们可以更新load_faces()函数,从加载的照片中提取人脸并将其存储在返回的面部列表中。

将这些结合起来,完整的示例列在下面。

在这种情况下,我们将加载的面部总数增加到50,000,为我们的GAN模型提供一个良好的训练数据集。

运行该示例可能需要几分钟时间,因为需要加载的面部数量较多。

在运行结束时,提取和调整大小的人脸数组将保存为压缩的NumPy数组,文件名为“img_align_celeba.npz”。

准备好的数据集以后可以随时加载,如下所示。

加载数据集将总结数组的形状,显示50K张80x80像素的图像和三个颜色通道。

我们现在准备好开发一个GAN模型来使用此数据集生成人脸。

如何开发生成对抗网络

在本节中,我们将开发一个用于我们已准备好的面部数据集的GAN。

第一步是定义模型。

判别器模型以一个80x80的彩色图像作为输入,并输出一个二元预测,判断图像是真实的(class=1)还是伪造的(class=0)。它被实现为一个适度的卷积神经网络,使用了GAN设计的最佳实践,例如使用斜率为0.2的LeakyReLU激活函数,使用2x2步长进行下采样,以及使用学习率为0.0002、动量为0.5的Adam版本的随机梯度下降

下面的define_discriminator()函数实现了这一点,它定义并编译了判别器模型并返回。图像的输入形状被参数化为默认函数参数,以防您以后想将该函数用于自己的图像数据。

生成器模型以潜在空间中的一个点作为输入,并输出一张80x80的彩色图像。

这是通过使用一个全连接层来解释潜在空间中的点,并提供足够的激活,可以将其重塑为许多副本(在此例中为128个)的输出图像的低分辨率版本(例如5x5)。然后,通过转置卷积层对其进行四次上采样,每次都将激活的大小加倍,区域扩大四倍。该模型使用了最佳实践,如LeakyReLU激活、核大小是步长大小的因子,以及输出层中的双曲正切(tanh)激活函数。

下面的define_generator()函数定义了生成器模型,但故意不编译它,因为它不直接训练,然后返回模型。潜在空间的大小被参数化为函数参数。

接下来,可以定义一个GAN模型,它将生成器模型和判别器模型组合成一个更大的模型。这个更大的模型将用于训练生成器中的模型权重,使用判别器模型计算的输出和误差。判别器模型是单独训练的,因此,在这个更大的GAN模型中,模型权重被标记为不可训练,以确保只有生成器模型的权重被更新。这种对判别器权重可训练性的改变仅在训练组合GAN模型时生效,而在单独训练判别器时不生效。

这个更大的GAN模型以潜在空间中的一个点作为输入,使用生成器模型生成一张图像,然后将该图像作为输入提供给判别器模型,最后输出或分类为真实或伪造。

下面的 define_gan() 函数实现了这一点,它接收已经定义的生成器和判别器模型作为输入。

现在我们已经定义了GAN模型,我们需要训练它。但是,在训练模型之前,我们需要输入数据。

第一步是加载和缩放预处理过的面部数据集。可以像上一节那样加载保存的NumPy数组,然后必须将像素值缩放到[-1,1]的范围,以匹配生成器模型的输出。

下面的 load_real_samples() 函数实现了这一点,它返回已加载和缩放的图像数据,为建模做好准备。

我们需要从数据集中获取一个批次(或半个批次)的真实图像来更新GAN模型。一种简单的方法是每次都从数据集中选择一个随机样本。

下面的 generate_real_samples() 函数实现了这一点,它接收准备好的数据集作为参数,选择并返回一个随机的面部图像样本及其对应的类别标签给判别器,特别是 class=1,表示它们是真实图像。

接下来,我们需要为生成器模型提供输入。这些是来自潜在空间的随机点,具体来说是高斯分布的随机变量

generate_latent_points() 函数实现了这一点,它接收潜在空间的维度作为参数,以及所需的点数,并返回它们作为生成器模型的输入样本批次。

接下来,我们需要使用潜在空间中的点作为生成器的输入,以生成新的图像。

下面的 generate_fake_samples() 函数实现了这一点,它接收生成器模型和潜在空间的维度作为参数,然后生成潜在空间中的点并将它们用作生成器模型的输入。该函数返回生成的图像及其对应的类别标签给判别器模型,特别是 class=0,表示它们是伪造的或生成的。

我们现在准备好拟合GAN模型了。

该模型训练100个训练周期,这是任意设定的,因为模型可能在最初几个周期后就开始生成合理的图像。使用128个样本的批次大小,每个训练周期涉及50,000/128,即约390个真实和伪造样本的批次以及对模型的更新。

首先,判别器模型更新半批次的真实样本,然后是半批次的伪造样本,两者合在一起构成一个批次的权重更新。然后通过组合的GAN模型更新生成器。重要的是,伪造样本的类别标签设置为1(真实)。这会更新生成器,使其在下一批次中更好地生成真实样本。

下面的 train() 函数实现了这一点,它接收定义的模型、数据集和潜在空间的维度作为参数,并使用默认参数来设置周期数和批次大小。

您会注意到,每训练10个周期,就会调用summarize_performance() 函数。

目前没有可靠的方法可以自动评估生成图像的质量。因此,我们必须在训练过程中定期生成图像,并在这些时候保存模型。这既提供了一个我们可以稍后加载并用于生成图像的检查点,也提供了一种防止训练过程失败的方法,因为训练过程可能会失败。

下面定义了summarize_performance()save_plot() 函数。

summarize_performance() 函数生成样本并评估判别器在真实和伪造样本上的性能。报告分类准确率,这可能有助于了解模型性能。调用 save_plot() 来创建和保存生成图像的图,然后将模型保存到文件中。

然后,我们可以定义潜在空间的维度,定义所有三个模型,并在加载的人脸数据集上训练它们。

将所有这些联系在一起,完整的示例如下。

在适度的硬件上运行示例可能需要很长时间。

我建议在GPU硬件上运行该示例。如果您需要帮助,可以快速开始使用AWS EC2实例来训练模型。请参阅教程

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

每个批次之后都会报告判别器在真实和伪造样本上的损失,以及生成器上的损失。

判别器的损失可能会下降到真实和生成样本的0.0值。

如果发生这种情况,它是一个训练失败的例子,模型很可能无法恢复,您应该重新开始训练过程。

检查生成的图,并根据图像质量最好的模型进行选择。

模型应该在训练大约30个周期后开始生成人脸。

这些人脸不完全清晰,但很明显它们是人脸,具有所有正确的特征(头发、眼睛、鼻子、嘴巴)大致在正确的位置。

Example of Celebrity Faces Generated by a Generative Adversarial Network

生成对抗网络生成名人面部的示例

如何探索生成人脸的潜在空间

在本节中,我们将使用我们训练好的GAN模型作为探索潜在空间的基础。

如何加载模型并生成人脸

第一步是加载保存的模型,并确认它可以生成合理的人脸。

可以使用Keras API中的 load_model() 函数加载模型。然后,我们可以生成一些潜在空间中的随机点,并将它们作为输入提供给加载的模型以生成新的人脸。然后可以将这些面部绘制出来。

完整的示例如下所示。

运行示例首先加载保存的模型。

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

然后,在100维潜在空间中创建25个随机点,将它们提供给生成器模型以创建25张人脸图像,然后将它们绘制在5x5的网格中。

Plot of Randomly Generated Faces Using the Loaded GAN Model

使用加载的GAN模型随机生成人脸的图

如何对生成的人脸进行插值

接下来,我们可以创建潜在空间中两个点之间的插值路径,并沿该路径生成人脸。

我们可以使用的最简单的插值是线性或均匀插值,在潜在空间的两个点之间。我们可以使用 linspace() NumPy函数 来计算两个点贡献的比例,然后枚举这些比例并为每个比例构造一个向量。

下面的 interpolate_points() 函数实现了这一点,它返回潜在空间中两点之间的线性插值向量序列,包括第一点和最后一点。

然后,我们可以生成潜在空间的两个点,进行插值,然后为每个插值向量生成一张图像。

结果将是一系列图像,这些图像在原始的两张图像之间进行过渡。下面的示例演示了两个人脸的插值。

运行示例会计算潜在空间中两点之间的插值路径,为每个点生成图像,并绘制结果。

您可以看到从左边的第一张脸到右边的最后一张脸,在十个步骤中有清晰的线性进展。

Plot Showing the Linear Interpolation Between Two GAN Generated Faces

展示生成人脸之间线性插值的图

我们可以更新示例以多次重复此过程,以便在单个图中查看多个生成人脸之间的过渡。

完整的示例如下所示。

运行示例会生成10个不同的起始人脸和10个匹配的人脸终点,以及它们之间的线性插值。

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

Plot Showing Multiple Linear Interpolations Between Two GAN Generated Faces

展示生成人脸之间多重线性插值的图

在这些情况下,我们执行了线性插值,这假设潜在空间是均匀分布的超立方体。严格来说,我们选择的潜在空间是100维超球面或多模高斯分布。

有一个名为球面线性插值函数,或“Slerp”的数学函数,在插值这个空间时应该使用它,以确保考虑了空间的弯曲。更多详情,我推荐阅读Soumith Chintala的dcgan.torch项目中的“线性插值问题”。在该项目中,提供了Python的Slerp函数的实现,我们可以将其作为我们自己的Slerp函数的基础,如下所示:

我们可以从我们的*interpolate_points()*函数中调用此函数,而不是执行手动线性插值。

进行了此更改的完整示例如下所示。

结果是又一个生成人脸之间的过渡,这次使用了正确的Slerp插值方法。

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

差异很微妙,但视觉上更正确。

Plot Showing Multiple Seraphically Linear Interpolation Between Two GAN Generated Faces

展示生成人脸之间多重球面线性插值的图

如何对人脸进行向量算术

最后,我们可以通过对生成的人脸进行向量算术来探索潜在空间。

首先,我们必须生成大量人脸,并保存人脸及其对应的潜在向量。然后,我们可以查看生成的人脸图,选择具有我们感兴趣特征的人脸,记下它们的索引(编号),并检索它们的潜在空间向量进行操作。

下面的示例将加载GAN模型并使用它来生成100张随机人脸。

运行示例会加载模型,生成人脸,并保存潜在向量和生成的人脸。

潜在向量被保存到一个名为*latent_points.npz*的压缩NumPy数组中。生成的100张人脸绘制在10x10的网格中,并保存到名为*generated_faces.png*的文件中。

在这种情况下,我们有一组很好的人脸可供使用。每个人脸都有一个我们可以用来检索潜在向量的索引。例如,第一张人脸是1,它对应于保存数组中的第一个向量(索引0)。

我们将执行操作

因此,我们需要三张微笑女性、中性女性和中性男性的脸。

在这种情况下,我们将使用图像中的以下索引:

  • 微笑女性:92, 98, 99
  • 中性女性:9, 21, 79
  • 中性男性:10, 30, 45
Plot of 100 Generated Faces Used as the Basis for Vector Arithmetic with Faces

用作人脸向量算术基础的100张生成人脸图

现在我们有了可用的潜在向量和目标算术,我们就可以开始了。

首先,我们可以指定我们偏好的人脸图像并加载保存的潜在点NumPy数组。

接下来,我们可以检索每个向量并计算每种向量类型(例如,微笑女性)的平均值。我们可以直接对单个图像执行向量算术,但如果我们处理的是具有所需属性的几个图像的平均值,则结果会更稳健。

下面的*average_points()*函数接受加载的潜在空间点数组,检索每个点,计算平均值,并返回所有向量。

我们现在可以使用此函数来检索所有所需的潜在空间点并生成图像。

最后,我们可以使用平均向量在潜在空间中进行向量算术并绘制结果。

将这些结合起来,完整的示例列在下面。

运行示例首先加载我们特定图像的潜在空间点,计算点的平均值,并生成这些点的对应人脸。

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

我们可以看到,确实,我们选择的人脸被正确检索,并且向量空间中点的平均值捕捉了我们想要的每条线上的突出特征(例如,微笑女性、中性女性等)。

Plot of Selected Generated Faces and the Average Generated Face for Each Row

绘制选定生成人脸和每行平均生成人脸的图

接下来,执行向量算术,结果是微笑的男性,正如我们所期望的那样。

Plot of the Resulting Generated Face Based on Vector Arithmetic in Latent Space

基于潜在空间向量算术所得生成人脸的图

扩展

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

  • 附加算术。尝试使用不同的人脸特征或不同的算术方法进行运算,并查看生成的人脸结果。
  • 附加插值。尝试在潜在空间中插值三个或更多点,并查看生成的人脸结果。
  • 调整模型。更新GAN模型的配置,使其训练更稳定,并能生成更高质量的人脸。

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

进一步阅读

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

书籍

论文

API

文章

总结

在本教程中,您将学习如何开发用于人脸生成的生成对抗网络,并探索潜在空间的结构及其对生成人脸的影响。

具体来说,你学到了:

  • 如何开发用于生成人脸的生成对抗网络。
  • 如何对潜在空间中的点进行插值,并生成从一张脸到另一张脸的变形图像。
  • 如何在潜在空间中执行向量算术,并在结果生成的面部中实现有针对性的效果。

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

立即开发生成对抗网络!

Generative Adversarial Networks with Python

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

...只需几行python代码

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

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

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

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

查看内容

74条关于“如何探索GAN潜在空间生成人脸”的回复

  1. Mankaran Singh 2019年7月5日晚上5:15 #

    非常详细的帖子!热切期待您关于GAN的书。

    • Jason Brownlee 2019年7月6日早上8:26 #

      谢谢!

      是的,这真是一个有趣的教程!🙂

      新书应该在一两周内准备好。我对此非常兴奋。

  2. Minel 2019年7月19日凌晨1:55 #

    你好,Jason

    在进行pip install之后,我在使用MTCNN时遇到了一些问题。我收到了消息“no module named cv2”。
    我不得不通过输入来安装它:
    python -m pip install opencv-python
    祝好

  3. Shubhesh 2019年8月1日凌晨12:28 #

    我得到这个值:
    Loaded: (50000, 218, 178, 3)
    可能是什么问题?

    • Jason Brownlee 2019年8月1日早上6:53 #

      您是否跳过了某一步?

      • Shubhesh 2019年8月2日凌晨5:40 #

        是的,那是一个愚蠢的错误,在一个函数里。现在没问题了。谢谢。

        • Jason Brownlee 2019年8月2日早上6:56 #

          很高兴听到这个消息。

          • Jucris 2022年8月23日晚上10:56 #

            嗨!

            我从您的教学中获得了灵感,并开发了一个用于花卉的GAN模型。我正在使用plotly的散点图在2D图表中绘制潜在点。但当我看到那些图像时,它们聚集在一起,但不是基于某个可识别的特征。有什么方法可以调整一些东西,使相似的图像聚集在一起,比如具有相似的颜色或形状等?

  4. Ryan 2019年8月11日凌晨12:48 #

    感谢您提供如此精彩的教程,我想知道如何对Cycle GAN做同样的事情来生成人脸,例如创建愤怒的人脸、微笑的人脸……

    • Jason Brownlee 2019年8月11日早上6:00 #

      这可能对CycleGAN没有意义,因为它用于图像翻译,而不是生成新图像,比如人脸。

  5. D. Uys 2019年8月15日凌晨2:04 #

    谢谢你。
    我很难理解什么是潜在空间?我阅读了您的一些GAN教程和其他教程。我觉得我对潜在空间是什么以及为什么使用它有一个很好的经验性理解,但我不知道如何决定其形状。为什么在DCGAN中潜在空间是一个100维的向量?为什么不是50D、20D或1000D?

    这也源于您另一篇教程中关于使用GAN网络进行简单1D函数建模的例子,其中您使用了5D潜在空间。我还读了您其他文章中的一些评论,您提到选择不同的潜在空间形状变得任意?我希望我在这里问对了问题。

    如果您能给我一个ELI5(像5岁小孩一样解释)的版本,我将非常感激!谢谢!

    • Jason Brownlee 2019年8月15日早上8:24 #

      大小/形状是任意的。更大可能提供更多自由度,过大或过小可能导致模型不稳定。

      它不是一个真实的事物,而是模型学会赋予它意义——可以看作是从中汲取灵感,但以一种一致的方式,使其有序,并且空间的各个部分映射到不同的特定输出——尽管每次模型训练时,这种结构/映射都会不同。

      这是一个难以理解的事情。你不是一个人🙂

      我认为在这篇文章中我很好地介绍了“潜在空间”。
      https://machinelearning.org.cn/what-are-generative-adversarial-networks-gans/

  6. Jun 2019年10月4日凌晨3:58 #

    你好,我对这个领域还很新,您的文章非常有帮助。
    但是,由于难以完全理解,我是否可以问几个具体的问题?

    首先,我知道train on batch函数可以提高gan_model的性能。
    但是,我不明白为什么生成latent_points总是使用randn函数来生成随机噪声。
    我猜噪声的值并不重要,因为即使噪声总是随机的,GAN模型也会随着训练过程的进行生成更好的图像。
    这是正确的吗?

    第二,您能否简要告诉我,在加载npz文件(如points = data[‘arr_0’])的每个过程中,“arr_0”是什么意思?

    第三,向量算术部分对我来说非常困难,我无法理解这部分在做什么。
    ”’
    # 平均向量
    smiling_woman = average_points(points, smiling_woman_ix)
    neutral_woman = average_points(points, neutral_woman_ix)
    neutral_man = average_points(points, neutral_man_ix)
    # 合并所有向量
    all_vectors = vstack((smiling_woman, neutral_woman, neutral_man))

    # 微笑女性 – 中性女性 + 中性男性 = 微笑男性
    result_vector = smiling_woman[-1] – neutral_woman[-1] + neutral_man[-1]
    ”’
    您能否详细解释一下?我明白“average_points”是在不同图像的向量之间进行平均,但无法理解average_point函数的内部工作原理,以及为什么向量的最后一个元素构成了result_vector。

    永远感谢您的文章。

  7. Dant. 2019年10月5日晚上6:26 #

    为什么它不被归类为DCGAN,即使它在判别器和生成器模型中都包含CNN?

  8. Silvia 2020年1月9日凌晨3:22 #

    您是否也探讨了降低潜在空间维度的可能性?这里是100维的,但对于某些应用来说,了解是否存在一个不能被跨越的下限,或者这对训练有什么影响,可能会很有用。

    • Jason Brownlee 2020年1月9日早上7:31 #

      是的,我做过实验。小而非常小的空间总是导致模式崩溃。

  9. tvtaerum 2020年3月1日早上10:49 #

    我终于在Github上发布了描述和代码,使用了我从您的几篇精彩的在线教程中学到的知识,并且我想确保我恰当地引用了您的工作。我发布的是一个cGAN,带有嵌入,并对您的工作和Centeno的工作进行了修改,我还做了一些相关的处理,例如演示如何从中断处重新启动cGAN,自动纠正不太离谱的学习率,以及其他相关的处理。这些都是当人们对别人在互联网上发布的内容进行“小的”修改时可能想做的事情,然后发现他们的“小的”修改会导致收敛问题。它目前在https://github.com/tvtaerum/cGans_with_embedding—housekeeping 上是“私有的”,但我想确保我恰当地引用您和您的工作。我才刚刚开始发布东西,但我发现从一开始就把事情做对是值得的。如果我和其他人想做类似的事情,最合适的方法是什么?您是否碰巧有示例?

  10. Francis 2020年3月2日 下午2:26 #

    0

    我正在尝试使用以下命令保存一个 tensorflow kersa 模型,其摘要如下:Model: “sequential_2” 等。使用以下命令:model.save(‘my_model.h5’) 我遇到了以下错误:ImportError:save_modelrequires h5py。 所以,我使用 conda install h5py 安装了 h5py。安装后,我得到了 h5py 的版本:h5py.__version__ ‘2.8.0’ 仍然,我遇到了相同的错误。即使我手动导入了 h5py。

    import h5py
    import tensorflow as tf
    from tensorflow import keras
    from tensorflow.keras import layers
    filename = ‘g_model.h5’
    model.save(filename)

    **ImportError:** save_model 需要 h5py。

  11. Alexander Soare 2020年4月5日 上午2:19 #

    嗨!

    再次感谢您提供的精彩材料。我从您的 CNN MNIST 教程开始,此后学到了很多东西。我有一个关于这个的问题
    在您定义完整 GAN 的函数中,您将 d_model.trainable 设置为 False。但在代码的其他地方我找不到任何地方在训练循环中更新 d_model 权重之前将其切换回 True。我是否遗漏了什么?

    祝好,
    Alex

  12. Lloyd 2020年4月9日 下午6:09 #

    嗨,Jason,
    我买了您关于 GAN 的书,就在它出版后不久,我想说它(以及像这样的帖子)非常棒且非常有帮助。
    不过,在整本书/帖子中,我开始注意到一些事情,想问一下
    GAN 的所有常见应用都处理方形图像……我将如何处理矩形图像?
    虽然我知道重塑和裁剪是解决这个问题的一个简单方法,但如果无法重塑图像怎么办?
    我一直在计划一项关于在工作中处理的一些数据集中使用 GAN 进行数据增强的研究,但当我开始查看现有文献时,我注意到几乎所有人都使用方形矩阵表示的数据(无论是图像还是其他)。我目前正在为不同的应用处理不同类型的矩阵,并且并非所有矩阵都与图像相关,最重要的是它们不是方形的。在大多数情况下,我获得和处理的数据是具有许多行和仅三列的矩阵。在某些情况下,我会有更多的列,但总的来说,根据我正在处理的应用,我的数据集大约是 13×3、17×3 或 30×3。
    您知道有处理矩形数据的论文或应用吗?或者您能否推荐一个起点,让我可以寻找一些灵感?

    • Jason Brownlee 2020年4月10日 上午8:23 #

      谢谢 Lloyd!

      是的,我预计结果对于矩形图像也适用,但正如您所说,需要调整网络配置。

      论文为了简单起见,处理的是方形图像。

      抱歉,暂时没有。我建议您亲自尝试。

  13. Jakob 2020年4月16日 下午5:53 #

    感谢您提供一本很棒的书,我玩得很开心。既然您征求反馈,如果我们探索扩展,那么……
    我注意到 CelebA 的图像质量参差不齐。有很多图像是侧面或非常扭曲的面部。由于 MTCNN 还提供鼻子和眼睛的位置,我尝试对数据准备算法进行了一些小改动。我没有从 200K CelebA 图像中随机选择 50K 张,而是倾向于选择鼻子中心到眼睛中心之间的垂直距离较短的图像。这会选择人们看得更直(以及一些鼻子歪斜的 🙂)的图像。
    让模型具有较少的变异性和较少的离群值姿势可以产生更一致的结果

  14. Junwei 2020年4月28日 下午6:09 #

    感谢您提供如此详细的优秀教程。我有一个问题,正如您在文章中所提到的,“鉴别器的损失可能会骤降到真实样本和生成样本的 0.0 值”。我遇到了这个问题,但这是怎么发生的?您能否解释一下这种现象的原因?

  15. Greg 2020年4月29日 上午2:51 #

    因为我花了大约 3 天的时间来找出为什么 import cv2 不工作,所以我将分享我的解决方案,以防你们中有人可能遇到同样的问题。

    对于 W10 N / pro N,您需要安装媒体功能包。

    没有这个,任何安装和导入 cv2 的高级方法都将不起作用……

    感谢 Jason 的这个了不起的博客,我正准备在我的机械工程博士工作中尝试使用 C-GAN,并且您为像我这样的非直接 AI/DL 研究人员澄清了许多关于此网络的秘密。
    我计划下个月购买您的 GAN 书。

    此致!

    • Jason Brownlee 2020年4月29日 上午6:32 #

      什么是“媒体功能包”?

      我们在本教程中甚至没有使用 opencv!

      • Greg 2020年4月29日 下午4:34 #

        是的,没有使用它,但……MTCNN 需要它才能工作:)
        “媒体功能包”是 W10 N 系列操作系统的一些功能的集合。

  16. kiran Prakash Sawant 2020年5月24日 下午9:48 #

    感谢您提供如此详细的优秀教程。像素值必须缩放到 [-1,1] 的范围才能匹配生成器模型的输出。为什么我们需要这样做??

    • Jason Brownlee 2020年5月25日 上午5:51 #

      生成器在生成范围在 -1 和 1 之间的像素时表现更好。

      为了匹配生成器模型的输出,以便真实图像和生成的图像具有相同的比例。

  17. Aria 2020年6月21日 下午1:42 #

    你好,

    在此示例中,当更新生成器的参数时,鉴别器的变量也会被更新,因为 train_on_batch 方法是在包含生成器和鉴别器的顺序模型上调用的。生成器的参数不应该独立于鉴别器的参数进行更新吗?

    • Jason Brownlee 2020年6月22日 上午6:09 #

      不完全是,我们将鉴别器设置为在其是生成器一部分时不可训练。

  18. Harry 2020年8月12日 下午6:08 #

    嗨,谢谢您的教程。
    我有一个错误。请帮我
    ‘tensorflow.python.framework.errors_impl.ResourceExhaustedError
    OOM 在为形状为[128,128,80,80]且类型为 float 的张量分配内存时出错,位于/job:localhost/replica:0/task:0/device:GPU:0,使用分配器 GPU_0_bfc
    [[node gradients_1/sequential_1/conv2d_2/convolution_grad/Conv2DBackpropInput (定义于 \Users\HP\miniconda3\envs\Tensorflow_v2_py3\lib\site-packages\keras\backend\tensorflow_backend.py:3009) ]]’

  19. Harry 2020年8月13日 下午3:44 #

    谢谢。我通过将 batch_size 减小到 64(之前是 128)解决了这个问题:)

  20. Harry 2020年8月13日 下午3:50 #

    您的教程非常棒。我尝试使用 X 光胸部数据集。因为它不同于包含 RGB 的数据集,所以没有成功。您有什么建议可以这样做吗?提前谢谢您

    • Jason Brownlee 2020年8月14日 上午5:55 #

      谢谢!

      好问题,我暂时没有好的建议。您可能需要尝试您的数据的 RGB 编码。

  21. Ali AOUF 2020年9月14日 下午9:21 #

    您好,先生!

    我可以使用您的代码进行 InfoGAN 人脸生成吗?

  22. Ali AOUF 2020年9月15日 上午2:10 #

    您好,先生,很棒的教程。
    我正在为学术研究开发一个人类面部 InfoGAN 模型,我想知道是否可以将您的模型用作基础代码,因为它很稳定,并且可以生成良好的图像。
    谢谢你。

  23. Dominique 2020年9月21日 上午3:42 #

    亲爱的 Jason,

    感谢您的精彩书籍。这是我读过的您的第 7 本书,总是一次愉快的体验。我几乎花了我整个周末的时间来玩 GAN。这个周末我写了一篇关于您的 GAN 书的第三部分和第四部分的评论。
    http://questioneurope.blogspot.com/2020/09/generative-adversarial-network-with.html

    我也遇到了与社区成员在运行 cGAN 时类似的 the network failure,但在第二次运行时似乎有所改善。

    诚挚的问候,
    Dominique

    • Jason Brownlee 2020年9月21日 上午8:15 #

      谢谢!你取得的令人印象深刻的进展令人赞叹。

      GAN 可能非常棘手。您必须通过构建/训练许多不同的模型来积累经验和信心——例如,书中采用的方法。

  24. Lee 2020年10月18日 下午8:30 #

    很棒的教程 Jason。但是,我如何对用于训练的 MNIST 数据进行插值?

    我的意思是,而不是使用生成的数据。

    由于代码不包含编码器,只包含作为解码器的生成器,我认为不行。

  25. Kevin 2020年10月25日 下午10:37 #

    感谢您的明确教程。
    而不是对生成数据进行潜在空间插值,我如何对原始 celebA 人脸进行插值?
    我想我需要某种编码器,但不知道如何将原始人脸映射到潜在空间!

    • Jason Brownlee 2020年10月26日 上午6:49 #

      如果模型是在 celebA 数据集上训练的,那么对潜在空间进行插值就会对 celebA 数据集进行插值。

  26. Ahmad 2021年1月1日 下午8:32 #

    亲爱的Jason Brownlee,
    感谢您分享您的优秀作品。您能否帮助我使用 Hinge 损失函数而不是二元交叉熵损失,在同一个模型中实现 80×80 图像尺寸的基本人脸生成?我尝试使用 Hinge 损失将数据缩放到 {-1, 1} 范围,但输出生成没有任何进展(只生成空白的灰色图像)。

    祝好

    • Jason Brownlee 2021年1月2日 上午6:23 #

      也许可以尝试调整您模型的学习参数?
      也许可以尝试调整您模型的网络架构?

  27. Artemiy 2021年1月9日 上午12:30 #

    你好!非常感谢您的文章。我有一个问题:我决定每 5 个训练周期输出一次鉴别器的准确率,针对 10,000 张图像(与文章中完全相同的方式)。也就是说,我每五个周期保存一次鉴别器,并针对 10,000 张图像运行其准确率。事实是,真实图像的准确率波动很大:第五个周期后——准确率是 99%,第 15 个周期后——75%,第 20 个周期后又是 92%。图像质量在每个周期后都会提高。您能否告诉我这种差异的原因?

    real – 是 d1,fake – 是 d2。
    {
    ‘descriminator_model_005.h5’: {‘real’: 99.98000264167786, ‘fake’: 100.0},
    ‘descriminator_model_010.h5’: {‘real’: 99.40000176429749, ‘fake’: 100.0},
    ‘descriminator_model_015.h5’: {‘real’: 75.51000118255615, ‘fake’: 90.85999727249146},
    ‘descriminator_model_020.h5’: {‘real’: 92.91999936103821, ‘fake’: 97.50000238418579},
    ‘descriminator_model_025.h5’: {‘real’: 94.0999984741211, ‘fake’: 97.97000288963318},
    ‘descriminator_model_030.h5’: {‘real’: 91.86000227928162, ‘fake’: 97.61999845504761},
    ‘descriminator_model_035.h5’: {‘real’: 84.42999720573425, ‘fake’: 98.83000254631042},
    ‘descriminator_model_040.h5’: {‘real’: 78.43999862670898, ‘fake’: 97.36999869346619},
    ‘descriminator_model_050.h5’: {‘real’: 86.82000041007996, ‘fake’: 100.0},
    ‘descriminator_model_055.h5’: {‘real’: 80.95999956130981, ‘fake’: 99.55999851226807},
    ‘descriminator_model_060.h5’: {‘real’: 82.56000280380249, ‘fake’: 100.0}
    }

  28. SudBan 2021年2月23日 上午9:25 #

    您好,非常感谢您提供的信息性文章。我有一个关于自定义训练的问题。我能否不训练图像,而是使用一些单独的编码器网络生成的自定义“嵌入”来训练和测试 GAN?也就是说,我首先使用单独的网络在自定义数据集上生成一些嵌入,然后将这些向量馈送到 GAN。您有什么建议吗?谢谢!

    • Jason Brownlee 2021年2月23日 上午10:15 #

      不客气。

      我暂时不确定,也许不行。您可能需要仔细考虑或甚至原型化以查看其是否可行。

  29. Max 2021年4月26日 上午5:03 #

    这是一个很棒的教程,但当我尝试使用 load_faces 时,它会显示一些警告,如下所示
    触发了 tf.function 重跟踪。重跟踪成本很高,而过多的重跟踪可能是由以下原因造成的:(1) 在循环中重复创建 @tf.function,(2) 传递形状不同的张量,(3) 传递 Python 对象而不是张量。对于 (1),请在循环外部定义您的 @tf.function。对于 (2),@tf.function 具有 experimental_relax_shapes=True 选项,可以放宽参数形状,从而避免不必要的重跟踪。对于 (3),请参考 https://tensorflowcn.cn/guide/function#controlling_retracinghttps://tensorflowcn.cn/api_docs/python/tf/function 以获取更多详细信息。

    您能告诉我如何解决这个问题吗?

  30. HackerCop 2021年12月5日 上午7:21 #

    这是一个很棒的教程,我注意到在“如何对生成的人脸进行插值”标题下的两个代码块中。np.Linspace 支持向量之间的插值,因此您不需要
    这两段代码

    而是只需将您想要插值的向量输入 np.linspace,例如:

    print(np.linspace([0,5],[1,6],num=10))

    [[0. 5. ]
    [0.11111111 5.11111111]
    [0.22222222 5.22222222]
    [0.33333333 5.33333333]
    [0.44444444 5.44444444]
    [0.55555556 5.55555556]
    [0.66666667 5.66666667]
    [0.77777778 5.77777778]
    [0.88888889 5.88888889]
    [1. 6. ]]

    • Adrian Tam
      Adrian Tam 2021年12月8日 上午7:32 #

      谢谢指出!

  31. Wilfredo 2022年7月6日 下午10:24 #

    嗨 Jason!您的代码效果很好。
    非常感谢您发布了优秀且具有启发性的 ML 博文……!
    是的,训练可能需要数小时。我在 Google Colab 上只能训练模型 40 个周期(大约三个半小时)。
    我已保存了三个模型,d_model、g_model 和 gan_model,但我无法继续训练。
    有什么建议如何做到这一点吗?提前感谢!

    • James Carmichael 2022年7月7日 上午6:48 #

      Wilfredo,您非常受欢迎!请详细说明训练无法继续的原因。这将使我们能够更好地帮助您。

  32. Jucris 2022年8月11日 上午5:22 #

    非常感谢您写这篇文章!您能否告诉我可视化潜在空间的最佳方法?我的意思是,例如 3D 中的点?

  33. Jucris 2022年8月24日 上午11:35 #

    嗨!

    我从您的教学中获得了灵感,并开发了一个用于花卉的GAN模型。我正在使用plotly的散点图在2D图表中绘制潜在点。但当我看到那些图像时,它们聚集在一起,但不是基于某个可识别的特征。有什么方法可以调整一些东西,使相似的图像聚集在一起,比如具有相似的颜色或形状等?

  34. Fidha Nasneen 2023年6月16日 下午2:46 #

    嗨 James,

    您的文章易于理解,谢谢。我想了解更多关于潜在空间和向量以及它们在 GAN 中如何工作的信息。我期待理论和数学解释。希望您能帮我解决这个问题。谢谢……

发表回复

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