深度学习 Day 7——如何使用对抗网络生成手写数字?

本文介绍了如何利用深度学习中的生成对抗网络(GAN)来生成手写数字。作者详细阐述了每个步骤,包括构建生成器和判别器模型,设置训练参数,训练过程以及损失函数的绘制。通过30000个epoch的训练,最终生成的图像质量较高,展示了GAN在图像生成领域的应用。
摘要由CSDN通过智能技术生成

深度学习——Day 7 如何使用对抗网络生成手写数字?

一、前言

活动地址:CSDN21天学习挑战赛

时间过得好快,转眼已经到啦活动的最后一周时间了,在本周的时间内,我们来接着跟着博主一起学习有关生成对抗网络的知识,每一周一个新内容,等后续21天学习挑战赛之后,我还会自行抽时间去学习有关深度学习方面的知识,到时候继续更新我的学习专栏,只是可能没有每周三篇这么高效了,哈哈哈。

后面的事我们后面再说,本文我们将使用GAN模型来实现手写数字的生成。

这是我的学习专栏:Python深度学习专栏

期待着你们的关注,谢谢!!!

废话不多说,我们开始最后一周的学习之旅叭!

二、我的环境

  • 电脑系统:Windows 11
  • 语言环境:Python 3.8
  • 编译器:DataSpell 2022
  • 深度学习环境:TensorFlow 2.3.0

这次使用的编译器跟之前的不一样了,我这次使用的是JetBrains公司在去年研发的新的IDE,这个IDE是专门为参与探索性数据分析和ML模型原型涉及的人员的编译器,我也是初次体验,并不是PyCharm不好了,而是我想试试这个新的IDE,两个编译器都可以。

给你们看看界面:

在这里插入图片描述

三、前期工作

1、导入库

导入库有助于预处理、转换和创建神经网络模型

import tensorflow as tf
from tensorflow.keras import layers, Sequential, Model

import matplotlib.pyplot as plt
import numpy as np
import pathlib

2、设置GPU

前面很多期博客也已经说过啦,如果是CPU可以忽略这部分代码,但推荐使用GPU,按自己实际情况来。

gpus = tf.config.list_physical_devices("GPU")

if gpus:
    tf.config.experimental.set_memory_growth(gpus[0], True)  #设置GPU显存用量按需使用
    tf.config.set_visible_devices([gpus[0]],"GPU")

3、定义训练参数

img_shape = (28, 28, 1)
latent_dim = 200
d_losses = []
g_losses = []
train(epochs=30000, batch_size=256, sample_interval=200)

四、构建生成器

对于生成器,我们需要输入一个n维向量,输出图片像素大小的图片,因此我们需要首先得到输入的向量,这里输入的向量我们将其视为携带输出的某些信息,比如说手写数字为数字几,手写的潦草程度等等。由于这里我们对于输出数字的具体信息不做要求,只要求其能够最大程度与真实手写数字相似,也就是能过骗过判别器就行。

def build_generator():
    """
    输入一串随机数字生成图片
    :return:模型噪声和图片样本
    """
    model = Sequential([
        layers.Dense(256, input_dim=latent_dim),
        layers.LeakyReLU(alpha=0.2),	# 激活函数
        layers.BatchNormalization(momentum=0.8),   # 归一化

        layers.Dense(512),
        layers.LeakyReLU(alpha=0.2),
        layers.BatchNormalization(momentum=0.8),

        layers.Dense(1024),
        layers.LeakyReLU(alpha=0.2),
        layers.BatchNormalization(momentum=0.8),

        layers.Dense(np.prod(img_shape), activation='tanh'),
        layers.Reshape(img_shape)
    ])

    noise = layers.Input(shape=(latent_dim,))
    img = model(noise)

    return Model(noise, img)

五、构建判别器

常见的判别器,输入图片,输出图片的真假标签,判别器和生成器一样,可以是任意的判别器模型。判别器还会返回概率,范围为[0,1],0表示假,1表示真。

def build_discriminator():
    """
    对输入的图片进行判别真假
    :return:模型图片和真实性
    """
    model = Sequential([
        layers.Flatten(input_shape=img_shape),
        layers.Dense(512),
        layers.LeakyReLU(alpha=0.2),
        layers.Dense(256),
        layers.LeakyReLU(alpha=0.2),
        layers.Dense(1, activation='sigmoid')
    ])

    img = layers.Input(shape=img_shape)
    validity = model(img)

    return Model(img, validity)

六、如何训练

生成器原理:通过判别器对其生成的图片进行判别,来实现提升

判别器原理:通过对输入的图片进行判别,从而达到提升的效果

在这里插入图片描述

# 创建判别器
discriminator = build_discriminator()

# 定义优化器
optimizer = tf.keras.optimizers.Adam(1e-4)
discriminator.compile(loss='binary_crossentropy',
                      optimizer=optimizer,
                      metrics=['accuracy'])

# 创建生成器
generator = build_generator()
gan_input = layers.Input(shape=(latent_dim,))
img = generator(gan_input)

# 在训练generate的时候不训练discriminator
discriminator.trainable = False

# 对生成的假图片进行预测
validity = discriminator(img)
combined = Model(gan_input, validity)
combined.compile(loss='binary_crossentropy', optimizer=optimizer)

七、训练模型

1、创建示例图像功能

创建一个从生成器生成随机样本网格并将它们保存到指定的文件夹的函数,简单的说就是,每隔一段时间保存它在某些时候创建的随机图像。

def sample_images(epoch):
    """
    保存样例图片
    """
    row, col = 4, 4
    noise = np.random.normal(0, 1, (row*col, latent_dim))
    gen_imgs = generator.predict(noise)

    fig, axs = plt.subplots(row, col)
    cnt = 0
    for i in range(row):
        for j in range(col):
            axs[i,j].imshow(gen_imgs[cnt, :,:,0], cmap='gray')
            axs[i,j].axis('off')
            cnt += 1
    fig.savefig("images/%05d.png" % epoch)
    plt.close()

2、训练判别器和生成器生成图像

现在我们开始训练判别器,让它对图像进行分类之后,我们创建一个与真实图像相同的随机噪声网格,并将其传递给生成器用来生成新图像,然后我们计算两个模型的损失值,并在生成的图像中,我们将标签作为一个传递,用它来欺骗判别器并检查它是不是能够将其判别为假。

def train(epochs, batch_size=128, sample_interval=50):
    # 加载数据
    (train_images,_), (_,_) = tf.keras.datasets.mnist.load_data()

    # 将图片标准化到 [-1, 1] 区间内
    train_images = (train_images - 127.5) / 127.5
    # 数据
    train_images = np.expand_dims(train_images, axis=3)

    # 创建标签
    true = np.ones((batch_size, 1))
    fake = np.zeros((batch_size, 1))

    # 进行循环训练
    for epoch in range(epochs):

        # 随机选择 batch_size 张图片
        idx = np.random.randint(0, train_images.shape[0], batch_size)
        imgs = train_images[idx]

        # 生成噪音
        noise = np.random.normal(0, 1, (batch_size, latent_dim))
        # 生成器通过噪音生成图片,gen_imgs的shape为:(128, 28, 28, 1)
        gen_imgs = generator.predict(noise)

        # 训练鉴别器
        d_loss_true = discriminator.train_on_batch(imgs, true)
        d_loss_fake = discriminator.train_on_batch(gen_imgs, fake)
        # 返回loss值
        d_loss = 0.5 * np.add(d_loss_true, d_loss_fake)

        # 训练生成器
        noise = np.random.normal(0, 1, (batch_size, latent_dim))
        g_loss = combined.train_on_batch(noise, true)

        print ("%d [D loss: %f, acc.: %.2f%%] [G loss: %f]" % (epoch, d_loss[0], 100*d_loss[1], g_loss))

        # 保存样例图片
        if epoch % sample_interval == 0:
            sample_images(epoch)

我们训练了30000个epoch,我们可以自定义训练epoch,数量大一点更好,随之训练时间也会变长。

它运行的结果片段:

...
12017 [D loss: 0.670972, acc.: 56.64%] [G loss: 0.813901]
12018 [D loss: 0.665062, acc.: 59.18%] [G loss: 0.826996]
12019 [D loss: 0.681316, acc.: 55.66%] [G loss: 0.828379]
12020 [D loss: 0.660552, acc.: 58.98%] [G loss: 0.792503]
12021 [D loss: 0.670574, acc.: 58.79%] [G loss: 0.820962]
12022 [D loss: 0.673457, acc.: 58.20%] [G loss: 0.813309]
12023 [D loss: 0.671243, acc.: 59.96%] [G loss: 0.829150]
12024 [D loss: 0.671412, acc.: 58.59%] [G loss: 0.822964]
12025 [D loss: 0.681179, acc.: 58.59%] [G loss: 0.828419]
12026 [D loss: 0.698231, acc.: 55.08%] [G loss: 0.792044]
12027 [D loss: 0.661436, acc.: 57.81%] [G loss: 0.807470]
12028 [D loss: 0.675412, acc.: 56.45%] [G loss: 0.825793]
12029 [D loss: 0.681389, acc.: 58.40%] [G loss: 0.814193]
12030 [D loss: 0.692790, acc.: 55.66%] [G loss: 0.815262]
...

3、绘制损失函数图

我们已经完成了GAN的训练,我们来看看它能达到什么样的准确率。

plt.title('loss function chart')
plt.plot(g_losses, label='g_losses')
plt.plot(d_losses, label='d_losses')
plt.legend()
plt.show()

在这里插入图片描述

八、检查结果

在这里我们将所有生成的图像生成一个GIF动图,更能直观的展现它训练时图像生成的过程。

import imageio.v2 as imageio

def compose_gif():
    # 图片地址
    data_dir = "E:\深度学习\深度学习 Day7\images"
    data_dir = pathlib.Path(data_dir)
    paths = list(data_dir.glob('*'))

    gif_images = []
    for path in paths:
        print(path)
        gif_images.append(imageio.imread(path))
    imageio.mimsave("test.gif", gif_images, fps=2)

compose_gif()

本想给你们看动图的,但是最后生成的动图文件大小超过来CSDN的上传大小,所以我就给大家放几张图片看看:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

可以发现最后生成器创建的图像清晰度还不错。

九、最后我想说

经过一大片幅的介绍和学习,大家应该简单的了解到了GAN的流程,GAN是人工智能领域的一个新领域,GAN是一种能为机器提供想象力的技术,这项技术在未来时间会得到非常好的发展机会,我们一起来慢慢学习。

本周要学习的内容就是以上有关内容啦,后续我依旧会继续更新我在学习过程中遇见的困难以及有关一些GAN知识的简单总结,大家尽情期待,也希望得到大家的认可和赞扬,非常感谢!

最后,创作不易,你们的鼓励将是我创作最大的动力,期待你们的点赞收藏转发三连,以上内容如有错误之处还请大家为我指出,和大家共勉!

在这里插入图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-北天-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值