飞道的博客

GAN生成漫画脸

266人阅读  评论(0)

最近对对抗生成网络GAN比较感兴趣,相关知识点文章还在编辑中,以下这个是一个练手的小项目~

 (在原模型上做了,为了减少计算量让其好训练一些。)

一、导入工具包


  
  1. import tensorflow as tf
  2. from tensorflow.keras import layers
  3. import numpy as np
  4. import os
  5. import time
  6. import glob
  7. import matplotlib.pyplot as plt
  8. from IPython.display import clear_output
  9. from IPython import display

1.1 设置GPU


  
  1. gpus = tf.config.list_physical_devices( "GPU")
  2. if gpus:
  3. gpu0 = gpus[ 0] #如果有多个GPU,仅使用第0个GPU
  4. tf.config.experimental.set_memory_growth(gpu0, True) #设置GPU显存用量按需使用
  5. tf.config.set_visible_devices([gpu0], "GPU")
  6. gpus
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]

二、导入训练数据

链接: 点这里


  
  1. fileList = glob.glob( './ani_face/*.jpg')
  2. len(fileList)
41621

2.1 数据可视化 


  
  1. # 随机显示几张图
  2. for index,i in enumerate(fileList[: 3]):
  3. display.display(display.Image(fileList[index]))

2.2 数据预处理


  
  1. # 文件名列表
  2. path_ds = tf.data.Dataset.from_tensor_slices(fileList)
  3. # 预处理,归一化,缩放
  4. def load_and_preprocess_image( path):
  5. image = tf.io.read_file(path)
  6. image = tf.image.decode_jpeg(image, channels= 3)
  7. image = tf.image.resize(image, [ 64, 64])
  8. image /= 255.0 # normalize to [0,1] range
  9. image = tf.reshape(image, [ 1, 64, 64, 3])
  10. return image
  11. image_ds = path_ds. map(load_and_preprocess_image)
  12. image_ds
<MapDataset shapes: (1, 64, 64, 3), types: tf.float32>

  
  1. # 查看一张图片
  2. for x in image_ds:
  3. plt.axis( "off")
  4. plt.imshow((x.numpy() * 255).astype( "int32")[ 0])
  5. break

三、网络构建

3.1 D网络


  
  1. discriminator = keras.Sequential(
  2. [
  3. keras.Input(shape=( 64, 64, 3)),
  4. layers.Conv2D( 64, kernel_size= 4, strides= 2, padding= "same"),
  5. layers.LeakyReLU(alpha= 0.2),
  6. layers.Conv2D( 128, kernel_size= 4, strides= 2, padding= "same"),
  7. layers.LeakyReLU(alpha= 0.2),
  8. layers.Conv2D( 128, kernel_size= 4, strides= 2, padding= "same"),
  9. layers.LeakyReLU(alpha= 0.2),
  10. layers.Flatten(),
  11. layers.Dropout( 0.2),
  12. layers.Dense( 1, activation= "sigmoid"),
  13. ],
  14. name= "discriminator",
  15. )
  16. discriminator.summary()
Model: "discriminator"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 32, 32, 64)        3136      
_________________________________________________________________
leaky_re_lu (LeakyReLU)      (None, 32, 32, 64)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 16, 16, 128)       131200    
_________________________________________________________________
leaky_re_lu_1 (LeakyReLU)    (None, 16, 16, 128)       0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 8, 8, 128)         262272    
_________________________________________________________________
leaky_re_lu_2 (LeakyReLU)    (None, 8, 8, 128)         0         
_________________________________________________________________
flatten (Flatten)            (None, 8192)              0         
_________________________________________________________________
dropout (Dropout)            (None, 8192)              0         
_________________________________________________________________
dense (Dense)                (None, 1)                 8193      
=================================================================
Total params: 404,801
Trainable params: 404,801
Non-trainable params: 0
 

3.2 G网络


  
  1. latent_dim = 128
  2. generator = keras.Sequential(
  3. [
  4. keras.Input(shape=(latent_dim,)),
  5. layers.Dense( 8 * 8 * 128),
  6. layers.Reshape(( 8, 8, 128)),
  7. layers.Conv2DTranspose( 128, kernel_size= 4, strides= 2, padding= "same"),
  8. layers.LeakyReLU(alpha= 0.2),
  9. layers.Conv2DTranspose( 256, kernel_size= 4, strides= 2, padding= "same"),
  10. layers.LeakyReLU(alpha= 0.2),
  11. layers.Conv2DTranspose( 512, kernel_size= 4, strides= 2, padding= "same"),
  12. layers.LeakyReLU(alpha= 0.2),
  13. layers.Conv2D( 3, kernel_size= 5, padding= "same", activation= "sigmoid"),
  14. ],
  15. name= "generator",
  16. )
  17. generator.summary()

3.3 重写 train_step


  
  1. class GAN(keras.Model):
  2. def __init__( self, discriminator, generator, latent_dim):
  3. super(GAN, self).__init__()
  4. self.discriminator = discriminator
  5. self.generator = generator
  6. self.latent_dim = latent_dim
  7. def compile( self, d_optimizer, g_optimizer, loss_fn):
  8. super(GAN, self). compile()
  9. self.d_optimizer = d_optimizer
  10. self.g_optimizer = g_optimizer
  11. self.loss_fn = loss_fn
  12. self.d_loss_metric = keras.metrics.Mean(name= "d_loss")
  13. self.g_loss_metric = keras.metrics.Mean(name= "g_loss")
  14. @property
  15. def metrics( self):
  16. return [self.d_loss_metric, self.g_loss_metric]
  17. def train_step( self, real_images):
  18. # 生成噪音
  19. batch_size = tf.shape(real_images)[ 0]
  20. random_latent_vectors = tf.random.normal(shape=(batch_size, self.latent_dim))
  21. # 生成的图片
  22. generated_images = self.generator(random_latent_vectors)
  23. # Combine them with real images
  24. combined_images = tf.concat([generated_images, real_images], axis= 0)
  25. # Assemble labels discriminating real from fake images
  26. labels = tf.concat(
  27. [tf.ones((batch_size, 1)), tf.zeros((batch_size, 1))], axis= 0
  28. )
  29. # Add random noise to the labels - important trick!
  30. labels += 0.05 * tf.random.uniform(tf.shape(labels))
  31. # 训练判别器,生成的当成0,真实的当成1
  32. with tf.GradientTape() as tape:
  33. predictions = self.discriminator(combined_images)
  34. d_loss = self.loss_fn(labels, predictions)
  35. grads = tape.gradient(d_loss, self.discriminator.trainable_weights)
  36. self.d_optimizer.apply_gradients(
  37. zip(grads, self.discriminator.trainable_weights)
  38. )
  39. # Sample random points in the latent space
  40. random_latent_vectors = tf.random.normal(shape=(batch_size, self.latent_dim))
  41. # Assemble labels that say "all real images"
  42. misleading_labels = tf.zeros((batch_size, 1))
  43. # Train the generator (note that we should *not* update the weights
  44. # of the discriminator)!
  45. with tf.GradientTape() as tape:
  46. predictions = self.discriminator(self.generator(random_latent_vectors))
  47. g_loss = self.loss_fn(misleading_labels, predictions)
  48. grads = tape.gradient(g_loss, self.generator.trainable_weights)
  49. self.g_optimizer.apply_gradients( zip(grads, self.generator.trainable_weights))
  50. # Update metrics
  51. self.d_loss_metric.update_state(d_loss)
  52. self.g_loss_metric.update_state(g_loss)
  53. return {
  54. "d_loss": self.d_loss_metric.result(),
  55. "g_loss": self.g_loss_metric.result(),
  56. }

3.4 设置回调函数


  
  1. class GANMonitor(keras.callbacks.Callback):
  2. def __init__( self, num_img=3, latent_dim=128):
  3. self.num_img = num_img
  4. self.latent_dim = latent_dim
  5. def on_epoch_end( self, epoch, logs=None):
  6. random_latent_vectors = tf.random.normal(shape=(self.num_img, self.latent_dim))
  7. generated_images = self.model.generator(random_latent_vectors)
  8. generated_images *= 255
  9. generated_images.numpy()
  10. for i in range(self.num_img):
  11. img = keras.preprocessing.image.array_to_img(generated_images[i])
  12. display.display(img)
  13. img.save( "gen_ani/generated_img_%03d_%d.png" % (epoch, i))

四、训练模型


  
  1. epochs = 100 # In practice, use ~100 epochs
  2. gan = GAN(discriminator=discriminator, generator=generator, latent_dim=latent_dim)
  3. gan. compile(
  4. d_optimizer=keras.optimizers.Adam(learning_rate= 0.0001),
  5. g_optimizer=keras.optimizers.Adam(learning_rate= 0.0001),
  6. loss_fn=keras.losses.BinaryCrossentropy(),
  7. )
  8. gan.fit(
  9. image_ds, epochs=epochs, callbacks=[GANMonitor(num_img= 10, latent_dim=latent_dim)]
  10. )

五、保存模型


  
  1. #保存模型
  2. gan.generator.save( './data/ani_G_model')

生成模型文件:点这里

六、生成漫画脸


  
  1. G_model = tf.keras.models.load_model( './data/ani_G_model/', compile= False)
  2. def randomGenerate():
  3. noise_seed = tf.random.normal([ 16, 128])
  4. predictions = G_model(noise_seed, training= False)
  5. fig = plt.figure(figsize=( 8, 8))
  6. for i in range(predictions.shape[ 0]):
  7. plt.subplot( 4, 4, i+ 1)
  8. img = (predictions[i].numpy() * 255 ).astype( 'int')
  9. plt.imshow(img )
  10. plt.axis( 'off')
  11. plt.show()

  
  1. count = 0
  2. while True:
  3. randomGenerate()
  4. clear_output(wait= True)
  5. time.sleep( 0.1)
  6. if count > 100:
  7. break
  8. count+= 1


转载:https://blog.csdn.net/suic009/article/details/128120410
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场