TensorFlow - 基于 GANs 生成人脸-云服务器玩法在线实验

[复制链接]
查看: 405|回复: 0

1

主题

1

帖子

7

积分

新手上路

Rank: 1

积分
7
发表于 2020-12-28 11:44:29 | 显示全部楼层 |阅读模式

实验内容

TensorFlow是由Google开发的用于数值计算的开源软件库,GANs 是生成对抗网络简称,包含生成网络 G 和判别网络 D,不断调整 G和 D: 优化 G,使它产生的数据,尽可能的让 D 无法区分真假; 优化 D,尽可能区分 G 产生的数据是假冒数据。

免费在线实验地址:点击进入

实验资源:云服务器,没有云服务器的朋友推荐1折抢购:69元/年的阿里云服务器或者88元/年的腾讯云服务器

简介
给定一批样本,基于 TensoFlow 训练 GANs 网络,能够生成类似的新样本,本教程主要参考 Brandon Amos 的 Image Completion 博客,GANs 网络包含 generator 网络(随机信号 z 作为输入,生成人脸图片)和 discriminator 网络(判断图片是否是人脸)。
步骤简介
本教程一共分为四个部分
  • generate_face.py - 读取人脸训练数据、产生随机数;
  • gan_model.py - GANs 网络模型;
  • train_gan.py - 训练 GANs 网络模型;
  • predict_gan.py - 生成人脸。
数据学习
任务时间:时间未知
获取训练数据
我们在腾讯云的 COS 上准备了 CelebA 训练数据,使用 wget 命令获取:
  1. wget http://tensorflow-1253675457.cosgz.myqcloud.com/face/img_align_celeba.zip
  2. unzip -q img_align_celeba.zip
复制代码
数据预处理
安装依赖库
  1. pip install scipy
  2. pip install pillow
复制代码
处理思路:
  • 原始图片大小为 218 x 178 ,从中间裁剪 108 x 108 区域,然后缩小为 64 x 64。
  • 生成维度为 100 服从正态分布的随机向量,作为 generator 网络的输入,生成新的人脸图片。
示例代码:
现在您可以在 /home/ubuntu 目录下创建源文件 generate_face.py,内容可参考:
示例代码:/home/ubuntu/generate_face.py
  1. #-*- coding:utf-8 -*-
  2. import itertools
  3. import os
  4. from glob import glob
  5. import numpy as np
  6. import scipy.misc
  7. import tensorflow as tf


  8. def image_manifold_size(num_images):
  9.     manifold_h = int(np.floor(np.sqrt(num_images)))
  10.     manifold_w = int(np.ceil(np.sqrt(num_images)))
  11.     assert manifold_h * manifold_w == num_images
  12.     return manifold_h, manifold_w

  13. def merge(images, size):
  14.     h, w = images.shape[1], images.shape[2]
  15.     img = np.zeros((int(h * size[0]), int(w * size[1]), 3))
  16.     for idx, image in enumerate(images):
  17.         i = idx % size[1]
  18.         j = idx // size[1]
  19.         img[j*h:j*h+h, i*w:i*w+w, :] = image
  20.     return img

  21. def imsave(images, size, path):
  22.     img = merge(images, size)
  23.     return scipy.misc.imsave(path, (255*img).astype(np.uint8))

  24. def inverse_transform(images):
  25.     return (images+1.)/2.

  26. def save_images(images,size,image_path):
  27.     return imsave(inverse_transform(images), size, image_path)

  28. class generateFace:
  29.     def __init__(self,hparams):
  30.         self.formats = ["png","jpg","jpeg"]
  31.         self.datas_path = self.get_datas_path(hparams.data_root)
  32.         self.datas_size = len(self.datas_path)
  33.         self.crop_h = hparams.crop_h
  34.         self.crop_w = hparams.crop_w
  35.         self.resize_h = hparams.resize_h
  36.         self.resize_w = hparams.resize_w
  37.         self.is_crop = hparams.is_crop
  38.         self.z_dim = hparams.z_dim
  39.         self._index_in_epoch = 0

  40.     def get_datas_path(self,data_root):
  41.         return list(itertools.chain.from_iterable(
  42.             glob(os.path.join(data_root,"*.{}".format(ext))) for ext in self.formats))

  43.     def get_image(self,path):
  44.         img = scipy.misc.imread(path,mode='RGB').astype(np.float)
  45.         if(self.is_crop): #截取中间部分
  46.             h,w = img.shape[:2] #图像宽、高
  47.             assert(h > self.crop_h and w > self.crop_w)
  48.             j = int(round((h - self.crop_h)/2.))
  49.             i = int(round((w - self.crop_w)/2.))
  50.             img = img[j:j+self.crop_h,i:i+self.crop_w]
  51.         img = scipy.misc.imresize(img,[self.resize_h,self.resize_w])
  52.         return np.array(img)/127.5 - 1.

  53.     def get_batch(self,batch_files):
  54.         batch_images = [self.get_image(path) for path in batch_files]
  55.         batch_images = np.array(batch_images).astype(np.float32)
  56.         batch_z = np.random.uniform(-1,1,size=(len(batch_files),self.z_dim))
  57.         return batch_images,batch_z

  58.     def get_sample(self,sample_size):
  59.         assert(self.datas_size > sample_size)
  60.         np.random.shuffle(self.datas_path)
  61.         sample_files = self.datas_path[0:sample_size]
  62.         return self.get_batch(sample_files)

  63.     def next_batch(self,batch_size):
  64.         assert(self.datas_size > batch_size)
  65.         start = self._index_in_epoch
  66.         self._index_in_epoch += batch_size
  67.         if(self._index_in_epoch > self.datas_size):
  68.             np.random.shuffle(self.datas_path)
  69.             start = 0
  70.             self._index_in_epoch = batch_size
  71.         end = self._index_in_epoch
  72.         batch_files = self.datas_path[start:end]
  73.         return self.get_batch(batch_files)
复制代码
生成数据:
我们可以直观感受下生成的数据。可以在终端中一步一步执行下面命令:
  • 启动 python:
    1. cd /home/ubuntu/
    2. python
    3. from generate_face import *
    4. import tensorflow as tf
    复制代码


  • 初始化 generate_face
    1. hparams = tf.contrib.training.HParams(
    2.     data_root = './img_align_celeba',
    3.     crop_h = 108,
    4.     crop_w = 108,
    5.     resize_h = 64,
    6.     resize_w = 64,
    7.     is_crop = True,
    8.     z_dim = 100,
    9.     batch_size = 64,
    10.     sample_size = 64,
    11.     output_h = 64,
    12.     output_w = 64,
    13.     gf_dim = 64,
    14.     df_dim = 64)
    15. face = generateFace(hparams)
    复制代码

  • 查看处理后的人脸数据和随机数据 z
    1. img,z = face.next_batch(1)
    2. z
    3. save_images(img,(1,1),"test.jpg")
    复制代码
    模型学习
  • GANs 模型
    • generator 网络:五层网络,采用反卷积,从 100 维的 z 信号生成人脸图片,网络结构见下图:
    • discriminator 网络:是一个五层的判别网络,网络结构见下图:
    示例代码:
    现在您可以在 /home/ubuntu 目录下创建源文件 gan_model.py,内容可参考:
    示例代码:/home/ubuntu/gan_model.py

    1.         d_loss_real = tf.reduce_mean(
    2.             tf.nn.sigmoid_cross_entropy_with_logits(logits=D_logits,
    3.                                                     labels=tf.ones_like(D)))#对于discriminator,尽量判断images是货真价实
    4.         d_loss_fake = tf.reduce_mean(
    5.             tf.nn.sigmoid_cross_entropy_with_logits(logits=D_logits_,
    6.                                                     labels=tf.zeros_like(D_)))#对于discriminator,尽量判断G是伪冒

    7.         d_loss_real_sum = tf.summary.scalar("d_loss_real",d_loss_real)
    8.         d_loss_fake_sum = tf.summary.scalar("d_loss_fake",d_loss_fake)

    9.         g_loss = tf.reduce_mean(
    10.             tf.nn.sigmoid_cross_entropy_with_logits(logits=D_logits_,
    11.                                                     labels=tf.ones_like(D_)))#对于generator,尽量然D判断G是货真价实的
    12.         d_loss = d_loss_real + d_loss_fake

    13.         g_loss_sum = tf.summary.scalar("g_loss", g_loss)
    14.         d_loss_sum = tf.summary.scalar("d_loss", d_loss)

    15.         t_vars = tf.trainable_variables() #discriminator、generator两个网络参数分开训练
    16.         d_vars = [var for var in t_vars if 'd_' in var.name]
    17.         g_vars = [var for var in t_vars if 'g_' in var.name]

    18.         g_sum = tf.summary.merge([z_sum,d__sum,G_sum,d_loss_fake_sum,g_loss_sum])
    19.         d_sum = tf.summary.merge([z_sum,d_sum,d_loss_real_sum,d_loss_sum])

    20.         return g_loss,d_loss,g_vars,d_vars,g_sum,d_sum,G

    21.     def optimizer(self,g_loss,d_loss,g_vars,d_vars,learning_rate = 0.0002,beta1=0.5):
    22.         d_optim = tf.train.AdamOptimizer(learning_rate,beta1=beta1).minimize(d_loss,global_step=self.global_step,var_list=d_vars)
    23.         g_optim = tf.train.AdamOptimizer(learning_rate,beta1=beta1).minimize(g_loss,var_list=g_vars)
    24.         return d_optim,g_optim
    复制代码
    训练 GANs 模型
    训练 13 万次后,损失函数基本保持不变,单个 GPU 大概需要 6 个小时左右,如果采用 CPU 大概需要 1 天半的时间,你可以调整循环次数,体验下训练过程,可以直接下载我们训练好的模型。
    示例代码:
    现在您可以在 /home/ubuntu 目录下创建源文件 train_gan.py,内容可参考:
    示例代码:/home/ubuntu/train_gan.py
    1. #-*- coding:utf-8 -*-
    2. from generate_face import *
    3. from gan_model import ganModel
    4. import tensorflow as tf

    5. if __name__ == '__main__':
    6.     hparams = tf.contrib.training.HParams(
    7.         data_root = './img_align_celeba',
    8.         crop_h = 108,    #对原始图片裁剪后高
    9.         crop_w = 108,    #对原始图片裁剪后宽
    10.         resize_h = 64,   #对裁剪后图片缩放的高
    11.         resize_w = 64,   #对裁剪图片缩放的宽
    12.         is_crop = True,  #是否裁剪
    13.         z_dim = 100,     #随机噪声z的维度,用户generator生成图片
    14.         batch_size = 64, #批次
    15.         sample_size = 64,#选取作为测试样本
    16.         output_h = 64,   #generator生成图片的高
    17.         output_w = 64,   #generator生成图片的宽
    18.         gf_dim = 64,     #generator的feature map的deep
    19.         df_dim = 64)     #discriminator的feature map的deep
    20.     face = generateFace(hparams)
    21.     sample_images,sample_z = face.get_sample(hparams.sample_size)
    22.     is_training = tf.placeholder(tf.bool,name='is_training')
    23.     images = tf.placeholder(tf.float32, [None,hparams.resize_h,hparams.output_w,3],name='real_images')
    24.     z = tf.placeholder(tf.float32, [None,hparams.z_dim], name='z')
    25.     model = ganModel(hparams)
    26.     g_loss,d_loss,g_vars,d_vars,g_sum,d_sum,G = model.build_model(is_training,images,z)
    27.     d_optim,g_optim = model.optimizer(g_loss,d_loss,g_vars,d_vars)

    28.     saver = tf.train.Saver(tf.global_variables())
    29.     with tf.Session() as sess:
    30.         ckpt = tf.train.get_checkpoint_state('./ckpt')
    31.         if ckpt and tf.train.checkpoint_exists(ckpt.model_checkpoint_path):
    32.             print("Reading model parameters from %s" % ckpt.model_checkpoint_path)
    33.             saver.restore(sess, ckpt.model_checkpoint_path)
    34.         else:
    35.             print("Created model with fresh parameters.")
    36.             sess.run(tf.global_variables_initializer())
    37.         summary_writer = tf.summary.FileWriter("train_gan", sess.graph)
    38.         step = 0
    39.         while True:
    40.             step = model.global_step.eval()
    41.             batch_images,batch_z = face.next_batch(hparams.batch_size)
    42.             #Update D network
    43.             _, summary_str = sess.run([d_optim,d_sum],
    44.                                            feed_dict={images:batch_images, z:batch_z, is_training:True})
    45.             summary_writer.add_summary(summary_str,step)

    46.             #Update G network
    47.             _, summary_str = sess.run([g_optim,g_sum],
    48.                                            feed_dict={z:batch_z, is_training:True})
    49.             summary_writer.add_summary(summary_str,step)

    50.             d_err = d_loss.eval({images:batch_images, z:batch_z, is_training:False})
    51.             g_err = g_loss.eval({z:batch_z,is_training:False})
    52.             print("step:%d,d_loss:%f,g_loss:%f" % (step,d_err,g_err))
    53.             if step%1000 == 0:
    54.                 samples, d_err, g_err = sess.run([G,d_loss,g_loss],
    55.                                                    feed_dict={images:sample_images, z:sample_z, is_training:False})
    56.                 print("sample step:%d,d_err:%f,g_err:%f" % (step,d_err,g_err))
    57.                 save_images(samples,image_manifold_size(samples.shape[0]), './samples/train_{:d}.png'.format(step))
    58.                 saver.save(sess,"./ckpt/gan.ckpt",global_step = step)
    复制代码
    然后执行:
    1. cd /home/ubuntu;
    2. python train_gan.py
    复制代码
    执行结果:
    1. step:1,d_loss:1.276464,g_loss:0.757655
    2. step:2,d_loss:1.245563,g_loss:0.916217
    3. step:3,d_loss:1.253453,g_loss:1.111729
    4. step:4,d_loss:1.381798,g_loss:1.408796
    5. step:5,d_loss:1.643821,g_loss:1.928348
    6. step:6,d_loss:1.770768,g_loss:2.165831
    7. step:7,d_loss:2.172084,g_loss:2.746789
    8. step:8,d_loss:2.192665,g_loss:3.120509
    复制代码
    下载已有模型:
    1. wget http://tensorflow-1253675457.cosgz.myqcloud.com/face/GANs_model.zip
    2. unzip -o GANs_model.zip
    复制代码
    生成人脸
    利用训练好的模型,我们可以开始生成人脸。
    示例代码:
    现在您可以在 /home/ubuntu 目录下创建源文件 predict_gan.py,内容可参考:
    示例代码:/home/ubuntu/predict_gan.py
    1. #-*- coding:utf-8 -*-
    2. from generate_face import *
    3. from gan_model import ganModel
    4. import tensorflow as tf
    5. import numpy as np

    6. if __name__ == '__main__':
    7.     hparams = tf.contrib.training.HParams(
    8.         z_dim = 100,
    9.         batch_size = 1,
    10.         gf_dim = 64,
    11.         df_dim = 64,
    12.         output_h = 64,
    13.         output_w = 64)

    14.     is_training = tf.placeholder(tf.bool,name='is_training')
    15.     z = tf.placeholder(tf.float32, [None,hparams.z_dim], name='z')
    16.     sample_z = np.random.uniform(-1,1,size=(hparams.batch_size,hparams.z_dim))
    17.     model = ganModel(hparams)
    18.     G = model.generator(z,is_training)
    19.     saver = tf.train.Saver()
    20.     with tf.Session() as sess:
    21.         saver.restore(sess,"gan.ckpt-130000")
    22.         samples = sess.run(G,feed_dict={z:sample_z,is_training:False})
    23.         save_images(samples,image_manifold_size(samples.shape[0]),'face.png')
    24.         print("done")
    复制代码
    然后执行:
    1. cd /home/ubuntu
    2. python predict_gan.py
    复制代码
    执行结果:
    现在您可以在 查看 /home/ubuntu/face.png
    完成实验

腾讯云
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

精彩图文



在线客服(工作时间:9:00-22:00)
400-600-6565

内容导航

微信客服

Copyright   ©2015-2019  云服务器社区  Powered by©Discuz!  技术支持:尊托网络     ( 湘ICP备15009499号-1 )