Adesh Gautam
Adesh Gautam

Reputation: 51

DCGAN generating just noise

I am trying to train DCGAN on the "Labeled Faces in the Wild" dataset with image shape (64,64,3). After training for 1000 or more epochs it is generating just noise. The code is as follows:

class GAN():

img_rows = 64
img_cols = 64
channels = 3

optimizer_G = Adam(0.0002, 0.5)
optimizer_D = Adam(0.0002, 0.5)

def __init__(self):

    # Initialize 
    self.img_rows = img_rows
    self.img_cols = img_cols
    self.channels = channels
    self.img_shape = (self.img_rows, self.img_cols, self.channels)
    self.latent_dim = 100

    # Build the discriminator
    self.discriminator = self.build_discriminator()

    # Build the generator
    self.generator = self.build_generator()

    # The generator takes noise as input and generates imgs
    z = Input(shape=(100,))
    img = self.generator(z)

    # For the combined model we will only train the generator
    self.discriminator.trainable = False

    # The discriminator takes generated images as input and determines validity
    validity = self.discriminator(img)

    # The combined model  (stacked generator and discriminator)
    # Trains the generator to fool the discriminator
    self.combined = Model(inputs=z, outputs=validity)
    self.combined.compile(loss='binary_crossentropy', optimizer=optimizer_G)


def build_generator(self):

    input_shape = (self.img_rows, self.img_cols, self.channels)
    mom=0.8

    generator = Sequential()
    generator.add(Dense(units= 512*4*4, kernel_initializer='glorot_uniform', input_dim=100))
    generator.add(Reshape(target_shape=(4, 4, 512)))
    generator.add(BatchNormalization(momentum=0.5))
    generator.add(Activation('relu'))

    generator.add(Conv2DTranspose(filters=256, kernel_size=(5, 5), strides=(2, 2), padding='same',
                                  data_format='channels_last',
                                  kernel_initializer='glorot_uniform'))
    generator.add(BatchNormalization(momentum=mom))
    generator.add(Activation('relu'))

    generator.add(Conv2DTranspose(filters=128, kernel_size=(5, 5), strides=(2, 2), padding='same',
                                  data_format='channels_last',
                                  kernel_initializer='glorot_uniform'))
    generator.add(BatchNormalization(momentum=mom))
    generator.add(Activation('relu'))

    generator.add(Conv2DTranspose(filters=64, kernel_size=(5, 5), strides=(2, 2), padding='same',
                                  data_format='channels_last',
                                  kernel_initializer='glorot_uniform'))
    generator.add(BatchNormalization(momentum=mom))
    generator.add(Activation('relu'))

    generator.add(Conv2DTranspose(filters=3, kernel_size=(5, 5), strides=(2, 2), padding='same',
                                  data_format='channels_last',
                                  kernel_initializer='glorot_uniform'))
    generator.add(Activation('tanh'))
    print("Generator: ")
    generator.summary()

    # optimizer = Adam(lr=0.00015, beta_1=0.5)
    generator.compile(loss='binary_crossentropy', optimizer=optimizer_D, metrics=None)

    return generator

def build_discriminator(self):
    drp = 0.5
    mom=0.8

    discriminator = Sequential()
    discriminator.add(Conv2D(filters=64, kernel_size=(5, 5), strides=(2, 2), padding='same',
                             data_format='channels_last',
                             kernel_initializer='glorot_uniform',
                             input_shape=self.img_shape))
    discriminator.add(LeakyReLU(0.2))
    discriminator.add(Dropout(drp))

    discriminator.add(Conv2D(filters=128, kernel_size=(5, 5), strides=(2, 2), padding='same',
                             data_format='channels_last',
                             kernel_initializer='glorot_uniform'))
    discriminator.add(BatchNormalization(momentum=mom))
    discriminator.add(LeakyReLU(0.2))
    discriminator.add(Dropout(drp))

    discriminator.add(Conv2D(filters=256, kernel_size=(5, 5), strides=(2, 2), padding='same',
                             data_format='channels_last',
                             kernel_initializer='glorot_uniform'))
    discriminator.add(BatchNormalization(momentum=mom))
    discriminator.add(LeakyReLU(0.2))
    discriminator.add(Dropout(drp))

    discriminator.add(Conv2D(filters=512, kernel_size=(5, 5), strides=(2, 2), padding='same',
                             data_format='channels_last',
                             kernel_initializer='glorot_uniform'))
    discriminator.add(BatchNormalization(momentum=mom))
    discriminator.add(LeakyReLU(0.2))
    discriminator.add(Dropout(drp))

    discriminator.add(Flatten())
    discriminator.add(Dense(1))
    discriminator.add(Activation('sigmoid'))
    print("Discriminator: ")
    discriminator.summary()

    # optimizer = Adam(lr=0.0002, beta_1=0.5)
    discriminator.compile(loss='binary_crossentropy', optimizer=optimizer_D, metrics=['accuracy'])

    return discriminator

def load_data(self):
    path = 'faces1'

    num_samples=len(os.listdir(path))
    print(num_samples)
    imlist = os.listdir(path)

    immatrix = np.array([np.array(Image.open(path + '/' + im2).resize((img_rows, img_cols))).flatten() for im2 in imlist], 'f')
    label=np.ones((num_samples,),dtype = int)
    label[0:] = 0      
    train_data = [immatrix,label]
    nb_classes = 2 

    X_train, X_test, y_train, y_test = train_test_split(train_data[0], train_data[1], test_size=0.1, random_state=4)
    X_train = X_train.reshape(X_train.shape[0], img_rows, img_cols, channels)
    X_test = X_test.reshape(X_test.shape[0], img_rows, img_cols, channels)
    X_train = X_train.astype('float32')
    X_test = X_test.astype('float32')
    X_train /= 255
    X_test /= 255

    print('X_train shape:', X_train.shape)
    print(X_train.shape[0], 'train samples')

    Y_train = np_utils.to_categorical(y_train, nb_classes)
    Y_test = np_utils.to_categorical(y_test, nb_classes)

    return X_train, X_test, Y_train, Y_test

def train(self, epochs, batch_size=128, sample_interval=50):

    # Load the dataset
    X_train, _, _, _ = self.load_data()

    # Rescale -1 to 1
    X_train = X_train / 127.5 - 1.
    # print(X_train.shape," 1")
    # X_train = np.expand_dims(X_train, axis=3)
    # print(X_train.shape," 2")
    # print(X_train)

    # Adversarial ground truths
    valid = np.ones((batch_size, 1))
    fake = np.zeros((batch_size, 1))

    d_loss_all, g_loss_all = [], []

    for epoch in range(epochs):

        #  Train Discriminator

        # Select a random batch of images
        idx = np.random.randint(0, X_train.shape[0], batch_size)
        imgs = X_train[idx]
        # print(idx)

        noise = np.random.normal(0, 1, (batch_size, 100))

        # Generate a batch of new images
        gen_imgs = self.generator.predict(noise)

        # Train the discriminator

        d_loss_real = self.discriminator.train_on_batch(imgs, valid)
        d_loss_fake = self.discriminator.train_on_batch(gen_imgs, fake)
        d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)

        #  Train Generator

        noise = np.random.normal(0, 1, (batch_size, 100))

        # Train the generator (to have the discriminator label samples as valid)
        g_loss = self.combined.train_on_batch(noise, valid)

        d_loss_all.append(d_loss[0])
        g_loss_all.append(g_loss)
        # Plot the progress
        print ("%d [D loss: %f, acc.: %.2f%%] [G loss: %f]" % (epoch, d_loss[0], 100*d_loss[1], g_loss))

        # If at save interval => save generated image samples
        if epoch % sample_interval == 0:
            self.sample_images(epoch)

    fig, ax = plt.subplots()

    plt.plot(d_loss_all, label='Discriminator', alpha=0.5)
    plt.plot(g_loss_all, label='Generator', alpha=0.5)
    plt.title("Training Losses")
    plt.legend()
    if epoch == 0:
      plt.legend()
    plt.pause(0.0000000001)
    plt.show()
    plt.savefig('trainingLossPlot.png')

def sample_images(self, epoch):
    r, c = 5, 5
    noise = np.random.normal(0, 1, (r * c, 100))
    gen_imgs = self.generator.predict(noise)

    # Rescale images 0 - 1
    gen_imgs = 0.5 * gen_imgs + 0.5

    fig, axs = plt.subplots(r, c)
    cnt = 0
    for i in range(r):
        for j in range(c):
            axs[i,j].imshow(gen_imgs[cnt, :,:,0], cmap='gray')
            axs[i,j].axis('off')
            cnt += 1
    fig.savefig("images/%d.png" % epoch)
    plt.show()
    plt.close()

gan = GAN()
gan.train(epochs=1000, batch_size=128, sample_interval=100)

The loss plot is like this

The generated images after 1000 epochs are these

The loss is converging of both generator and discriminator still noise is being produced. What tweaks needs to be done?

Upvotes: 1

Views: 1631

Answers (1)

R.A.B
R.A.B

Reputation: 37

Have you tried gen_imgs[cnt, :,:,0].astype(np.uint8) in imshow()? If it's not that it might be the network design...

Good luck!

Upvotes: 0

Related Questions