生成对抗网络项目:1~5(3)https://developer.aliyun.com/article/1426894
配置判别器网络
在继续之前,让我们看一下判别器网络的架构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uV0IsSKA-1681652801321)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/0bbb9055-1c43-4f7d-a900-fdf515b6d068.png)]
上图给出了生成器网络架构的顶层概述。
如前所述,判别器网络是一个包含 10 层的 CNN(您可以根据需要向网络添加更多层)。 基本上,它会拍摄大小为64 x 64 x 3
的图像,使用 2D 卷积层对其进行下采样,然后将其传递到完全连接的层进行分类。 它的输出是对给定图像是伪图像还是真实图像的预测。 可以为 0 或 1;可以为 0。 如果输出为 1,则传递到判别器的图像是真实的;如果输出为 0,则传递的图像是伪图像。
让我们看一下判别器网络中的各层:
编号 | 层名称 | 配置 |
1. | 输入层 | input_shape=(batch_size, 64, 64, 3) ,output_shape=(batch_size, 64, 64, 3) |
2. | 2D 卷积层 | filters=128 ,kernel_size=(5, 5) ,strides=(1, 1) ,padding='valid' ,input_shape=(batch_size, 64, 64, 3) ,output_shape=(batch_size, 64, 64, 128) , activation='leakyrelu' ,leaky_relu_alpha=0.2 |
3. | 2D 最大池化 | pool_size=(2, 2) ,input_shape=(batch_size, 64, 64, 128) ,output_shape=(batch_size, 32, 32, 128) |
4. | 2D 卷积层 | filters=256 ,kernel_size=(3, 3) ,strides=(1, 1) ,padding='valid' ,input_shape=(batch_size, 32, 32, 128) ,output_shape=(batch_size, 30, 30, 256) , activation='leakyrelu' ,leaky_relu_alpha=0.2 |
5. | 2D 最大池化 | pool_size=(2, 2) ,input_shape=(batch_size, 30, 30, 256) ,output_shape=(batch_size, 15, 15, 256) |
6. | 2D 卷积层 | filters=512 ,kernel_size=(3, 3) ,strides=(1, 1) ,padding='valid' ,input_shape=(batch_size, 15, 15, 256) ,output_shape=(batch_size, 13, 13, 512) , activation='leakyrelu' ,leaky_relu_alpha=0.2 |
7. | 2D 最大池化 | pool_size=(2, 2) ,input_shape=(batch_size, 13, 13, 512) ,output_shape=(batch_size, 6, 6, 512) |
8. | 展开层 | input_shape=(batch_size, 6, 6, 512) ,output_shape=(batch_size, 18432) |
9. | 密集层 | neurons=1024 ,input_shape=(batch_size, 18432) ,output_shape=(batch_size, 1024) ,activation='leakyrelu' ,'leakyrelu_alpha'=0.2 |
10. | 密集层 | neurons=1 ,input_shape=(batch_size, 1024) ,output_shape=(batch_size, 1) ,activation='sigmoid' |
L 等人研究了张量如何从第一层流到最后一层。 下图显示了不同层的输入和输出形状:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uAIlExaG-1681652801326)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/9a5468ed-810e-429c-8a0a-af8eb1d673b0.png)]
该配置对具有 TensorFlow 后端和channels_last
格式的 Keras API 有效。
设置项目
我们已经克隆/下载了所有章节的完整代码。 下载的代码包含一个名为Chapter04
的目录,该目录包含本章的全部代码。 执行以下命令来设置项目:
- 首先,导航到父目录,如下所示:
cd Generative-Adversarial-Networks-Projects
- 现在,将目录从当前目录更改为
Chapter04
:
cd Chapter04
- 接下来,为该项目创建一个 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
文件,以获取有关如何设置项目的更多说明。 开发人员经常会遇到依赖关系不匹配的问题。 为每个项目创建一个单独的虚拟环境将解决此问题。
在本节中,我们已成功设置项目并安装了所需的依赖项。 在下一部分中,我们将使用数据集,包括下载和清理数据集。
下载并准备动漫角色数据集
要训练 DCGAN 网络,我们需要一个动漫人物数据集,其中包含人物的裁剪面孔。 收集数据集有多种方法。 我们可以使用公开可用的数据集,也可以抓取一个,只要不违反网站的抓取策略即可。 在本章中,我们将仅出于教育和演示目的刮取图像。 我们使用名为 gallery-dl
的搜寻器工具从 pixiv.net
抓取了图像。 这是一个命令行工具,可用于从网站下载图像集,例如 pixiv.net,exhentai.org,danbooru.donmai.us 和更多。 它可通过以下链接获得。
下载数据集
在本节中,我们将介绍安装依赖项和下载数据集所需的不同步骤。 在执行以下命令之前,激活为此项目创建的虚拟环境:
- 执行以下命令安装
gallery-dl
:
pip install --upgrade gallery-dl
- 或者,您可以使用以下命令安装
gallery-dl
的最新开发版本:
pip install --upgrade https://github.com/mikf/gallery-dl/archive/master.zip
- 如果上述命令不起作用,请按照官方存储库中的说明进行操作:
# Official gallery-dl Github repo https://github.com/mikf/gallery-dl
- 最后,执行以下命令以使用
gallery-dl.
从danbooru.donmai.us
下载图像:
gallery-dl https://danbooru.donmai.us/posts?tags=face
下载图像需要您自担风险。 所提供的信息仅用于教育目的,我们不支持非法刮取。 我们没有图像的版权,因为图像由其各自所有者托管。 出于商业目的,请联系网站的各自所有者或您所使用的内容。
探索数据集
在裁剪或调整图像大小之前,请查看下载的图像:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SRwTHOso-1681652801326)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/503cd7f0-4105-49a5-9095-d400768e7eb9.png)]
如您所见,有些图像还包含其他身体部位,我们在训练图像中不需要这些部位。 在下一部分中,我们将仅从这些图像中裁剪出人脸。 此外,我们会将所有图像调整为训练所需的大小。
裁剪数据集中的图像并调整其大小
在本节中,我们将从图像中裁剪出面孔。 我们将使用python-animeface
从图像中裁剪出面孔。 这是一个开源 GitHub 存储库,可从命令行的图像中自动裁剪人脸。 它可以通过以下链接公开获得。
执行以下步骤来裁剪图像并调整其大小:
- 首先,下载
python-animeface
:
pip install animeface
- 接下来,导入任务所需的模块:
import glob import os import animeface from PIL import Image
- 接下来,定义参数:
total_num_faces = 0
- 接下来,遍历所有图像以进行裁剪并一一调整其大小:
for index, filename in enumerate(glob.glob('/path/to/directory/containing/images/*.*')):
- 在循环内,打开当前图像并检测其中的人脸:
try: # Open image im = Image.open(filename) # Detect faces faces = animeface.detect(im) except Exception as e: print("Exception:{}".format(e)) continue
- 接下来,获取图像中检测到的人脸坐标:
fp = faces[0].face.pos # Get coordinates of the face detected in the image coordinates = (fp.x, fp.y, fp.x+fp.width, fp.y+fp.height)
- 现在,将人脸裁剪出图像:
# Crop image cropped_image = im.crop(coordinates)
- 接下来,将裁剪后的人脸图像调整为
(64, 64)
的大小:
# Resize image cropped_image = cropped_image.resize((64, 64), Image.ANTIALIAS)
- 最后,将裁剪并调整大小的图像保存到所需目录:
cropped_image.save("/path/to/directory/to/store/cropped/images/filename.png"))
包装在 Python 函数中的完整代码如下所示:
import glob import os import animeface from PIL import Image total_num_faces = 0 for index, filename in enumerate(glob.glob('/path/to/directory/containing/images/*.*')): # Open image and detect faces try: im = Image.open(filename) faces = animeface.detect(im) except Exception as e: print("Exception:{}".format(e)) continue # If no faces found in the current image if len(faces) == 0: print("No faces found in the image") continue fp = faces[0].face.pos # Get coordinates of the face detected in the image coordinates = (fp.x, fp.y, fp.x+fp.width, fp.y+fp.height) # Crop image cropped_image = im.crop(coordinates) # Resize image cropped_image = cropped_image.resize((64, 64), Image.ANTIALIAS) # Show cropped and resized image # cropped_image.show() # Save it in the output directory cropped_image.save("/path/to/directory/to/store/cropped/images/filename.png")) print("Cropped image saved successfully") total_num_faces += 1 print("Number of faces detected till now:{}".format(total_num_faces)) print("Total number of faces:{}".format(total_num_faces))
前面的脚本将从包含下载图像的文件夹中加载所有图像,使用python-animeface
库检测人脸,然后从初始图像中裁剪出人脸。 然后,裁切后的图像将被调整为64 x 64
的大小。如果要更改图像的大小,请相应地更改生成器和判别器的架构。 我们现在准备在我们的网络上工作。
使用 Keras 实现 DCGAN
在本节中,我们将在 Keras 框架中编写 DCGAN 的实现。 Keras 是一个使用 TensorFlow 或 Teano 作为后端的元框架。 它提供了用于神经网络的高级 API。 与低级框架(如 TensorFlow)相比,它还具有预构建的神经网络层,优化器,正则化器,初始化器和数据预处理层,可轻松进行原型制作。 让我们开始编写生成器网络的实现。
生成器
如 DCGAN 部分的“架构”中所述,生成器网络由一些 2D 卷积层,上采样层,整形层和批归一化层组成 。 在 Keras 中,每个操作都可以指定为一个层。 甚至激活函数也是 Keras 中的层,可以像正常的密集层一样添加到模型中。
执行以下步骤来创建生成器网络:
- 让我们开始创建一个
Sequential
Keras 模型:
gen_model = Sequential()
- 接下来,添加一个具有 2,048 个节点的密集层,然后添加一个激活层
tanh
:
gen_model.add(Dense(units=2048)) gen_model.add(Activation('tanh'))
- 接下来,添加第二层,它也是一个具有 16,384 个神经元的密集层。 接下来是
batch normalization
层,其中default hyperparameters
和tanh
作为激活函数:
gen_model.add(Dense(256`8`8)) gen_model.add(BatchNormalization()) gen_model.add(Activation('tanh'))
第二密集层的输出是大小为16384
的张量。 此处,(256, 8, 8)
是密集层中神经元的数量。
- 接下来,向网络中添加一个重塑层,以将张量从最后一层重塑为(
batch_size, 8, 8, 256
)**:**形状的张量
# Reshape layer gen_model.add(Reshape((8, 8, 256), input_shape=(256`8`8,)))
- 接下来,添加 2D 上采样层以将形状从
(8, 8, 256)
更改为(16, 16, 256)
。 上采样大小为(2, 2)
,这将张量的大小增加到其原始大小的两倍。 在这里,我们有 256 个张量为16 x 16
:的张量。
gen_model.add(UpSampling2D(size=(2, 2)))
- 接下来,添加一个 2D 卷积层。 这使用指定数量的过滤器在张量上应用 2D 卷积。 在这里,我们使用 64 个过滤器和一个
(5, 5)
形状的内核:
gen_model.add(Conv2D(128, (5, 5), padding='same')) gen_model.add(Activation('tanh'))
- 接下来,添加 2D 向上采样层以将张量的形状从
(batch_size, 16, 16, 64)
更改为(batch_size, 32, 32, 64)
:
gen_model.add(UpSampling2D(size=(2, 2)))
2D 上采样层将张量的行和列分别以[0]
和[1]
的大小重复 。
- 接下来,在第二个 2D 卷积层上添加
64
过滤器和,将(5, 5)
的核大小tanh
作为激活函数:
gen_model.add(Conv2D(64, (5, 5), padding='same')) gen_model.add(Activation('tanh'))
- 接下来,添加 2D 上采样层,将形状从
(batch_size, 32, 32, 64)
更改为(batch_size, 64, 64, 64)
:
gen_model.add(UpSampling2D(size=(2, 2)))
- 最后,在第三个 2D 卷积层上添加三个过滤器,核大小
(5, 5)
,然后是tanh
作为激活函数:
gen_model.add(Conv2D(3, (5, 5), padding='same')) gen_model.add(Activation('tanh'))
生成器网络将输出(batch_size, 64, 64, 3)
形状的张量。 这批张量中的一个图像张量类似于具有三个通道的大小为64 x 64
的图像: 红色,绿色和蓝色(RGB)。
用 Python 方法包装的生成器网络的完整代码如下所示:
def get_generator(): gen_model = Sequential() gen_model.add(Dense(input_dim=100, output_dim=2048)) gen_model.add(LeakyReLU(alpha=0.2)) gen_model.add(Dense(256 * 8 * 8)) gen_model.add(BatchNormalization()) gen_model.add(LeakyReLU(alpha=0.2)) gen_model.add(Reshape((8, 8, 256), input_shape=(256 * 8 * 8,))) gen_model.add(UpSampling2D(size=(2, 2))) gen_model.add(Conv2D(128, (5, 5), padding='same')) gen_model.add(LeakyReLU(alpha=0.2)) gen_model.add(UpSampling2D(size=(2, 2))) gen_model.add(Conv2D(64, (5, 5), padding='same')) gen_model.add(LeakyReLU(alpha=0.2)) gen_model.add(UpSampling2D(size=(2, 2))) gen_model.add(Conv2D(3, (5, 5), padding='same')) gen_model.add(LeakyReLU(alpha=0.2)) return gen_model
现在我们已经创建了生成器网络,让我们开始创建判别器网络。
判别器
如 DCGAN 的架构中所述,判别器网络具有三个 2D 卷积层,每个层均具有激活函数,后跟两个最大合并层。 网络的尾部包含两个完全连接的(密集)层,用作分类层。 首先,让我们看一下判别器网络中的不同层:
- 所有卷积层都具有
LeakyReLU
作为激活函数,其alpha
值为 0.2 - 卷积层分别具有 128、256 和 512 个过滤器。 它们的核大小分别为
(5, 5)
,(3, 3)
和(3, 3)
。 - 在卷积层之后,我们有一个展开层,它将输入平坦化为一维张量。
- 此后,网络具有两个密集层,分别具有 1,024 个神经元和一个神经元。
- 第一密集层具有
LeakyReLU
作为激活函数,而第二层具有 Sigmoid 作为激活函数。 Sigmoid 激活用于二分类。 我们正在训练辨别器网络,以区分真实图像还是伪图像。
执行以下步骤来创建判别器网络:
- 让我们开始创建一个
Sequential
Keras 模型:
dis_model = Sequential()
- 添加一个 2D 卷积层,该层采用形状为
(64, 64, 3)
的输入图像。 该层的超参数如下。 另外,添加具有0.2
的alpha
值的LeakyReLU
作为激活函数:
- 过滤器:128
- 核大小:
(5, 5)
- 填充:相同
dis_model.add(Conv2D(filters=128, kernel_size=5, padding='same', input_shape=(64, 64, 3))) dis_model.add(LeakyReLU(alpha=0.2))
- 接下来,添加池大小为
(2, 2)
的 2D 最大池化层。 最大池用于对图像表示进行下采样,并通过在表示的非重叠子区域上使用最大过滤来应用它:
dis_model.add(MaxPooling2D(pool_size=(2, 2)))
来自第一层的输出张量的形状将为(batch_size, 32, 32, 128)
。
- 接下来,添加具有以下配置的另一个 2D 卷积层:
- 过滤器:256
- 核大小:
(3, 3)
- 激活函数:
LeakyReLU
,具有alpha
0.2 - 2D 最大池中的池大小:
(2, 2)
dis_model.add(Conv2D(filters=256, kernel_size=3)) dis_model.add(LeakyReLU(alpha=0.2)) dis_model.add(MaxPooling2D(pool_size=(2, 2)))
该层的输出张量的形状将为 (batch_size, 30, 30, 256)
。
- 接下来,添加具有以下配置的第三个 2D 卷积层:
- 过滤器: 512
- 核大小:
(3, 3)
- 激活函数:
LeakyReLU
,带有alpha
0.2 - 2D 最大池中的池大小:
(2, 2)
dis_model.add(Conv2D(512, (3, 3))) dis_model.add(LeakyReLU(alpha=0.2)) dis_model.add(MaxPooling2D(pool_size=(2, 2)))
该层的输出张量的形状将为 (batch_size, 13, 13, 512)
。
- 接下来,添加一个展开层。 这将使输入变平而不影响批量大小。 它产生一个二维张量:
dis_model.add(Flatten())
来自平坦化层的张量的输出形状将为(batch_size, 18432,)
。
- 接下来,添加具有
1024
神经元和alpha
0.2 作为激活函数的LeakyReLU
的密集层:
dis_model.add(Dense(1024)) dis_model.add(LeakyReLU(alpha=0.2))
- 最后,添加带有一个神经元的密集层以进行二分类。 Sigmoid 函数最适合二分类,因为它给出了分类的可能性:
dis_model.add(Dense(1)) dis_model.add(Activation('tanh'))
网络将生成形状为(batch_size, 1)
的输出张量。 输出张量包含类的概率。
包裹在 Python 方法中的判别器网络的完整代码如下:
def get_discriminator(): dis_model = Sequential() dis_model.add( Conv2D(128, (5, 5), padding='same', input_shape=(64, 64, 3)) ) dis_model.add(LeakyReLU(alpha=0.2)) dis_model.add(MaxPooling2D(pool_size=(2, 2))) dis_model.add(Conv2D(256, (3, 3))) dis_model.add(LeakyReLU(alpha=0.2)) dis_model.add(MaxPooling2D(pool_size=(2, 2))) dis_model.add(Conv2D(512, (3, 3))) dis_model.add(LeakyReLU(alpha=0.2)) dis_model.add(MaxPooling2D(pool_size=(2, 2))) dis_model.add(Flatten()) dis_model.add(Dense(1024)) dis_model.add(LeakyReLU(alpha=0.2)) dis_model.add(Dense(1)) dis_model.add(Activation('sigmoid')) return dis_model
在本节中,我们已成功实现了判别器和生成器网络。 在下一部分中,我们将在“下载和准备动漫角色数据集”部分中准备的数据集上训练模型。
训练 DCGAN
同样,训练 DCGAN 类似于训练朴素 GAN 网络。 这是一个四步过程:
- 加载数据集。
- 构建和编译网络。
- 训练判别器网络。
- 训练生成器网络。
我们将在本节中一步一步地进行这些步骤。
让我们从定义变量和超参数开始:
dataset_dir = "/Path/to/dataset/directory/*.*" batch_size = 128 z_shape = 100 epochs = 10000 dis_learning_rate = 0.0005 gen_learning_rate = 0.0005 dis_momentum = 0.9 gen_momentum = 0.9 dis_nesterov = True gen_nesterov = True
在这里,我们为训练指定了不同的超参数。 现在,我们将看到如何为训练加载数据集。
加载样本
要训练 DCGAN 网络,我们需要将数据集加载到内存中,并且需要定义一种机制来加载成批的内存。 执行以下步骤以加载数据集:
- 首先加载所有裁剪,调整大小并保存在
cropped
文件夹中的图像。 正确指定目录的路径,以便glob.glob
方法可以创建其中所有文件的列表。 要读取图像,请使用scipy.misc
模块中的imread
方法。 以下代码显示了加载目录中所有图像的不同步骤:
# Loading images all_images = [] for index, filename in enumerate(glob.glob('/Path/to/cropped/images/directory/*.*')): image = imread(filename, flatten=False, mode='RGB') all_images.append(image)
- 接下来,为所有图像创建一个
ndarray
。 最终ndarray
的形状将为(total_num_images, 64, 64, 3)
。 此外,标准化所有图像:
# Convert to Numpy ndarray X = np.array(all_images) X = (X - 127.5) / 127.5
现在我们已经加载了数据集,接下来我们将看到如何构建和编译网络。
建立和编译网络
在本节中,我们将构建和编译训练所需的网络:
- 首先定义训练所需的优化器,如下所示:
# Define optimizers dis_optimizer = SGD(lr=dis_learning_rate, momentum=dis_momentum, nesterov=dis_nesterov) gen_optimizer = SGD(lr=gen_learning_rate, momentum=gen_momentum, nesterov=gen_nesterov)
- 接下来,创建生成器模型的实例,并编译生成器模型(编译将初始化权重参数,优化器算法,损失函数以及使用网络所需的其他必要步骤):
gen_model = build_generator() gen_model.compile(loss='binary_crossentropy', optimizer=gen_optimizer)
使用binary_crossentropy
作为生成器网络的loss
函数,并使用gen_optimizer
作为优化器。
- 接下来,创建判别模型的实例,并对其进行编译,如下所示:
dis_model = build_discriminator() dis_model.compile(loss='binary_crossentropy', optimizer=dis_optimizer)
同样,使用binary_crossentropy
作为判别器网络的损失函数,并使用dis_optimizer
作为优化器。
- 接下来,创建一个对抗模型。 一个对抗者将两个网络都包含在一个模型中。 对抗模型的架构如下:
- 输入 -> 生成器 -> 判别器 -> 输出
创建和编译对抗模型的代码如下:
adversarial_model = Sequential() adversarial_model.add(gen_model) dis_model.trainable = False adversarial_model.add(dis_model)
当我们训练该网络时,我们不想训练判别器网络,因此在将其添加到对抗模型之前,使其变为不可训练的。
编译对抗模型,如下所示:
adversarial_model.compile(loss='binary_crossentropy', optimizer=gen_optimizer)
使用binary_crossentropy
作为损失函数,使用gen_optimizer
作为对抗模型的优化器。
在开始训练之前,添加 TensorBoard 以可视化显示损失,如下所示:
tensorboard = TensorBoard(log_dir="logs/{}".format(time.time()), write_images=True, write_grads=True, write_graph=True) tensorboard.set_model(gen_model) tensorboard.set_model(dis_model)
我们将针对指定的迭代次数训练网络,因此创建一个应运行指定次数的循环。 在每个周期内,我们将在大小为 128 的微型批量上训练网络。 计算需要处理的批量数量:
for epoch in range(epcohs): print("Epoch is", epoch) number_of_batches = int(X.shape[0] / batch_size) print("Number of batches", number_of_batches) for index in range(number_of_batches):
现在,我们将仔细研究训练过程。 以下几点说明了 DCGAN 训练中涉及的不同步骤:
- 最初,这两个网络都是幼稚的并且具有随机权重。
- 训练 DCGAN 网络的标准过程是首先对一批样本进行判别器训练。
- 为此,我们需要假样本和真实样本。 我们已经有了真实的样本,因此现在需要生成伪样本。
- 要生成伪样本,请在均匀分布上创建形状为
(100, )
的潜向量。 将此潜向量馈入未经训练的生成器网络。 生成器网络将生成伪样本,我们将其用于训练判别器网络。 - 合并真实图像和伪图像以创建一组新的样本图像。 我们还需要创建一个标签数组:真实图像使用标签 1,伪图像使用标签 0。
训练判别器网络
执行以下步骤来训练判别器网络:
- 首先从正态分布中采样一批噪声向量,如下所示:
z_noise = np.random.normal(0, 1, size=(batch_size, z_shape))
要对值进行采样,请使用 Numpy 库中np.random
模块中的normal()
方法。
- 接下来,从所有图像集中采样一批真实图像:
image_batch = X[index * batch_size:(index + 1) * batch_size]
- 接下来,使用生成器网络生成一批伪图像:
generated_images = gen_model.predict_on_batch(z_noise)
- 接下来,创建真实标签和伪标签:
y_real = np.ones(batch_size) - np.random.random_sample(batch_size) * 0.2 y_fake = np.random.random_sample(batch_size) * 0.2
- 接下来,在真实图像和真实标签上训练判别器网络:
dis_loss_real = dis_model.train_on_batch(image_batch, y_real)
- 同样,在伪造图像和伪造标签上对其进行训练:
dis_loss_fake = dis_model.train_on_batch(generated_images, y_fake)
- 接下来,计算平均损失并将其打印到控制台:
d_loss = (dis_loss_real+dis_loss_fake)/2 print("d_loss:", d_loss)
到目前为止,我们一直在训练判别器网络。 在下一部分中,让我们训练生成器网络。
训练生成器网络
为了训练生成器网络,我们必须训练对抗模型。 当我们训练对抗模型时,它只训练生成器网络,而冻结判别器网络。 由于我们已经训练过判别器网络,因此我们不会对其进行训练。 执行以下步骤来训练对抗模型:
- 首先重新创建一批噪声向量。 从高斯/正态分布中采样以下噪声向量:
z_noise = np.random.normal(0, 1, size=(batch_size, z_shape))
- 接下来,对这批噪声向量训练对抗模型,如下所示:
g_loss = adversarial_model.train_on_batch(z_noise, [1] * batch_size)
我们在一批噪声向量和实数标签上训练对抗模型。 在这里,实数标签是一个所有值均等于 1 的向量。我们还在训练生成器,以欺骗判别器网络。 为此,我们为它提供一个向量,该向量的所有值均等于 1。在此步骤中,生成器将接收来自生成器网络的反馈,并相应地进行改进。
- 最后,将生成器损失打印到控制台以跟踪损失:
print("g_loss:", g_loss)
有一种被动的方法可以评估训练过程。 每 10 个周期后,生成伪造图像并手动检查图像质量:
if epoch % 10 == 0: z_noise = np.random.normal(0, 1, size=(batch_size, z_shape)) gen_images1 = gen_model.predict_on_batch(z_noise) for img in gen_images1[:2]: save_rgb_img(img, "results/one_{}.png".format(epoch))
这些图像将帮助您决定是继续训练还是尽早停止训练。 如果生成的高分辨率图像的质量良好,请停止训练。 或者继续训练,直到您的模型变好为止。
我们已经成功地在动画角色数据集上训练了 DCGAN 网络。 现在我们可以使用该模型生成动漫人物图像。
生成图像
为了生成图像,我们需要一个从潜在空间采样的噪声向量。 Numpy 有一种称为uniform()
的方法,可以根据均匀分布生成向量。 让我们看看如何在以下步骤中生成图像:
- 通过添加以下代码行,创建大小为
(batch_size, 100)
的噪声向量:
z_noise = np.random.normal(0, 1, size=(batch_size, z_shape))
- 然后,使用生成器模型的
predict_on_batch
方法生成图像。 将上一步中创建的噪声向量馈入其中:
gen_images = gen_model.predict_on_batch(z_noise)
- 现在我们已经生成了图像,通过添加以下代码行将其保存。 创建一个名为
results
的目录来存储生成的图像:
imsave('results/image_{}.jpg'.format(epoch),gen_images[0])
现在,您可以打开这些生成的图像以测量生成的模型的质量。 这是一种评估模型表现的被动方法。
保存模型
在 Keras 中保存模型只需要一行代码。 要保存生成器模型,请添加以下行:
# Specify the path for the generator model gen_model.save("directory/for/the/generator/model.h5")
同样,通过添加以下行来保存判别器模型:
# Specify the path for the discriminator model dis_model.save("directory/for/the/discriminator/model.h5")
可视化生成的图像
在将网络训练了 100 个时间段后,生成器将开始生成合理的图像。 让我们看一下生成的图像。
在 100 个周期之后,图像显示如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ybF9YUlh-1681652801327)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/bad2e9c8-167e-436b-9078-4fa53cffc0a2.png)]
在 200 个周期之后,图像显示如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CaseySAv-1681652801327)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/82a9152b-d3fb-467b-837f-96af60995452.png)]
要生成非常好的图像,请将网络训练 10,000 个周期。
可视化损失
为了可视化训练的损失,请按以下方式启动 TensorBoard 服务器:
tensorboard --logdir=logs
现在,在浏览器中打开localhost:6006
。 Tensorboard 的标量部分包含两种损失的图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ObBR232L-1681652801327)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/590d57c0-43e3-4ca8-ad30-8bd20887ecc5.png)]
这些图将帮助您决定是继续还是停止训练。 如果损失不再减少,您就可以停止训练,因为没有改善的机会。 如果损失持续增加,则必须停止训练。 使用超参数,然后选择一组您认为可以提供更好结果的超参数。 如果损失逐渐减少,请继续训练模型。
可视化图
Tensorboard 的GRAPHS
部分包含两个网络的图。 如果网络表现不佳,这些图可以帮助您调试网络。 它们还显示了每个图中的张量流和不同的操作:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LXsBK9yD-1681652801327)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/gan-proj/img/9bdd11ae-60a0-4d18-b9ba-9e9a46e9514f.png)]
调整超参数
超参数是模型的属性,在模型训练期间是固定的。 不同的参数可以具有不同的精度。 让我们看一下一些常用的超参数:
- 学习率
- 批量大小
- 周期数
- 生成器优化器
- 判别器优化器
- 层数
- 密集层中的单元数
- 激活函数
- 损失函数
在“使用 Keras 实现 DCGAN”的部分中,学习率是固定的:生成器模型为 0.0005,判别器模型为 0.0005。 批量大小为 128。调整这些值可能会导致我们创建更好的模型。 如果您的模型没有生成合理的图像,请尝试更改这些值,然后再次运行模型。
DCGAN 的实际应用
可以为不同的使用案例定制 DCGAN。 DCGAN 的各种实际应用包括:
- 动画角色的生成:目前,动画师使用计算机软件手动绘制字符,有时还绘制在纸上。 这是一个手动过程,通常需要很多时间。 使用 DCGAN,可以在更短的时间内生成新的动漫角色,从而改善了创作过程。
- 数据集的扩充:如果您想训练一个监督的机器学习模型,要训练一个好的模型,您将需要一个大的数据集。 DCGAN 可以通过扩展现有数据集来提供帮助,因此可以增加监督模型训练所需的数据集大小。
- MNIST 字符的生成:MNIST 数据集包含 60,000 张手写数字图像。 要训练复杂的监督学习模型,MNIST 数据集是不够的。 DCGAN 一旦受过训练,将生成可以添加到原始数据集中的新数字。
- 人脸生成:DCGAN 使用卷积神经网络,非常擅长生成逼真的图像。
- 特征提取器:训练后,可以使用判别器从中间层提取特征。 这些提取的特征在样式迁移和人脸识别等任务中很有用。 样式迁移涉及生成图像的内部表示,用于计算样式和内容损失。 请参阅以下论文,以了解有关样式迁移的更多信息。
总结
在本章中,我们介绍了深度卷积生成对抗网络。 我们从基本介绍 DCGAN 开始,然后深入探讨了 DCGAN 网络的架构。 之后,我们设置项目并安装必要的依赖项。 然后,我们研究了下载和准备数据集所需的不同步骤。 然后,我们准备了网络的 Keras 实现,并在我们的数据集中对其进行了训练。 经过训练后,我们将其用于生成新的动漫角色。 我们还探讨了 DCGAN 在实际用例中的不同应用。
在下一章中,我们将研究用于高分辨率图像生成的 SRGAN。
生成对抗网络项目:1~5(5)https://developer.aliyun.com/article/1426896