forked from kame-hame-haa/generatorNeuralNetwork
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDCGAN_walkthrough.py
173 lines (133 loc) · 7.64 KB
/
DCGAN_walkthrough.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#Import the libraries we will need.
import tensorflow as tf
import numpy as np
import input_data
import matplotlib.pyplot as plt
import tensorflow.contrib.slim as slim
import os
import scipy.misc
import scipy
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
# This function performns a leaky relu activation, which is needed for the discriminator network.
def lrelu(x, leak=0.2, name="lrelu"):
with tf.variable_scope(name):
f1 = 0.5 * (1 + leak)
f2 = 0.5 * (1 - leak)
return f1 * x + f2 * abs(x)
# The below functions are taken from carpdem20's implementation https://github.com/carpedm20/DCGAN-tensorflow
# They allow for saving sample images from the generator to follow progress
def save_images(images, size, image_path):
return imsave(inverse_transform(images), size, image_path)
def imsave(images, size, path):
return scipy.misc.imsave(path, merge(images, size))
def inverse_transform(images):
return (images + 1.) / 2.
def merge(images, size):
h, w = images.shape[1], images.shape[2]
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
return img
def generator(z):
zP = slim.fully_connected(z, 4 * 4 * 256, normalizer_fn=slim.batch_norm, \
activation_fn=tf.nn.relu, scope='g_project', weights_initializer=initializer)
zCon = tf.reshape(zP, [-1, 4, 4, 256])
gen1 = slim.convolution2d_transpose( \
zCon, num_outputs=64, kernel_size=[5, 5], stride=[2, 2], \
padding="SAME", normalizer_fn=slim.batch_norm, \
activation_fn=tf.nn.relu, scope='g_conv1', weights_initializer=initializer)
gen2 = slim.convolution2d_transpose( \
gen1, num_outputs=32, kernel_size=[5, 5], stride=[2, 2], \
padding="SAME", normalizer_fn=slim.batch_norm, \
activation_fn=tf.nn.relu, scope='g_conv2', weights_initializer=initializer)
gen3 = slim.convolution2d_transpose( \
gen2, num_outputs=16, kernel_size=[5, 5], stride=[2, 2], \
padding="SAME", normalizer_fn=slim.batch_norm, \
activation_fn=tf.nn.relu, scope='g_conv3', weights_initializer=initializer)
g_out = slim.convolution2d_transpose( \
gen3, num_outputs=1, kernel_size=[32, 32], padding="SAME", \
biases_initializer=None, activation_fn=tf.nn.tanh, \
scope='g_out', weights_initializer=initializer)
return g_out
def discriminator(bottom, reuse=False):
dis1 = slim.convolution2d(bottom, 16, [4, 4], stride=[2, 2], padding="SAME", \
biases_initializer=None, activation_fn=lrelu, \
reuse=reuse, scope='d_conv1', weights_initializer=initializer)
dis2 = slim.convolution2d(dis1, 32, [4, 4], stride=[2, 2], padding="SAME", \
normalizer_fn=slim.batch_norm, activation_fn=lrelu, \
reuse=reuse, scope='d_conv2', weights_initializer=initializer)
dis3 = slim.convolution2d(dis2, 64, [4, 4], stride=[2, 2], padding="SAME", \
normalizer_fn=slim.batch_norm, activation_fn=lrelu, \
reuse=reuse, scope='d_conv3', weights_initializer=initializer)
d_out = slim.fully_connected(slim.flatten(dis3), 1, activation_fn=tf.nn.sigmoid, \
reuse=reuse, scope='d_out', weights_initializer=initializer)
return d_out
tf.reset_default_graph()
z_size = 100 #Size of z vector used for generator.
#This initializaer is used to initialize all the weights of the network.
initializer = tf.truncated_normal_initializer(stddev=0.02)
#These two placeholders are used for input into the generator and discriminator, respectively.
z_in = tf.placeholder(shape=[None,z_size],dtype=tf.float32) #Random vector
real_in = tf.placeholder(shape=[None,32,32,1],dtype=tf.float32) #Real images
Gz = generator(z_in) #Generates images from random z vectors
Dx = discriminator(real_in) #Produces probabilities for real images
Dg = discriminator(Gz,reuse=True) #Produces probabilities for generator images
#These functions together define the optimization objective of the GAN.
d_loss = -tf.reduce_mean(tf.log(Dx) + tf.log(1.-Dg)) #This optimizes the discriminator.
g_loss = -tf.reduce_mean(tf.log(Dg)) #This optimizes the generator.
tvars = tf.trainable_variables()
#The below code is responsible for applying gradient descent to update the GAN.
trainerD = tf.train.AdamOptimizer(learning_rate=0.0002,beta1=0.5)
trainerG = tf.train.AdamOptimizer(learning_rate=0.0002,beta1=0.5)
d_grads = trainerD.compute_gradients(d_loss,tvars[9:]) #Only update the weights for the discriminator network.
g_grads = trainerG.compute_gradients(g_loss,tvars[0:9]) #Only update the weights for the generator network.
update_D = trainerD.apply_gradients(d_grads)
update_G = trainerG.apply_gradients(g_grads)
batch_size = 128 #Size of image batch to apply at each iteration.
iterations = 500000 #Total number of iterations to use.
sample_directory = './figs' #Directory to save sample images from generator in.
model_directory = './models' #Directory to save trained model to.
init = tf.initialize_all_variables()
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(init)
for i in range(iterations):
zs = np.random.uniform(-1.0,1.0,size=[batch_size,z_size]).astype(np.float32) #Generate a random z batch
xs,_ = mnist.train.next_batch(batch_size) #Draw a sample batch from MNIST dataset.
xs = (np.reshape(xs,[batch_size,28,28,1]) - 0.5) * 2.0 #Transform it to be between -1 and 1
xs = np.lib.pad(xs, ((0,0),(2,2),(2,2),(0,0)),'constant', constant_values=(-1, -1)) #Pad the images so the are 32x32
_,dLoss = sess.run([update_D,d_loss],feed_dict={z_in:zs,real_in:xs}) #Update the discriminator
_,gLoss = sess.run([update_G,g_loss],feed_dict={z_in:zs}) #Update the generator, twice for good measure.
_,gLoss = sess.run([update_G,g_loss],feed_dict={z_in:zs})
if i % 10 == 0:
print("Gen Loss: " + str(gLoss) + " Disc Loss: " + str(dLoss))
z2 = np.random.uniform(-1.0,1.0,size=[batch_size,z_size]).astype(np.float32) #Generate another z batch
newZ = sess.run(Gz,feed_dict={z_in:z2}) #Use new z to get sample images from generator.
if not os.path.exists(sample_directory):
os.makedirs(sample_directory)
#Save sample generator images for viewing training progress.
save_images(np.reshape(newZ[0:36],[36,32,32]),[6,6],sample_directory+'/fig'+str(i)+'.png')
if i % 1000 == 0 and i != 0:
if not os.path.exists(model_directory):
os.makedirs(model_directory)
saver.save(sess,model_directory+'/model-'+str(i)+'.cptk')
print("Saved Model")
sample_directory = './figs' # Directory to save sample images from generator in.
model_directory = './models' # Directory to load trained model from.
batch_size_sample = 36
init = tf.initialize_all_variables()
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(init)
# Reload the model.
print('Loading Model...')
ckpt = tf.train.get_checkpoint_state(model_directory)
saver.restore(sess, ckpt.model_checkpoint_path)
zs = np.random.uniform(-1.0, 1.0, size=[batch_size_sample, z_size]).astype(np.float32) # Generate a random z batch
newZ = sess.run(Gz, feed_dict={z_in: z2}) # Use new z to get sample images from generator.
if not os.path.exists(sample_directory):
os.makedirs(sample_directory)
save_images(np.reshape(newZ[0:batch_size_sample], [36, 32, 32]), [6, 6],
sample_directory + '/fig' + str(i) + '.png')