Why is my GAN providing the same output every time I run it and why is their no variety?

Viewed 219

When ever I run the code below I get all of the same images: gan output

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)
0 Answers
Related