

def generator(input, image_size):

    image_resize = image_size //4
    kernel_size = 5
    layer_filters = [128,64,32,1]
    
    x = Dense(image_resize*image_resize*layer_filters[0])(inputs)
    x = Reshape((image_resize,image_resize,layer_filter[0]))(x)
    for filters in layer_filters:
        if filters >layer_filters[-3]:
            strides =2
        else:
            strides =1
        x = BatchNormalization()(x)
        x = Activation('relu')(x)
        x = Conv2DTranspose(filters=filters,kernel_size=kernel_size, strides=strides,padding='same')(x)
    x = Activation('sigmoid')(x)
    generator = Model(inputs,x,name='generator')
    return generator


def descriminator(inputs):

    kernel_size =5
    layer_filters=[32,64,128,256]

    x =inputs
    for filters in layer_filters:
        if filters == layer_filters[-1]:
            strides = 1
        else:
            strides =2

        x = LeakyReLU(alpha=0.2)(x)
        x = Conv2D(filters=filters, kernel_size=kernel_size,strides=strides,padding='same')(x)
    x = flatten()(x)
    x = Dense(1)(x)
    x = Activation('sigmoid')(x)
    discriminator = Model(inputs,x,name='discriminator')
    return discriminator

def Build_and_train_models():
    (x_train,_),(_,_) = mnist.load_data()
    image_size = x_train.shape[1]
    x_train = x_train.astype('float32') /255
    model_name = "dcgan_mnist"

    latent_size =100
    batch_size =64
    train_steps= 40000
    lr = 2e-4
    decay=6e-8
    input_shape=(image_size,image_size,1)
    inputs = Input(shape=input_shape,name = 'discriminator_input')
    discriminator = discriminator(inputs)
    optimizer = RMSprop(lr = lr*0.5,decay=decay *0.5)
    discriminator.trainable=False
    adversarial - Model(inputs,discriminator(generator(inputs)),name = model_name)
    adversarial.compile(loss= 'binary_crossentropy',optimizer=optimizer,metrics=['accuracy'])
    adversarial.summary()

    models = (generator,discriminator,adversarial)
    params=(batch_size,latent_size,train_steps,model_name)
    train(models,x_train,params)


def train(models, x_train, params):
    """Train the Discriminator and Adversarial Networks
    Alternately train Discriminaor and Adversarial networks by batch.
    Discriminator is trained first with properly real and fake images.
    Adversarial is trained next with fake images pretending to be real
    Generate sample images per save_interval.

    # Arguments
        models (list): Generator, Discriminator, Adversarial models
        x_train (tensor): Train images
        params (list) : Networks parameters
    """
    # the GAN models
    # generator, discriminator, adversarial = models
    # network parameters
    batch_size, latent_size, train_steps, model_name = params
    # the generator image is saved every 500 steps
    save_interval = 500
    # noise vector to see how the generator output evolves
    # during training
    noise_input = np.random.uniform(-1.0, 1.0, size=[16, latent_size])
    # number of elements in train dataset
    train_size = x_train.shape[0]
    for i in range(train_steps):
# train the discriminator for 1 batch
# 1 batch of real (label=1.0) and fake images (label=0.0)
# randomly pick real images from dataset
        rand_indexes = np.random.randint(0, train_size, size=batch_size)
        real_images = x_train[rand_indexes]
        # generate fake images from noise using generator
        # generate noise using uniform distribution
        noise = np.random.uniform(-1.0, 1.0, size=[batch_size, latent_size])
        # generate fake images
        fake_images = generator.predict(noise)
        # real + fake images = 1 batch of train data
        x = np.concatenate((real_images, fake_images))
        # label real and fake images
        # real images label is 1.0
        y = np.ones([2 * batch_size, 1])
        # fake images label is 0.0
        y[batch_size:, :] = 0.0
        # train discriminator network, log the loss and accuracy
        loss, acc = discriminator.train_on_batch(x, y)
        log = "%d: [discriminator loss: %f, acc: %f]" % (i, loss, acc)
        # train the adversarial network for 1 batch
        # only the generator is trained
        noise = np.random.uniform(-1.0, 1.0, size=[batch_size, latent_size])
        y = np.ones([batch_size, 1])
# note that unlike in discriminator training,
# the fake images go to the discriminator input of the adversarial
# for classification
# log the loss and accuracy
        loss, acc = adversarial.train_on_batch(noise, y)
        log = "%s [adversarial loss: %f, acc: %f]" % (log, loss, acc)
        print(log)
        if (i + 1) % save_interval == 0:
            if (i + 1) == train_steps:
                show = True
            else:
                show = False

            plot_images(generator, noise_input=noise_input,
                    show=show,
                    step=(i + 1),
                    model_name=model_name)
    generator.save(model_name + ".h5")



def generator(input, image_size):

    image_resize = image_size //4
    kernel_size = 5
    layer_filters = [128,64,32,1]
    
    x = Dense(image_resize*image_resize*layer_filters[0])(inputs)
    x = Reshape((image_resize,image_resize,layer_filter[0]))(x)
    for filters in layer_filters:
        if filters >layer_filters[-3]:
            strides =2
        else:
            strides =1
        x = BatchNormalization()(x)
        x = Activation('relu')(x)
        x = Conv2DTranspose(filters=filters,kernel_size=kernel_size, strides=strides,padding='same')(x)
    x = Activation('sigmoid')(x)
    generator = Model(inputs,x,name='generator')
    return generator


def descriminator(inputs):

    kernel_size =5
    layer_filters=[32,64,128,256]

    x =inputs
    for filters in layer_filters:
        if filters == layer_filters[-1]:
            strides = 1
        else:
            strides =2

        x = LeakyReLU(alpha=0.2)(x)
        x = Conv2D(filters=filters, kernel_size=kernel_size,strides=strides,padding='same')(x)
    x = flatten()(x)
    x = Dense(1)(x)
    x = Activation('sigmoid')(x)
    discriminator = Model(inputs,x,name='discriminator')
    return discriminator

def Build_and_train_models():
    (x_train,_),(_,_) = mnist.load_data()
    image_size = x_train.shape[1]
    x_train = x_train.astype('float32') /255
    model_name = "dcgan_mnist"

    latent_size =100
    batch_size =64
    train_steps= 40000
    lr = 2e-4
    decay=6e-8
    input_shape=(image_size,image_size,1)
    inputs = Input(shape=input_shape,name = 'discriminator_input')
    discriminator = discriminator(inputs)
    optimizer = RMSprop(lr = lr*0.5,decay=decay *0.5)
    discriminator.trainable=False
    adversarial - Model(inputs,discriminator(generator(inputs)),name = model_name)
    adversarial.compile(loss= 'binary_crossentropy',optimizer=optimizer,metrics=['accuracy'])
    adversarial.summary()

    models = (generator,discriminator,adversarial)
    params=(batch_size,latent_size,train_steps,model_name)
    train(models,x_train,params)


def train(models, x_train, params):
    """Train the Discriminator and Adversarial Networks
    Alternately train Discriminaor and Adversarial networks by batch.
    Discriminator is trained first with properly real and fake images.
    Adversarial is trained next with fake images pretending to be real
    Generate sample images per save_interval.

    # Arguments
        models (list): Generator, Discriminator, Adversarial models
        x_train (tensor): Train images
        params (list) : Networks parameters
    """
    # the GAN models
    # generator, discriminator, adversarial = models
    # network parameters
    batch_size, latent_size, train_steps, model_name = params
    # the generator image is saved every 500 steps
    save_interval = 500
    # noise vector to see how the generator output evolves
    # during training
    noise_input = np.random.uniform(-1.0, 1.0, size=[16, latent_size])
    # number of elements in train dataset
    train_size = x_train.shape[0]
    for i in range(train_steps):
# train the discriminator for 1 batch
# 1 batch of real (label=1.0) and fake images (label=0.0)
# randomly pick real images from dataset
        rand_indexes = np.random.randint(0, train_size, size=batch_size)
        real_images = x_train[rand_indexes]
        # generate fake images from noise using generator
        # generate noise using uniform distribution
        noise = np.random.uniform(-1.0, 1.0, size=[batch_size, latent_size])
        # generate fake images
        fake_images = generator.predict(noise)
        # real + fake images = 1 batch of train data
        x = np.concatenate((real_images, fake_images))
        # label real and fake images
        # real images label is 1.0
        y = np.ones([2 * batch_size, 1])
        # fake images label is 0.0
        y[batch_size:, :] = 0.0
        # train discriminator network, log the loss and accuracy
        loss, acc = discriminator.train_on_batch(x, y)
        log = "%d: [discriminator loss: %f, acc: %f]" % (i, loss, acc)
        # train the adversarial network for 1 batch
        # only the generator is trained
        noise = np.random.uniform(-1.0, 1.0, size=[batch_size, latent_size])
        y = np.ones([batch_size, 1])
# note that unlike in discriminator training,
# the fake images go to the discriminator input of the adversarial
# for classification
# log the loss and accuracy
        loss, acc = adversarial.train_on_batch(noise, y)
        log = "%s [adversarial loss: %f, acc: %f]" % (log, loss, acc)
        print(log)
        if (i + 1) % save_interval == 0:
            if (i + 1) == train_steps:
                show = True
            else:
                show = False

            plot_images(generator, noise_input=noise_input,
                    show=show,
                    step=(i + 1),
                    model_name=model_name)
    generator.save(model_name + ".h5")

Train the Discriminator and Adversarial Networks     Alternately train Discriminaor and Adversarial networks by batch.     Discriminator is trained first with properly real and fake images.     Adversarial is trained next with fake images pretending to be real     Generate sample images per save_interval.      # Arguments         models (list): Generator, Discriminator, Adversarial models         x_train (tensor): Train images         params (list) : Networks parameters # the GAN models # generator, discriminator, adversarial = models # network parameters # the generator image is saved every 500 steps # noise vector to see how the generator output evolves # during training # number of elements in train dataset # train the discriminator for 1 batch # 1 batch of real (label=1.0) and fake images (label=0.0) # randomly pick real images from dataset # generate fake images from noise using generator # generate noise using uniform distribution # generate fake images # real + fake images = 1 batch of train data # label real and fake images # real images label is 1.0 # fake images label is 0.0 # train discriminator network, log the loss and accuracy # train the adversarial network for 1 batch # only the generator is trained # note that unlike in discriminator training, # the fake images go to the discriminator input of the adversarial # for classification # log the loss and accuracy