-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathflowers.py
More file actions
315 lines (203 loc) · 10.6 KB
/
flowers.py
File metadata and controls
315 lines (203 loc) · 10.6 KB
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
# Tensorflow / Keras
from tensorflow import keras # for building Neural Networks
print('Tensorflow/Keras: %s' % keras.__version__) # print version
from keras.models import Sequential # for assembling a Neural Network model
from keras.layers import Dense, Reshape, Flatten, Conv2D, Conv2DTranspose, ReLU, LeakyReLU, Dropout # adding layers to the Neural Network model
from tensorflow.keras.utils import plot_model # for plotting model diagram
from tensorflow.keras.optimizers import Adam # for model optimization
# Data manipulation
import numpy as np # for data manipulation
print('numpy: %s' % np.__version__) # print version
import sklearn
print('sklearn: %s' % sklearn.__version__) # print version
from sklearn.preprocessing import MinMaxScaler # for scaling inputs used in the generator and discriminator
# Visualization
import cv2 # for ingesting images
print('OpenCV: %s' % cv2.__version__) # print version
import matplotlib
import matplotlib.pyplot as plt # or data visualizationa
print('matplotlib: %s' % matplotlib.__version__) # print version
import graphviz # for showing model diagram
print('graphviz: %s' % graphviz.__version__) # print version
# Other utilities
import sys
import os
# Specify the location of images after you have downloaded them
ImgLocation = 'C:/Users/Alkios/Downloads/flowgan/imgs'
# Create a list to store image paths
ImagePaths = []
for image in list(os.listdir(ImgLocation)):
ImagePaths = ImagePaths+[ImgLocation + "/"+image]
# Load images and resize to 64 x 64
data_lowres = []
for img in ImagePaths:
image = cv2.imread(img)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image_lowres = cv2.resize(image, (64, 64))
data_lowres.append(image_lowres)
# Convert image data to numpy array and standardize values (divide by 255 since RGB values ranges from 0 to 255)
data_lowres = np.array(data_lowres, dtype = "float") / 255.0
# Show data shape
print("Shape of data_lowres: ", data_lowres.shape)
# Display 10 real images
fig, axs = plt.subplots(2, 5, sharey = False, tight_layout = True, figsize = (16,9), facecolor = 'white')
n = 0
for i in range(0,2):
for j in range(0,5):
axs[i,j].matshow(data_lowres[n])
n=n+1
plt.show()
# Scaler
scaler = MinMaxScaler(feature_range=(-1, 1))
# Select images that we want to use for model trainng
data = data_lowres.copy()
print("Original shape of the data: ", data.shape)
# Reshape array
data = data.reshape(-1, 1)
print("Reshaped data: ", data.shape)
# Fit the scaler
scaler.fit(data)
# Scale the array
data = scaler.transform(data)
# Reshape back to the original shape
data = data.reshape(data_lowres.shape[0], 64, 64, 3)
print("Shape of the scaled array: ", data.shape)
def generator(latent_dim):
model = Sequential(name="Generator") # Model
# Hidden Layer 1: Start with 8 x 8 image
n_nodes = 8 * 8 * 128 # number of nodes in the first hidden layer
model.add(Dense(n_nodes, input_dim=latent_dim, name='Generator-Hidden-Layer-1'))
model.add(Reshape((8, 8, 128), name='Generator-Hidden-Layer-Reshape-1'))
# Hidden Layer 2: Upsample to 16 x 16
model.add(Conv2DTranspose(filters=128, kernel_size=(4,4), strides=(2,2), padding='same', name='Generator-Hidden-Layer-2'))
model.add(ReLU(name='Generator-Hidden-Layer-Activation-2'))
# Hidden Layer 3: Upsample to 32 x 32
model.add(Conv2DTranspose(filters=256, kernel_size=(4,4), strides=(2,2), padding='same', name='Generator-Hidden-Layer-3'))
model.add(ReLU(name='Generator-Hidden-Layer-Activation-3'))
# Hidden Layer 4: Upsample to 64 x 64
model.add(Conv2DTranspose(filters=512, kernel_size=(4,4), strides=(2,2), padding='same', name='Generator-Hidden-Layer-4'))
model.add(ReLU(name='Generator-Hidden-Layer-Activation-4'))
# Output Layer (Note, we use 3 filters because we have 3 channels for a color image. Grayscale would have only 1 channel)
model.add(Conv2D(filters=3, kernel_size=(5,5), activation='tanh', padding='same', name='Generator-Output-Layer'))
return model
# Instantiate
latent_dim=100 # Our latent space has 100 dimensions. We can change it to any number
gen_model = generator(latent_dim)
# Show model summary and plot model diagram
gen_model.summary()
#plot_model(gen_model, show_shapes=True, show_layer_names=True, dpi=400)
def discriminator(in_shape=(64,64,3)):
model = Sequential(name="Discriminator") # Model
# Hidden Layer 1
model.add(Conv2D(filters=64, kernel_size=(4,4), strides=(2, 2), padding='same', input_shape=in_shape, name='Discriminator-Hidden-Layer-1'))
model.add(LeakyReLU(alpha=0.2, name='Discriminator-Hidden-Layer-Activation-1'))
# Hidden Layer 2
model.add(Conv2D(filters=128, kernel_size=(4,4), strides=(2, 2), padding='same', input_shape=in_shape, name='Discriminator-Hidden-Layer-2'))
model.add(LeakyReLU(alpha=0.2, name='Discriminator-Hidden-Layer-Activation-2'))
# Hidden Layer 3
model.add(Conv2D(filters=128, kernel_size=(4,4), strides=(2, 2), padding='same', input_shape=in_shape, name='Discriminator-Hidden-Layer-3'))
model.add(LeakyReLU(alpha=0.2, name='Discriminator-Hidden-Layer-Activation-3'))
# Flatten and Output Layers
model.add(Flatten(name='Discriminator-Flatten-Layer')) # Flatten the shape
model.add(Dropout(0.3, name='Discriminator-Flatten-Layer-Dropout')) # Randomly drop some connections for better generalization
model.add(Dense(1, activation='sigmoid', name='Discriminator-Output-Layer')) # Output Layer
# Compile the model
model.compile(loss='binary_crossentropy', optimizer=Adam(learning_rate=0.0002, beta_1=0.5), metrics=['accuracy'])
return model
# Instantiate
dis_model = discriminator()
# Show model summary and plot model diagram
dis_model.summary()
#plot_model(dis_model, show_shapes=True, show_layer_names=True, dpi=400)
def def_gan(generator, discriminator):
# We don't want to train the weights of discriminator at this stage. Hence, make it not trainable
discriminator.trainable = False
# Combine
model = Sequential(name="DCGAN") # GAN Model
model.add(generator) # Add Generator
model.add(discriminator) # Add Disriminator
# Compile the model
model.compile(loss='binary_crossentropy', optimizer=Adam(learning_rate=0.0002, beta_1=0.5))
return model
# Instantiate
gan_model = def_gan(gen_model, dis_model)
# Show model summary and plot model diagram
gan_model.summary()
#plot_model(gan_model, show_shapes=True, show_layer_names=True, dpi=400)
def real_samples(n, dataset):
# Samples of real data
X = dataset[np.random.choice(dataset.shape[0], n, replace=True), :]
# Class labels
y = np.ones((n, 1))
return X, y
def latent_vector(latent_dim, n):
# Generate points in the latent space
latent_input = np.random.randn(latent_dim * n)
# Reshape into a batch of inputs for the network
latent_input = latent_input.reshape(n, latent_dim)
return latent_input
def performance_summary(generator, discriminator, dataset, latent_dim, n=50):
# Get samples of the real data
x_real, y_real = real_samples(n, dataset)
# Evaluate the descriminator on real data
_, real_accuracy = discriminator.evaluate(x_real, y_real, verbose=0)
# Get fake (generated) samples
x_fake, y_fake = fake_samples(generator, latent_dim, n)
# Evaluate the descriminator on fake (generated) data
_, fake_accuracy = discriminator.evaluate(x_fake, y_fake, verbose=0)
# summarize discriminator performance
print("*** Evaluation ***")
print("Discriminator Accuracy on REAL images: ", real_accuracy)
print("Discriminator Accuracy on FAKE (generated) images: ", fake_accuracy)
# Display 6 fake images
x_fake_inv_trans=x_fake.reshape(-1, 1)
x_fake_inv_trans=scaler.inverse_transform(x_fake_inv_trans)
x_fake_inv_trans=x_fake_inv_trans.reshape(n, 64, 64, 3)
fig, axs = plt.subplots(2, 3, sharey=False, tight_layout=True, figsize=(12,6), facecolor='white')
k=0
for i in range(0,2):
for j in range(0,3):
axs[i,j].matshow(x_fake_inv_trans[k])
k=k+1
plt.show()
def fake_samples(generator, latent_dim, n):
# Generate points in latent space
latent_output = latent_vector(latent_dim, n)
# Predict outputs (i.e., generate fake samples)
X = generator.predict(latent_output)
# Create class labels
y = np.zeros((n, 1))
return X, y
def train(g_model, d_model, gan_model, dataset, latent_dim, n_epochs=3001, n_batch=32, n_eval=100):
# Our batch to train the discriminator will consist of half real images and half fake (generated) images
half_batch = int(n_batch / 2)
# We will manually enumare epochs
for i in range(n_epochs):
# Discriminator training
# Prep real samples
x_real, y_real = real_samples(half_batch, dataset)
# Prep fake (generated) samples
x_fake, y_fake = fake_samples(g_model, latent_dim, half_batch)
# Train the discriminator using real and fake samples
X, y = np.vstack((x_real, x_fake)), np.vstack((y_real, y_fake))
discriminator_loss, _ = d_model.train_on_batch(X, y)
# Generator training
# Get values from the latent space to be used as inputs for the generator
x_gan = latent_vector(latent_dim, n_batch)
# While we are generating fake samples,
# we want GAN generator model to create examples that resemble the real ones,
# hence we want to pass labels corresponding to real samples, i.e. y=1, not 0.
y_gan = np.ones((n_batch, 1))
# Train the generator via a composite GAN model
generator_loss = gan_model.train_on_batch(x_gan, y_gan)
# Evaluate the model at every n_eval epochs
if (i) % n_eval == 0:
print("Epoch number: ", i)
print("*** Training ***")
print("Discriminator Loss ", discriminator_loss)
print("Generator Loss: ", generator_loss)
performance_summary(g_model, d_model, dataset, latent_dim)
train(gen_model, dis_model, gan_model, data, latent_dim)
gen_model.save_weights("genmodel.h5")
dis_model.save_weights("dis_model.h5")
gan_model.save_weights("gan_model.h5")