1. 程式人生 > >Tensorflow(1.0)基於對抗生成網路生成明星臉

Tensorflow(1.0)基於對抗生成網路生成明星臉

經過一天的訓練已經基本有了人樣:


原文是基於python2.7切tensorflow版本較老

下面在python3.5和Tensorflow1.0版本執行成功

# -*- coding:utf-8 -*-  

import os
import random
import numpy as np
import tensorflow as tf
from PIL import Image
import scipy.misc as misc
My_DATA='G:\\CelebA\\Img\\img_align_celeba'
train_images=[]
for image_filename in os.listdir(My_DATA):
    if image_filename.endswith('.jpg'):
        train_images.append(os.path.join(My_DATA,image_filename))

random.shuffle(train_images)
batch_size=64
num_batch=len(train_images)//batch_size

Image_size=64
Image_channel=3
def get_next_batch(pointer):
    image_batch=[]
    images=train_images[pointer*batch_size:(pointer+1)*batch_size]
    for img in images:
        arr=Image.open(img)
        arr=arr.resize((Image_size,Image_size))
        arr=np.array(arr)
        arr=arr.astype('float32')/127.5-1
        image_batch.append(arr)
    return image_batch
z_dim=100
noise=tf.placeholder(tf.float32,[None,z_dim],name='noise')
x=tf.placeholder(tf.float32,[batch_size,Image_size,Image_size,Image_channel],name='X')
train_phase=tf.placeholder(tf.bool)

def batch_norm(x, beta, gamma, phase_train, scope='bn', decay=0.9, eps=1e-5):
    with tf.variable_scope(scope):
        #beta = tf.get_variable(name='beta', shape=[n_out], initializer=tf.constant_initializer(0.0), trainable=True)
        #gamma = tf.get_variable(name='gamma', shape=[n_out], initializer=tf.random_normal_initializer(1.0, stddev), trainable=True)
        batch_mean, batch_var = tf.nn.moments(x, [0, 1, 2], name='moments')
        ema = tf.train.ExponentialMovingAverage(decay=decay)

        def mean_var_with_update():
            ema_apply_op = ema.apply([batch_mean, batch_var])
            with tf.control_dependencies([ema_apply_op]):
                return tf.identity(batch_mean), tf.identity(batch_var)

        mean, var = tf.cond(phase_train, mean_var_with_update, lambda: (ema.average(batch_mean), ema.average(batch_var)))
        normed = tf.nn.batch_normalization(x, mean, var, beta, gamma, eps)
    return normed

generator_variables_dict = {
        "W_1": tf.Variable(tf.truncated_normal([z_dim, 2 * Image_size * Image_size], stddev=0.02), name='Generator/W_1'),
        "b_1": tf.Variable(tf.constant(0.0, shape=[2 * Image_size * Image_size]), name='Generator/b_1'),
        'beta_1': tf.Variable(tf.constant(0.0, shape=[512]), name='Generator/beta_1'),
        'gamma_1': tf.Variable(tf.random_normal(shape=[512], mean=1.0, stddev=0.02), name='Generator/gamma_1'),

        "W_2": tf.Variable(tf.truncated_normal([5, 5, 256, 512], stddev=0.02), name='Generator/W_2'),
        "b_2": tf.Variable(tf.constant(0.0, shape=[256]), name='Generator/b_2'),
        'beta_2': tf.Variable(tf.constant(0.0, shape=[256]), name='Generator/beta_2'),
        'gamma_2': tf.Variable(tf.random_normal(shape=[256], mean=1.0, stddev=0.02), name='Generator/gamma_2'),

        "W_3": tf.Variable(tf.truncated_normal([5, 5, 128, 256], stddev=0.02), name='Generator/W_3'),
        "b_3": tf.Variable(tf.constant(0.0, shape=[128]), name='Generator/b_3'),
        'beta_3': tf.Variable(tf.constant(0.0, shape=[128]), name='Generator/beta_3'),
        'gamma_3': tf.Variable(tf.random_normal(shape=[128], mean=1.0, stddev=0.02), name='Generator/gamma_3'),
        
        "W_4": tf.Variable(tf.truncated_normal([5, 5, 64, 128], stddev=0.02), name='Generator/W_4'),
        "b_4": tf.Variable(tf.constant(0.0, shape=[64]), name='Generator/b_4'),
        'beta_4': tf.Variable(tf.constant(0.0, shape=[64]), name='Generator/beta_4'),
        'gamma_4': tf.Variable(tf.random_normal(shape=[64], mean=1.0, stddev=0.02), name='Generator/gamma_4'),

        "W_5": tf.Variable(tf.truncated_normal([5, 5, Image_channel, 64], stddev=0.02), name='Generator/W_5'),
        "b_5": tf.Variable(tf.constant(0.0, shape=[Image_channel]), name='Generator/b_5')
}
def generator(noise):
        with tf.variable_scope("Generator"):
            out_1 = tf.matmul(noise, generator_variables_dict["W_1"]) + generator_variables_dict['b_1']
            out_1 = tf.reshape(out_1, [-1, Image_size//16, Image_size//16, 512])
            out_1 = batch_norm(out_1, generator_variables_dict["beta_1"], generator_variables_dict["gamma_1"], train_phase, scope='bn_1')
            out_1 = tf.nn.relu(out_1, name='relu_1')
    
            out_2 = tf.nn.conv2d_transpose(out_1, generator_variables_dict['W_2'],  output_shape=tf.stack([tf.shape(out_1)[0], Image_size//8, Image_size//8, 256]), strides=[1, 2, 2, 1], padding='SAME')
            out_2 = tf.nn.bias_add(out_2, generator_variables_dict['b_2'])
            out_2 = batch_norm(out_2, generator_variables_dict["beta_2"], generator_variables_dict["gamma_2"], train_phase, scope='bn_2')
            out_2 = tf.nn.relu(out_2, name='relu_2')
    
            out_3 = tf.nn.conv2d_transpose(out_2, generator_variables_dict['W_3'],  output_shape=tf.stack([tf.shape(out_2)[0], Image_size//4, Image_size//4, 128]), strides=[1, 2, 2, 1], padding='SAME')
            out_3 = tf.nn.bias_add(out_3, generator_variables_dict['b_3'])
            out_3 = batch_norm(out_3, generator_variables_dict["beta_3"], generator_variables_dict["gamma_3"], train_phase, scope='bn_3')
            out_3 = tf.nn.relu(out_3, name='relu_3')
    
            out_4 = tf.nn.conv2d_transpose(out_3, generator_variables_dict['W_4'],  output_shape=tf.stack([tf.shape(out_3)[0], Image_size//2, Image_size//2, 64]), strides=[1, 2, 2, 1], padding='SAME')
            out_4 = tf.nn.bias_add(out_4, generator_variables_dict['b_4'])
            out_4 = batch_norm(out_4, generator_variables_dict["beta_4"], generator_variables_dict["gamma_4"], train_phase, scope='bn_4')
            out_4 = tf.nn.relu(out_4, name='relu_4')
    
            out_5 = tf.nn.conv2d_transpose(out_4, generator_variables_dict['W_5'],  output_shape=tf.stack([tf.shape(out_4)[0], Image_size, Image_size, Image_channel]), strides=[1, 2, 2, 1], padding='SAME')
            out_5 = tf.nn.bias_add(out_5, generator_variables_dict['b_5'])
            out_5 = tf.nn.tanh(out_5, name='tanh_5')
    
            return out_5
discriminator_variables_dict = {
    "W_1": tf.Variable(tf.truncated_normal([4, 4, Image_channel, 32], stddev=0.002), name='Discriminator/W_1'),
    "b_1": tf.Variable(tf.constant(0.0, shape=[32]), name='Discriminator/b_1'),
    'beta_1': tf.Variable(tf.constant(0.0, shape=[32]), name='Discriminator/beta_1'),
    'gamma_1': tf.Variable(tf.random_normal(shape=[32], mean=1.0, stddev=0.02), name='Discriminator/gamma_1'),
        
    "W_2": tf.Variable(tf.truncated_normal([4, 4, 32, 64], stddev=0.002), name='Discriminator/W_2'),
    "b_2": tf.Variable(tf.constant(0.0, shape=[64]), name='Discriminator/b_2'),
    'beta_2': tf.Variable(tf.constant(0.0, shape=[64]), name='Discriminator/beta_2'),
    'gamma_2': tf.Variable(tf.random_normal(shape=[64], mean=1.0, stddev=0.02), name='Discriminator/gamma_2'),
        
    "W_3": tf.Variable(tf.truncated_normal([4, 4, 64, 128], stddev=0.002), name='Discriminator/W_3'),
    "b_3": tf.Variable(tf.constant(0.0, shape=[128]), name='Discriminator/b_3'),
    'beta_3': tf.Variable(tf.constant(0.0, shape=[128]), name='Discriminator/beta_3'),
    'gamma_3': tf.Variable(tf.random_normal(shape=[128], mean=1.0, stddev=0.02), name='Discriminator/gamma_3'),
        
    "W_4": tf.Variable(tf.truncated_normal([4, 4, 64, 128], stddev=0.002), name='Discriminator/W_4'),
    "b_4": tf.Variable(tf.constant(0.0, shape=[64]), name='Discriminator/b_4'),
    'beta_4': tf.Variable(tf.constant(0.0, shape=[64]), name='Discriminator/beta_4'),
    'gamma_4': tf.Variable(tf.random_normal(shape=[64], mean=1.0, stddev=0.02), name='Discriminator/gamma_4'),
        
    "W_5": tf.Variable(tf.truncated_normal([4, 4, 32, 64], stddev=0.002), name='Discriminator/W_5'),
    "b_5": tf.Variable(tf.constant(0.0, shape=[32]), name='Discriminator/b_5'),
    'beta_5': tf.Variable(tf.constant(0.0, shape=[32]), name='Discriminator/beta_5'),
    'gamma_5': tf.Variable(tf.random_normal(shape=[32], mean=1.0, stddev=0.02), name='Discriminator/gamma_5'),
        
    "W_6": tf.Variable(tf.truncated_normal([4, 4, 3, 32], stddev=0.002), name='Discriminator/W_6'),
    "b_6": tf.Variable(tf.constant(0.0, shape=[3]), name='Discriminator/b_6')
}
def discriminator(input_images):
    with tf.variable_scope("Discriminator"):
            out_1 = tf.nn.conv2d(input_images, discriminator_variables_dict['W_1'], strides=[1, 2, 2, 1], padding='SAME')
            out_1 = tf.nn.bias_add(out_1, discriminator_variables_dict['b_1'])
            out_1 = batch_norm(out_1, discriminator_variables_dict['beta_1'], discriminator_variables_dict['gamma_1'], train_phase, scope='bn_1')
            out_1 = tf.maximum(0.2 * out_1, out_1, 'leaky_relu_1')

            out_2 = tf.nn.conv2d(out_1, discriminator_variables_dict['W_2'], strides=[1, 2, 2, 1], padding='SAME')
            out_2 = tf.nn.bias_add(out_2, discriminator_variables_dict['b_2'])
            out_2 = batch_norm(out_2, discriminator_variables_dict['beta_2'], discriminator_variables_dict['gamma_2'], train_phase, scope='bn_2')
            out_2 = tf.maximum(0.2 * out_2, out_2, 'leaky_relu_2')

            out_3 = tf.nn.conv2d(out_2, discriminator_variables_dict['W_3'], strides=[1, 2, 2, 1], padding='SAME')
            out_3 = tf.nn.bias_add(out_3, discriminator_variables_dict['b_3'])
            out_3 = batch_norm(out_3, discriminator_variables_dict['beta_3'], discriminator_variables_dict['gamma_3'], train_phase, scope='bn_3')
            out_3 = tf.maximum(0.2 * out_3, out_3, 'leaky_relu_3')
            encode=tf.reshape(out_3,[-1,2*Image_size*Image_size])
            
            out_3=tf.reshape(encode,[-1,Image_size//8,Image_size//8,128])
            out_4 = tf.nn.conv2d_transpose(out_3, discriminator_variables_dict['W_4'],  output_shape=tf.stack([tf.shape(out_3)[0], Image_size//4, Image_size//4, 64]), strides=[1, 2, 2, 1], padding='SAME')
            out_4 = tf.nn.bias_add(out_4, discriminator_variables_dict['b_4'])
            out_4 = batch_norm(out_4, discriminator_variables_dict['beta_4'], discriminator_variables_dict['gamma_4'], train_phase, scope='bn_4')
            out_4 = tf.maximum(0.2 * out_4, out_4, 'leaky_relu_4')
        
            out_5 = tf.nn.conv2d_transpose(out_4, discriminator_variables_dict['W_5'],  output_shape=tf.stack([tf.shape(out_4)[0], Image_size//2, Image_size//2, 32]), strides=[1, 2, 2, 1], padding='SAME')
            out_5 = tf.nn.bias_add(out_5, discriminator_variables_dict['b_5'])
            out_5 = batch_norm(out_5, discriminator_variables_dict['beta_5'], discriminator_variables_dict['gamma_5'], train_phase, scope='bn_5')
            out_5 = tf.maximum(0.2 * out_5, out_5, 'leaky_relu_5')
        
            out_6 = tf.nn.conv2d_transpose(out_5, discriminator_variables_dict['W_6'],  output_shape=tf.stack([tf.shape(out_5)[0], Image_size, Image_size, 3]), strides=[1, 2, 2, 1], padding='SAME')
            out_6 = tf.nn.bias_add(out_6, discriminator_variables_dict['b_6'])
            decoded = tf.nn.tanh(out_6, name="tanh_6")
        
            return encode, decoded

_, real_decoded = discriminator(x)
real_loss = tf.sqrt(2 * tf.nn.l2_loss(real_decoded - x)) / batch_size
fake_image=generator(noise)
_,fake_decoded=discriminator(fake_image)
fake_loss = tf.sqrt(2 * tf.nn.l2_loss(fake_decoded - fake_image)) / batch_size

margin=20
D_loss=real_loss+tf.maximum(1-fake_loss,0)
G_loss=fake_loss

def optimizer(loss, d_or_g):
    optim = tf.train.AdamOptimizer(learning_rate=0.001, beta1=0.5)
    #print([v.name for v in tf.trainable_variables() if v.name.startswith(d_or_g)])
    var_list = [v for v in tf.trainable_variables() if v.name.startswith(d_or_g)]
    gradient = optim.compute_gradients(loss, var_list=var_list)
    return optim.apply_gradients(gradient)

train_op_G = optimizer(G_loss, 'Generator')
train_op_D = optimizer(D_loss, 'Discriminator')
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer(), feed_dict={train_phase: True})
    saver = tf.train.Saver()

   
    ckpt = tf.train.get_checkpoint_state('.')
    if ckpt != None:
        print(ckpt.model_checkpoint_path)
        saver.restore(sess, ckpt.model_checkpoint_path)
    else:
        print("沒找到模型")

    step = 0
    for i in range(40):
        for j in range(num_batch):
            batch_noise = np.random.uniform(-1.0, 1.0, size=[batch_size, z_dim]).astype(np.float32)

            d_loss, _ = sess.run([D_loss, train_op_D], feed_dict={noise: batch_noise, x: get_next_batch(j), train_phase: True})
            g_loss, _ = sess.run([G_loss, train_op_G], feed_dict={noise: batch_noise, x: get_next_batch(j), train_phase: True})
            g_loss, _ = sess.run([G_loss, train_op_G], feed_dict={noise: batch_noise, x: get_next_batch(j), train_phase: True})

            print(step, d_loss, g_loss)

          
            if step % 100 == 0:
                saver.save(sess, "D://celeba.model", global_step=step)

                test_noise = np.random.uniform(-1.0, 1.0, size=(5, z_dim)).astype(np.float32)
                images = sess.run(fake_image, feed_dict={noise: test_noise, train_phase: False})

                for k in range(5):
                    image = images[k, :, :, :]
                    image += 1
                    image *= 127.5
                    image = np.clip(image, 0, 255).astype(np.uint8)
                    image = np.reshape(image, (Image_size, Image_size, -1))
                    misc.imsave('D://fake_image' + str(step) + str(k) + '.jpg', image)

            step += 1