# 训练并预测

```import numpy as np
import paddle
import paddle.fluid as fluid
import matplotlib.pyplot as plt```

## 定义网络

```# 定义生成器
def Generator(y, name="G"):
def deconv(x, num_filters, filter_size=5, stride=2, dilation=1, padding=2, output_size=None, act=None):
return fluid.layers.conv2d_transpose(input=x,
num_filters=num_filters,
output_size=output_size,
filter_size=filter_size,
stride=stride,
dilation=dilation,
padding=padding,
act=act)
with fluid.unique_name.guard(name + "/"):
# 第一组全连接和BN层
y = fluid.layers.fc(y, size=2048)
y = fluid.layers.batch_norm(y)
# 第二组全连接和BN层
y = fluid.layers.fc(y, size=128 * 7 * 7)
y = fluid.layers.batch_norm(y)
# 进行形状变换
y = fluid.layers.reshape(y, shape=(-1, 128, 7, 7))
# 第一组转置卷积运算
y = deconv(x=y, num_filters=128, act='relu', output_size=[14, 14])
# 第二组转置卷积运算
y = deconv(x=y, num_filters=1, act='tanh', output_size=[28, 28])
return y```

```# 判别器 Discriminator
def Discriminator(images, name="D"):
# 定义一个卷积池化组
def conv_pool(input, num_filters, act=None):
return fluid.nets.simple_img_conv_pool(input=input,
filter_size=5,
num_filters=num_filters,
pool_size=2,
pool_stride=2,
act=act)

with fluid.unique_name.guard(name + "/"):
y = fluid.layers.reshape(x=images, shape=[-1, 1, 28, 28])
# 第一个卷积池化组
y = conv_pool(input=y, num_filters=64, act='leaky_relu')
# 第一个卷积池化加回归层
y = conv_pool(input=y, num_filters=128)
y = fluid.layers.batch_norm(input=y, act='leaky_relu')
# 第二个卷积池化加回归层
y = fluid.layers.fc(input=y, size=1024)
y = fluid.layers.batch_norm(input=y, act='leaky_relu')
# 最后一个分类器输出
y = fluid.layers.fc(input=y, size=1, act='sigmoid')
return y```

## 定义训练程序

```# 创建判别器D识别生成器G生成的假图片程序
train_d_fake = fluid.Program()
# 创建判别器D识别真实图片程序
train_d_real = fluid.Program()
# 创建生成器G生成符合判别器D的程序
train_g = fluid.Program()
# 创建共同的一个初始化的程序
startup = fluid.Program()
# 噪声维度
z_dim = 100```

```# 从Program获取prefix开头的参数名字
def get_params(program, prefix):
all_params = program.global_block().all_parameters()
return [t.name for t in all_params if t.name.startswith(prefix)]```

```# 训练判别器D识别真实图片
with fluid.program_guard(train_d_real, startup):
# 创建读取真实数据集图片的data，并且label为1
real_image = fluid.layers.data('image', shape=[1, 28, 28])
ones = fluid.layers.fill_constant_batch_size_like(real_image, shape=[-1, 1], dtype='float32', value=1)

# 判别器D判断真实图片的概率
p_real = Discriminator(real_image)
# 获取损失函数
real_cost = fluid.layers.sigmoid_cross_entropy_with_logits(p_real, ones)
real_avg_cost = fluid.layers.mean(real_cost)

# 获取判别器D的参数
d_params = get_params(train_d_real, "D")

# 创建优化方法
optimizer = fluid.optimizer.AdamOptimizer(learning_rate=2e-4)
optimizer.minimize(real_avg_cost, parameter_list=d_params)```

```# 训练判别器D识别生成器G生成的图片为假图片
with fluid.program_guard(train_d_fake, startup):
# 利用创建假的图片data，并且label为0
z = fluid.layers.data(name='z', shape=[z_dim, 1, 1])
zeros = fluid.layers.fill_constant_batch_size_like(z, shape=[-1, 1], dtype='float32', value=0)

# 判别器D判断假图片的概率
p_fake = Discriminator(Generator(z))

# 获取损失函数
fake_cost = fluid.layers.sigmoid_cross_entropy_with_logits(p_fake, zeros)
fake_avg_cost = fluid.layers.mean(fake_cost)

# 获取判别器D的参数
d_params = get_params(train_d_fake, "D")

# 创建优化方法
optimizer = fluid.optimizer.AdamOptimizer(learning_rate=2e-4)
optimizer.minimize(fake_avg_cost, parameter_list=d_params)```

```# 训练生成器G生成符合判别器D标准的假图片
with fluid.program_guard(train_g, startup):
# 噪声生成图片为真实图片的概率，Label为1
z = fluid.layers.data(name='z', shape=[z_dim, 1, 1])
ones = fluid.layers.fill_constant_batch_size_like(z, shape=[-1, 1], dtype='float32', value=1)

# 生成图片
fake = Generator(z)
# 克隆预测程序
infer_program = train_g.clone(for_test=True)

# 生成符合判别器的假图片
p = Discriminator(fake)

# 获取损失函数
g_cost = fluid.layers.sigmoid_cross_entropy_with_logits(p, ones)
g_avg_cost = fluid.layers.mean(g_cost)

# 获取G的参数
g_params = get_params(train_g, "G")

# 只训练G
optimizer = fluid.optimizer.AdamOptimizer(learning_rate=2e-4)
optimizer.minimize(g_avg_cost, parameter_list=g_params)```

## 训练并预测

```# 噪声生成
def z_reader():
while True:
yield np.random.normal(0.0, 1.0, (z_dim, 1, 1)).astype('float32')```

```# 读取MNIST数据集，不使用label
def mnist_reader(reader):
def r():
for img, label in reader():
yield img.reshape(1, 28, 28)
return r```

```# 显示图片
def show_image_grid(images, pass_id=None):
# fig = plt.figure(figsize=(5, 5))
# fig.suptitle("Pass {}".format(pass_id))
# gs = plt.GridSpec(8, 8)
# gs.update(wspace=0.05, hspace=0.05)

for i, image in enumerate(images[:64]):
# 保存生成的图片
plt.imsave("image/test_%d.png" % i, image[0])
# 以下代码在jupyter可用
#     ax = plt.subplot(gs[i])
#     plt.axis('off')
#     ax.set_xticklabels([])
#     ax.set_yticklabels([])
#     ax.set_aspect('equal')
#     plt.imshow(image[0], cmap='Greys_r')
# plt.show()```

```# 生成真实图片reader
mnist_generator = paddle.batch(
paddle.reader.shuffle(mnist_reader(paddle.dataset.mnist.train()), 30000), batch_size=128)
# 生成假图片的reader
z_generator = paddle.batch(z_reader, batch_size=128)()```

```# 创建执行器
# place = fluid.CPUPlace()
place = fluid.CUDAPlace(0)
exe = fluid.Executor(place)
# 初始化参数
exe.run(startup)```

```# 测试噪声数据
test_z = np.array(next(z_generator))```

```# 开始训练
for pass_id in range(5):
for i, real_image in enumerate(mnist_generator()):
# 训练判别器D识别生成器G生成的假图片
r_fake = exe.run(program=train_d_fake,
fetch_list=[fake_avg_cost],
feed={'z': np.array(next(z_generator))})

# 训练判别器D识别真实图片
r_real = exe.run(program=train_d_real,
fetch_list=[real_avg_cost],
feed={'image': np.array(real_image)})

# 训练生成器G生成符合判别器D标准的假图片
r_g = exe.run(program=train_g,
fetch_list=[g_avg_cost],
feed={'z': np.array(next(z_generator))})
print("Pass：%d，fake_avg_cost：%f, real_avg_cost：%f, g_avg_cost：%f" % (pass_id, r_fake[0][0], r_real[0][0], r_g[0][0]))

# 测试生成的图片
r_i = exe.run(program=infer_program,
fetch_list=[fake],
feed={'z': test_z})

# 显示生成的图片
show_image_grid(r_i[0], pass_id)```

# 参考资料

0 条评论

• ### 《PaddlePaddle从入门到炼丹》七——强化学习

本章介绍使用PaddlePaddle实现强化学习，通过自我学习，完成一个经典控制类的游戏，相关游戏介绍可以在Gym官网上了解。我们这次玩的是一个CartPole...

• ### 《PaddlePaddle从入门到炼丹》四——卷积神经网络

上一章我们通过学习线性回归例子入门了深度学习，同时也熟悉了PaddlePaddle的使用方式，那么我们在本章学习更有趣的知识点卷积神经网络。深度学习之所以那么流...

• ### 《PaddlePaddle从入门到炼丹》五——循环神经网络

除了卷积神经网络，深度学习中还有循环神经网络也是很常用的，循环神经网络更常用于自然语言处理任务上。我们在这一章中，我们就来学习如何使用PaddlePaddle来...

• ### 《PaddlePaddle从入门到炼丹》十三——自定义图像数生成

我们在第六章介绍了生成对抗网络，并使用生成对抗网络训练mnist数据集，生成手写数字图片。那么本章我们将使用对抗生成网络训练我们自己的图片数据集，并生成图片。在...

• ### 《PaddlePaddle从入门到炼丹》十四——把预测模型部署在服务器

如果读者使用过百度等的一些图像识别的接口，比如百度的细粒度图像识别接口，应该了解这个过程，省略其他的安全方面的考虑。这个接口大体的流程是，我们把图像上传到百度的...

• ### 《PaddlePaddle从入门到炼丹》三——线性回归

在第二章，我们已经学习了如何使用PaddlePaddle来进行加法计算，从这个小小的例子中，我们掌握了PaddlePaddle的使用方式。在本章中，我们将介绍使...

• ### 速成记｜安装PaddlePaddle到底分几步？

和哪个版本的PaddlePaddle可以牵手成功，首先对自己的“英雄”要足够了解，尤其是这三个硬性条件

• ### 《PaddlePaddle从入门到炼丹》二——计算1+1

在第一章介绍了PaddlePaddle的安装，接下来我们将介绍如何使用PaddlePaddle。PaddlePaddle是百度在2016年9月27日开源的一个深...

• ### GAN生成对抗网络入门介绍

GAN（Generative Adversarial Network）生成对抗网络，由Ian Goodfellow在2014年提出。

• ### 《PaddlePaddle从入门到炼丹》十二——自定义文本数据集分类

我们在第五章学习了循环神经网络，在第五章中我们使用循环神经网络实现了一个文本分类的模型，不过使用的数据集是PaddlePaddle自带的一个数据集，我们并没有了...

• ### 《PaddlePaddle从入门到炼丹》十——VisualDL 训练可视化

VisualDL是一个面向深度学习任务设计的可视化工具，包含了scalar、参数分布、模型结构、图像可视化等功能。可以这样说：“所见即所得”。我们可以借助Vis...

• ### 张东升，我知道是你！如何使用GAN做一个秃头生产器

最近一部电视剧《隐秘的角落》在网上引起了众多讨论，要说这是2020年全网热度最高的电视剧也不为过。而剧中反派Boss张东升也是网友讨论的话题之一，特别是他的秃头...

• ### 《PaddlePaddle从入门到炼丹》九——迁移学习

在深度学习训练中，例如图像识别训练，每次从零开始训练都要消耗大量的时间和资源。而且当数据集比较少时，模型也难以拟合的情况。基于这种情况下，就出现了迁移学习，通过...

• ### 如何用免费GPU学习AI算法？这篇算法资源大集锦别错过

上一次写了篇薅GPU百度AI Studio计算资源的文章，收到很多AI算法初学者私信，问我能不能补充一些AI Studio的学习资源。有求必应向来是我的风格，于...

• ### 从第一本书开始，如何成为深度学习工程师（上篇）

小编结合资料与工程师经验，梳理出一条深度学习工程师的成长路径及“练级大法”，希望可以帮到各位“炼丹师”稳步进阶，畅游深度学习海洋~

• ### 吾有一术，名曰炼丹。北大博士生用文言开发深度学习网络，还有Pytorch脚本

最近文言编程语言 / wenyan-lang火了——GitHub项目已经超过12.7K Stars。

• ### 实操|如何进阶深度学习工程师（下篇）

这里所定义的中阶选手，是深度学习理论基础扎实，实操方面尝试扩展深度学习更多应用场景的侠客。由此，从初阶→中阶，基本流程保持不变，变化的是每个步骤的深入程度。

• ### 生成型对抗性网络入门实战一波流

前几节用代码介绍了生成型对抗性网络的实现，但后来我觉得代码的实现七拐八弯，很多不必要的烦琐会增加读者的理解负担，于是花时间把代码进行强力精简，希望由此能帮助有需...