深度学习笔记(三)——GAN⼊门实现MNIST数据集
深度学习笔记(三)——GAN⼊门实现MNIST数据集
⽂章⽬录
闲聊
这周的任务完成了哇,但是本着好好学习,天天向上的宏伟计划(PS:⼀直感觉GAN蛮好玩的,打算玩玩),所以打算尝试学习下GAN。
什么是GAN?
⽣成式对抗⽹络(GAN)是近年来复杂分布上⽆监督学习最具前景的⽅法之⼀,GAN的主要灵感来源于博弈论中零和博弈的思想,应⽤到深度学习中来说是通过⽣成⽹络G(Generator)和判别⽹络D(Discriminator)不断博弈,进⽽使G学习到数据的分布 ,如果是在图⽚⽣成上进⾏应⽤,就是
G是⼀个⽣成式的⽹络,它接收⼀个随机的噪声z(随机数),通过这个噪声⽣成图像
D是⼀个判别⽹络,判别⼀张图⽚是不是“真实的”。它的输⼊参数是x,x代表⼀张图⽚,输出D(x)代表x为真实图⽚的概率,如果为1,就代表100%是真实的图⽚,⽽输出为0,就代表不可能是真实的图⽚
G的⽬的是⽣成让判别的模型⽆法判断真伪的输出tensorflow入门教程
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
避免使⽤RELU和pooling层,减少稀疏梯度的可能性,可以使⽤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, division
from tensorflow.keras.datasets import mnist
from tensorflow.keras.layers import Input, Dense, Reshape, Flatten, Dropout
from tensorflow.keras.layers import BatchNormalization, Activation, ZeroPadding2D
# from tensorflow.keras.layers.advanced_activations import LeakyReLU
from tensorflow.keras.layers import LeakyReLU
# from tensorflow.volutional import UpSampling2D, Conv2D
from tensorflow.keras.layers import UpSampling2D, Conv2D
from dels import Sequential, Model
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt
import sys
import os
import numpy as np
class GAN():
def__init__(self):
# --------------------------------- #
# ⾏28,列28,也就是mnist的shape
# --------------------------------- #
self.img_rows =28
self.img_cols =28
self.channels =1
# 28,28,1
self.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()
self.discriminatorpile(loss='binary_crossentropy',
optimizer=optimizer,
metrics=['accuracy'])
gan_input = Input(shape=(self.latent_dim,))
img = ator(gan_input)
# 在训练generate的时候不训练discriminator
ainable =False
# 对⽣成的假图⽚进⾏预测
validity = self.discriminator(img)
selfbined = Model(gan_input, validity)
selfbinedpile(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()
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论