No account yet ?
main.py
Tested in Anaconda and Python 3.7
import os ## GAN Variants from GAN import GAN from CGAN import CGAN from infoGAN import infoGAN from ACGAN import ACGAN from EBGAN import EBGAN from WGAN import WGAN from WGAN_GP import WGAN_GP from DRAGAN import DRAGAN from LSGAN import LSGAN from BEGAN import BEGAN ## VAE Variants from VAE import VAE from CVAE import CVAE from utils import show_all_variables from utils import check_folder import tensorflow as tf import argparse """parsing and configuration""" def parse_args(): desc = "Tensorflow implementation of GAN collections" parser = argparse.ArgumentParser(description=desc) parser.add_argument('--gan_type', type=str, default='GAN', choices=['GAN', 'CGAN', 'infoGAN', 'ACGAN', 'EBGAN', 'BEGAN', 'WGAN', 'WGAN_GP', 'DRAGAN', 'LSGAN', 'VAE', 'CVAE'], help='The type of GAN', required=True) parser.add_argument('--dataset', type=str, default='mnist', choices=['mnist', 'fashion-mnist', 'celebA'], help='The name of dataset') parser.add_argument('--epoch', type=int, default=20, help='The number of epochs to run') parser.add_argument('--batch_size', type=int, default=64, help='The size of batch') parser.add_argument('--z_dim', type=int, default=62, help='Dimension of noise vector') parser.add_argument('--checkpoint_dir', type=str, default='checkpoint', help='Directory name to save the checkpoints') parser.add_argument('--result_dir', type=str, default='results', help='Directory name to save the generated images') parser.add_argument('--log_dir', type=str, default='logs', help='Directory name to save training logs') return check_args(parser.parse_args()) """checking arguments""" def check_args(args): # --checkpoint_dir check_folder(args.checkpoint_dir) # --result_dir check_folder(args.result_dir) # --result_dir check_folder(args.log_dir) # --epoch assert args.epoch >= 1, 'number of epochs must be larger than or equal to one' # --batch_size assert args.batch_size >= 1, 'batch size must be larger than or equal to one' # --z_dim assert args.z_dim >= 1, 'dimension of noise vector must be larger than or equal to one' return args """main""" def main(): # parse arguments args = parse_args() if args is None: exit() # open session models = [GAN, CGAN, infoGAN, ACGAN, EBGAN, WGAN, WGAN_GP, DRAGAN, LSGAN, BEGAN, VAE, CVAE] with tf.Session(config=tf.ConfigProto(allow_soft_placement=True)) as sess: # declare instance for GAN gan = None for model in models: if args.gan_type == model.model_name: gan = model(sess, epoch=args.epoch, batch_size=args.batch_size, z_dim=args.z_dim, dataset_name=args.dataset, checkpoint_dir=args.checkpoint_dir, result_dir=args.result_dir, log_dir=args.log_dir) if gan is None: raise Exception("[!] There is no option for " + args.gan_type) # build graph gan.build_model() # show network architecture show_all_variables() # launch the graph in a session gan.train() print(" [*] Training finished!") # visualize learned generator gan.visualize_results(args.epoch-1) print(" [*] Testing finished!") if __name__ == '__main__': main()
EBGAN.py
Tested in Anaconda and Python 3.7
#-*- coding: utf-8 -*- from __future__ import division import os import time import tensorflow as tf import numpy as np from ops import * from utils import * class EBGAN(object): model_name = "EBGAN" # name for checkpoint def __init__(self, sess, epoch, batch_size, z_dim, dataset_name, checkpoint_dir, result_dir, log_dir): self.sess = sess self.dataset_name = dataset_name self.checkpoint_dir = checkpoint_dir self.result_dir = result_dir self.log_dir = log_dir self.epoch = epoch self.batch_size = batch_size if dataset_name == 'mnist' or dataset_name == 'fashion-mnist': # parameters self.input_height = 28 self.input_width = 28 self.output_height = 28 self.output_width = 28 self.z_dim = z_dim # dimension of noise-vector self.c_dim = 1 # EBGAN Parameter self.pt_loss_weight = 0.1 self.margin = max(1,self.batch_size/64.) # margin for loss function # usually margin of 1 is enough, but for large batch size it must be larger than 1 # train self.learning_rate = 0.0002 self.beta1 = 0.5 # test self.sample_num = 64 # number of generated images to be saved # load mnist self.data_X, self.data_y = load_mnist(self.dataset_name) # get number of batches for a single epoch self.num_batches = len(self.data_X) // self.batch_size else: raise NotImplementedError # borrowed from https://github.com/shekkizh/EBGAN.tensorflow/blob/master/EBGAN/Faces_EBGAN.py def pullaway_loss(self, embeddings): """ Pull Away loss calculation :param embeddings: The embeddings to be orthogonalized for varied faces. Shape [batch_size, embeddings_dim] :return: pull away term loss """ norm = tf.sqrt(tf.reduce_sum(tf.square(embeddings), 1, keep_dims=True)) normalized_embeddings = embeddings / norm similarity = tf.matmul( normalized_embeddings, normalized_embeddings, transpose_b=True) batch_size = tf.cast(tf.shape(embeddings)[0], tf.float32) pt_loss = (tf.reduce_sum(similarity) - batch_size) / (batch_size * (batch_size - 1)) return pt_loss def discriminator(self, x, is_training=True, reuse=False): # It must be Auto-Encoder style architecture # Architecture : (64)4c2s-FC32-FC64*14*14_BR-(1)4dc2s_S with tf.variable_scope("discriminator", reuse=reuse): net = tf.nn.relu(conv2d(x, 64, 4, 4, 2, 2, name='d_conv1')) net = tf.reshape(net, [self.batch_size, -1]) code = (linear(net, 32, scope='d_fc6')) # bn and relu are excluded since code is used in pullaway_loss net = tf.nn.relu(bn(linear(code, 64 * 14 * 14, scope='d_fc3'), is_training=is_training, scope='d_bn3')) net = tf.reshape(net, [self.batch_size, 14, 14, 64]) out = tf.nn.sigmoid(deconv2d(net, [self.batch_size, 28, 28, 1], 4, 4, 2, 2, name='d_dc5')) # recon loss recon_error = tf.sqrt(2 * tf.nn.l2_loss(out - x)) / self.batch_size return out, recon_error, code def generator(self, z, is_training=True, reuse=False): # Network Architecture is exactly same as in infoGAN (https://arxiv.org/abs/1606.03657) # Architecture : FC1024_BR-FC7x7x128_BR-(64)4dc2s_BR-(1)4dc2s_S with tf.variable_scope("generator", reuse=reuse): net = tf.nn.relu(bn(linear(z, 1024, scope='g_fc1'), is_training=is_training, scope='g_bn1')) net = tf.nn.relu(bn(linear(net, 128 * 7 * 7, scope='g_fc2'), is_training=is_training, scope='g_bn2')) net = tf.reshape(net, [self.batch_size, 7, 7, 128]) net = tf.nn.relu( bn(deconv2d(net, [self.batch_size, 14, 14, 64], 4, 4, 2, 2, name='g_dc3'), is_training=is_training, scope='g_bn3')) out = tf.nn.sigmoid(deconv2d(net, [self.batch_size, 28, 28, 1], 4, 4, 2, 2, name='g_dc4')) return out def build_model(self): # some parameters image_dims = [self.input_height, self.input_width, self.c_dim] bs = self.batch_size """ Graph Input """ # images self.inputs = tf.placeholder(tf.float32, [bs] + image_dims, name='real_images') # noises self.z = tf.placeholder(tf.float32, [bs, self.z_dim], name='z') """ Loss Function """ # output of D for real images D_real_img, D_real_err, D_real_code = self.discriminator(self.inputs, is_training=True, reuse=False) # output of D for fake images G = self.generator(self.z, is_training=True, reuse=False) D_fake_img, D_fake_err, D_fake_code = self.discriminator(G, is_training=True, reuse=True) # get loss for discriminator self.d_loss = D_real_err + tf.maximum(self.margin - D_fake_err,0) # get loss for generator self.g_loss = D_fake_err + self.pt_loss_weight*self.pullaway_loss(D_fake_code) """ Training """ # divide trainable variables into a group for D and a group for G t_vars = tf.trainable_variables() d_vars = [var for var in t_vars if 'd_' in var.name] g_vars = [var for var in t_vars if 'g_' in var.name] # optimizers with tf.control_dependencies(tf.get_collection(tf.GraphKeys.UPDATE_OPS)): self.d_optim = tf.train.AdamOptimizer(self.learning_rate, beta1=self.beta1) \ .minimize(self.d_loss, var_list=d_vars) self.g_optim = tf.train.AdamOptimizer(self.learning_rate*5, beta1=self.beta1) \ .minimize(self.g_loss, var_list=g_vars) """" Testing """ # for test self.fake_images = self.generator(self.z, is_training=False, reuse=True) """ Summary """ d_loss_real_sum = tf.summary.scalar("d_error_real", D_real_err) d_loss_fake_sum = tf.summary.scalar("d_error_fake", D_fake_err) d_loss_sum = tf.summary.scalar("d_loss", self.d_loss) g_loss_sum = tf.summary.scalar("g_loss", self.g_loss) # final summary operations self.g_sum = tf.summary.merge([d_loss_fake_sum, g_loss_sum]) self.d_sum = tf.summary.merge([d_loss_real_sum, d_loss_sum]) def train(self): # initialize all variables tf.global_variables_initializer().run() # graph inputs for visualize training results self.sample_z = np.random.uniform(-1, 1, size=(self.batch_size , self.z_dim)) # saver to save model self.saver = tf.train.Saver() # summary writer self.writer = tf.summary.FileWriter(self.log_dir + '/' + self.model_name, self.sess.graph) # restore check-point if it exits could_load, checkpoint_counter = self.load(self.checkpoint_dir) if could_load: start_epoch = (int)(checkpoint_counter / self.num_batches) start_batch_id = checkpoint_counter - start_epoch * self.num_batches counter = checkpoint_counter print(" [*] Load SUCCESS") else: start_epoch = 0 start_batch_id = 0 counter = 1 print(" [!] Load failed...") # loop for epoch start_time = time.time() for epoch in range(start_epoch, self.epoch): # get batch data for idx in range(start_batch_id, self.num_batches): batch_images = self.data_X[idx*self.batch_size:(idx+1)*self.batch_size] batch_z = np.random.uniform(-1, 1, [self.batch_size, self.z_dim]).astype(np.float32) # update D network _, summary_str, d_loss = self.sess.run([self.d_optim, self.d_sum, self.d_loss], feed_dict={self.inputs: batch_images, self.z: batch_z}) self.writer.add_summary(summary_str, counter) # update G network _, summary_str, g_loss = self.sess.run([self.g_optim, self.g_sum, self.g_loss], feed_dict={self.z: batch_z}) self.writer.add_summary(summary_str, counter) # display training status counter += 1 print("Epoch: [%2d] [%4d/%4d] time: %4.4f, d_loss: %.8f, g_loss: %.8f" \ % (epoch, idx, self.num_batches, time.time() - start_time, d_loss, g_loss)) # save training results for every 300 steps if np.mod(counter, 300) == 0: samples = self.sess.run(self.fake_images, feed_dict={self.z: self.sample_z}) tot_num_samples = min(self.sample_num, self.batch_size) manifold_h = int(np.floor(np.sqrt(tot_num_samples))) manifold_w = int(np.floor(np.sqrt(tot_num_samples))) save_images(samples[:manifold_h * manifold_w, :, :, :], [manifold_h, manifold_w], './' + check_folder(self.result_dir + '/' + self.model_dir) + '/' + self.model_name + '_train_{:02d}_{:04d}.png'.format( epoch, idx)) # After an epoch, start_batch_id is set to zero # non-zero value is only for the first epoch after loading pre-trained model start_batch_id = 0 # save model self.save(self.checkpoint_dir, counter) # show temporal results self.visualize_results(epoch) # save model for final step self.save(self.checkpoint_dir, counter) def visualize_results(self, epoch): tot_num_samples = min(self.sample_num, self.batch_size) image_frame_dim = int(np.floor(np.sqrt(tot_num_samples))) """ random condition, random noise """ z_sample = np.random.uniform(-1, 1, size=(self.batch_size, self.z_dim)) samples = self.sess.run(self.fake_images, feed_dict={self.z: z_sample}) save_images(samples[:image_frame_dim * image_frame_dim, :, :, :], [image_frame_dim, image_frame_dim], check_folder(self.result_dir + '/' + self.model_dir) + '/' + self.model_name + '_epoch%03d' % epoch + '_test_all_classes.png') @property def model_dir(self): return "{}_{}_{}_{}".format( self.model_name, self.dataset_name, self.batch_size, self.z_dim) def save(self, checkpoint_dir, step): checkpoint_dir = os.path.join(checkpoint_dir, self.model_dir, self.model_name) if not os.path.exists(checkpoint_dir): os.makedirs(checkpoint_dir) self.saver.save(self.sess,os.path.join(checkpoint_dir, self.model_name+'.model'), global_step=step) def load(self, checkpoint_dir): import re print(" [*] Reading checkpoints...") checkpoint_dir = os.path.join(checkpoint_dir, self.model_dir, self.model_name) ckpt = tf.train.get_checkpoint_state(checkpoint_dir) if ckpt and ckpt.model_checkpoint_path: ckpt_name = os.path.basename(ckpt.model_checkpoint_path) self.saver.restore(self.sess, os.path.join(checkpoint_dir, ckpt_name)) counter = int(next(re.finditer("(\d+)(?!.*\d)",ckpt_name)).group(0)) print(" [*] Success to read {}".format(ckpt_name)) return True, counter else: print(" [*] Failed to find a checkpoint") return False, 0
utils.py
Tested in Anaconda and Python 3.7
""" Most codes from https://github.com/carpedm20/DCGAN-tensorflow """ from __future__ import division import math import random import pprint import cv2 import imageio import numpy as np from time import gmtime, strftime from six.moves import xrange import matplotlib.pyplot as plt import os, gzip import tensorflow as tf import tensorflow.contrib.slim as slim def load_mnist(dataset_name): data_dir = os.path.join("./data", dataset_name) def extract_data(filename, num_data, head_size, data_size): with gzip.open(filename) as bytestream: bytestream.read(head_size) buf = bytestream.read(data_size * num_data) data = np.frombuffer(buf, dtype=np.uint8).astype(np.float) return data data = extract_data(data_dir + '/train-images-idx3-ubyte.gz', 60000, 16, 28 * 28) trX = data.reshape((60000, 28, 28, 1)) data = extract_data(data_dir + '/train-labels-idx1-ubyte.gz', 60000, 8, 1) trY = data.reshape((60000)) data = extract_data(data_dir + '/t10k-images-idx3-ubyte.gz', 10000, 16, 28 * 28) teX = data.reshape((10000, 28, 28, 1)) data = extract_data(data_dir + '/t10k-labels-idx1-ubyte.gz', 10000, 8, 1) teY = data.reshape((10000)) trY = np.asarray(trY) teY = np.asarray(teY) X = np.concatenate((trX, teX), axis=0) y = np.concatenate((trY, teY), axis=0).astype(np.int) seed = 547 np.random.seed(seed) np.random.shuffle(X) np.random.seed(seed) np.random.shuffle(y) y_vec = np.zeros((len(y), 10), dtype=np.float) for i, label in enumerate(y): y_vec[i, y[i]] = 1.0 return X / 255., y_vec def check_folder(log_dir): if not os.path.exists(log_dir): os.makedirs(log_dir) return log_dir def show_all_variables(): model_vars = tf.trainable_variables() slim.model_analyzer.analyze_vars(model_vars, print_info=True) def get_image(image_path, input_height, input_width, resize_height=64, resize_width=64, crop=True, grayscale=False): image = imread(image_path, grayscale) return transform(image, input_height, input_width, resize_height, resize_width, crop) def save_images(images, size, image_path): return imsave(inverse_transform(images), size, image_path) def imread(path, grayscale = False): if (grayscale): return imageio.imread(path, flatten = True).astype(np.float) else: return imageio.imread(path).astype(np.float) def merge_images(images, size): return inverse_transform(images) def merge(images, size): h, w = images.shape[1], images.shape[2] if (images.shape[3] in (3,4)): c = images.shape[3] img = np.zeros((h * size[0], w * size[1], c)) for idx, image in enumerate(images): i = idx % size[1] j = idx // size[1] img[j * h:j * h + h, i * w:i * w + w, :] = image return img elif images.shape[3]==1: img = np.zeros((h * size[0], w * size[1])) for idx, image in enumerate(images): i = idx % size[1] j = idx // size[1] img[j * h:j * h + h, i * w:i * w + w] = image[:,:,0] return img else: raise ValueError('in merge(images,size) images parameter ''must have dimensions: HxW or HxWx3 or HxWx4') def imsave(images, size, path): image = np.squeeze(merge(images, size)) return imageio.imsave(path, image) def center_crop(x, crop_h, crop_w, resize_h=64, resize_w=64): if crop_w is None: crop_w = crop_h h, w = x.shape[:2] j = int(round((h - crop_h)/2.)) i = int(round((w - crop_w)/2.)) return cv2.resize(x[j:j+crop_h, i:i+crop_w], [resize_h, resize_w]) def transform(image, input_height, input_width, resize_height=64, resize_width=64, crop=True): if crop: cropped_image = center_crop(image, input_height, input_width, resize_height, resize_width) else: cropped_image = cv2.resize(image, [resize_height, resize_width]) return np.array(cropped_image)/127.5 - 1. def inverse_transform(images): return (images+1.)/2. """ Drawing Tools """ # borrowed from https://github.com/ykwon0407/variational_autoencoder/blob/master/variational_bayes.ipynb def save_scattered_image(z, id, z_range_x, z_range_y, name='scattered_image.jpg'): N = 10 plt.figure(figsize=(8, 6)) plt.scatter(z[:, 0], z[:, 1], c=np.argmax(id, 1), marker='o', edgecolor='none', cmap=discrete_cmap(N, 'jet')) plt.colorbar(ticks=range(N)) axes = plt.gca() axes.set_xlim([-z_range_x, z_range_x]) axes.set_ylim([-z_range_y, z_range_y]) plt.grid(True) plt.savefig(name) # borrowed from https://gist.github.com/jakevdp/91077b0cae40f8f8244a def discrete_cmap(N, base_cmap=None): """Create an N-bin discrete colormap from the specified input map""" # Note that if base_cmap is a string or None, you can simply do # return plt.cm.get_cmap(base_cmap, N) # The following works for string, None, or a colormap instance: base = plt.cm.get_cmap(base_cmap) color_list = base(np.linspace(0, 1, N)) cmap_name = base.name + str(N) return base.from_list(cmap_name, color_list, N)
tensorflow-generative-model-collections
Copyright (c) Apache.
python main.py --dataset mnist --gan_type EBGAN --epoch 25 --batch_size 64
python main.py --dataset fashion-mnist --gan_type EBGAN --epoch 40 --batch_size 64
Welcome, my name is Eric Soupet and I am the administrator of the site elodees.com. elodees.com is a state of the art of Artificial Intelligence and aims to be collaborative, you can now offer content such as articles, events, tutorials, ... so don't hesitate !
Platform images credit : Pixabay - Pixabay License | Pexels - Pexels License