700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 深度学习笔记(三)——GAN入门实现MNIST数据集

深度学习笔记(三)——GAN入门实现MNIST数据集

时间:2023-07-25 05:35:17

相关推荐

深度学习笔记(三)——GAN入门实现MNIST数据集

深度学习笔记(三)——GAN入门实现MNIST数据集

文章目录

深度学习笔记(三)——GAN入门实现MNIST数据集闲聊什么是GAN?GeneratorDiscriminatorGAN的特点为什么GAN不适合处理文本数据GAN的优化器为什么不常用SGD训练技巧具体实现GeneratorDiscriminator训练全部代码结语参考:训练结果

闲聊

这周的任务完成了哇,但是本着好好学习,天天向上的宏伟计划(PS:一直感觉GAN蛮好玩的,打算玩玩),所以打算尝试学习下GAN。

什么是GAN?

论文

生成式对抗网络(GAN)是近年来复杂分布上无监督学习最具前景的方法之一,GAN的主要灵感来源于博弈论中零和博弈的思想,应用到深度学习中来说是通过生成网络G(Generator)和判别网络D(Discriminator)不断博弈,进而使G学习到数据的分布,如果是在图片生成上进行应用,就是

G是一个生成式的网络,它接收一个随机的噪声z(随机数),通过这个噪声生成图像

D是一个判别网络,判别一张图片是不是“真实的”。它的输入参数是x,x代表一张图片,输出D(x)代表x为真实图片的概率,如果为1,就代表100%是真实的图片,而输出为0,就代表不可能是真实的图片

G的目的是生成让判别的模型无法判断真伪的输出

D的目的是判断这个是否真实

Generator

什么是生成(generation)?就是模型通过学习一些数据,然后生成类似的数据。让机器看一些图片,然后自己来产生的图片,这就是生成。

以前就有很多生成的技术,比如auto-encoder(自编码器):

训练一个encoder(编码器),把image input转换成code,然后训练一个decoder解码器,将code转换成一个Image,然后计算得到的image和image input之间的MSE(mean square error)

训练完模型后,取出后半部分的decoder,输入一个随机的code,就能通过Generator生成一个image

Discriminator

上面讲到了Generator可以根据一个随机的code生成图片,但是这里涉及到了一个问题,生成出来的图片,到底让我们看是怎么样的呢?这个时候就需要Discriminator对Generator生成的图片进行判别

如果非要简单地形容一下就是自己和自己下围棋?

GAN的特点

GAN是一种生成式模型,相比较其他生成模型(玻尔兹曼机和GSNs)只用到了反向传播,而不需要复杂的马尔科夫链GAN采用的是一种无监督的学习方式训练,可以被广泛用在无监督学习和半监督学习领域GAN不适合处理离散形式的数据,比如文本GAN中的G的梯度更新信息来自于D,而不是样本数据它存在两个不同的网络,而不是传统的单一网络

为什么GAN不适合处理文本数据

对于文本来说,通常需要将一个词映射为一个高维向量,最终预测输出的是一个one-hot向量,假设softmax的输出(0.2,0.3,0.1,0.2,0.15,0.05)那么变为onehot是(0,1,0,0,0,0),如果softmax输出是(0.2,0.25,0.2,0.1,0.15,0.1),而onehot仍然是(0,1,0,0,0,0)。对于G来说,输出了不同的结果,但是D给出了相同的判别结果,并不能梯度更新信息很好的传递到G

GAN的优化器为什么不常用SGD

SGD容易震荡,容易使GAN训练不稳定GAN的目的是在高维非凸的参数空间中找到纳什均衡点,GAN的均衡点是一个鞍点,但是SGD只会找到局部极小值,因为SGD解决的是求最小值问题,GAN是一个博弈问题

训练技巧

输入规范化到(-1,1)之间,最后一层的激活函数使用tanh(BEGAN除外)使用wassertein GAN的损失函数,如果有标签数据的话,尽量使用标签,也有人提出使用反转标签效果很好,另外使用标签平滑,单边标签平滑或者双边标签平滑使用mini-batch norm, 如果不用batch norm可以使用instance norm或者weight norm避免使用RELUpooling层,减少稀疏梯度的可能性,可以使用leakrelu激活函数优化器尽量选择ADAM,学习率不要设置太大,初始1e-4可以参考,另外可以随着训练进行不断缩小学习率,给D的网络层增加高斯噪声,相当于是一种正则

具体实现

代码参考

Generator

生成网络的目标是输入一行正太分布的随机数,生成mnist手写体图片,输出一个28x28x1的图片

全连接层:256——>512——>1024——>784-变形->28x28

def build_generator(self):# --------------------------------- ## 生成器,输入一串随机数字# --------------------------------- #model = Sequential()model.add(Dense(256, input_dim=self.latent_dim))model.add(LeakyReLU(alpha=0.2))model.add(BatchNormalization(momentum=0.8))model.add(Dense(512))model.add(LeakyReLU(alpha=0.2))model.add(BatchNormalization(momentum=0.8))model.add(Dense(1024))model.add(LeakyReLU(alpha=0.2))model.add(BatchNormalization(momentum=0.8))model.add(Dense(np.prod(self.img_shape), activation='tanh'))model.add(Reshape(self.img_shape))noise = Input(shape=(self.latent_dim,))img = model(noise)return Model(noise, img)

Discriminator

判别模型的目的是根据输入的图片判断出真伪。因此它的输入一个28,28,1维的图片,输出是0到1之间的数,1代表判断这个图片是真的,0代表判断这个图片是假的。

全连接层:28x28-打平->784——>512——>256——>1(0或1真伪)

def build_discriminator(self):# ----------------------------------- ## 评价器,对输入进来的图片进行评价# ----------------------------------- #model = Sequential()# 输入一张图片model.add(Flatten(input_shape=self.img_shape))model.add(Dense(512))model.add(LeakyReLU(alpha=0.2))model.add(Dense(256))model.add(LeakyReLU(alpha=0.2))# 判断真伪model.add(Dense(1, activation='sigmoid'))img = Input(shape=self.img_shape)validity = model(img)return Model(img, validity)

训练

GAN的训练分为如下几个步骤:

随机选取batch_size个真实的图片随机生成batch_size个N维向量,传入到Generator中生成batch_size个虚假图片真实图片的label为1,虚假图片的label为0,将真实图片和虚假图片当作训练集传入到Discriminator中进行训练将虚假图片的Discriminator预测结果与1的对比作为loss对Generator进行训练(与1对比的意思是,如果Discriminator将虚假图片判断为1,说明这个生成的图片很“真实”)

全部代码

from __future__ import print_function, divisionfrom tensorflow.keras.datasets import mnistfrom tensorflow.keras.layers import Input, Dense, Reshape, Flatten, Dropoutfrom tensorflow.keras.layers import BatchNormalization, Activation, ZeroPadding2D# from tensorflow.keras.layers.advanced_activations import LeakyReLUfrom tensorflow.keras.layers import LeakyReLU# from tensorflow.keras.layers.convolutional import UpSampling2D, Conv2Dfrom tensorflow.keras.layers import UpSampling2D, Conv2Dfrom tensorflow.keras.models import Sequential, Modelfrom tensorflow.keras.optimizers import Adamimport matplotlib.pyplot as pltimport sysimport osimport numpy as npclass GAN():def __init__(self):# --------------------------------- ## 行28,列28,也就是mnist的shape# --------------------------------- #self.img_rows = 28self.img_cols = 28self.channels = 1# 28,28,1self.img_shape = (self.img_rows, self.img_cols, self.channels)self.latent_dim = 100# adam优化器optimizer = Adam(0.0002, 0.5)self.discriminator = self.build_discriminator()pile(loss='binary_crossentropy',optimizer=optimizer,metrics=['accuracy'])self.generator = self.build_generator()gan_input = Input(shape=(self.latent_dim,))img = self.generator(gan_input)# 在训练generate的时候不训练discriminatorself.discriminator.trainable = False# 对生成的假图片进行预测validity = self.discriminator(img)bined = Model(gan_input, validity)pile(loss='binary_crossentropy', optimizer=optimizer)def build_generator(self):# --------------------------------- ## 生成器,输入一串随机数字# --------------------------------- #model = Sequential()model.add(Dense(256, input_dim=self.latent_dim))model.add(LeakyReLU(alpha=0.2))model.add(BatchNormalization(momentum=0.8))model.add(Dense(512))model.add(LeakyReLU(alpha=0.2))model.add(BatchNormalization(momentum=0.8))model.add(Dense(1024))model.add(LeakyReLU(alpha=0.2))model.add(BatchNormalization(momentum=0.8))model.add(Dense(np.prod(self.img_shape), activation='tanh'))model.add(Reshape(self.img_shape))noise = Input(shape=(self.latent_dim,))img = model(noise)return Model(noise, img)def build_discriminator(self):# ----------------------------------- ## 评价器,对输入进来的图片进行评价# ----------------------------------- #model = Sequential()# 输入一张图片model.add(Flatten(input_shape=self.img_shape))model.add(Dense(512))model.add(LeakyReLU(alpha=0.2))model.add(Dense(256))model.add(LeakyReLU(alpha=0.2))# 判断真伪model.add(Dense(1, activation='sigmoid'))img = Input(shape=self.img_shape)validity = model(img)return Model(img, validity)def train(self, epochs, batch_size=128, sample_interval=50):# 获得数据(X_train, _), (_, _) = mnist.load_data()# 进行标准化X_train = X_train / 127.5 - 1.X_train = np.expand_dims(X_train, axis=3)# 创建标签valid = np.ones((batch_size, 1))fake = np.zeros((batch_size, 1))for epoch in range(epochs):# --------------------------- ## 随机选取batch_size个图片# 对discriminator进行训练# --------------------------- #idx = np.random.randint(0, X_train.shape[0], batch_size)imgs = X_train[idx]noise = np.random.normal(0, 1, (batch_size, self.latent_dim))gen_imgs = self.generator.predict(noise)d_loss_real = self.discriminator.train_on_batch(imgs, valid)d_loss_fake = self.discriminator.train_on_batch(gen_imgs, fake)d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)# --------------------------- ## 训练generator# --------------------------- #noise = np.random.normal(0, 1, (batch_size, self.latent_dim))g_loss = bined.train_on_batch(noise, valid)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:self.sample_images(epoch)def sample_images(self, epoch):r, c = 5, 5noise = np.random.normal(0, 1, (r * c, self.latent_dim))gen_imgs = self.generator.predict(noise)gen_imgs = 0.5 * gen_imgs + 0.5fig, axs = plt.subplots(r, c)cnt = 0for i in range(r):for j in range(c):axs[i,j].imshow(gen_imgs[cnt, :,:,0], cmap='gray')axs[i,j].axis('off')cnt += 1fig.savefig("images/%d.png" % epoch)plt.close()if __name__ == '__main__':if not os.path.exists("./images"):os.makedirs("./images")gan = GAN()gan.train(epochs=30000, batch_size=256, sample_interval=200)

结语

终于跑了一次GAN了,还是蛮好玩的

参考:

深度学习----GAN(生成对抗神经网络)原理解析

好像还挺好玩的GAN1——Keras搭建简单GAN生成MNIST手写体

训练结果

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。