DCGAN--Keras实现

该文详细介绍了如何使用Keras构建和训练一个DeepConvolutionalGenerativeAdversarialNetwork(DCGAN),包括导入必要的库,定义模型输入维度,构建生成器和鉴别器的详细步骤,以及训练和显示生成图像的过程。重点讨论了生成器的卷积逆过程和鉴别器的图像分类结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一、Keras与tf.keras?

这个博客简单明了
前两篇文章可以看看,会通透很多。
Keras是一个高级API,不过如果我们想要自定义损失函数或者其他,只能使用Tensorflow来定义
tf,keras包含了所有Keras API,所以,我们最好还是使用tf.keras

二、keras中Model的使用

见此篇博客

三、使用Keras来实现DCGan

在这里使用的是Minst 手写数据集

我是在colab实现的,具体的版本如下:

1、导入必要的包

代码如下(示例):

%matplotlib inline
 
import matplotlib.pyplot as plt
import numpy as np
 
from keras.datasets import mnist
from keras.layers import Activation, BatchNormalization, Dense, Dropout, Flatten, Reshape
from keras.layers import LeakyReLU
from keras.layers.convolutional import Conv2D, Conv2DTranspose
from keras.models import Sequential
from keras.optimizers import Adam

2.指定模型输入维度:图像尺寸和噪声向量 的长度

代码如下(示例):

img_rows = 28
img_cols = 28
channels = 1
 
# 输入图像的维度
img_shape = (img_rows, img_cols, channels)
 
# 噪声向量Z的长度
z_dim = 100

3、构建生成器

解释:生成器其实是一个卷积的逆过程,卷积网络一般被用于图像分类中,在卷积的过程中,我们不断的减少宽高提升通道数,但是在生成器中,我们输入的是一个随机向量,我们需要让它最终输出一个图像,这里输出的是28**28*1的灰度图。
在这里插入图片描述
综合所有步骤如下。
(1)取一个随机噪声向量 ,通过全连接层将其重塑为7×7×256
张量。
(2)使用转置卷积,将7×7×256张量转换为14×14×128张量。
(3)应用批归一化和LeakyReLU激活函数。
(4)使用转置卷积,将14×14×128张量转换为14×14×64张
量。注意:宽度和高度尺寸保持不变。可以通过将
Conv2DTranspose中的stride参数设置为1来实现。
(5)应用批归一化和LeakyReLU激活函数。
(6)使用转置卷积,将14×14×64张量转换为输出图像大小
28×28×1。
(7)应用tanh激活函数。

def build_generator(z_dim):
   #序列化model
    model = Sequential()
 
    # 通过全连接层将输入重新调整大小7*7*256的张量
    model.add(Dense(256 * 7 * 7, input_dim=z_dim))
    model.add(Reshape((7, 7, 256)))
 
    # 通过转置卷积层将7*7*256的张量转换为14*14*128的张量
    model.add(Conv2DTranspose(128, kernel_size=3, strides=2, padding='same'))
 
    # 批归一化
    model.add(BatchNormalization())
 
    # Leaky ReLU 激活函数
    model.add(LeakyReLU(alpha=0.01))
 
    # 通过转置卷积层将14*14*128的张量转换为14*14*64的张量
    model.add(Conv2DTranspose(64, kernel_size=3, strides=1, padding='same'))
 
    # 批归一化
    model.add(BatchNormalization())
 
    # Leaky ReLU 激活函数
    model.add(LeakyReLU(alpha=0.01))
 
    # 通过转置卷积层将14*14*64的张量转换为28*28*1的张量
    model.add(Conv2DTranspose(1, kernel_size=3, strides=2, padding='same'))
 
    # 带有tanh激活函数的的输出层
    model.add(Activation('tanh'))
 
    return model

4、构造鉴别器

鉴别器与普通的卷积神经网络用来进行图像分类没什么区别,输入图像,输出一个值用来判断图像真伪。在这里插入图片描述

综合所有步骤如下。
(1)使用卷积层将28×28×1的输入图像转换为14×14×32的张
量。
(2)应用LeakyReLU激活函数。
(3)使用卷积层将14×14×32的张量转换为7×7×64的张量。
(4)应用批归一化和LeakyReLU激活函数。
(5)使用卷积层将7×7×64的张量转换为3×3×128的张量。
(6)应用批归一化和LeakyReLU激活函数。
(7)将3×3×128张量展成大小为3×3×128=1152的向量。
(8)使用全连接层,输入sigmoid激活函数计算输入图像是否真
实的概率。

def build_discriminator(img_shape):
 
    model = Sequential()
 
    # 通过卷积层将大小为28*28*1的张量转变为14*14*32的张量
    model.add(Conv2D(32, kernel_size=3,strides=2, input_shape=img_shape,padding='same'))
 
    # Leaky ReLU 激活函数
    model.add(LeakyReLU(alpha=0.01))
 
    # 通过卷积层将大小为14*14*32的张量转变为7*7*64的张量
    model.add(
        Conv2D(64,
               kernel_size=3,
               strides=2,
               input_shape=img_shape,
               padding='same'))
 
    # 批归一化
    model.add(BatchNormalization())
 
    # Leaky ReLU 激活函数
    model.add(LeakyReLU(alpha=0.01))
 
    # 通过卷积层将7*7*64的张量转变为3*3*128的张量
    model.add(
        Conv2D(128,
               kernel_size=3,
               strides=2,
               input_shape=img_shape,
               padding='same'))
 
    # 批归一化
    model.add(BatchNormalization())
 
    # Leaky ReLU 激活函数    
    model.add(LeakyReLU(alpha=0.01))
 
    # 带有sigmoid激活函数的输出层
    model.add(Flatten())
    model.add(Dense(1, activation='sigmoid'))
 
    return model

5、构建并编译DCGan

def build_gan(generator, discriminator):
    model = Sequential()
 
    # 将生成器和鉴定器结合到一起
    model.add(generator)
    model.add(discriminator)
 
    return model
# 构建并编译鉴定器(使用了二元交叉熵作为损失函数,Adam的优化算法)
discriminator = build_discriminator(img_shape)
discriminator.compile(loss='binary_crossentropy',
                      optimizer=Adam(),
                      metrics=['accuracy'])
 
# 构建生成器
generator = build_generator(z_dim)
 
# 在生成器训练的时候,将鉴定器的参数固定
discriminator.trainable = False
 
#构建并编译固定的鉴定器的GAN模型,并训练生成器
gan = build_gan(generator, discriminator)
gan.compile(loss='binary_crossentropy', optimizer=Adam())
# 在生成器训练的时候,将鉴定器的参数固定
discriminator.trainable = False
 
#构建并编译固定的鉴定器的GAN模型,并训练生成器
gan = build_gan(generator, discriminator)
gan.compile(loss='binary_crossentropy', optimizer=Adam())

6、对模型进行训练

losses = []
accuracies = []
iteration_checkpoints = []
 
 
def train(iterations, batch_size, sample_interval):
 
    # 导入mnist数据集
    (X_train, _), (_, _) = mnist.load_data()
 
    # 灰度像素值从[0,255]缩放到[-1, 1]
    X_train = X_train / 127.5 - 1.0
    X_train = np.expand_dims(X_train, axis=3)
 
    # 真实图像的标签都为1
    real = np.ones((batch_size, 1))
 
    # 假图像的标签都为0
    fake = np.zeros((batch_size, 1))
 
    for iteration in range(iterations):
 
        # -------------------------
        #  训练鉴定器
        # -------------------------
 
        # 抽取真实图像的一个批次
        idx = np.random.randint(0, X_train.shape[0], batch_size)
        imgs = X_train[idx]
 
        # 生成一批次的假图像
        z = np.random.normal(0, 1, (batch_size, 100))
        gen_imgs = generator.predict(z)
 
        # 训练鉴定器
        d_loss_real = discriminator.train_on_batch(imgs, real)
        d_loss_fake = discriminator.train_on_batch(gen_imgs, fake)
        d_loss, accuracy = 0.5 * np.add(d_loss_real, d_loss_fake)
 
        # ---------------------
        # 训练生成器
        # ---------------------
 
        # 生成一批次的假照片
        z = np.random.normal(0, 1, (batch_size, 100))
        gen_imgs = generator.predict(z)
 
        # 训练生成器
        g_loss = gan.train_on_batch(z, real)
 
        if (iteration + 1) % sample_interval == 0:
 
            # 保存损失和准确率以便训练后绘图
            losses.append((d_loss, g_loss))
            accuracies.append(100.0 * accuracy)
            iteration_checkpoints.append(iteration + 1)
 
            # 输出训练过程
            print("%d [D loss: %f, acc.: %.2f%%] [G loss: %f]" %
                  (iteration + 1, d_loss, 100.0 * accuracy, g_loss))
 
            # 输出生成图像的采样
            sample_images(generator)

7、显示生成图像

为完整起见,清单4.7包含了sample_images()函数,它在指定的
训练迭代中输出一个4×4的图像网格。

def sample_images(generator, image_grid_rows=4, image_grid_columns=4):
 
    # 样本的随机噪声(4*4张的合成图)
    z = np.random.normal(0, 1, (image_grid_rows * image_grid_columns, z_dim))
 
    # 从随机噪声中生成图像
    gen_imgs = generator.predict(z)
 
    # 将图像像素值重新缩放为[0,1]内
    gen_imgs = 0.5 * gen_imgs + 0.5
 
    # 建立图像网格
    fig, axs = plt.subplots(image_grid_rows,
                            image_grid_columns,
                            figsize=(4, 4),
                            sharey=True,
                            sharex=True)
 
    cnt = 0
    for i in range(image_grid_rows):
        for j in range(image_grid_columns):
            # 输出一个图像网格
            axs[i, j].imshow(gen_imgs[cnt, :, :, 0], cmap='gray')
            axs[i, j].axis('off')
            cnt += 1

8、运行模型

# 设置超参数
iterations = 10000
batch_size = 128
sample_interval = 1000
 
# 训练模型直到指定的迭代次数
train(iterations, batch_size, sample_interval)

总结

遇到的问题:
1、keras的更新
2、TensorFlow中padding卷积的两种方式“SAME”和“VALID”与我之前学习过的深度学习不同。tensorflow见此
3、numpy中expand_dims()函数详解
4、np.random.randint()的用法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值