六、StackGAN - 逼真的文本到图像合成
文本到图像的合成是生成对抗网络(GAN)的用例之一,它具有许多工业应用,就像前面章节中描述的 GAN 一样。 从文本描述中合成图像非常困难,因为要构建可以生成反映文本含义的图像的模型非常困难。 一个试图解决这个问题的网络是 StackGAN。 在本章中,我们将使用 TensorFlow 作为后端在 Keras 框架中实现 StackGAN。
在本章中,我们将介绍以下主题:
- StackGAN 简介
- StackGAN 的架构
- 数据收集与准备
- StackGAN 的 Keras 实现
- 训练 StackGAN
- 评估模型
- pix2pix 网络的实际应用
StackGAN 简介
之所以这样称呼 StackGAN,是因为它具有两个 GAN,这些 GAN 堆叠在一起形成了一个能够生成高分辨率图像的网络。 它分为两个阶段,第一阶段和第二阶段。第一阶段网络生成具有基本颜色和粗略草图的低分辨率图像,并以文本嵌入为条件;而第二阶段网络获取由第一阶段网络生成的图像,并生成以文字嵌入为条件的高分辨率图像。 基本上,第二个网络会纠正缺陷并添加引人注目的细节,从而产生更逼真的高分辨率图像。
我们可以将 StackGAN 网络与画家的作品进行比较。 当画家开始工作时,他们会绘制原始形状,例如线条,圆形和矩形。 然后,他们尝试填充颜色。 随着绘画的进行,越来越多的细节被添加。 在 StackGAN 中,第一阶段与绘制基本形状有关,而第二阶段与校正由第一阶段网络生成的图像中的缺陷有关。第二阶段还添加了更多细节,以使图像看起来更逼真。 这两个阶段的生成器网络都是条件生成对抗网络(CGAN)。 第一个 GAN 以文本描述为条件,而第二网络以文本描述和第一个 GAN 生成的图像为条件。
StackGAN 的架构
StackGAN 是一个两阶段的网络。 每个阶段都有两个生成器和两个判别器。 StackGAN 由许多网络组成,这些网络如下:
- 阶段 1 GAN :文本编码器,条件增强网络,生成器网络,判别器网络,嵌入压缩器网络
- 阶段 2 GAN :文本编码器,条件增强网络,生成器网络,判别器网络,嵌入压缩器网络
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FYOTYhCZ-1681652906140)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/6f2f1522-849c-4ee4-9c08-57884ea1b6b1.png)]
来源:arXiv:1612.03242 [cs.CV]
上图是不言自明的。 它代表了 StackGAN 网络的两个阶段。 如您所见,第一步是生成大小为64x64
的图像。 然后,第二阶段拍摄这些低分辨率图像,并生成大小为256x256
的高分辨率图像。 在接下来的几节中,我们将探讨 StackGAN 网络中的不同组件。 但是,在进行此操作之前,让我们熟悉本章中使用的符号:
表示法 | 说明 |
t |
这是真实数据分发的文本描述。 |
z |
这是来自高斯分布的随机采样噪声向量。 |
φ[t] |
这是预训练编码器生成的给定文本描述的文本嵌入。 |
c_hat[0] |
此文本条件变量是从分布中采样的高斯条件变量。 它抓住了的不同含义。 |
N(μ(φ[t]), ∑(φ[t])) |
这是条件高斯分布。 |
N(0, I) |
这是正态分布。 |
∑(φ[t]) |
这是一个对角协方差矩阵。 |
pdata |
这是真正的数据分配。 |
pz |
这就是高斯分布。 |
D1 |
这是第一阶段的判别器。 |
G1 |
这是第一阶段生成器。 |
D2 |
这是第二阶段的判别器。 |
G2 |
这是第二阶段生成器。 |
N2 |
这些是随机噪声变量的大小。 |
c_hat |
这些是第二阶段 GAN 的高斯潜在变量。 |
文字编码器网络
文本编码器网络的唯一目的是将文本描述(t
)转换为文本嵌入(φ[t]
)。 在本章中,我们不会训练文本编码器网络。 我们将使用经过预训练的文本嵌入。 按照“数据准备”部分中给出的步骤下载预训练的文本嵌入。 如果您想训练自己的文本编码器,请参阅《学习细粒度视觉描述的深度表示》,该文章可在这里找到。 文本编码器网络将句子编码为 1,024 维文本嵌入。 文本编码器网络在两个阶段都是相同的。
条件增强块
条件增强(CA)网络从表示为N(μ(φ[t]), ∑(φ[t]))
的分布中采样随机潜在变量c_hat
。 我们将在后面的部分中详细了解这种分布。 添加 CA 块有很多优点,如下所示:
- 它为网络增加了随机性。
- 通过捕获具有各种姿势和外观的各种对象,它使生成器网络变得强大。
- 它产生更多的图像-文本对。 使用大量的图文对,我们可以训练一个可以处理干扰的健壮网络。
获取条件增强变量
从文本编码器获得文本嵌入(φ[t]
)后,将它们馈送到完全连接的层以生成诸如平均值μ[0]
和标准差σ[0]
的值。然后使用这些值,通过将σ[0]
放置在矩阵(∑(φ[t])
)的对角线上来创建对角协方差矩阵。 最后,我们使用μ[0]
和∑[0]
创建高斯分布,可以表示为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YQZiOqEK-1681652906141)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/bcc5921a-1e7e-497a-b134-61a55d04cecb.png)]
然后,我们从刚创建的高斯分布中采样c_hat[0]
。 计算c_hat[0]
的公式如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OlYIe3mt-1681652906142)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/5bbaa568-0f1e-431b-b8d1-f8bacae72282.png)]
前面的方程式很不言自明。 为了对c_hat[0]
进行采样,我们首先将σ[0]
和进行元素逐个相乘,然后将输出添加到μ[0]
中。 我们将在“StackGAN 的 Keras 实现”部分中详细介绍如何计算 CA 变量c_hat[0]
。
第一阶段
StackGAN 网络的主要组成部分是生成器网络和判别器网络。 在本节中,我们将详细探讨这两个网络。
生成器网络
第一阶段生成器网络是具有几个上采样层的深度卷积神经网络。 生成器网络是 CGAN ,其条件是处于c_hat[0]
和随机变量z
。 生成器网络采用高斯条件变量c_hat[0]
和随机噪声变量z
,并生成大小为64x64x3
的图像。 生成的低分辨率图像可能具有原始形状和基本颜色,但会存在各种缺陷。 这里,z
是从维数为N[z]
的高斯分布P[z]
采样的随机噪声变量。 生成器网络生成的图像可以表示为s[0] = G[0](z, c_hat[0])
。 让我们看一下生成器网络的架构,如以下屏幕截图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t1cEebkh-1681652906142)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/04c840a1-a6ae-4b3d-a141-ed58f9dae21b.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CoTJMrlO-1681652906142)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/c4ba3b4c-3d2b-4156-8e94-aea9a2e8c781.png)]
第一阶段的生成器网络架构
如您所见,生成器网络包含几个卷积层,其中每个卷积层后跟一个批量规范化层或一个激活层。 它的唯一目的是生成大小为64x64x3
的图像。 现在我们有了生成器网络的基本概念,让我们探索判别器网络。
判别器网络
类似于生成器网络,判别器网络是一个深度卷积神经网络,其中包含一系列下采样卷积层。 下采样层从图像生成特征映射,无论它们是真实数据分布P_data
的真实图像还是生成器网络生成的图像。 然后,我们将特征映射连接到文本嵌入。 我们使用压缩和空间复制将嵌入的文本转换为连接所需的格式。 空间压缩和复制包括一个完全连接的层,该层用于压缩嵌入到N[d]
维输出的文本,然后通过空间复制将其转换为M[d] × M[d] × N[d]
维张量。 然后将特征映射以及压缩的和空间复制的文本嵌入沿通道维级联。 最后,我们具有一个节点的完全连接层,该层用于二分类。 让我们看一下判别器网络的架构,如以下屏幕截图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dKCcidP7-1681652906142)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/fc0175ae-38b7-42aa-99ec-1bdbe36a8edf.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ET7sHCuY-1681652906143)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/3fd25fcc-55fa-4bce-b1d7-4f4d801ba076.png)]
第一阶段判别器网络的架构
如您所见,生成器网络包含几个卷积层。 判别器网络的唯一目的是区分来自真实数据分布的图像和生成器网络生成的图像。 现在,我们来看看 StackGAN 的第一阶段中使用的损失。
StackGAN 第一阶段的损失
StackGAN 的第一阶段中使用了两个损失,如下所示:
- 生成器损失
- 判别器损失
判别器损失l[D]
可以表示为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pTn0xKKZ-1681652906143)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/01fddc7c-38fb-4dc6-ac3b-3c73b448e65a.png)]
公式前面的很不言自明。 它代表了判别器网络的损失函数,其中两个网络都以文本嵌入为条件。
生成器损失l[G]
可以表示为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-atNnJmrc-1681652906143)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/6567c751-fa0d-4009-b4bd-b864d4ecab7c.png)]
公式前面的也很容易解释。 它代表了生成器网络的损失函数,其中两个网络都以文本嵌入为条件。 此外,它还包括损失函数的 KL 发散项。
第二阶段
第二阶段 StackGAN 的主要组件是生成器网络和判别器网络。 生成器网络是编码器-解码器类型的网络。 在此阶段不使用随机噪声z
,假设s[0]
已保留了随机性,其中s[0]
是第一阶段的生成器网络生成的图像。
我们首先使用预训练的文本编码器生成高斯条件变量c_hat
。 这将生成嵌入φ[t]
的相同文本。 第一阶段和第二阶段条件增强具有不同的完全连接层,用于生成不同的均值和标准差。 这意味着第二阶段 GAN 学会了在文本嵌入中捕获有用的信息,而这些信息被第一阶段 GAN 省略了。
第一阶段 GAN 生成的图像存在的问题是,它们可能缺少生动的对象部分,它们可能包含形状失真,并且它们可能会忽略对于生成逼真的图像非常重要的重要细节。 第二阶段 GAN 建立在第一阶段 GAN 的输出上。 第二阶段 GAN 取决于第一阶段 GAN 生成的低分辨率图像和文本描述。 它通过校正缺陷产生高分辨率的图像。
生成器网络
生成器网络还是深层卷积神经网络。 第一阶段的结果是低分辨率图像,它经过几个下采样层以生成图像特征。 然后,将图像特征和文本条件变量沿通道大小连接在一起。 之后,将级联张量馈入一些残差块,这些残差块学习跨图像和文本特征的多峰表示。 最后,最后一个操作的输出被馈送到一组上采样层,这些上采样层生成大小为256x256x3
的高分辨率图像。 让我们看一下生成器网络的架构,如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4EbUF29p-1681652906143)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/028e54b4-8184-45bd-8edf-abc7b7e8de97.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l6KINxt6-1681652906144)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/cd2083c4-1490-4eef-a931-c924f6366e86.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l6hnwcF7-1681652906144)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/f0da2f12-07bd-477a-97a6-dc21589a0b1f.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-niCj5rCH-1681652906144)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/6b5db762-e527-4194-85ab-83cc4ff9a1b5.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zttgkj77-1681652906144)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/e196749b-1617-4fcb-bbc5-14c392c944f1.png)]
第二阶段生成器的架构
该生成器网络的唯一目的是从低分辨率图像生成高分辨率图像。 低分辨率图像首先由第一阶段的生成器网络生成,然后馈送到第二阶段的生成器网络,后者生成高分辨率图像。
判别器网络
类似于生成器网络,判别器网络是一个深度卷积神经网络,并且包含额外的下采样层,因为图像的大小比第一阶段中的判别器网络大。 判别器是一个可识别匹配的判别器(有关更多信息,请参见以下链接,它使我们可以更好地实现图片和条件文本的对齐。 在训练期间,判别器将真实图像及其对应的文本描述作为正样本对,而负样本对则由两组组成。 第一组是具有不匹配的文本嵌入的真实图像,而第二组是具有相应的文本嵌入的合成图像。 让我们看一下判别器网络的架构,如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iYVqGM9i-1681652906144)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/a8c04bff-bd5a-4350-8b08-bd2ef6ae193b.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ePIrahCy-1681652906145)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/73371faa-5c7e-475f-a169-4229e9d04b24.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fmSUa3IH-1681652906145)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/42eb238c-1bba-415e-b416-469f04e29932.png)]
第二阶段判别器网络的架构
关于判别器网络架构的更多信息可以在“StackGAN 的 Keras 实现”部分中找到。
StackGAN 第二阶段的损失
与任何其他 GAN 相似,第二阶段 GAN 中的生成器G
和判别器D
也可以通过最大化判别器的损失并将生成器网络的损失最小化来训练 。
生成器损失l[G]
可以表示为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HHHAR54a-1681652906145)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/24684f0c-814c-4b33-bfe7-c177cfe19a46.png)]
前面的方程式非常不言自明。 它代表了判别器网络的损失函数,其中两个网络都以文本嵌入为条件。 一个主要区别是生成器网络以s[0]
和c_hat
作为输入,其中s[0]
是第一阶段生成的图像,c_hat
是 CA 变量。
判别器损失l[D]
可以表示为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pnDyMxQA-1681652906145)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/8d494e68-1020-471d-91de-e2d6acf9552c.png)]
前面的方程式也很容易解释。 它代表了生成器网络的损失函数,其中两个网络都以文本嵌入为条件。 它还包括对损失函数的 Kullback-Leibler(KL)发散项。
设置项目
如果尚未使用所有章节的完整代码克隆存储库,请立即克隆存储库。 下载的代码有一个名为Chapter06
的目录,其中包含本章的全部代码。 执行以下命令来设置项目:
- 首先,导航到父目录,如下所示:
cd Generative-Adversarial-Networks-Projects
- 现在,将目录从当前目录更改为
Chapter06
:
cd Chapter06
- 接下来,为该项目创建一个 Python 虚拟环境:
virtualenv venv virtualenv venv -p python3 # Create a virtual environment using python3 interpreter virtualenv venv -p python2 # Create a virtual environment using python2 interpreter
我们将为此项目使用此新创建的虚拟环境。 每章都有其自己单独的虚拟环境。
- 激活新创建的虚拟环境:
source venv/bin/activate
激活虚拟环境后,将在其中执行所有其他命令。
- 通过执行以下命令,安装
requirements.txt
文件中提供的所有库:
pip install -r requirements.txt
您可以参考 README.md
文件,以获取有关如何设置项目的更多说明。 开发人员经常会遇到依赖关系不匹配的问题。 为每个项目创建一个单独的虚拟环境将解决此问题。
在本节中,我们已成功设置项目并安装了所需的依赖项。 在下一节中,我们将处理数据集。
数据准备
在本节中,我们将使用 CUB 数据集,该数据集是不同鸟类的图像数据集,可以在以下链接中找到。 CUB 数据集包含 11,788 个高分辨率图像。 我们还将需要字符 CNN-RNN 文本嵌入,可以在以下链接中找到它们。 这些是预训练的文本嵌入。 按照以下几节中给出的说明下载和提取数据集。
下载数据集
可以从这里手动下载CUB
数据集。 另外,我们可以执行以下命令来下载数据集:
wget http://www.vision.caltech.edu/visipedia-data/CUB-200-2011/CUB_200_2011.tgz
下载数据集后,我们可以将其提取并放在data/birds/
目录中。
提取数据集
CUB
数据集是压缩文件,需要提取。 使用以下命令提取CUB
数据集:
tar -xvzf CUB_200_2011.tgz
使用以下命令提取字符 CNN-RNN 嵌入:
unzip birds.zip
最后,将CUB_200_2011
放在data/birds
目录中。 现在可以使用我们的数据集了。
探索数据集
CUB 数据集总共包含 200 种不同鸟类的 11,788 张图像。 CUB 数据集中的图像包括以下内容:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-09QRcWKe-1681652906145)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/65c94f59-5ff4-47de-91ea-301d83e34811.png)]
这四张图片显示了黑脚信天翁,长尾小鹦鹉,bobolink 和 Brandt’s cormorant。
在设计网络之前,了解数据集非常重要。 确保您仔细浏览 CUB 数据集中的图像。
StackGAN 的 Keras 实现
StackGAN 的 Keras 实现分为两部分:第一阶段和第二阶段。 我们将在以下各节中实现这些阶段。
第一阶段
第一阶段 StackGAN 包含生成器网络和判别器网络。 它还具有一个文本编码器网络和一个条件增强网络(CA 网络),下面将对此进行详细说明。 生成器网络获取文本条件变量(c_hat[0]
)以及噪声向量(x
)。 经过一组上采样层后,它会生成大小为64x64x3
的低分辨率图像。 判别器网络拍摄此低分辨率图像,并尝试识别图像是真实的还是伪造的。 生成器网络是具有一组下采样层的网络,其后是连接,然后是分类层。 在以下各节中,我们将详细探讨 StackGAN 的架构。
第一阶段 StackGAN 网络中使用的网络如下:
- 文本编码器网络
- 条件增强网络
- 生成器网络
- 判别器网络
但是,在开始编写实现之前,请创建一个 Python 文件 main.py
,然后按如下所示导入基本模块:
import os import pickle import random import time import PIL import numpy as np import pandas as pd import tensorflow as tf from PIL import Image from keras import Input, Model from keras import backend as K from keras.callbacks import TensorBoard from keras.layers import Dense, LeakyReLU, BatchNormalization, ReLU, Reshape, UpSampling2D, Conv2D, Activation, \ concatenate, Flatten, Lambda, Concatenate from keras.optimizers import Adam from keras_preprocessing.image import ImageDataGenerator from matplotlib import pyplot as plt
文字编码器网络
文本编码器网络的唯一目的是将文本描述(t
)转换为文本嵌入(φ[t]
)。 该网络将句子编码为 1,024 维文本嵌入。 我们已经下载了预训练的字符 CNN-RNN 文本嵌入。 我们将使用它们来训练我们的网络。
条件增强网络
CA 网络的目的是将文本嵌入向量(φ[t]
)转换为条件潜在变量(c_hat[0]
)。 在 CA 网络中,文本嵌入向量穿过具有非线性的完全连接层,从而产生均值μ(φ[t])
和对角协方差矩阵∑(φ[t])
。
以下代码显示了如何创建 CA 网络:
- 首先创建一个具有 256 个节点的完整连接层,并使用
LeakyReLU
作为激活函数:
input_layer = Input(shape=(1024,)) x = Dense(256)(input_layer) mean_logsigma = LeakyReLU(alpha=0.2)(x)
输入形状为(batch_size
,1024
),输出形状为(batch_size
,256
)。
- 接下来,将
mean_logsigma
分为mean
和log_sigma
张量:
mean = x[:, :128] log_sigma = x[:, 128:]
此操作将创建两个张量的张量(batch_size
,128
)和(batch_size
和128
)。
- 接下来,使用以下代码计算文本条件变量。 有关如何生成文本条件变量的更多信息,请参见“StackGAN 架构”小节中的“条件增强(CA)块”部分:
stddev = K.exp(log_sigma) epsilon = K.random_normal(shape=K.constant((mean.shape[1], ), dtype='int32')) c = stddev * epsilon + mean
这将产生一个张量为(batch_size
,128
)的张量,这是我们的文本条件变量。 CA 网络的完整代码如下:
def generate_c(x): mean = x[:, :128] log_sigma = x[:, 128:] stddev = K.exp(log_sigma) epsilon = K.random_normal(shape=K.constant((mean.shape[1], ), dtype='int32')) c = stddev * epsilon + mean return c
条件块的整个代码如下所示:
def build_ca_model(): input_layer = Input(shape=(1024,)) x = Dense(256)(input_layer) mean_logsigma = LeakyReLU(alpha=0.2)(x) c = Lambda(generate_c)(mean_logsigma) return Model(inputs=[input_layer], outputs=[c])
在代码前面的中,build_ca_model()
方法创建一个 Keras 模型,其中具有一个完全连接的层并且以LeakyReLU
作为激活函数。
生成器网络
生成器网络是条件生成对抗网络(CGAN)。 我们将要创建的生成器网络以文本条件变量为条件。 它采用从潜在空间采样的随机噪声向量,并生成形状为64x64x3
的图像。
让我们从编写生成器网络的代码开始:
- 首先创建一个输入层,以将输入(噪声变量)馈送到网络:
input_layer2 = Input(shape=(100, ))
- 接下来,将文本条件变量与噪声变量沿维度 1 连接:
gen_input = Concatenate(axis=1)([c, input_layer2])
此处,c
是文本条件变量。 在上一步中,我们编写了代码来生成文本条件变量,gen_input
将成为我们对生成器网络的输入。
- 接下来,创建具有
128
84*4 (16,384)
节点的dense layer
和ReLU
激活层,如下所示:
x = Dense(128 * 8 * 4 * 4, use_bias=False)(gen_input) x = ReLU()(x)
- 之后,将最后一层的输出重塑为大小为
(batch_size, 4, 4, 128*8)
的张量:
x = Reshape((4, 4, 128 * 8), input_shape=(128 * 8 * 4 * 4,))(x)
该操作将二维张量整形为二维张量。
- 接下来,创建一个二维向上采样卷积块。 该块包含一个上采样层,一个卷积层和一个批归一化层。 批量规范化后,使用
ReLU
作为此块的激活函数:
x = UpSampling2D(size=(2, 2))(x) x = Conv2D(512, kernel_size=3, padding="same", strides=1, use_bias=False)(x) x = BatchNormalization()(x) x = ReLU()(x)
- 之后,再创建三个 3D 上采样卷积块,如下所示:
x = UpSampling2D(size=(2, 2))(x) x = Conv2D(256, kernel_size=3, padding="same", strides=1, use_bias=False)(x) x = BatchNormalization()(x) x = ReLU()(x) x = UpSampling2D(size=(2, 2))(x) x = Conv2D(128, kernel_size=3, padding="same", strides=1, use_bias=False)(x) x = BatchNormalization()(x) x = ReLU()(x) x = UpSampling2D(size=(2, 2))(x) x = Conv2D(64, kernel_size=3, padding="same", strides=1, use_bias=False)(x) x = BatchNormalization()(x) x = ReLU()(x)
- 最后,创建一个卷积层,它将生成一个低分辨率图像:
x = Conv2D(3, kernel_size=3, padding="same", strides=1, use_bias=False)(x) x = Activation(activation='tanh')(x)
- 现在,通过如下指定网络的输入和输出来创建 Keras 模型:
stage1_gen = Model(inputs=[input_layer, input_layer2], outputs=[x, mean_logsigma])
这里,x
将是模型的输出,其形状将是(batch_size, 64, 64, 3)
。
生成器网络的整个代码如下所示:
def build_stage1_generator(): """ Builds a generator model """ input_layer = Input(shape=(1024,)) x = Dense(256)(input_layer) mean_logsigma = LeakyReLU(alpha=0.2)(x) c = Lambda(generate_c)(mean_logsigma) input_layer2 = Input(shape=(100,)) gen_input = Concatenate(axis=1)([c, input_layer2]) x = Dense(128 * 8 * 4 * 4, use_bias=False)(gen_input) x = ReLU()(x) x = Reshape((4, 4, 128 * 8), input_shape=(128 * 8 * 4 * 4,))(x) x = UpSampling2D(size=(2, 2))(x) x = Conv2D(512, kernel_size=3, padding="same", strides=1, use_bias=False)(x) x = BatchNormalization()(x) x = ReLU()(x) x = UpSampling2D(size=(2, 2))(x) x = Conv2D(256, kernel_size=3, padding="same", strides=1, use_bias=False)(x) x = BatchNormalization()(x) x = ReLU()(x) x = UpSampling2D(size=(2, 2))(x) x = Conv2D(128, kernel_size=3, padding="same", strides=1, use_bias=False)(x) x = BatchNormalization()(x) x = ReLU()(x) x = UpSampling2D(size=(2, 2))(x) x = Conv2D(64, kernel_size=3, padding="same", strides=1, use_bias=False)(x) x = BatchNormalization()(x) x = ReLU()(x) x = Conv2D(3, kernel_size=3, padding="same", strides=1, use_bias=False)(x) x = Activation(activation='tanh')(x) stage1_gen = Model(inputs=[input_layer, input_layer2], outputs=[x, mean_logsigma]) return stage1_gen
此模型在单个网络中同时包含 CA 网络和生成器网络。 它需要两个输入并返回两个输出。 输入是文本嵌入和噪声变量,而输出是生成的图像和mean_logsigma
。
我们现在已经成功实现了生成器网络。 让我们进入判别器网络。
判别器网络
判别器网络是分类器网络。 它包含一组下采样层,并对给定图像是真实的还是伪造的进行分类。
让我们从编写网络代码开始:
- 首先创建一个输入层以将输入提供给网络:
input_layer = Input(shape=(64, 64, 3))
- 接下来,添加具有以下参数的二维卷积层:
- 过滤器:
64
- 核大小:
(4, 4)
- 步幅:
2
- 填充:
'same'
- 使用偏差:
False
- 激活:
LeakyReLU
,alpha=0.2
stage1_dis = Conv2D(64, (4, 4), padding='same', strides=2, input_shape=(64, 64, 3), use_bias=False)(input_layer) stage1_dis = LeakyReLU(alpha=0.2)(stage1_dis)
- 之后,添加两个卷积层,每个卷积层之后是一个批量归一化层和一个
LeakyReLU
激活函数,具有以下参数:
- 过滤器:
128
- 核大小:
(4, 4)
- 步幅:
2
- 填充:
'same'
- 使用偏差:
False
- 激活:
LeakyReLU
,alpha=0.2
x = Conv2D(128, (4, 4), padding='same', strides=2, use_bias=False)(x) x = BatchNormalization()(x) x = LeakyReLU(alpha=0.2)(x)
- 接下来,再添加一个 2D 卷积层,然后添加批量规范化层和
LeakyReLU
激活函数,并具有以下参数:
- 过滤器:
256
- 核大小:
(4, 4)
- 步幅:
2
- 填充:
'same'
- 使用偏差:
False
- 激活:
LeakyReLU
,alpha=0.2
x = Conv2D(256, (4, 4), padding='same', strides=2, use_bias=False)(x) x = BatchNormalization()(x) x = LeakyReLU(alpha=0.2)(x)
- 之后,再添加一个 2D 卷积层,然后添加批量规范化层和 LeakyReLU 激活函数,并具有以下参数:
- 过滤器:
512
- 核大小:
(4, 4)
- 步幅:
2
- 填充:
'same'
- 使用偏差:
False
- 激活:
LeakyReLU
和alpha=0.2
x = Conv2D(512, (4, 4), padding='same', strides=2, use_bias=False)(x) x = BatchNormalization()(x) x = LeakyReLU(alpha=0.2)(x)
- 然后,创建另一个输入层以接收空间复制和压缩的文本嵌入:
input_layer2 = Input(shape=(4, 4, 128))
- 添加一个连接层以连接
x
和input_layer2
:
merged_input = concatenate([x, input_layer2])
- 之后,添加另一个 2D 卷积层,然后添加批量归一化层,并使用以下参数将
LeakyReLU
作为激活函数:
- 过滤器:
512
- 核大小:
1
- 步幅:
1
- 填充:
'same'
- 批量规范化:是
- 激活:
LeakyReLU
,alpha 0.2
x2 = Conv2D(64 * 8, kernel_size=1, padding="same", strides=1)(merged_input) x2 = BatchNormalization()(x2) x2 = LeakyReLU(alpha=0.2)(x2)
- 现在,展开张量并添加一个密集的分类器层:
# Flatten the tensor x2 = Flatten()(x2) # Classifier layer x2 = Dense(1)(x2) x2 = Activation('sigmoid')(x2)
- 最后,创建 Keras 模型:
stage1_dis = Model(inputs=[input_layer, input_layer2], outputs=[x2])
该模型输出输入图像属于真实类别或伪类别的概率。 判别器网络的完整代码如下:
def build_stage1_discriminator(): input_layer = Input(shape=(64, 64, 3)) x = Conv2D(64, (4, 4), padding='same', strides=2, input_shape=(64, 64, 3), use_bias=False)(input_layer) x = LeakyReLU(alpha=0.2)(x) x = Conv2D(128, (4, 4), padding='same', strides=2, use_bias=False)(x) x = BatchNormalization()(x) x = LeakyReLU(alpha=0.2)(x) x = Conv2D(256, (4, 4), padding='same', strides=2, use_bias=False)(x) x = BatchNormalization()(x) x = LeakyReLU(alpha=0.2)(x) x = Conv2D(512, (4, 4), padding='same', strides=2, use_bias=False)(x) x = BatchNormalization()(x) x = LeakyReLU(alpha=0.2)(x) input_layer2 = Input(shape=(4, 4, 128)) merged_input = concatenate([x, input_layer2]) x2 = Conv2D(64 * 8, kernel_size=1, padding="same", strides=1)(merged_input) x2 = BatchNormalization()(x2) x2 = LeakyReLU(alpha=0.2)(x2) x2 = Flatten()(x2) x2 = Dense(1)(x2) x2 = Activation('sigmoid')(x2) stage1_dis = Model(inputs=[input_layer, input_layer2], outputs=[x2]) return stage1_dis
该模型有两个输入和一个输出。 输入是低分辨率图像和压缩文本嵌入,而输出是概率。 既然我们已经成功地编写了判别器网络的实现,那么让我们创建对抗网络。
生成对抗网络项目:6~9(2)https://developer.aliyun.com/article/1426898