赞
踩
目录
该文代码下载:GAN
GAN:Generative Adversarial Networks 是一种无监督的深度学习模型,提出于2014年,被誉为“近年来复杂分布上无监督学习最具前景的方法之一。”
希望生成器G能够学习到样本的真实分布,那么G就能生成之前不存在的但是却又很真实的样本。
数据增强增加训练集
eg:
JSD散度最小时。使两个分布相等
分为生成器和判别器两部分。
整体代码为:
- import tensorflow as tf
- import matplotlib.pyplot as plt
-
- import numpy as np
-
-
- (train_images, train_labels),(_, _) = tf.keras.datasets.mnist.load_data()
- print(train_images.shape) #(60000, 28, 28)
- # print(train_labels.shape) 输出(60000,) 实际上用不到标签值
-
-
- train_images = tf.expand_dims(train_images, -1)# 或者用 train_labels = train_images.reshape(60000,28,281,1)
- print(train_images.shape)
-
- print(train_images.dtype) #<dtype: 'uint8'>
- # train_images = train_images.astype('float32') # 把uint8类型转成float32类型
- train_images = tf.cast(train_images, tf.float32)
-
- print(train_images.dtype)
- train_images = (train_images - 127.5)/127.5 # 归一化到[-1,1]
- print(train_images.shape)
-
- BATCH_SIZE = 64
-
- #创建数据集
- datasets = tf.data.Dataset.from_tensor_slices(train_images) # 最常用的创建数据集的方法from_tensor_slices,从train_images中创建datasets
- print(datasets) #<TensorSliceDataset shapes: (28, 28, 1), types: tf.float32>
-
- datasets = datasets.shuffle(60000).batch(BATCH_SIZE) # (64, 28, 28)
- print(datasets) #<BatchDataset shapes: (None, 28, 28, 1), types: tf.float32>
-
-
- # 生成器
- def generator_model():
- model = tf.keras.Sequential()
- # 输入100,到隐含层1,256个神经元
- model.add(tf.keras.layers.Dense(256, input_shape=(100,), use_bias=False)) # 输入一个100维的随机向量作为输入
- model.add(tf.keras.layers.BatchNormalization())
- model.add(tf.keras.layers.LeakyReLU())
-
- # 隐含层2,512个神经元
- model.add(tf.keras.layers.Dense(512, use_bias=False)) # 输入一个100维的随机向量作为输入
- model.add(tf.keras.layers.BatchNormalization())
- model.add(tf.keras.layers.LeakyReLU())
-
- # 输出层是784个神经元
- model.add(tf.keras.layers.Dense(28 * 28 * 1, use_bias=False, activation='tanh')) # 输入一个100维的随机向量作为输入
- model.add(tf.keras.layers.BatchNormalization())
-
- # 把784维的向量,reshape成一张图像,且注意其每一个值都是(-1,1)因为上面用的tanh做激活函数
- model.add(tf.keras.layers.Reshape((28, 28, 1)))
-
- return model
-
-
- # 判别器
- def discriminator_model():
- model = tf.keras.Sequential()
- model.add(tf.keras.layers.Flatten()) # 判别器输入是一张图像[28, 28, 1],所以先flatten成一个向量作为神经元的输入层,连接到后面的隐含层
-
- model.add(tf.keras.layers.Dense(512, use_bias=False))
- model.add(tf.keras.layers.BatchNormalization())
- model.add(tf.keras.layers.LeakyReLU())
-
- model.add(tf.keras.layers.Dense(256, use_bias=False))
- model.add(tf.keras.layers.BatchNormalization())
- model.add(tf.keras.layers.LeakyReLU())
-
- model.add(tf.keras.layers.Dense(1)) # 用sigmoid激活的话就认为<0.5认为不是一张真实的图像,>0.5认为是一张真实的图像,
- # 不用sigmoid激活就认为<0是假的图像,>0是真的图像
- return model
-
-
- # 损失函数
- cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True) #二分类的交叉熵损失
- # 解释一下from_logits=True:
- # logits表示网络的直接输出,没经过sigmoid或者softmax的概率化。from_logits=False就表示把已经概率化了的输出,重新映射回原值,那么=True就是上面没有经过概率化输出
-
- #判别器的loss
- def discriminator_loss(real_out, fake_out): # image_out(64, 1), fake_out(64, 1)
- #判别器的loss有两部分:真实的图像希望能判别为1,生成的图像希望能判别为0
- image_real_loss = cross_entropy(0.9 * tf.ones_like(real_out), real_out) # cross_entropy(y_true, y_pred)
- image_fake_loss = cross_entropy(tf.zeros_like(fake_out), fake_out)
- return image_real_loss + image_fake_loss #整个的loss就是两部分合并起来
-
- #生成器的loss
- def generator_loss(fake_out): # fake_out为(64, 1), 就是对64张生成图像的预测结果
- # print("fake_out:",fake_out.shape)
- return cross_entropy(0.9*tf.ones_like(fake_out), fake_out) #希望生成的图像 image_fake被判定为真
-
- # 生成器和判别器是两个模型,所以设置两个分别的优化器
- generator_optimizer = tf.keras.optimizers.Adam(1e-4)
- discriminator_optimizer = tf.keras.optimizers.Adam(1e-4)
-
- # 训练
- epochs = 100
- noise_dim = 100
-
- nsamples = 20 #每个epoch都生成20个数据看一下生成的效果
- z = tf.random.normal([nsamples, noise_dim]) #生成16个随机100维的向量,用这16个随机向量来观察生成的手写数字的情况
-
- generator = generator_model()
- discriminator = discriminator_model()
-
-
- # 对一个batch进行训练的函数
- @tf.function # 加上这句话会训练的特别快
- def train_step(images): # 接受一个批次的图像(64, 28, 28, 1)
- noise = tf.random.normal([BATCH_SIZE, noise_dim]) # (64, 100)
- with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape: # 要追踪两个model的梯度
-
- gen_image = generator(noise, training=True) # 返回(64,28,28,1)
-
- real_out = discriminator(images,
- training=True) # 把images(64, 28, 28, 1)送入判别器返回(64,1) 64是64张图像,1是每个图像的返回结果, 因为最后之后一个神经元
- fake_out = discriminator(gen_image, training=True) # 把生成的图像(64,28,28,1),送入判别器得到(64, 1)
-
- # 以上都是为了得到loss, 通过记录loss的获得流程, 最终通过调整参数利用优化器, 降低loss
- gen_loss = generator_loss(fake_out) # 生成器希望让生成图像被判别为真
- disc_loss = discriminator_loss(real_out, fake_out)
-
- gradient_gen = gen_tape.gradient(gen_loss, generator.trainable_variables) # 计算生成器损失和生成器变量之间的梯度
- gradient_disc = disc_tape.gradient(disc_loss, discriminator.trainable_variables) # 计算判别器损失和生成器变量之间的梯度
-
- # 更新参数
- generator_optimizer.apply_gradients(zip(gradient_gen, generator.trainable_variables))
- discriminator_optimizer.apply_gradients(zip(gradient_disc, discriminator.trainable_variables))
-
-
- def generator_plot_images(gen_model, test_noise): # 传进来的就是 z = tf.random.normal([nsamples, noise_dim]) # (20, 100)
- pred_images = gen_model(test_noise, training=False)
- fig = plt.figure(figsize=(20, 1))
- # for i in range(pred_images.shape[0]):
- # plt.subplot(4, 4, i+1)
- # plt.imshow((pred_images[i,:,:,0] + 1) / 2, cmap='gray')
- # plt.axis('off')
-
- for i in range(nsamples): # 实际上就是pred_images.shape[0]
- plt.subplot(1, 20, i + 1)
- plt.imshow((pred_images[i, :, :, 0] + 1) / 2, cmap='binary') # pred_images是[20,28,28,1]
- plt.axis('off')
- plt.show() # 不加这句话就不能在训练的过程中看到生成的结果
-
- def train(dataset, epochs):
- for epoch in range(epochs):
- for image_batch in dataset:#image_batch就是(256, 28, 28, 1)
- train_step(image_batch)
- print("Epoch{}/{}".format(epoch+1, epochs))
- generator_plot_images(generator, z)
-
-
- train(datasets, epochs)
刚开始生成的图像不好,基本是噪声,随着训练的增加,训练结果越来越好。
DCGAN:Deep Convolutonal Generative Adversarial Networks 深度卷积生成对抗性网络
实际上DCGAN就是将判别器和生成器中原始GAN的多层感知机替换成卷积神经网络。
网络结构:
DCGAN的代码和1.6节原始GAN的区别在于生成器和判别器。
生成器代码为:
- def generator_model():
- model = tf.keras.Sequential()
- model.add(tf.keras.layers.Dense(7*7*256, use_bias=False,input_shape=(100,)))
- model.add(tf.keras.layers.BatchNormalization())
- model.add(tf.keras.layers.LeakyReLU())
-
- model.add(tf.keras.layers.Reshape((7, 7, 256))) #(7, 7, 256)
-
- model.add(tf.keras.layers.Conv2DTranspose(128, (5,5), strides=(1,1), padding='same', use_bias=False)) # (7, 7, 128)
- model.add(tf.keras.layers.BatchNormalization())
- model.add(tf.keras.layers.LeakyReLU())
-
- model.add(tf.keras.layers.Conv2DTranspose(64, (5,5), strides=(2,2), padding='same', use_bias=False)) # (14, 14, 64)
- model.add(tf.keras.layers.BatchNormalization())
- model.add(tf.keras.layers.LeakyReLU())
-
- model.add(tf.keras.layers.Conv2DTranspose(1, (5,5), strides=(2,2), padding='same', use_bias=False, activation='tanh')) # (28, 28, 1)
- # model.add(tf.keras.layers.BatchNormalization()) # 最后一层不用BN,
- # model.add(tf.keras.layers.LeakyReLU()) # (28, 28, 1) # 并用tanh激活
-
- return model
判别器代码为:
- def discriminator_model():
- model = tf.keras.Sequential()
- # (28, 28, 1) -> (14, 14, 64)
- model.add(tf.keras.layers.Conv2D(64, (5,5), strides=(2, 2), padding='same', input_shape=(28, 28, 1)))
- model.add(tf.keras.layers.LeakyReLU())
- model.add(tf.keras.layers.Dropout(0.3)) # 开始不希望判别器太厉害, 卷完之后变成(14, 14, 64)
-
- # (14, 14, 64) -> (7, 7, 128)
- model.add(tf.keras.layers.Conv2D(128, (5,5), strides=(2, 2), padding='same')) # (7, 7, 128)
- model.add(tf.keras.layers.LeakyReLU())
- model.add(tf.keras.layers.Dropout(0.3))
-
- # (7, 7, 128) -> (4, 4, 256) # ceil(7/2)
- model.add(tf.keras.layers.Conv2D(256, (5,5), strides=(2, 2), padding='same')) #(4, 4, 256)
- model.add(tf.keras.layers.LeakyReLU())
-
- model.add(tf.keras.layers.Flatten()) # 打平
-
- model.add(tf.keras.layers.Dense(1)) # 一个输出
- return model
最终结果比原始GAN要好一些。
CGAN:Conditional Generative Adversarial Networks 条件GAN
数学描述:
可以看作是每一个类别y都对应一个属于自己的目标函数。有了这个约束,假如生成了清晰但是类别与标签不匹配的图像,也会当作fake来进行打分,因此可以通过调整标签的值,来改变生成数据的类别。
CGAN通过结合标签信息来提高生成数据的质量
生成器代码:
- def generator_model():
- noise = tf.keras.layers.Input(shape=((noise_dim))) # 输入的噪声是100维
- label = tf.keras.layers.Input(shape=(())) # 输入的标签就是1个数,但是这个数可以表示有10个类别,所以在下面Embedding第一个是10,第二个是50是映射成50个神经元
-
- x = tf.keras.layers.Embedding(10, 50, input_length=1)(label) # 把一个长度是1的标签(没有有one-hot编码)
-
- #把x和noise合并在一起变成长度为150的向量
- x = tf.keras.layers.concatenate([noise, x])
-
- x = tf.keras.layers.Dense(3*3*128, use_bias=False)(x)
-
- x = tf.keras.layers.Reshape((3, 3, 128))(x) # 注意reshape大写R
- x = tf.keras.layers.BatchNormalization()(x)
-
- x = tf.keras.layers.ReLU()(x)
-
- #下面开始反卷积: (3, 3, 128) -> (7, 7, 64) -> (14, 14, 32) -> (28, 28, 1)
- x = tf.keras.layers.Conv2DTranspose(64, (3,3), strides=(2,2), use_bias=False)(x) #填充方式如果是same那么是(6, 6, 64),但是默认是vaild填充
- x = tf.keras.layers.BatchNormalization()(x)
- x = tf.keras.layers.ReLU()(x)
-
- #(7, 7, 64) -> (14, 14, 32)
- x = tf.keras.layers.Conv2DTranspose(32, (3,3), strides=(2,2), padding='same', use_bias=False)(x) #填充方式如果是same那么是(6,6,64),但是默认是vaild填充
- x = tf.keras.layers.BatchNormalization()(x)
- x = tf.keras.layers.ReLU()(x)
-
- #(14, 14, 32) -> (28, 28, 1)
- x = tf.keras.layers.Conv2DTranspose(1, (3,3), strides=(2,2), padding='same', use_bias=False)(x) #填充方式如果是same那么是(6,6,64),但是默认是vaild填充
- x = tf.keras.layers.Activation('tanh')(x)
-
- model = tf.keras.Model(inputs=[noise, label], outputs=x)
- return model
判别器代码:
- def discriminator_model():
- image = tf.keras.layers.Input(shape=((28, 28, 1)))
- label = tf.keras.layers.Input(shape=(()))
-
- x = tf.keras.layers.Embedding(10, 28*28, input_length=1)(label)
- x = tf.keras.layers.Reshape((28,28,1))(x)
- x = tf.keras.layers.concatenate([x, image])#合并到一起形状变成(28, 28, 2)
-
- x = tf.keras.layers.Conv2D(32, (3, 3), strides=(2,2), padding='same', use_bias=False)(x) # (14, 14, 32)
- x = tf.keras.layers.BatchNormalization()(x)
- x = tf.keras.layers.LeakyReLU()(x)
- x = tf.keras.layers.Dropout(0.5)(x) #不要快速成为一个很厉害的判别器
-
- x = tf.keras.layers.Conv2D(64, (3, 3), strides=(2,2), padding='same', use_bias=False)(x) # (7, 7, 64)
- x = tf.keras.layers.BatchNormalization()(x)
- x = tf.keras.layers.LeakyReLU()(x)
- x = tf.keras.layers.Dropout(0.5)(x)
-
- x = tf.keras.layers.Conv2D(128, (3, 3), strides=(2,2), padding='same', use_bias=False)(x) # (3, 3, 128)
- x = tf.keras.layers.BatchNormalization()(x)
- x = tf.keras.layers.LeakyReLU()(x)
- x = tf.keras.layers.Dropout(0.5)(x)
-
- x = tf.keras.layers.Flatten()(x)
-
- logits = tf.keras.layers.Dense(1)(x) #未激活的输出
-
- model = tf.keras.Model(inputs=[image, label], outputs=logits)
- return model
自编码器:
包括两部分,一个Enconder一个Decoder,输入一张图像,目标是经过编码得到一个向量,然后将这个中间向量解码输出之后,输入图像和输出图像尽可能像,将输入输出图像的差异定义为loss,则优化loss就可以训练出Encoder和Decoder。
作用:去噪、降维、图像生成(把Decoder部分单独拿出来,给定一个向量,就能生成一张图像,但是随便给一个向量都能生成想要的图像吗?不一定,因为生成器要求输入的向量必须是经过Encoder之后的向量,如果想随机给一个向量,然后它随机产生一张正确的图像,这就引出了下面的变分自编码器。)
VAE:
设置两个损失,第一个是使得输入图像和输出图像尽可能的像,第二个损失是想让Encoder之后的向量满足一个分布,如正态分布,那么Encoder之后的向量就更加满足一个正态分布,那么就可以随机给一个正态分布的向量,就可以产生一个满足要求的图像。
VAE-GAN
包括encoder和decoder两部分,另外,训练的是x_train,标签也是x_train。
将x_test(原始图像)输入自编码器,得到decoder_test(生成的图像)。
模型代码:
- input_dim = tf.keras.layers.Input(shape=(input_size,))
-
- #encode
- en = tf.keras.layers.Dense(hidden_size,activation='relu')(input_dim) #把input_dim传入这一层
-
- #decode
- de = tf.keras.layers.Dense(output_size,activation='sigmoid')(en)
-
- model = tf.keras.Model(inputs=input_dim,outputs=de)
-
- model.summary()
- model.compile(optimizer='adam',loss='mse')
- model.fit(x_train,x_train,epochs=50,batch_size=256,shuffle=True,validation_data=(x_test,x_test))
使用手写数字数据集,整体代码为:
- import tensorflow as tf
- import matplotlib.pyplot as plt
-
- (x_train,_), (x_test,_) = tf.keras.datasets.mnist.load_data()
-
- print(x_train.shape, x_test.shape) #(60000, 28, 28) (10000, 28, 28)
-
- x_train = x_train.reshape(x_train.shape[0],-1) #变成60000 * 784的向量
- x_test = x_test.reshape(x_test.shape[0],-1)
- print(x_train.shape, x_test.shape) #(60000, 784) (10000, 784)
-
- #归一化(像素值都是0-255的,归一化为0-1之间的数)
- '''
- tf.cast()函数的作用是执行 tensorflow 中张量数据类型转换,比如读入的图片如果是int8类型的,一般在要在训练前把图像的数据格式转换为float32。
- '''
- x_train = tf.cast(x_train, tf.float32) / 255
- x_test = tf.cast(x_test, tf.float32) / 255
-
- input_size = 784
- hidden_size = 32
- output_size = 784
-
- input_dim = tf.keras.layers.Input(shape=(input_size,))
-
- #encode
- en = tf.keras.layers.Dense(hidden_size,activation='relu')(input_dim) #把input_dim传入这一层
-
- #decode
- de = tf.keras.layers.Dense(output_size,activation='sigmoid')(en)
-
- model = tf.keras.Model(inputs=input_dim,outputs=de)
-
- model.summary()
-
- model.compile(optimizer='adam',loss='mse')
-
- model.fit(x_train,x_train,epochs=50,batch_size=256,shuffle=True,validation_data=(x_test,x_test))
-
- #获得encoder(功能可以把一张图像压缩为一个向量)
- encode = tf.keras.Model(inputs=input_dim,outputs=en)
-
- #获得decoder(把一个向量还原回图像)
- input_decoder = tf.keras.layers.Input(shape=(hidden_size,))
- output_decoder = model.layers[-1](input_decoder)
-
- decode = tf.keras.Model(inputs=input_decoder,outputs=output_decoder)
-
- #调用encoder把测试集数据压缩为32维向量
- # encode_test = encode(x_test) # encode.predict(x_test)可以返回numpy数据(10000,32)
- encode_test = encode.predict(x_test)
- print(encode_test.shape)
- # (10000, 32)
-
- #调用decoder把向量解码回图像
- # decode_test = decode(encode_test)
- decode_test = decode.predict(encode_test)
- print(decode_test.shape)
- # (10000, 784)
-
- x_test = x_test.numpy()
-
- #画图
- n = 10 #画两行10列的子图
- plt.figure(figsize=(20,4))#宽20,高4
- for i in range(1,10):
- ax = plt.subplot(2, n, i)
- plt.imshow(x_test[i].reshape(28,28),cmap='binary')
- plt.axis('off')
- ax = plt.subplot(2, n, n+i)
- plt.imshow(decode_test[i].reshape(28,28),cmap='binary')
- plt.axis('off')
- plt.show()
-
-
自己添加噪声,代码为:
- #噪声系数
- factor = 0.5
- x_train_noise = x_train + factor * np.random.normal(0,1,size=x_train.shape) # 给x_train添加噪声x_train.shape:60000*784
- x_test_noise = x_test + factor * np.random.normal(0,1,size=x_test.shape) # 给x_train添加噪声x_test.shape:10000*784
-
- x_train_noise = np.clip(x_train_noise,0.,1.)
- x_test_noise = np.clip(x_test_noise,0.,1.)
-
- print("x_train:",x_train.shape) #x_train: (60000, 784)
- print("x_test:",x_test.shape) #x_test: (10000, 784)
-
- print("x_train_noise:",x_train_noise.shape) #x_train_noise: (60000, 784)
- print("x_test_noise:",x_test_noise.shape) #x_test_noise: (10000, 784)
-
- plt.figure(figsize=(10,2))
- for i in range(1,11):#画10张图像,i从1到10
- ax = plt.subplot(1,10,i)
- plt.imshow(x_train_noise[i].reshape(28,28))
- plt.show()
训练的是x_train_noise,标签是x_train
将x_test_noise(带噪声的图像)放入自编码器,得到decoder_test(不带噪声的图像)。
同样对手写数字识别图像进行去噪,整体代码为:
-
- input_decoder = tf.keras.layers.Input(shape=(hidden_size,))
- output_decoder = model.layers[-1](input_decoder)
-
- decode = tf.keras.Model(inputs=input_decoder,outputs=output_decoder)
-
- #调用encoder把测试集数据压缩为32维向量
- # encode_test = encode(x_test) # encode.predict(x_test)可以返回numpy数据(10000,32)
- encode_test = encode.predict(x_test_noise)
-
- #调用decoder把向量解码回图像
- # decode_test = decode(encode_test)
- decode_test = decode.predict(encode_test)
-
- x_test = x_test.numpy()
-
- #画图
- n = 10 #画两行10列的子图
- plt.figure(figsize=(20,4))#宽20,高4
- for i in range(1,10):
- ax = plt.subplot(2, n, i)
- plt.imshow(x_test_noise[i].reshape(28,28))
- ax = plt.subplot(2, n, n+i)
- plt.imshow(decode_test[i].reshape(28,28))
- plt.show()
首先也是自己添加噪声,和2.3.2一样。
encode:用卷积提取特征; decode:用反卷积上采样,还原回原来的图像
模型代码为:
- #encode:用卷积提取特征
- # en = tf.keras.layers.Dense(hidden_size,activation='relu')(input_dim) #把input_dim传入这一层
- input_dim = tf.keras.layers.Input(shape=x_train.shape[1:]) # x_train.shape[1:] 输出:TensorShape([28, 28, 1])
- x = tf.keras.layers.Conv2D(16,3,activation='relu',padding='same')(input_dim) #28*28*16(16个3*3的卷积核)
- x = tf.keras.layers.MaxPooling2D(padding='same')(x) #14*14*16(same就是保持原图大小不动,然后用2*2的池化窗口做池化)
- x = tf.keras.layers.Conv2D(32,3,activation='relu',padding='same')(x) #14*14*32(再用32个3*3的卷积核做卷积得到14*14*32)
- x = tf.keras.layers.MaxPooling2D(padding='same')(x) #7*7*32
-
- #decode:用反卷积上采样,还原回原来的图像
- x = tf.keras.layers.Conv2DTranspose(16, 3, strides=2, activation='relu', padding='same')(x)#stride就是把图像扩大回原来的2倍,把7*7*32的变成了14*14*16
- x = tf.keras.layers.Conv2DTranspose(1, 3, strides=2, activation='sigmoid', padding='same')(x)#28*28*1
-
- model = tf.keras.Model(inputs=input_dim,outputs=x)
-
- model.summary()
- model.compile(optimizer=tf.keras.optimizers.Adam(0.001),loss='mse')
- #训练的时候用带噪声的图像,输出是去除噪声的
- model.fit(x_train_noise,x_train,epochs=50,batch_size=256,shuffle=True,validation_data=(x_test_noise,x_test))
训练的是x_train_noise,标签是x_train
将x_test_noise(带噪声的图像)放入卷积自编码器,得到pre_test(不带噪声的图像)。
同样对手写数字识别图像进行去噪,整体代码为:
- import tensorflow as tf
- import matplotlib.pyplot as plt
- import numpy as np
-
-
- (x_train,_), (x_test,_) = tf.keras.datasets.mnist.load_data()
-
- # 现在是增加一个维度作为通道信息
- x_train = np.expand_dims(x_train, -1)#在最后一个维度加一个通道信息(如这个就是单通道的,维度就是1)
- x_test = np.expand_dims(x_test, -1)
- print(x_train.shape, x_test.shape) #((60000, 28, 28, 1), (10000, 28, 28, 1))
-
- #归一化像素值都是0-255的,归一化为0-1之间的数)
- x_train = tf.cast(x_train, tf.float32) / 255
- x_test = tf.cast(x_test, tf.float32) / 255
-
- # 增加噪声
- #噪声系数
- factor = 0.5
- x_train_noise = x_train + factor * np.random.normal(0,1,size=x_train.shape) # 给x_train添加噪声x_train.shape:60000*784
- x_test_noise = x_test + factor * np.random.normal(0,1,size=x_test.shape) # 给x_train添加噪声x_test.shape:10000*784
-
- x_train_noise = np.clip(x_train_noise,0.,1.)
- x_test_noise = np.clip(x_test_noise,0.,1.)
-
- print("x_train:",x_train.shape)
- print("x_test:",x_test.shape)
-
- print("x_train_noise:",x_train_noise.shape)
- print("x_test_noise:",x_test_noise.shape)
-
- plt.figure(figsize=(10,2))
- for i in range(1,11):#画10张图像,i从1到10
- ax = plt.subplot(1,10,i)
- plt.imshow(x_train_noise[i].reshape(28,28))
- plt.show()
-
-
- #encode:用卷积提取特征
- # en = tf.keras.layers.Dense(hidden_size,activation='relu')(input_dim) #把input_dim传入这一层
- input_dim = tf.keras.layers.Input(shape=x_train.shape[1:]) # x_train.shape[1:] 输出:TensorShape([28, 28, 1])
- x = tf.keras.layers.Conv2D(16,3,activation='relu',padding='same')(input_dim) #28*28*16(16个3*3的卷积核)
- x = tf.keras.layers.MaxPooling2D(padding='same')(x) #14*14*16(same就是保持原图大小不动,然后用2*2的池化窗口做池化)
- x = tf.keras.layers.Conv2D(32,3,activation='relu',padding='same')(x) #14*14*32(再用32个3*3的卷积核做卷积得到14*14*32)
- x = tf.keras.layers.MaxPooling2D(padding='same')(x) #7*7*32
-
- #decode:用反卷积上采样,还原回原来的图像
- x = tf.keras.layers.Conv2DTranspose(16, 3, strides=2, activation='relu', padding='same')(x)#stride就是把图像扩大回原来的2倍,把7*7*32的变成了14*14*16
- x = tf.keras.layers.Conv2DTranspose(1, 3, strides=2, activation='sigmoid', padding='same')(x)#28*28*1
-
- model = tf.keras.Model(inputs=input_dim,outputs=x)
-
- model.summary()
- model.compile(optimizer=tf.keras.optimizers.Adam(0.001),loss='mse')
- #训练的时候用带噪声的图像,输出是去除噪声的
- model.fit(x_train_noise,x_train,epochs=50,batch_size=256,shuffle=True,validation_data=(x_test_noise,x_test))
-
-
- pre_test = model.predict(x_test_noise)
-
- #画图
- n = 10 #画两行10列的子图
- plt.figure(figsize=(20,4))#宽20,高4
- for i in range(1,11):
- ax = plt.subplot(2, n, i)
- plt.imshow(x_test_noise[i].reshape(28,28))
- ax = plt.subplot(2, n, n+i)
- plt.imshow(pre_test[i].reshape(28,28))
- plt.show()
-
ACGAN模型为:
ACGAN既能生成图像又能进行分类
生成器的输入包括class(label)和noise两部分,其中class是训练数据的标签也就是label, 生成器将两个部分拼接,输出是一张图像;
判别器输入图像(真的和生成的),输出是两部分,一部分判别真假(batch,1),一部分输出是分类的结果。
损失函数:
生成器代码:
- def generator_model():
- noise = tf.keras.layers.Input(shape=((noise_dim,))) # 输入的噪声是100维
- label = tf.keras.layers.Input(shape=(())) # 输入的标签就是1个数,但是这个数可以表示有10个类别,所以在下面Embedding第一个是10,第二个是50是映射成50个神经元
-
- x = tf.keras.layers.Embedding(10, 50, input_length=1)(label) # 把一个长度是1的标签(没有有one-hot编码)
-
- #把x和noise合并在一起变成长度为150的向量
- x = tf.keras.layers.concatenate([noise, x])
-
- x = tf.keras.layers.Dense(3*3*128, use_bias=False)(x)
-
- x = tf.keras.layers.Reshape((3, 3, 128))(x) # 注意reshape大写R
- x = tf.keras.layers.BatchNormalization()(x)
- x = tf.keras.layers.ReLU()(x)
-
- #下面开始反卷积: (3, 3, 128) -> (7, 7, 64) -> (14, 14, 32) -> (28, 28, 1)
- x = tf.keras.layers.Conv2DTranspose(64, (3,3), strides=(2,2), use_bias=False)(x) #填充方式如果是same那么是(6, 6, 64),但是默认是vaild填充
- x = tf.keras.layers.BatchNormalization()(x)
- x = tf.keras.layers.ReLU()(x)
-
- #(7, 7, 64) -> (14, 14, 32)
- x = tf.keras.layers.Conv2DTranspose(32, (3,3), strides=(2,2), padding='same', use_bias=False)(x) #填充方式如果是same那么是(6,6,64),但是默认是vaild填充
- x = tf.keras.layers.BatchNormalization()(x)
- x = tf.keras.layers.ReLU()(x)
-
- #(14, 14, 32) -> (28, 28, 1)
- x = tf.keras.layers.Conv2DTranspose(1, (3,3), strides=(2,2), padding='same', use_bias=False)(x) #填充方式如果是same那么是(6,6,64),但是默认是vaild填充
- x = tf.keras.layers.Activation('tanh')(x) # [-1, 1]
-
- model = tf.keras.Model(inputs=[noise, label], outputs=x)
- return model
判别器代码:
- def discriminator_model():
- image = tf.keras.layers.Input(shape=((28, 28, 1)))
- # label = tf.keras.layers.Input(shape=(())) 去掉输入
-
- # x = tf.keras.layers.Embedding(10, 28*28, input_length=1)(label)
- # x = tf.keras.layers.Reshape((28,28,1))(x)
- # x = tf.keras.layers.concatenate([x, image])
-
- x = tf.keras.layers.Conv2D(32, (3, 3), strides=(2,2), padding='same', use_bias=False)(image) # (14, 14, 32)
- x = tf.keras.layers.BatchNormalization()(x)
- x = tf.keras.layers.LeakyReLU()(x)
- x = tf.keras.layers.Dropout(0.5)(x) #不要快速成为一个很厉害的判别器
-
- x = tf.keras.layers.Conv2D(64, (3, 3), strides=(2,2), padding='same', use_bias=False)(x) # (7, 7, 64)
- x = tf.keras.layers.BatchNormalization()(x)
- x = tf.keras.layers.LeakyReLU()(x)
- x = tf.keras.layers.Dropout(0.5)(x)
-
- x = tf.keras.layers.Conv2D(128, (3, 3), strides=(2,2), padding='same', use_bias=False)(x) # (3, 3, 128)
- x = tf.keras.layers.BatchNormalization()(x)
- x = tf.keras.layers.LeakyReLU()(x)
- x = tf.keras.layers.Dropout(0.5)(x)
-
- x = tf.keras.layers.Flatten()(x)
-
- S_out = tf.keras.layers.Dense(1)(x) #未激活的判断图像真假的输出
- C_out = tf.keras.layers.Dense(10)(x) #分类输出,一共10类
-
- # model = tf.keras.Model(inputs=[image, label], outputs=logits)
- model = tf.keras.Model(inputs=image, outputs=[S_out, C_out]) #多输出模型
-
- return model
医学类图像,可能病发病率不一样,样本就不足。或者样本标记不够
从2D到3D的重建,生物医学领域,心脏、胃等建模
如基于某一个病情,自动给出推荐需要用什么药,其实质是在一个数据库中根据病例做药物选择的过程。
针对不同人的病情做一个个性化推荐,捕捉每个个体之间的细微差异,于是引入GAN来做药物推荐。——AAE
有很多正常数据,但是没有很多异常数据,于是可以通过生成器来学习到正常数据的分布,然后将需要检测到的异常图通过前面的生成器得到其正常图的样子,然后对比即可找出异常。
缺点:对于比较小的异常,因为GAN生成图并不能做到细节非常明显,所以很难检测。
将低分辨率图像转换成高分辨率的
深度学习训练得到的降噪很容易模糊。
GAN:学习噪声,构造带噪声的图像,进行配对带噪声的和不带噪声的图像对比
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。