tensorflow实践---DCGAN深度卷积对抗生成网络

GAN(Generative Adversarial Network) : 生成对抗网络

        GAN是一种生成式模型,也是一种无监督学习模型。其最大的特点是为深度网络提供了一种对抗训练的方式,此方式有助于解决一些普通训练方式不容易解决的问题。GAN 主要包括了两个部分,即生成器 generator 与判别器 discriminator。生成器主要用来学习真实图像分布从而让自身生成的图像更加真实,以骗过判别器。判别器则需要对接收的图片进行真假判别。在整个过程中,生成器努力地让生成的图像更加真实,而判别器则努力地去识别出图像的真假,这个过程相当于一个二人博弈,随着时间的推移,生成器和判别器在不断地进行对抗,最终两个网络达到了一个动态均衡:生成器生成的图像接近于真实图像分布,而判别器识别不出真假图像,对于给定图像的预测为真的概率基本接近 0.5(相当于随机猜测类别)。

DCGAN(Deep Convolutional GAN):深度卷积生成对抗网络

生成模型和判别模型都运用了深度卷积 神经网络的生成对抗网络。DCGAN的发明者想到能不能把卷积神经网络反一反,用于生成图像。Generator(生成网络) 利用了类似反卷积的神经网络模型,Discriminator(判别网络) 利用了卷积的神经网络模型。

代码分为以下三块:

1.构建网络(network.py)

import tensorflow as tf

# Hyper parameter(超参数)
EPOCHS = 100
BATCH_SIZE = 128
LEARNING_RATE = 0.0002
BETA_1 = 0.5


# 定义判别器模型
def discriminator_model():
    model = tf.keras.models.Sequential()

    model.add(tf.keras.layers.Conv2D(
        64,  # 64 个过滤器,输出的深度(depth)是 64
        (5, 5),  # 过滤器在二维的大小是(5 * 5)
        padding='same',  # same 表示输出的大小不变,因此需要在外围补零2圈
        input_shape=(64, 64, 3)  # 输入形状 [64, 64, 3]。3 表示 RGB 三原色
    ))
    model.add(tf.keras.layers.Activation("tanh"))  # 添加 Tanh 激活层
    model.add(tf.keras.layers.MaxPool2D(pool_size=(2, 2)))  # 池化层
    model.add(tf.keras.layers.Conv2D(128, (5, 5)))
    model.add(tf.keras.layers.Activation("tanh"))
    model.add(tf.keras.layers.MaxPool2D(pool_size=(2, 2)))
    model.add(tf.keras.layers.Conv2D(128, (5, 5)))
    model.add(tf.keras.layers.Activation("tanh"))
    model.add(tf.keras.layers.MaxPool2D(pool_size=(2, 2)))
    model.add(tf.keras.layers.Flatten())  # 扁平化
    model.add(tf.keras.layers.Dense(1024))  # 1024 个神经元的全连接层
    model.add(tf.keras.layers.Activation("tanh"))
    model.add(tf.keras.layers.Dense(1))  # 1 个神经元的全连接层
    model.add(tf.keras.layers.Activation("sigmoid"))  # 添加 Sigmoid 激活层

    return model


# 定义生成器模型
# 从随机数来生成图片
def generator_model():
    model = tf.keras.models.Sequential()
    # 输入的维度是 100, 输出维度(神经元个数)是1024 的全连接层
    model.add(tf.keras.layers.Dense(input_dim=100, units=1024))
    model.add(tf.keras.layers.Activation("tanh"))
    model.add(tf.keras.layers.Dense(128 * 8 * 8))  # 8192 个神经元的全连接层
    model.add(tf.keras.layers.BatchNormalization())  # 批标准化
    model.add(tf.keras.layers.Activation("tanh"))
    model.add(tf.keras.layers.Reshape((8, 8, 128), input_shape=(128 * 8 * 8, )))  # 8 x 8 像素
    model.add(tf.keras.layers.UpSampling2D(size=(2, 2)))  # 16 x 16像素
    model.add(tf.keras.layers.Conv2D(128, (5, 5), padding="same"))
    model.add(tf.keras.layers.Activation("tanh"))
    model.add(tf.keras.layers.UpSampling2D(size=(2, 2)))  # 32 x 32像素
    model.add(tf.keras.layers.Conv2D(128, (5, 5), padding="same"))
    model.add(tf.keras.layers.Activation("tanh"))
    model.add(tf.keras.layers.UpSampling2D(size=(2, 2)))  # 64 x 64像素
    model.add(tf.keras.layers.Conv2D(3, (5, 5), padding="same"))
    model.add(tf.keras.layers.Activation("tanh"))

    return model


# 构造一个 Sequential 对象,包含一个 生成器 和一个 判别器
# 输入 -> 生成器 -> 判别器 -> 输出
def generator_containing_discriminator(generator, discriminator):
    model = tf.keras.models.Sequential()
    model.add(generator)
    discriminator.trainable = False  # 初始时 判别器 不可被训练
    model.add(discriminator)
    return model
2.训练网络(train.py)
import os
import glob
import numpy as np
from scipy import misc
import tensorflow as tf

from network import *


def train():
    # 确保包含所有图片的 images 文件夹在所有 Python 文件的同级目录下
    # 当然了,你也可以自定义文件夹名和路径
    if not os.path.exists("images"):
        raise Exception("包含所有图片的 images 文件夹不在此目录下,请添加")

    # 获取训练数据
    data = []
    for image in glob.glob("images/*"):
        image_data = misc.imread(image)  # imread 利用 PIL 来读取图片数据
        data.append(image_data)
    input_data = np.array(data)

    # 将数据标准化成 [-1, 1] 的取值, 这也是 Tanh 激活函数的输出范围
    # 像素值最大255 减去一半127.5 再除以 127.5 被限制到-1到1之间。
    input_data = (input_data.astype(np.float32) - 127.5) / 127.5

    # 构造 生成器 和 判别器
    g = generator_model()
    d = discriminator_model()

    # 构建 生成器 和 判别器 组成的网络模型
    d_on_g = generator_containing_discriminator(g, d)

    # 优化器用 Adam Optimizer
    g_optimizer = tf.keras.optimizers.Adam(lr=LEARNING_RATE, beta_1=BETA_1)
    d_optimizer = tf.keras.optimizers.Adam(lr=LEARNING_RATE, beta_1=BETA_1)

    # 配置 生成器 和 判别器
    g.compile(loss="binary_crossentropy", optimizer=g_optimizer)
    d_on_g.compile(loss="binary_crossentropy", optimizer=g_optimizer)
    d.trainable = True
    d.compile(loss="binary_crossentropy", optimizer=d_optimizer)

    # 开始训练
    for epoch in range(EPOCHS):
        for index in range(int(input_data.shape[0] / BATCH_SIZE)):
            input_batch = input_data[index * BATCH_SIZE: (index + 1) * BATCH_SIZE]

            # 连续型均匀分布的随机数据(噪声)
            random_data = np.random.uniform(-1, 1, size=(BATCH_SIZE, 100))
            # 生成器 生成的图片数据
            generated_images = g.predict(random_data, verbose=0)

            input_batch = np.concatenate((input_batch, generated_images))
            output_batch = [1] * BATCH_SIZE + [0] * BATCH_SIZE

            # 训练 判别器,让它具备识别不合格生成图片的能力
            d_loss = d.train_on_batch(input_batch, output_batch)

            # 当训练 生成器 时,让 判别器 不可被训练
            d.trainable = False

            # 重新生成随机数据。很关键
            random_data = np.random.uniform(-1, 1, size=(BATCH_SIZE, 100))

            # 训练 生成器,并通过不可被训练的 判别器 去判别
            g_loss = d_on_g.train_on_batch(random_data, [1] * BATCH_SIZE)

            # 恢复 判别器 可被训练
            d.trainable = True

            # 打印损失
            print("Epoch {}, 第 {} 步, 生成器的损失: {:.3f}, 判别器的损失: {:.3f}".format(epoch, index, g_loss, d_loss))

        # 保存 生成器 和 判别器 的参数
        # 大家也可以设置保存时名称不同(比如后接 epoch 的数字),参数文件就不会被覆盖了
        if epoch % 10 == 9:
            g.save_weights("generator_weight", True)
            d.save_weights("discriminator_weight", True)


if __name__ == "__main__":
    train()

训练网络的部分结果如下:

3.生成网络

"""
用 DCGAN 的生成器模型 和 训练得到的生成器参数文件 来生成图片
"""

import numpy as np
from PIL import Image
import tensorflow as tf

from network import *


def generate():
    # 构造生成器
    g = generator_model()

    # 配置 生成器
    g.compile(loss="binary_crossentropy", optimizer=tf.keras.optimizers.Adam(lr=LEARNING_RATE, beta_1=BETA_1))

    # 加载训练好的 生成器 参数
    g.load_weights("generator_weight")

    # 连续型均匀分布的随机数据(噪声)
    random_data = np.random.uniform(-1, 1, size=(BATCH_SIZE, 100))

    # 用随机数据作为输入,生成器 生成图片数据
    images = g.predict(random_data, verbose=1)

    # 用生成的图片数据生成 PNG 图片
    for i in range(BATCH_SIZE):
        image = images[i] * 127.5 + 127.5
        Image.fromarray(image.astype(np.uint8)).save("image-%s.png" % i)


if __name__ == "__main__":
    generate()



 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 24
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值