当前位置:   article > 正文

GAN生成对抗网络_生成对抗网络(gan)

生成对抗网络(gan)

目录

1. GAN的介绍 

1.1 GAN的引入

1.2 GAN模型的主要组成

1.3 GAN训练的目的

1.4 GAN的网络结构示意图

 1.5 数学描述

1.6 原始GAN-手写数字图像生成代码

2. 常见的GAN

2.1 DCGAN

2.1.1 DCGAN代码:

2.2 CGAN

2.2.1 条件GAN的代码:

2.3 VAE-GAN 自编码器GAN

2.3.1 自编码器代码实现:

2.3.2 自编码器去噪代码实现:

2.3.3 卷积自编码器去噪代码实现:

2.4 CycleGAN  循环GAN

2.5 ACGAN

3. GAN的应用

3.1 图像合成 

3.2 生物医药发现

3.3 异常检测

3.4 高分辨率图像 Super Resolution

3.5 图像去噪


该文代码下载:GAN​​​​​​​

1. GAN的介绍 

1.1 GAN的引入

GAN:Generative Adversarial Networks 是一种无监督的深度学习模型,提出于2014年,被誉为“近年来复杂分布上无监督学习最具前景的方法之一。”

1.2 GAN模型的主要组成

  • 生成器G(generator)
  • 判别器D(discriminator)

1.3 GAN训练的目的

希望生成器G能够学习到样本的真实分布P_{data}(x),那么G就能生成之前不存在的但是却又很真实的样本。

数据增强增加训练集

eg:

1.4 GAN的网络结构示意图

 1.5 数学描述

 JSD散度最小时。使两个分布相等

1.6 原始GAN-手写数字图像生成代码

分为生成器和判别器两部分。

整体代码为

  1. import tensorflow as tf
  2. import matplotlib.pyplot as plt
  3. import numpy as np
  4. (train_images, train_labels),(_, _) = tf.keras.datasets.mnist.load_data()
  5. print(train_images.shape) #(60000, 28, 28)
  6. # print(train_labels.shape) 输出(60000,) 实际上用不到标签值
  7. train_images = tf.expand_dims(train_images, -1)# 或者用 train_labels = train_images.reshape(60000,28,281,1)
  8. print(train_images.shape)
  9. print(train_images.dtype) #<dtype: 'uint8'>
  10. # train_images = train_images.astype('float32') # 把uint8类型转成float32类型
  11. train_images = tf.cast(train_images, tf.float32)
  12. print(train_images.dtype)
  13. train_images = (train_images - 127.5)/127.5 # 归一化到[-1,1]
  14. print(train_images.shape)
  15. BATCH_SIZE = 64
  16. #创建数据集
  17. datasets = tf.data.Dataset.from_tensor_slices(train_images) # 最常用的创建数据集的方法from_tensor_slices,从train_images中创建datasets
  18. print(datasets) #<TensorSliceDataset shapes: (28, 28, 1), types: tf.float32>
  19. datasets = datasets.shuffle(60000).batch(BATCH_SIZE) # (64, 28, 28)
  20. print(datasets) #<BatchDataset shapes: (None, 28, 28, 1), types: tf.float32>
  21. # 生成器
  22. def generator_model():
  23. model = tf.keras.Sequential()
  24. # 输入100,到隐含层1,256个神经元
  25. model.add(tf.keras.layers.Dense(256, input_shape=(100,), use_bias=False)) # 输入一个100维的随机向量作为输入
  26. model.add(tf.keras.layers.BatchNormalization())
  27. model.add(tf.keras.layers.LeakyReLU())
  28. # 隐含层2,512个神经元
  29. model.add(tf.keras.layers.Dense(512, use_bias=False)) # 输入一个100维的随机向量作为输入
  30. model.add(tf.keras.layers.BatchNormalization())
  31. model.add(tf.keras.layers.LeakyReLU())
  32. # 输出层是784个神经元
  33. model.add(tf.keras.layers.Dense(28 * 28 * 1, use_bias=False, activation='tanh')) # 输入一个100维的随机向量作为输入
  34. model.add(tf.keras.layers.BatchNormalization())
  35. # 把784维的向量,reshape成一张图像,且注意其每一个值都是(-1,1)因为上面用的tanh做激活函数
  36. model.add(tf.keras.layers.Reshape((28, 28, 1)))
  37. return model
  38. # 判别器
  39. def discriminator_model():
  40. model = tf.keras.Sequential()
  41. model.add(tf.keras.layers.Flatten()) # 判别器输入是一张图像[28, 28, 1],所以先flatten成一个向量作为神经元的输入层,连接到后面的隐含层
  42. model.add(tf.keras.layers.Dense(512, use_bias=False))
  43. model.add(tf.keras.layers.BatchNormalization())
  44. model.add(tf.keras.layers.LeakyReLU())
  45. model.add(tf.keras.layers.Dense(256, use_bias=False))
  46. model.add(tf.keras.layers.BatchNormalization())
  47. model.add(tf.keras.layers.LeakyReLU())
  48. model.add(tf.keras.layers.Dense(1)) # 用sigmoid激活的话就认为<0.5认为不是一张真实的图像,>0.5认为是一张真实的图像,
  49. # 不用sigmoid激活就认为<0是假的图像,>0是真的图像
  50. return model
  51. # 损失函数
  52. cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True) #二分类的交叉熵损失
  53. # 解释一下from_logits=True:
  54. # logits表示网络的直接输出,没经过sigmoid或者softmax的概率化。from_logits=False就表示把已经概率化了的输出,重新映射回原值,那么=True就是上面没有经过概率化输出
  55. #判别器的loss
  56. def discriminator_loss(real_out, fake_out): # image_out(64, 1), fake_out(64, 1)
  57. #判别器的loss有两部分:真实的图像希望能判别为1,生成的图像希望能判别为0
  58. image_real_loss = cross_entropy(0.9 * tf.ones_like(real_out), real_out) # cross_entropy(y_true, y_pred)
  59. image_fake_loss = cross_entropy(tf.zeros_like(fake_out), fake_out)
  60. return image_real_loss + image_fake_loss #整个的loss就是两部分合并起来
  61. #生成器的loss
  62. def generator_loss(fake_out): # fake_out为(64, 1), 就是对64张生成图像的预测结果
  63. # print("fake_out:",fake_out.shape)
  64. return cross_entropy(0.9*tf.ones_like(fake_out), fake_out) #希望生成的图像 image_fake被判定为真
  65. # 生成器和判别器是两个模型,所以设置两个分别的优化器
  66. generator_optimizer = tf.keras.optimizers.Adam(1e-4)
  67. discriminator_optimizer = tf.keras.optimizers.Adam(1e-4)
  68. # 训练
  69. epochs = 100
  70. noise_dim = 100
  71. nsamples = 20 #每个epoch都生成20个数据看一下生成的效果
  72. z = tf.random.normal([nsamples, noise_dim]) #生成16个随机100维的向量,用这16个随机向量来观察生成的手写数字的情况
  73. generator = generator_model()
  74. discriminator = discriminator_model()
  75. # 对一个batch进行训练的函数
  76. @tf.function # 加上这句话会训练的特别快
  77. def train_step(images): # 接受一个批次的图像(64, 28, 28, 1)
  78. noise = tf.random.normal([BATCH_SIZE, noise_dim]) # (64, 100)
  79. with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape: # 要追踪两个model的梯度
  80. gen_image = generator(noise, training=True) # 返回(64,28,28,1)
  81. real_out = discriminator(images,
  82. training=True) # 把images(64, 28, 28, 1)送入判别器返回(64,1) 64是64张图像,1是每个图像的返回结果, 因为最后之后一个神经元
  83. fake_out = discriminator(gen_image, training=True) # 把生成的图像(64,28,28,1),送入判别器得到(64, 1)
  84. # 以上都是为了得到loss, 通过记录loss的获得流程, 最终通过调整参数利用优化器, 降低loss
  85. gen_loss = generator_loss(fake_out) # 生成器希望让生成图像被判别为真
  86. disc_loss = discriminator_loss(real_out, fake_out)
  87. gradient_gen = gen_tape.gradient(gen_loss, generator.trainable_variables) # 计算生成器损失和生成器变量之间的梯度
  88. gradient_disc = disc_tape.gradient(disc_loss, discriminator.trainable_variables) # 计算判别器损失和生成器变量之间的梯度
  89. # 更新参数
  90. generator_optimizer.apply_gradients(zip(gradient_gen, generator.trainable_variables))
  91. discriminator_optimizer.apply_gradients(zip(gradient_disc, discriminator.trainable_variables))
  92. def generator_plot_images(gen_model, test_noise): # 传进来的就是 z = tf.random.normal([nsamples, noise_dim]) # (20, 100)
  93. pred_images = gen_model(test_noise, training=False)
  94. fig = plt.figure(figsize=(20, 1))
  95. # for i in range(pred_images.shape[0]):
  96. # plt.subplot(4, 4, i+1)
  97. # plt.imshow((pred_images[i,:,:,0] + 1) / 2, cmap='gray')
  98. # plt.axis('off')
  99. for i in range(nsamples): # 实际上就是pred_images.shape[0]
  100. plt.subplot(1, 20, i + 1)
  101. plt.imshow((pred_images[i, :, :, 0] + 1) / 2, cmap='binary') # pred_images是[20,28,28,1]
  102. plt.axis('off')
  103. plt.show() # 不加这句话就不能在训练的过程中看到生成的结果
  104. def train(dataset, epochs):
  105. for epoch in range(epochs):
  106. for image_batch in dataset:#image_batch就是(256, 28, 28, 1)
  107. train_step(image_batch)
  108. print("Epoch{}/{}".format(epoch+1, epochs))
  109. generator_plot_images(generator, z)
  110. train(datasets, epochs)

刚开始生成的图像不好,基本是噪声,随着训练的增加,训练结果越来越好。

2. 常见的GAN

2.1 DCGAN

DCGAN:Deep Convolutonal Generative Adversarial Networks 深度卷积生成对抗性网络

实际上DCGAN就是将判别器和生成器中原始GAN的多层感知机替换成卷积神经网络。

网络结构:

  • 步长卷积 (D)和分数卷积 (G)取代池化层
  • D和G里使用批归一化处理
  • 移除全连接层
  • 在G中使用ReLU激活函数,除最后一层使用Tanh输出
  • 在D中使用LeakyReLU激活函数

2.1.1 DCGAN代码:

DCGAN的代码和1.6节原始GAN的区别在于生成器和判别器。

生成器代码为:

  1. def generator_model():
  2. model = tf.keras.Sequential()
  3. model.add(tf.keras.layers.Dense(7*7*256, use_bias=False,input_shape=(100,)))
  4. model.add(tf.keras.layers.BatchNormalization())
  5. model.add(tf.keras.layers.LeakyReLU())
  6. model.add(tf.keras.layers.Reshape((7, 7, 256))) #(7, 7, 256)
  7. model.add(tf.keras.layers.Conv2DTranspose(128, (5,5), strides=(1,1), padding='same', use_bias=False)) # (7, 7, 128)
  8. model.add(tf.keras.layers.BatchNormalization())
  9. model.add(tf.keras.layers.LeakyReLU())
  10. model.add(tf.keras.layers.Conv2DTranspose(64, (5,5), strides=(2,2), padding='same', use_bias=False)) # (14, 14, 64)
  11. model.add(tf.keras.layers.BatchNormalization())
  12. model.add(tf.keras.layers.LeakyReLU())
  13. model.add(tf.keras.layers.Conv2DTranspose(1, (5,5), strides=(2,2), padding='same', use_bias=False, activation='tanh')) # (28, 28, 1)
  14. # model.add(tf.keras.layers.BatchNormalization()) # 最后一层不用BN,
  15. # model.add(tf.keras.layers.LeakyReLU()) # (28, 28, 1) # 并用tanh激活
  16. return model

判别器代码为:

  1. def discriminator_model():
  2. model = tf.keras.Sequential()
  3. # (28, 28, 1) -> (14, 14, 64)
  4. model.add(tf.keras.layers.Conv2D(64, (5,5), strides=(2, 2), padding='same', input_shape=(28, 28, 1)))
  5. model.add(tf.keras.layers.LeakyReLU())
  6. model.add(tf.keras.layers.Dropout(0.3)) # 开始不希望判别器太厉害, 卷完之后变成(14, 14, 64)
  7. # (14, 14, 64) -> (7, 7, 128)
  8. model.add(tf.keras.layers.Conv2D(128, (5,5), strides=(2, 2), padding='same')) # (7, 7, 128)
  9. model.add(tf.keras.layers.LeakyReLU())
  10. model.add(tf.keras.layers.Dropout(0.3))
  11. # (7, 7, 128) -> (4, 4, 256) # ceil(7/2)
  12. model.add(tf.keras.layers.Conv2D(256, (5,5), strides=(2, 2), padding='same')) #(4, 4, 256)
  13. model.add(tf.keras.layers.LeakyReLU())
  14. model.add(tf.keras.layers.Flatten()) # 打平
  15. model.add(tf.keras.layers.Dense(1)) # 一个输出
  16. return model

最终结果比原始GAN要好一些。

2.2 CGAN

CGAN:Conditional Generative Adversarial Networks 条件GAN

数学描述:

可以看作是每一个类别y都对应一个属于自己的目标函数。有了这个约束,假如生成了清晰但是类别与标签不匹配的图像,也会当作fake来进行打分,因此可以通过调整标签的值,来改变生成数据的类别。

2.2.1 条件GAN的代码:

 CGAN通过结合标签信息来提高生成数据的质量

生成器代码:

  1. def generator_model():
  2. noise = tf.keras.layers.Input(shape=((noise_dim))) # 输入的噪声是100维
  3. label = tf.keras.layers.Input(shape=(())) # 输入的标签就是1个数,但是这个数可以表示有10个类别,所以在下面Embedding第一个是10,第二个是50是映射成50个神经元
  4. x = tf.keras.layers.Embedding(10, 50, input_length=1)(label) # 把一个长度是1的标签(没有有one-hot编码)
  5. #把x和noise合并在一起变成长度为150的向量
  6. x = tf.keras.layers.concatenate([noise, x])
  7. x = tf.keras.layers.Dense(3*3*128, use_bias=False)(x)
  8. x = tf.keras.layers.Reshape((3, 3, 128))(x) # 注意reshape大写R
  9. x = tf.keras.layers.BatchNormalization()(x)
  10. x = tf.keras.layers.ReLU()(x)
  11. #下面开始反卷积: (3, 3, 128) -> (7, 7, 64) -> (14, 14, 32) -> (28, 28, 1)
  12. x = tf.keras.layers.Conv2DTranspose(64, (3,3), strides=(2,2), use_bias=False)(x) #填充方式如果是same那么是(6, 6, 64),但是默认是vaild填充
  13. x = tf.keras.layers.BatchNormalization()(x)
  14. x = tf.keras.layers.ReLU()(x)
  15. #(7, 7, 64) -> (14, 14, 32)
  16. x = tf.keras.layers.Conv2DTranspose(32, (3,3), strides=(2,2), padding='same', use_bias=False)(x) #填充方式如果是same那么是(6,6,64),但是默认是vaild填充
  17. x = tf.keras.layers.BatchNormalization()(x)
  18. x = tf.keras.layers.ReLU()(x)
  19. #(14, 14, 32) -> (28, 28, 1)
  20. x = tf.keras.layers.Conv2DTranspose(1, (3,3), strides=(2,2), padding='same', use_bias=False)(x) #填充方式如果是same那么是(6,6,64),但是默认是vaild填充
  21. x = tf.keras.layers.Activation('tanh')(x)
  22. model = tf.keras.Model(inputs=[noise, label], outputs=x)
  23. return model

判别器代码:

  1. def discriminator_model():
  2. image = tf.keras.layers.Input(shape=((28, 28, 1)))
  3. label = tf.keras.layers.Input(shape=(()))
  4. x = tf.keras.layers.Embedding(10, 28*28, input_length=1)(label)
  5. x = tf.keras.layers.Reshape((28,28,1))(x)
  6. x = tf.keras.layers.concatenate([x, image])#合并到一起形状变成(28, 28, 2)
  7. x = tf.keras.layers.Conv2D(32, (3, 3), strides=(2,2), padding='same', use_bias=False)(x) # (14, 14, 32)
  8. x = tf.keras.layers.BatchNormalization()(x)
  9. x = tf.keras.layers.LeakyReLU()(x)
  10. x = tf.keras.layers.Dropout(0.5)(x) #不要快速成为一个很厉害的判别器
  11. x = tf.keras.layers.Conv2D(64, (3, 3), strides=(2,2), padding='same', use_bias=False)(x) # (7, 7, 64)
  12. x = tf.keras.layers.BatchNormalization()(x)
  13. x = tf.keras.layers.LeakyReLU()(x)
  14. x = tf.keras.layers.Dropout(0.5)(x)
  15. x = tf.keras.layers.Conv2D(128, (3, 3), strides=(2,2), padding='same', use_bias=False)(x) # (3, 3, 128)
  16. x = tf.keras.layers.BatchNormalization()(x)
  17. x = tf.keras.layers.LeakyReLU()(x)
  18. x = tf.keras.layers.Dropout(0.5)(x)
  19. x = tf.keras.layers.Flatten()(x)
  20. logits = tf.keras.layers.Dense(1)(x) #未激活的输出
  21. model = tf.keras.Model(inputs=[image, label], outputs=logits)
  22. return model

2.3 VAE-GAN 自编码器GAN

自编码器:

包括两部分,一个Enconder一个Decoder,输入一张图像,目标是经过编码得到一个向量,然后将这个中间向量解码输出之后,输入图像和输出图像尽可能像,将输入输出图像的差异定义为loss,则优化loss就可以训练出Encoder和Decoder。

作用:去噪、降维、图像生成(把Decoder部分单独拿出来,给定一个向量,就能生成一张图像,但是随便给一个向量都能生成想要的图像吗?不一定,因为生成器要求输入的向量必须是经过Encoder之后的向量,如果想随机给一个向量,然后它随机产生一张正确的图像,这就引出了下面的变分自编码器。)

VAE:

设置两个损失,第一个是使得输入图像和输出图像尽可能的像,第二个损失是想让Encoder之后的向量满足一个分布,如正态分布,那么Encoder之后的向量就更加满足一个正态分布,那么就可以随机给一个正态分布的向量,就可以产生一个满足要求的图像。

VAE-GAN 

2.3.1 自编码器代码实现:

包括encoder和decoder两部分,另外,训练的是x_train,标签也是x_train

将x_test(原始图像)输入自编码器,得到decoder_test(生成的图像)。

模型代码:

  1. input_dim = tf.keras.layers.Input(shape=(input_size,))
  2. #encode
  3. en = tf.keras.layers.Dense(hidden_size,activation='relu')(input_dim) #把input_dim传入这一层
  4. #decode
  5. de = tf.keras.layers.Dense(output_size,activation='sigmoid')(en)
  6. model = tf.keras.Model(inputs=input_dim,outputs=de)
  7. model.summary()
  8. model.compile(optimizer='adam',loss='mse')
  9. model.fit(x_train,x_train,epochs=50,batch_size=256,shuffle=True,validation_data=(x_test,x_test))

使用手写数字数据集,整体代码为:

  1. import tensorflow as tf
  2. import matplotlib.pyplot as plt
  3. (x_train,_), (x_test,_) = tf.keras.datasets.mnist.load_data()
  4. print(x_train.shape, x_test.shape) #(60000, 28, 28) (10000, 28, 28)
  5. x_train = x_train.reshape(x_train.shape[0],-1) #变成60000 * 784的向量
  6. x_test = x_test.reshape(x_test.shape[0],-1)
  7. print(x_train.shape, x_test.shape) #(60000, 784) (10000, 784)
  8. #归一化(像素值都是0-255的,归一化为0-1之间的数)
  9. '''
  10. tf.cast()函数的作用是执行 tensorflow 中张量数据类型转换,比如读入的图片如果是int8类型的,一般在要在训练前把图像的数据格式转换为float32。
  11. '''
  12. x_train = tf.cast(x_train, tf.float32) / 255
  13. x_test = tf.cast(x_test, tf.float32) / 255
  14. input_size = 784
  15. hidden_size = 32
  16. output_size = 784
  17. input_dim = tf.keras.layers.Input(shape=(input_size,))
  18. #encode
  19. en = tf.keras.layers.Dense(hidden_size,activation='relu')(input_dim) #把input_dim传入这一层
  20. #decode
  21. de = tf.keras.layers.Dense(output_size,activation='sigmoid')(en)
  22. model = tf.keras.Model(inputs=input_dim,outputs=de)
  23. model.summary()
  24. model.compile(optimizer='adam',loss='mse')
  25. model.fit(x_train,x_train,epochs=50,batch_size=256,shuffle=True,validation_data=(x_test,x_test))
  26. #获得encoder(功能可以把一张图像压缩为一个向量)
  27. encode = tf.keras.Model(inputs=input_dim,outputs=en)
  28. #获得decoder(把一个向量还原回图像)
  29. input_decoder = tf.keras.layers.Input(shape=(hidden_size,))
  30. output_decoder = model.layers[-1](input_decoder)
  31. decode = tf.keras.Model(inputs=input_decoder,outputs=output_decoder)
  32. #调用encoder把测试集数据压缩为32维向量
  33. # encode_test = encode(x_test) # encode.predict(x_test)可以返回numpy数据(10000,32)
  34. encode_test = encode.predict(x_test)
  35. print(encode_test.shape)
  36. # (10000, 32)
  37. #调用decoder把向量解码回图像
  38. # decode_test = decode(encode_test)
  39. decode_test = decode.predict(encode_test)
  40. print(decode_test.shape)
  41. # (10000, 784)
  42. x_test = x_test.numpy()
  43. #画图
  44. n = 10 #画两行10列的子图
  45. plt.figure(figsize=(20,4))#宽20,高4
  46. for i in range(1,10):
  47. ax = plt.subplot(2, n, i)
  48. plt.imshow(x_test[i].reshape(28,28),cmap='binary')
  49. plt.axis('off')
  50. ax = plt.subplot(2, n, n+i)
  51. plt.imshow(decode_test[i].reshape(28,28),cmap='binary')
  52. plt.axis('off')
  53. plt.show()

2.3.2 自编码器去噪代码实现:

自己添加噪声,代码为:

  1. #噪声系数
  2. factor = 0.5
  3. x_train_noise = x_train + factor * np.random.normal(0,1,size=x_train.shape) # 给x_train添加噪声x_train.shape:60000*784
  4. x_test_noise = x_test + factor * np.random.normal(0,1,size=x_test.shape) # 给x_train添加噪声x_test.shape:10000*784
  5. x_train_noise = np.clip(x_train_noise,0.,1.)
  6. x_test_noise = np.clip(x_test_noise,0.,1.)
  7. print("x_train:",x_train.shape) #x_train: (60000, 784)
  8. print("x_test:",x_test.shape) #x_test: (10000, 784)
  9. print("x_train_noise:",x_train_noise.shape) #x_train_noise: (60000, 784)
  10. print("x_test_noise:",x_test_noise.shape) #x_test_noise: (10000, 784)
  11. plt.figure(figsize=(10,2))
  12. for i in range(1,11):#画10张图像,i从1到10
  13. ax = plt.subplot(1,10,i)
  14. plt.imshow(x_train_noise[i].reshape(28,28))
  15. plt.show()

训练的是x_train_noise,标签是x_train

将x_test_noise(带噪声的图像)放入自编码器,得到decoder_test(不带噪声的图像)。

同样对手写数字识别图像进行去噪,整体代码为:
  1. input_decoder = tf.keras.layers.Input(shape=(hidden_size,))
  2. output_decoder = model.layers[-1](input_decoder)
  3. decode = tf.keras.Model(inputs=input_decoder,outputs=output_decoder)
  4. #调用encoder把测试集数据压缩为32维向量
  5. # encode_test = encode(x_test) # encode.predict(x_test)可以返回numpy数据(10000,32)
  6. encode_test = encode.predict(x_test_noise)
  7. #调用decoder把向量解码回图像
  8. # decode_test = decode(encode_test)
  9. decode_test = decode.predict(encode_test)
  10. x_test = x_test.numpy()
  11. #画图
  12. n = 10 #画两行10列的子图
  13. plt.figure(figsize=(20,4))#宽20,高4
  14. for i in range(1,10):
  15. ax = plt.subplot(2, n, i)
  16. plt.imshow(x_test_noise[i].reshape(28,28))
  17. ax = plt.subplot(2, n, n+i)
  18. plt.imshow(decode_test[i].reshape(28,28))
  19. plt.show()

2.3.3 卷积自编码器去噪代码实现:

首先也是自己添加噪声,和2.3.2一样。

encode:用卷积提取特征;  decode:用反卷积上采样,还原回原来的图像

模型代码为:

  1. #encode:用卷积提取特征
  2. # en = tf.keras.layers.Dense(hidden_size,activation='relu')(input_dim) #把input_dim传入这一层
  3. input_dim = tf.keras.layers.Input(shape=x_train.shape[1:]) # x_train.shape[1:] 输出:TensorShape([28, 28, 1])
  4. x = tf.keras.layers.Conv2D(16,3,activation='relu',padding='same')(input_dim) #28*28*16(16个3*3的卷积核)
  5. x = tf.keras.layers.MaxPooling2D(padding='same')(x) #14*14*16(same就是保持原图大小不动,然后用2*2的池化窗口做池化)
  6. x = tf.keras.layers.Conv2D(32,3,activation='relu',padding='same')(x) #14*14*32(再用32个3*3的卷积核做卷积得到14*14*32)
  7. x = tf.keras.layers.MaxPooling2D(padding='same')(x) #7*7*32
  8. #decode:用反卷积上采样,还原回原来的图像
  9. x = tf.keras.layers.Conv2DTranspose(16, 3, strides=2, activation='relu', padding='same')(x)#stride就是把图像扩大回原来的2倍,把7*7*32的变成了14*14*16
  10. x = tf.keras.layers.Conv2DTranspose(1, 3, strides=2, activation='sigmoid', padding='same')(x)#28*28*1
  11. model = tf.keras.Model(inputs=input_dim,outputs=x)
  12. model.summary()
  13. model.compile(optimizer=tf.keras.optimizers.Adam(0.001),loss='mse')
  14. #训练的时候用带噪声的图像,输出是去除噪声的
  15. 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(不带噪声的图像)。

同样对手写数字识别图像进行去噪,整体代码为:

  1. import tensorflow as tf
  2. import matplotlib.pyplot as plt
  3. import numpy as np
  4. (x_train,_), (x_test,_) = tf.keras.datasets.mnist.load_data()
  5. # 现在是增加一个维度作为通道信息
  6. x_train = np.expand_dims(x_train, -1)#在最后一个维度加一个通道信息(如这个就是单通道的,维度就是1)
  7. x_test = np.expand_dims(x_test, -1)
  8. print(x_train.shape, x_test.shape) #((60000, 28, 28, 1), (10000, 28, 28, 1))
  9. #归一化像素值都是0-255的,归一化为0-1之间的数)
  10. x_train = tf.cast(x_train, tf.float32) / 255
  11. x_test = tf.cast(x_test, tf.float32) / 255
  12. # 增加噪声
  13. #噪声系数
  14. factor = 0.5
  15. x_train_noise = x_train + factor * np.random.normal(0,1,size=x_train.shape) # 给x_train添加噪声x_train.shape:60000*784
  16. x_test_noise = x_test + factor * np.random.normal(0,1,size=x_test.shape) # 给x_train添加噪声x_test.shape:10000*784
  17. x_train_noise = np.clip(x_train_noise,0.,1.)
  18. x_test_noise = np.clip(x_test_noise,0.,1.)
  19. print("x_train:",x_train.shape)
  20. print("x_test:",x_test.shape)
  21. print("x_train_noise:",x_train_noise.shape)
  22. print("x_test_noise:",x_test_noise.shape)
  23. plt.figure(figsize=(10,2))
  24. for i in range(1,11):#画10张图像,i从1到10
  25. ax = plt.subplot(1,10,i)
  26. plt.imshow(x_train_noise[i].reshape(28,28))
  27. plt.show()
  28. #encode:用卷积提取特征
  29. # en = tf.keras.layers.Dense(hidden_size,activation='relu')(input_dim) #把input_dim传入这一层
  30. input_dim = tf.keras.layers.Input(shape=x_train.shape[1:]) # x_train.shape[1:] 输出:TensorShape([28, 28, 1])
  31. x = tf.keras.layers.Conv2D(16,3,activation='relu',padding='same')(input_dim) #28*28*16(16个3*3的卷积核)
  32. x = tf.keras.layers.MaxPooling2D(padding='same')(x) #14*14*16(same就是保持原图大小不动,然后用2*2的池化窗口做池化)
  33. x = tf.keras.layers.Conv2D(32,3,activation='relu',padding='same')(x) #14*14*32(再用32个3*3的卷积核做卷积得到14*14*32)
  34. x = tf.keras.layers.MaxPooling2D(padding='same')(x) #7*7*32
  35. #decode:用反卷积上采样,还原回原来的图像
  36. x = tf.keras.layers.Conv2DTranspose(16, 3, strides=2, activation='relu', padding='same')(x)#stride就是把图像扩大回原来的2倍,把7*7*32的变成了14*14*16
  37. x = tf.keras.layers.Conv2DTranspose(1, 3, strides=2, activation='sigmoid', padding='same')(x)#28*28*1
  38. model = tf.keras.Model(inputs=input_dim,outputs=x)
  39. model.summary()
  40. model.compile(optimizer=tf.keras.optimizers.Adam(0.001),loss='mse')
  41. #训练的时候用带噪声的图像,输出是去除噪声的
  42. model.fit(x_train_noise,x_train,epochs=50,batch_size=256,shuffle=True,validation_data=(x_test_noise,x_test))
  43. pre_test = model.predict(x_test_noise)
  44. #画图
  45. n = 10 #画两行10列的子图
  46. plt.figure(figsize=(20,4))#宽20,高4
  47. for i in range(1,11):
  48. ax = plt.subplot(2, n, i)
  49. plt.imshow(x_test_noise[i].reshape(28,28))
  50. ax = plt.subplot(2, n, n+i)
  51. plt.imshow(pre_test[i].reshape(28,28))
  52. plt.show()

2.4 CycleGAN  循环GAN

 

2.5 ACGAN

ACGAN 简介与代码实战

ACGAN模型为:

ACGAN既能生成图像又能进行分类

生成器的输入包括class(label)和noise两部分,其中class是训练数据的标签也就是label, 生成器将两个部分拼接,输出是一张图像;

判别器输入图像(真的和生成的),输出是两部分,一部分判别真假(batch,1),一部分输出是分类的结果。

损失函数:

 

生成器代码:

  1. def generator_model():
  2. noise = tf.keras.layers.Input(shape=((noise_dim,))) # 输入的噪声是100维
  3. label = tf.keras.layers.Input(shape=(())) # 输入的标签就是1个数,但是这个数可以表示有10个类别,所以在下面Embedding第一个是10,第二个是50是映射成50个神经元
  4. x = tf.keras.layers.Embedding(10, 50, input_length=1)(label) # 把一个长度是1的标签(没有有one-hot编码)
  5. #把x和noise合并在一起变成长度为150的向量
  6. x = tf.keras.layers.concatenate([noise, x])
  7. x = tf.keras.layers.Dense(3*3*128, use_bias=False)(x)
  8. x = tf.keras.layers.Reshape((3, 3, 128))(x) # 注意reshape大写R
  9. x = tf.keras.layers.BatchNormalization()(x)
  10. x = tf.keras.layers.ReLU()(x)
  11. #下面开始反卷积: (3, 3, 128) -> (7, 7, 64) -> (14, 14, 32) -> (28, 28, 1)
  12. x = tf.keras.layers.Conv2DTranspose(64, (3,3), strides=(2,2), use_bias=False)(x) #填充方式如果是same那么是(6, 6, 64),但是默认是vaild填充
  13. x = tf.keras.layers.BatchNormalization()(x)
  14. x = tf.keras.layers.ReLU()(x)
  15. #(7, 7, 64) -> (14, 14, 32)
  16. x = tf.keras.layers.Conv2DTranspose(32, (3,3), strides=(2,2), padding='same', use_bias=False)(x) #填充方式如果是same那么是(6,6,64),但是默认是vaild填充
  17. x = tf.keras.layers.BatchNormalization()(x)
  18. x = tf.keras.layers.ReLU()(x)
  19. #(14, 14, 32) -> (28, 28, 1)
  20. x = tf.keras.layers.Conv2DTranspose(1, (3,3), strides=(2,2), padding='same', use_bias=False)(x) #填充方式如果是same那么是(6,6,64),但是默认是vaild填充
  21. x = tf.keras.layers.Activation('tanh')(x) # [-1, 1]
  22. model = tf.keras.Model(inputs=[noise, label], outputs=x)
  23. return model

 判别器代码:

  1. def discriminator_model():
  2. image = tf.keras.layers.Input(shape=((28, 28, 1)))
  3. # label = tf.keras.layers.Input(shape=(())) 去掉输入
  4. # x = tf.keras.layers.Embedding(10, 28*28, input_length=1)(label)
  5. # x = tf.keras.layers.Reshape((28,28,1))(x)
  6. # x = tf.keras.layers.concatenate([x, image])
  7. x = tf.keras.layers.Conv2D(32, (3, 3), strides=(2,2), padding='same', use_bias=False)(image) # (14, 14, 32)
  8. x = tf.keras.layers.BatchNormalization()(x)
  9. x = tf.keras.layers.LeakyReLU()(x)
  10. x = tf.keras.layers.Dropout(0.5)(x) #不要快速成为一个很厉害的判别器
  11. x = tf.keras.layers.Conv2D(64, (3, 3), strides=(2,2), padding='same', use_bias=False)(x) # (7, 7, 64)
  12. x = tf.keras.layers.BatchNormalization()(x)
  13. x = tf.keras.layers.LeakyReLU()(x)
  14. x = tf.keras.layers.Dropout(0.5)(x)
  15. x = tf.keras.layers.Conv2D(128, (3, 3), strides=(2,2), padding='same', use_bias=False)(x) # (3, 3, 128)
  16. x = tf.keras.layers.BatchNormalization()(x)
  17. x = tf.keras.layers.LeakyReLU()(x)
  18. x = tf.keras.layers.Dropout(0.5)(x)
  19. x = tf.keras.layers.Flatten()(x)
  20. S_out = tf.keras.layers.Dense(1)(x) #未激活的判断图像真假的输出
  21. C_out = tf.keras.layers.Dense(10)(x) #分类输出,一共10类
  22. # model = tf.keras.Model(inputs=[image, label], outputs=logits)
  23. model = tf.keras.Model(inputs=image, outputs=[S_out, C_out]) #多输出模型
  24. return model

3. GAN的应用

  1. 高分辨率图像
  2. 目标检测 
  •  合成 Synthesis
  • 分割 Segmentation
  • 重建 Reconstruction
  • 检测 Detection
  • 降噪 De-noising
  • 分类 Classification

3.1 图像合成 

医学类图像,可能病发病率不一样,样本就不足。或者样本标记不够

从2D到3D的重建,生物医学领域,心脏、胃等建模

3.2 生物医药发现

如基于某一个病情,自动给出推荐需要用什么药,其实质是在一个数据库中根据病例做药物选择的过程。

针对不同人的病情做一个个性化推荐,捕捉每个个体之间的细微差异,于是引入GAN来做药物推荐。——AAE

3.3 异常检测

有很多正常数据,但是没有很多异常数据,于是可以通过生成器来学习到正常数据的分布,然后将需要检测到的异常图通过前面的生成器得到其正常图的样子,然后对比即可找出异常。

缺点:对于比较小的异常,因为GAN生成图并不能做到细节非常明显,所以很难检测。

3.4 高分辨率图像 Super Resolution

将低分辨率图像转换成高分辨率的

3.5 图像去噪

深度学习训练得到的降噪很容易模糊。

GAN:学习噪声,构造带噪声的图像,进行配对带噪声的和不带噪声的图像对比

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/712261
推荐阅读
相关标签
  

闽ICP备14008679号