keras padding_GAN整体思路以及使用Keras搭建DCGAN

整体思路:

1:使用噪音,通过一系列的转秩卷积(逆卷积)操作,生成一张图片;

2:使用正常的卷积神经网络判断图片的真假。

训练细节:

1:在训练判决器网络时,对真实图像,加上正标签,对假图像加上假标签,使得判别器能够完美的发现假图像;

2:训练生成器时,给假图像打上正标签,使得判别器能够返回假图像在变成真图像所需要拟合的变化

模型细节:

1:整个网络是两个模型的组合。首先是生成器,然后是判别器;

2:在训练判别器时,使用的网络仅仅是判别器网络,训练的参数也仅仅是判别器网络的参数;

3:训练生成器时,使用的是组合的模型,即先用生成器网络生成图像,再用判别器网络判断优化方向。在优化生成器网络参数时,需要关闭判别器网络。也就是说,尽管反向传播回来的梯度是从判别器开始的,但是判别器的参数不参与优化工作,这也是为什么训练生成器时需要先将判别器网络的梯度更新关闭的原因。

代码重点讲解:

生成器网络搭建:

def generator_model():
    model = tf.keras.Sequential()
    #将100维的噪音升维到7*7*256,方便后面转换为图像矩阵
    model.add(layers.Dense(7*7*256, use_bias=False, input_shape=(100,)))
    model.add(layers.BatchNormalization()) 
    model.add(layers.LeakyReLU())
     #转换为图像矩阵
    model.add(layers.Reshape((7, 7, 256)))
    assert model.output_shape == (None, 7, 7, 256) # Note: None is the batch size
    #使用逆卷积操作,将图片进行尺寸的放大(逆卷积讲解:https://blog.csdn.net/nima1994/article/details/83959495;逆卷积和向上采样的区别:https://www.zhihu.com/question/290376931)
    model.add(layers.Conv2DTranspose(128, (5, 5), strides=(1, 1), padding='same', use_bias=False))
    assert model.output_shape == (None, 7, 7, 128)  
    model.add(layers.BatchNormalization())
    model.add(layers.LeakyReLU())

    model.add(layers.Conv2DTranspose(64, (5, 5), strides=(2, 2), padding='same', use_bias=False))
    assert model.output_shape == (None, 14, 14, 64)    
    model.add(layers.BatchNormalization())
    model.add(layers.LeakyReLU())
    #一维卷积,通道合并,生成28*28*1的图像
    model.add(layers.Conv2DTranspose(1, (5, 5), strides=(2, 2), padding='same', use_bias=False, activation='tanh'))
    assert model.output_shape == (None, 28, 28, 1)
 
    return model

252bf13a104bc935483cc9590de1ae16.png

判别器网络搭建:

def discriminator_model():
    model = tf.keras.Sequential()
    model.add(layers.Conv2D(64, (5, 5), strides=(2, 2), padding='same', 
                                     input_shape=[28, 28, 1]))
    model.add(layers.LeakyReLU())
    model.add(layers.Dropout(0.3))
 
    model.add(layers.Conv2D(128, (5, 5), strides=(2, 2), padding='same'))
    model.add(layers.LeakyReLU())
    model.add(layers.Dropout(0.3))
     #将特征图像展平,然后做一个汇总输出,输出维度为1,即判别图片为真假图片的概率
    model.add(layers.Flatten())
    model.add(layers.Dense(1))
 
    return model

损失函数:

cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True)

判别器损失函数:

def discriminator_loss(real_output, fake_output):

#对真图像,定义标签为1,ones_lisk为输出real_output维度的1,然后使用交叉熵损失,表示真图像距离被判断为真图像有多大的差距

real_loss = cross_entropy(tf.ones_like(real_output), real_output)

#对假图片,定义标签为0,然后使用交叉熵损失,表示假图像距离被判断为假图像有多大的差距

fake_loss = cross_entropy(tf.zeros_like(fake_output), fake_output)

#总的损失为在真假图像上的损失之和,即图片的预测与图片的标签之间的差距

total_loss = real_loss + fake_loss

return total_loss

生成器损失函数:

def generator_loss(fake_output):

#将假图像的标签定为1,衡量假图像距离真图像还有多大的差距,这也是生成器网络需要优化的方向

return cross_entropy(tf.ones_like(fake_output), fake_output)

生成对抗网络(自此开始引自github,与上文不是一个作者,可能代码有出入,主要是看整体的思路):

23687b4e267c90c25d78035ba5378bc5.png

将生成器网络和判别器网络加入,生成器网络在前,判别器网络在后,同时将判别器网络的参数更新关闭。因为这个网络的主要作用就是优化生成器,因此判别器不参与优化。

进行训练:

a77511c9343e7daa15e43919b617161f.png

首先,在83,84行初始化两个模型,然后构建生成对抗网络d_on_g。

上图中的88,89,91行是设置损失函数的,作用等同于上面写的损失函数内容。(截图和代码并不是来自同一个作者,因此这里只表达的了整体逻辑,而非真正没有错误的)

然后设置判别器网络可优化参数,对每一批次,首先先生成噪音数据,然后用噪音数据生成假图像。然后将假图像与真图像组合,并合并标签,假图像为0,真图像为1,,在106行,开始训练判别器网络,注意,此时训练的仅仅是判别器网络d。训练使用的是Keras中的train_on_batch,解释:https://blog.csdn.net/weixin_42886817/article/details/99855287

判别器网络训练完毕后,在使用噪音生成假图像,此时将其标签设置为1(在110行,[1]*BATCH_SIZE即设置y),然后关闭判别器网络的优化,开始训练d_on_g网络,此网络由生成器和判别器组成,由于前面将判别器网络的参数优化给关闭了,因此在这里只优化生成器网络。

代码来自:https://github.com/jacobgil/keras-dcgan/blob/master/dcgan.py

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 Keras DCGAN 代码示例: ```python from keras.datasets import mnist from keras.models import Sequential, Model from keras.layers import Input, Dense, Reshape, Flatten, Dropout from keras.layers import Conv2D, Conv2DTranspose, LeakyReLU from keras.optimizers import Adam import numpy as np # 设置输入形状 img_rows = 28 img_cols = 28 channels = 1 img_shape = (img_rows, img_cols, channels) z_dim = 100 # 构建生成器模型 def build_generator(z_dim): model = Sequential() # 全连接层 model.add(Dense(128 * 7 * 7, input_dim=z_dim)) model.add(LeakyReLU(alpha=0.01)) model.add(Reshape((7, 7, 128))) # 转置卷积层 model.add(Conv2DTranspose(64, kernel_size=3, strides=2, padding='same')) model.add(LeakyReLU(alpha=0.01)) # 转置卷积层 model.add(Conv2DTranspose(1, kernel_size=3, strides=2, padding='same', activation='tanh')) return model # 构建鉴别器模型 def build_discriminator(img_shape): model = Sequential() # 卷积层 model.add(Conv2D(32, kernel_size=3, strides=2, input_shape=img_shape, padding='same')) model.add(LeakyReLU(alpha=0.01)) # 卷积层 model.add(Conv2D(64, kernel_size=3, strides=2, input_shape=img_shape, padding='same')) model.add(LeakyReLU(alpha=0.01)) # 卷积层 model.add(Conv2D(128, kernel_size=3, strides=2, input_shape=img_shape, padding='same')) model.add(LeakyReLU(alpha=0.01)) # 扁平层 model.add(Flatten()) model.add(Dropout(0.4)) # 输出层 model.add(Dense(1, activation='sigmoid')) return model # 构建深度卷积生成对抗网络模型 def build_gan(generator, discriminator): model = Sequential() # 生成器 + 鉴别器 model.add(generator) model.add(discriminator) return model # 构建鉴别器模型 discriminator = build_discriminator(img_shape) # 编译鉴别器模型 discriminator.compile(loss='binary_crossentropy', optimizer=Adam(), metrics=['accuracy']) # 构建生成器模型 generator = build_generator(z_dim) # 保持鉴别器不可训练 discriminator.trainable = False # 构建深度卷积生成对抗网络模型 gan = build_gan(generator, discriminator) # 编译深度卷积生成对抗网络模型 gan.compile(loss='binary_crossentropy', optimizer=Adam()) # 加载 MNIST 数据集 (X_train, _), (_, _) = mnist.load_data() # 标准化输入数据 X_train = X_train / 127.5 - 1. X_train = np.expand_dims(X_train, axis=3) # 定义训练参数 batch_size = 64 epochs = 30000 sample_interval = 200 # 构建噪声向量 z = np.random.normal(0, 1, (batch_size, z_dim)) # 训练深度卷积生成对抗网络 for epoch in range(epochs): # --------------------- # 训练鉴别器 # --------------------- # 随机选择一个批次的真实图像 idx = np.random.randint(0, X_train.shape[0], batch_size) real_imgs = X_train[idx] # 生成假图像 noise = np.random.normal(0, 1, (batch_size, z_dim)) fake_imgs = generator.predict(noise) # 训练鉴别器 d_loss_real = discriminator.train_on_batch(real_imgs, np.ones((batch_size, 1))) d_loss_fake = discriminator.train_on_batch(fake_imgs, np.zeros((batch_size, 1))) d_loss = 0.5 * np.add(d_loss_real, d_loss_fake) # --------------------- # 训练生成器 # --------------------- # 生成噪声向量 noise = np.random.normal(0, 1, (batch_size, z_dim)) # 训练生成器 g_loss = gan.train_on_batch(noise, np.ones((batch_size, 1))) # 打印损失和准确率指标 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: # 生成噪声向量 noise = np.random.normal(0, 1, (1, z_dim)) # 生成假图像 gen_imgs = generator.predict(noise) # 反标准化输出图像 gen_imgs = 0.5 * gen_imgs + 0.5 # 保存生成的图像 plt.imshow(gen_imgs[0, :, :, 0], cmap='gray') plt.savefig("images/%d.png" % epoch) ``` 这个代码实现了一个简单的深度卷积生成对抗网络,用于生成 MNIST 数字图像。在训练过程中,它首先训练鉴别器,然后再训练生成器,以最小化鉴别器对假图像的判断。最后,它生成一些样本图像并将它们保存到磁盘上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值