When ever I run the code below I get all of the same images: 
I have run the GAN a couple of more times and they all produce the same image to the one shown above. I don't know if it has anything to do with the noise, or the way that I am saving the images but I can't figure it out. The end product looks good but I just want there to be variation not just the same picture each time I run the GAN.
I am unsure why this is happening and any help would be appreciated.
random_dim = 100
PREVIEW_ROWS = 3
PREVIEW_COLS = 3
PREVIEW_MARGIN = 4
IMAGE_SIZE = 128
WIDTH = 128
HEIGHT = 128
CHANNELS = 3
def save_images(cnt, noise, generator):
image_array = np.full((PREVIEW_MARGIN + (PREVIEW_ROWS * (IMAGE_SIZE + PREVIEW_MARGIN)), PREVIEW_MARGIN + (PREVIEW_COLS * (IMAGE_SIZE + PREVIEW_MARGIN)), 3), 255, dtype=np.uint8)
generated_images = generator.predict(noise)
generated_images = 0.5 * generated_images + 0.5
image_count = 0
for row in range(PREVIEW_ROWS):
for col in range(PREVIEW_COLS):
r = row * (IMAGE_SIZE + PREVIEW_MARGIN) + PREVIEW_MARGIN
c = col * (IMAGE_SIZE + PREVIEW_MARGIN) + PREVIEW_MARGIN
image_array[r:r + IMAGE_SIZE, c:c + IMAGE_SIZE] = generated_images[image_count] * 255
image_count += 1
output_path = 'output'
if not os.path.exists(output_path):
os.makedirs(output_path)
filename = os.path.join(output_path, f"trained-{cnt}.png")
im = Image.fromarray(image_array)
im.save(filename)
def get_optimizer():
return Adam(lr=0.0002, beta_1=0.5)
def get_generator():
gen_input = Input(shape=random_dim)
generator = Sequential()
generator.add(Dense(128 * 16 * 16, input_dim=random_dim))
generator.add(LeakyReLU())
generator.add(Reshape((16, 16, 128)))
generator.add(Conv2D(256, 5, padding='same'))
generator.add(LeakyReLU())
generator.add(Conv2DTranspose(256, 4, strides=2, padding='same'))
generator.add(LeakyReLU())
generator.add(Conv2DTranspose(256, 4, strides=2, padding='same'))
generator.add(LeakyReLU())
generator.add(Conv2DTranspose(256, 4, strides=2, padding="same"))
generator.add(LeakyReLU())
generator.add(Conv2D(512, 5, padding='same'))
generator.add(LeakyReLU())
generator.add(Conv2D(512, 5, padding='same'))
generator.add(LeakyReLU())
generator.add(Conv2D(3, 7, activation='tanh', padding="same"))
input = Input(shape=(random_dim,))
generated_image = generator(input)
generator.summary()
return Model(input, generated_image)
def get_discriminator():
disc_input = Input(shape=(128, 128, 3))
discriminator = Sequential()
discriminator.add(Conv2D(256, 3, input_shape=(128, 128, 3)))
discriminator.add(LeakyReLU())
discriminator.add(Conv2D(256, 4, strides=2))
discriminator.add(LeakyReLU())
discriminator.add(Conv2D(256, 4, strides=2))
discriminator.add(LeakyReLU())
discriminator.add(Conv2D(256, 4, strides=2))
discriminator.add(LeakyReLU())
discriminator.add(Conv2D(256, 4, strides=2))
discriminator.add(LeakyReLU())
discriminator.add(Flatten())
discriminator.add(Dropout(0.4))
discriminator.add(Dense(1, activation='sigmoid'))
discriminator = Model(disc_input, discriminator(disc_input))
optimizer = RMSprop(
lr = .0001,
clipvalue = 1.0,
decay = 1e-8
)
discriminator.compile(loss='binary_crossentropy', optimizer=optimizer)
discriminator.summary()
return discriminator
def get_gan_network(discriminator, random_dim, generator, optimizer):
# We initially set trainable to False since we only want to train either the
# generator or discriminator at a time
discriminator.trainable = False
# gan input (noise) will be 100-dimensional vectors
gan_input = Input(shape=(random_dim,))
# the output of the generator (an image)
x = generator(gan_input)
# get the output of the discriminator (probability if the image is real or not)
gan_output = discriminator(x)
gan = Model(inputs=gan_input, outputs=gan_output)
gan.compile(loss='binary_crossentropy', optimizer=optimizer)
return gan
X_train = training_data
fixed_noise = np.random.normal(0, 1, (PREVIEW_ROWS * PREVIEW_COLS, 100))
def train(epochs=1, batchSize=128):
batchCount = X_train.shape[0] / batchSize
print(X_train.shape[0])
print('Epochs:', epochs)
print('Batch size:', batchSize)
print('Batches per epoch:', batchCount)
adam = get_optimizer()
generator = get_generator()
discriminator = get_discriminator()
discriminator.trainable = False
gan = get_gan_network(discriminator, random_dim, generator, adam)
y_real = np.ones((batchSize, 1))
y_fake = np.zeros((batchSize, 1))
d_losses = []
a_losses = []
real_scores = []
fake_scores = []
start = 0
for step in tdqm(range(1000)):
start_time = time.time()
latent_vectors = np.random.randn(batchSize, random_dim)
generated = generator.predict(latent_vectors)
real = training_data[start:start + batchSize]
combined_images = np.concatenate([generated, real])
labels = np.concatenate([np.ones((batchSize, 1)), np.zeros((batchSize, 1))])
labels += .05 * np.random.random(labels.shape)
d_loss = discriminator.train_on_batch(combined_images, labels)
d_losses.append(d_loss)
latent_vectors = np.random.randn(batchSize, random_dim)
misleading_targets = np.zeros((batchSize, 1))
a_loss = gan.train_on_batch(latent_vectors, misleading_targets)
a_losses.append(a_loss)
#if step == 1 or step % 20 == 0:
if step % 50 == 49:
save_images(step, fixed_noise, generator)
if __name__ == '__main__':
train(1000, 16)