Generator model doesn't produce pictures during training
I'm training GAN with MNIST and I want to visualize Generator output with noise input during training.
Here is the code:
from numpy import expand_dims
import numpy as np
import time
import tensorflow as tf
from numpy import zeros
from numpy import ones
from numpy import vstack
from numpy.random import randn
from numpy.random import randint
from tensorflow.keras.datasets.mnist import load_data
from tensorflow.keras.optimizers import Adam
from tensorflow.keras import layers, Sequential
import matplotlib.pyplot as plt
from IPython import display
import imageio # for creating gifs
import PIL
(trainX, _), (_, _) = load_data()
# add channels dimension
X = expand_dims(trainX, axis=-1)
# convert from unsigned ints to floats
X = X.astype('float32')
# scale from [0,255] to [0,1]
dataset = X / 255.0
def define_generator(latent_dim):
model = Sequential()
# foundation for 7x7 image
n_nodes = 128 * 7 * 7
model.add(layers.Dense(n_nodes, input_dim=latent_dim))
model.add(layers.LeakyReLU())
model.add(layers.Reshape((7, 7, 128)))
# upsample to 14x14
model.add(layers.Conv2DTranspose(128, (4,4), strides=(2,2), padding='same'))
model.add(layers.LeakyReLU())
# upsample to 28x28
model.add(layers.Conv2DTranspose(128, (4,4), strides=(2,2), padding='same'))
model.add(layers.LeakyReLU())
model.add(layers.Conv2D(1, (7,7), activation='sigmoid', padding='same'))
return model
def define_discriminator(in_shape=(28,28,1)):
model = Sequential()
model.add(layers.Conv2D(128, (5,5), strides=(2, 2), padding='same', input_shape=in_shape))
model.add(layers.LeakyReLU())
model.add(layers.Dropout(0.3))
model.add(layers.Conv2D(128, (5,5), strides=(2, 2), padding='same'))
model.add(layers.LeakyReLU())
model.add(layers.Dropout(0.3))
model.add(layers.Flatten())
model.add(layers.Dense(1, activation='sigmoid'))
# compile model
opt = Adam(lr=0.0002)
model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])
return model
# size of the noise vector
latent_dim = 100
num_examples_to_generate = 16
g_model = define_generator(latent_dim)
d_model = define_discriminator()
# define the combined generator and discriminator model, for updating the generator
def define_gan(g_model, d_model):
# make weights in the discriminator not trainable
d_model.trainable = False
# connect them
model = Sequential()
# add generator
model.add(g_model)
# add the discriminator
model.add(d_model)
# compile model
opt = Adam(lr=0.0002)
model.compile(loss='binary_crossentropy', optimizer=opt)
return model
gan_model = define_gan(g_model, d_model)
# select real samples
def generate_real_samples(dataset, n_samples):
# choose random instances
ix = randint(0, dataset.shape[0], n_samples)
# retrieve selected images
X = dataset[ix]
# generate 'real' class labels (1)
y = ones((n_samples, 1))
return X, y
# generate points in latent space as input for the generator
def generate_latent_points(latent_dim, n_samples):
# generate noise vector for training
x_input = randn(latent_dim * n_samples)
# reshape into a batch of inputs for the network
x_input = x_input.reshape(n_samples, latent_dim)
return x_input
# use the generator to generate n fake examples, with class labels
def generate_fake_samples(g_model, latent_dim, n_samples):
# generate points in latent space
x_input = generate_latent_points(latent_dim, n_samples)
# predict outputs
X = g_model.predict(x_input)
# create 'fake' class labels (0)
y = zeros((n_samples, 1))
return X, y
def generate_and_save_images(epoch):
# for generating the fake images after each epoch
# generate points in the latent space
noise = randn(latent_dim * num_examples_to_generate)
# reshape into a batch of inputs for the network
noise = noise.reshape(num_examples_to_generate, latent_dim)
predictions = g_model(noise, training=False)
fig = plt.figure(figsize=(4, 4))
for i in range(predictions.shape[0]):
plt.subplot(4, 4, i+1)
plt.imshow(predictions[i, :, :, 0], cmap='gray')
plt.axis('off')
plt.savefig('image_at_epoch_{:04d}.png'.format(epoch))
plt.show()
def train(g_model, d_model, gan_model, dataset, latent_dim, n_epochs=60, n_batch=256):
bat_per_epo = int(dataset.shape[0] / n_batch)
half_batch = int(n_batch / 2)
for epoch in range(n_epochs):
start = time.time()
for batch in range(bat_per_epo):
X_real, y_real = generate_real_samples(dataset, half_batch)
X_fake, y_fake = generate_fake_samples(g_model, latent_dim, half_batch)
X = vstack((X_real, X_fake))
y = vstack((y_real, y_fake))
d_loss, _ = d_model.train_on_batch(X,y)
X_gan = generate_latent_points(latent_dim, n_batch)
y_gan = ones((n_batch, 1))
g_loss = gan_model.train_on_batch(X_gan, y_gan)
display.clear_output(wait=True)
generate_and_save_images(epoch + 1)
print('Time for epoch {} is {} sec'.format(epoch + 1, time.time()-start))
display.clear_output(wait=True)
generate_and_save_images(n_epochs)
train(g_model, d_model, gan_model, dataset, latent_dim)
The output that I'm getting is:
Output for train(...) command
There is no error or something just I can't see the output from the Generator with the noise input.
The function that is supposed to show the output is generate_and_save_images
.
when you use cmap="gray"
in plt.imshow()
you must either unscale your output or set vmin and vmax.
From what I see you scaled by dividing 255, so you must multiply your data by 255 or, alternativle set vmin=0, vmax=1
Option1:
plt.imshow(predictions[i, :, :, 0]*255, cmap='gray')
Option2:
plt.imshow(predictions[i, :, :, 0], cmap='gray', vmin=0, vmax=1)