当然,在您准备好构建自己的 GAN 之前,我们还要介绍更多细节。 接下来,让我们更深入地研究生成器。
# 发电机架构
在此示例中,我们使用适合于生成*28 x 28*灰度图像的图层大小,这正是我们稍后在 MNIST 示例中将要执行的操作。 如果您以前没有使用过生成器,那么生成器的算法可能会有些棘手,因此我们将在遍历每一层时进行介绍。 下图显示了体系结构:
在此示例中,我们使用适合于生成`28 x 28`灰度图像的图层大小,这正是我们稍后在 MNIST 示例中将要执行的操作。 如果您以前没有使用过生成器,那么生成器的算法可能会有些棘手,因此我们将在遍历每一层时进行介绍。 下图显示了体系结构:
![](img/6e7de048-2461-4be3-a702-f4d0a87d3c43.png)
生成器的输入只是 100 x 1 的随机向量,我们将其称为噪声向量。 当此噪声矢量是从正态分布生成时,GAN 往往工作得最好。
网络的第一层是密集的并且完全连接。 它为我们提供了一种建立线性代数的方法,以便最终得到正确的输出形状。 对于每个卷积块,我们最终将第一轴和第二轴(最终将成为图像的高度和宽度的行和列)加倍,而通道数逐渐缩小到 1。我们最终需要高度和宽度 输出张数为 28。因此,我们将需要从*7 x 7 x 128* 张量开始,以便它可以移动到 *14 x 14* ,然后最终是 *28 x 28* 。 为此,我们将密集层的大小设置为 *128 x 7 x 7* 神经元或 6,272 单位。 这使我们可以将密集层的输出重塑为 *7 x 7 x 128*。 如果现在看来这还不算什么,请不用担心,在编写代码后,这才有意义。
网络的第一层是密集的并且完全连接。 它为我们提供了一种建立线性代数的方法,以便最终得到正确的输出形状。 对于每个卷积块,我们最终将第一轴和第二轴(最终将成为图像的高度和宽度的行和列)加倍,而通道数逐渐缩小到 1。我们最终需要高度和宽度 输出张数为 28。因此,我们将需要从`7 x 7 x 128`张量开始,以便它可以移动到`14 x 14`,然后最终是`28 x 28`。 为此,我们将密集层的大小设置为`128 x 7 x 7`神经元或 6,272 单位。 这使我们可以将密集层的输出重塑为`7 x 7 x 128`。 如果现在看来这还不算什么,请不用担心,在编写代码后,这才有意义。
DCGAN 框架是使用迷你批处理来进行训练的,这与我之前在本书中对网络进行训练的方式相同。 但是,稍后在构建代码时,您会注意到我们正在构建一个训练循环,该循环明确控制每个更新批处理的情况,而不仅仅是调用`models.fit()`方法并依靠 Keras 为我们处理它。 我这样做是因为 GAN 训练需要多个模型来更新同一批次中的权重,所以它比我们以前所做的单个参数更新要稍微复杂一些。
DCGAN 框架是使用迷你批量来进行训练的,这与我之前在本书中对网络进行训练的方式相同。 但是,稍后在构建代码时,您会注意到我们正在构建一个训练循环,该循环明确控制每个更新批量的情况,而不仅仅是调用`models.fit()`方法并依靠 Keras 为我们处理它。 我这样做是因为 GAN 训练需要多个模型来更新同一批次中的权重,所以它比我们以前所做的单个参数更新要稍微复杂一些。
我们以前没有使用过`UpSampling2D`层。 该层将增加输入张量的行和列,从而使通道保持不变。 它通过重复输入张量中的值来实现。 默认情况下,它将使输入加倍。 如果给`UpSampling2D`层一个*7 x 7 x 128* 输入,它将给我们一个 *14 x 14 x 128*输出。
我们以前没有使用过`UpSampling2D`层。 该层将增加输入张量的行和列,从而使通道保持不变。 它通过重复输入张量中的值来实现。 默认情况下,它将使输入加倍。 如果给`UpSampling2D`层一个`7 x 7 x 128`输入,它将给我们一个`14 x 14 x 128`输出。
通常,当我们构建一个 CNN 时,我们从一个非常高和宽的图像开始,并使用卷积层来获得一个非常深但又不高又不宽的张量。 在这里,我将相反。 我将使用一个密集层并进行重塑,以*7 x 7 x 128* 张量开始,然后将其加倍两次后,剩下 *28 x 28* 张量。 由于我需要灰度图像,因此可以使用具有单个单元的卷积层来获得 *28 x 28 x 1*输出。
通常,当我们构建一个 CNN 时,我们从一个非常高和宽的图像开始,并使用卷积层来获得一个非常深但又不高又不宽的张量。 在这里,我将相反。 我将使用一个密集层并进行重塑,以`7 x 7 x 128`张量开始,然后将其加倍两次后,剩下`28 x 28`张量。 由于我需要灰度图像,因此可以使用具有单个单元的卷积层来获得`28 x 28 x 1`输出。
注意,这里的形状是`half_batch`*x 28 x 28 x 1*。 `half_batch`正是您所想的。 我们将创建一半的生成图像,因为另一半将是真实数据,我们将在下一步进行组装。 要获取真实图像,我们将在`X_train`上生成一组随机索引,并将`X_train`的切片用作真实图像,如以下代码所示:
注意,这里的形状是`half_batch x 28 x 28 x 1`。 `half_batch`正是您所想的。 我们将创建一半的生成图像,因为另一半将是真实数据,我们将在下一步进行组装。 要获取真实图像,我们将在`X_train`上生成一组随机索引,并将`X_train`的切片用作真实图像,如以下代码所示: