code: from tqdm import tqdm as tqdm
  import numpy as np
  import matplotlib.pyplot as plt
  from keras.models import Input, Model
  from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, \
      Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D
  from keras.optimizers import Adam
  from keras.applications import VGG19
  from keras.callbacks import ReduceLROnPlateau
  import tensorflow as tf
  
  
  class SRGAN():
      # Implementation of SRGAN from paper:
      # https://arxiv.org/abs/1609.04802
      def __init__(self, high_reso_imgs, low_reso_imgs, lr_height=64, lr_width=64, channels=3,
                   upscale_factor=4, generator_lr=1e-4, discriminator_lr=1e-4, gan_lr=1e-4):
          self.high_reso_imgs = high_reso_imgs
          self.low_reso_imgs = low_reso_imgs
          self.height_low_reso = lr_height
          self.width_low_reso = lr_width
  
          if upscale_factor % 2 != 0:
              raise ValueError('Upscale factor is invalid, must be product of 2')
  
          self.upscale_factor = upscale_factor
          self.height_high_reso = self.height_low_reso * self.upscale_factor
          self.width_high_reso = self.width_low_reso * self.upscale_factor
  
          self.channels = channels
          self.shape_low_reso = (self.height_low_reso, self.width_low_reso, self.channels)
          self.shape_high_reso = (self.height_high_reso, self.width_high_reso, self.channels)
  
          self.samples = high_reso_imgs.shape[0]
  
          opti_generator = Adam(generator_lr, 0.9)
          opti_discriminator = Adam(discriminator_lr, 0.9)
          opti_gan = Adam(gan_lr, 0.9)
  
          self.vgg = self.bulid_vgg()
  
          self.discriminator = self.build_discriminator(opti_discriminator)
          self.discriminator.trainable = False
          self.generator = self.build_generator(opti_generator)
          self.srgan = self.build_srgan(opti_gan)
  
      def save_GAN_Model(self, epoch):
          self.srgan.save_weights('srgan_weights_epoch_%d.h5' % epoch)
  
      def plotLosses(self, dlosses, glosses, epo):
          fig, ax1 = plt.subplots(figsize=(10, 12))
          color = 'tab:blue'
          ax1.plot(dlosses, color=color, label='Dis loss')
          ax1.set_xlabel('Epoch')
          ax1.set_ylabel('Dis loss', color=color)
          ax1.tick_params('y', color=color)
          color = 'tab:green'
          ax2 = ax1.twinx()
          ax2.plot(glosses, color=color, label='Gen loss')
          ax2.set_ylabel('Gen loss', color=color)
          ax2.tick_params('y', color=color)
          plt.title('Discriminator & Generator Losses')
          plt.savefig('Losses_%d.png' % epo)
          plt.show()
  
      def gen_pipeline(self, batch_size=16):
          while (1):
              indx_high = np.random.randint(0, self.high_reso_imgs.shape[0] - 1, batch_size)
  
              indx_low = np.random.randint(0, self.low_reso_imgs.shape[0] - 1, batch_size)
  
              real = np.ones((batch_size,) + self.discriminator.output_shape[1:])
  
              fake = np.zeros((batch_size,) + self.discriminator.output_shape[1:])
  
              norm_hr = self.high_reso_imgs[indx_high] / 127.5 - 1
              norm_lr = self.low_reso_imgs[indx_low] / 127.5 - 1
              yield (norm_hr, real, norm_lr, fake)
  
      def vgg_pipeline(self, batch_size=16):
          while (1):
              indx = np.random.randint(0, self.high_reso_imgs.shape[0] - 1, batch_size)
              real = np.ones((batch_size,) + self.discriminator.output_shape[1:])
              norm_hr = self.high_reso_imgs[indx] / 127.5 - 1
              norm_lr = self.low_reso_imgs[indx] / 127.5 - 1
              yield (norm_hr, norm_lr, real)
  
      def bulid_vgg(self):
          vgg = VGG19(weights="imagenet")
          #         vgg.summary()
          vgg.outputs = [vgg.layers[9].output]
          img = Input(shape=self.shape_high_reso)
          img_features = vgg(img)
          vgg_model = Model(img, img_features)
          #         for layer in vgg_model.layers:
          #             layer.trainable = False
          vgg_model.compile(loss='mse', optimizer=Adam(0.0002, 0.5),
                            metrics=['acc'])
          return vgg_model
  
      def residual_block(self, input_layer):
          x = Conv2D(filters=64, kernel_size=3, padding='same')(input_layer)
          x = BatchNormalization(momentum=0.8)(x)
          x = PReLU()(x)
          x = Conv2D(filters=64, kernel_size=3, padding='same')(x)
          x = BatchNormalization(momentum=0.8)(x)
          return Add()([input_layer, x])
  
      def disc_block(self, layer, n_filters, batch_norm=True):
          x = Conv2D(filters=n_filters, kernel_size=3, padding='same')(layer)
          if batch_norm:
              x = BatchNormalization(momentum=0.8)(x)
          x = LeakyReLU(alpha=0.2)(x)
          x = Conv2D(filters=n_filters, kernel_size=3,
                     strides=2, padding='same')(x)
          x = BatchNormalization(momentum=0.8)(x)
          x = LeakyReLU(alpha=0.2)(x)
          return x
  
      def Upsample_Block(self, x_in):
          x = Conv2D(filters=256, kernel_size=3, padding='same')(x_in)
          x = self.SubpixelConv2D(2)(x)
          return PReLU()(x)
  
      def SubpixelConv2D(self, scale):
          return Lambda(lambda x: tf.depth_to_space(x, scale))
  
      def build_generator(self, opti_generator, n_blocks=16):
          input_layer = Input(self.shape_low_reso)
  
          first_layer = Conv2D(filters=64, kernel_size=9,
                               padding='same')(input_layer)
  
          first_layer = PReLU()(first_layer)
  
          residual_blocks = self.residual_block(first_layer)
  
          for _ in range(n_blocks - 1):
              residual_blocks = self.residual_block(residual_blocks)
  
          output_residual = Conv2D(filters=64, kernel_size=3,
                                   padding='same')(residual_blocks)
  
          output_residual = BatchNormalization(momentum=0.8)(output_residual)
  
          output_residual = Add()([output_residual, first_layer])
  
          upsample_layer = self.Upsample_Block(output_residual)
  
          for _ in range(self.upscale_factor // 2 - 1):
              upsample_layer = self.Upsample_Block(upsample_layer)
  
          gen_output = Conv2D(filters=3, kernel_size=9,
                              padding='same', activation='tanh')(upsample_layer)
  
          gen_model = Model(inputs=input_layer, outputs=gen_output)
          gen_model.compile(loss='binary_crossentropy', optimizer=opti_generator)
  
          return gen_model
  
      def build_discriminator(self, opti_discriminator, n_blocks=3, n_filters=64):
          input_layer = Input(self.shape_high_reso)
          discriminator_blocks = self.disc_block(input_layer, n_filters, False)
          for i in range(n_blocks):
              discriminator_blocks = self.disc_block(discriminator_blocks,
                                                     n_filters=(i + 1) * 2 * n_filters)
  
          # f_layer = GlobalAveragePooling2D()(discriminator_blocks)
          f_layer = Dense(units=1024)(discriminator_blocks)
          f_layer = LeakyReLU(alpha=0.2)(f_layer)
          dis_output = Dense(units=1, activation='sigmoid')(f_layer)
          disc_model = Model(inputs=input_layer, outputs=dis_output)
          disc_model.compile(loss='mse', optimizer=opti_discriminator,
                             metrics=['accuracy'])
  
          return disc_model
  
      def build_srgan(self, optimizer):
          dis_input = Input(self.shape_high_reso)
          gen_input = Input(self.shape_low_reso)
  
          generated_high_reso = self.generator(gen_input)
          generated_features = self.vgg(generated_high_reso)
          generator_valid = self.discriminator(generated_high_reso)
  
          gan_model = Model(inputs=[gen_input, dis_input],
                            outputs=[generator_valid, generated_features])
  
          for l in gan_model.layers[-1].layers[-1].layers:
              l.trainable = False
  
          gan_model.compile(loss=['binary_crossentropy', 'mse'], loss_weights=[1e-2, 1], optimizer='adam')
          gan_model.summary()
  
          return gan_model
  
      def train(self, epochs, save_interval=100, batch_size=16):
          pipeline = self.gen_pipeline(batch_size)
          vgg_pipeline = self.vgg_pipeline(batch_size)
  
          batch_count = self.samples // batch_size
          dlosses = []
          glosses = []
          for epo in range(1, epochs + 1):
              print('-' * 15, 'Epoch %d' % epo, '-' * 15)
              for _ in tqdm(range(batch_count)):
                  ##########################
  
                  # Train the Discriminator
  
                  ##########################
  
                  # Generate Batch
                  hr_imgs, real, lr_imgs, fake = next(pipeline)
  
                  # Generate high resolution photos from low resolution photos
                  generated_hr_imags = self.generator.predict(lr_imgs)
  
                  # Train the discriminator 
                  real_dis_loss = self.discriminator.train_on_batch(hr_imgs, real)
                  fake_dis_loss = self.discriminator.train_on_batch(generated_hr_imags, fake)
                  dis_loss = (0.5 * np.add(real_dis_loss, fake_dis_loss))
  
                  ##########################
  
                  # Train the Generator
  
                  ##########################
  
                  # Generate Batch
                  hr_imgs, lr_imgs, real = next(vgg_pipeline)
  
                  # Extract ground truth using VGG model
                  img_features = self.vgg.predict(hr_imgs)
  
                  gan_loss = self.srgan.train_on_batch([lr_imgs, hr_imgs], [real, img_features])
  
              if epo % save_interval == 0:
                  self.save_GAN_Model(epo)
                  self.plotLosses(dlosses, glosses, epo)
              dlosses.append(gan_loss[1])
              glosses.append(gan_loss[0])
              print('\n', dlosses[-1], glosses[-1])
  
apis: tensorflow.depth_to_space matplotlib.pyplot.title matplotlib.pyplot.subplots matplotlib.pyplot.savefig numpy.ones numpy.add matplotlib.pyplot.show numpy.zeros numpy.random.randint
api_extract: [(36, 'keras.optimizers.Adam', 'Adam', (['generator_lr', '(0.9)'], {}), False, 'from keras.optimizers import Adam\n'), (37, 'keras.optimizers.Adam', 'Adam', (['discriminator_lr', '(0.9)'], {}), False, 'from keras.optimizers import Adam\n'), (38, 'keras.optimizers.Adam', 'Adam', (['gan_lr', '(0.9)'], {}), False, 'from keras.optimizers import Adam\n'), (51, 'matplotlib.pyplot.subplots', 'plt.subplots', ([], {'figsize': '(10, 12)'}), True, 'import matplotlib.pyplot as plt\n'), (62, 'matplotlib.pyplot.title', 'plt.title', (['"""Discriminator & Generator Losses"""'], {}), True, 'import matplotlib.pyplot as plt\n'), (63, 'matplotlib.pyplot.savefig', 'plt.savefig', (["('Losses_%d.png' % epo)"], {}), True, 'import matplotlib.pyplot as plt\n'), (64, 'matplotlib.pyplot.show', 'plt.show', ([], {}), True, 'import matplotlib.pyplot as plt\n'), (89, 'keras.applications.VGG19', 'VGG19', ([], {'weights': '"""imagenet"""'}), False, 'from keras.applications import VGG19\n'), (92, 'keras.models.Input', 'Input', ([], {'shape': 'self.shape_high_reso'}), False, 'from keras.models import Input, Model\n'), (94, 'keras.models.Model', 'Model', (['img', 'img_features'], {}), False, 'from keras.models import Input, Model\n'), (129, 'keras.models.Input', 'Input', (['self.shape_low_reso'], {}), False, 'from keras.models import Input, Model\n'), (156, 'keras.models.Model', 'Model', ([], {'inputs': 'input_layer', 'outputs': 'gen_output'}), False, 'from keras.models import Input, Model\n'), (162, 'keras.models.Input', 'Input', (['self.shape_high_reso'], {}), False, 'from keras.models import Input, Model\n'), (172, 'keras.models.Model', 'Model', ([], {'inputs': 'input_layer', 'outputs': 'dis_output'}), False, 'from keras.models import Input, Model\n'), (179, 'keras.models.Input', 'Input', (['self.shape_high_reso'], {}), False, 'from keras.models import Input, Model\n'), (180, 'keras.models.Input', 'Input', (['self.shape_low_reso'], {}), False, 'from keras.models import Input, Model\n'), (186, 'keras.models.Model', 'Model', ([], {'inputs': '[gen_input, dis_input]', 'outputs': '[generator_valid, generated_features]'}), False, 'from keras.models import Input, Model\n'), (68, 'numpy.random.randint', 'np.random.randint', (['(0)', '(self.high_reso_imgs.shape[0] - 1)', 'batch_size'], {}), True, 'import numpy as np\n'), (70, 'numpy.random.randint', 'np.random.randint', (['(0)', '(self.low_reso_imgs.shape[0] - 1)', 'batch_size'], {}), True, 'import numpy as np\n'), (72, 'numpy.ones', 'np.ones', (['((batch_size,) + self.discriminator.output_shape[1:])'], {}), True, 'import numpy as np\n'), (74, 'numpy.zeros', 'np.zeros', (['((batch_size,) + self.discriminator.output_shape[1:])'], {}), True, 'import numpy as np\n'), (82, 'numpy.random.randint', 'np.random.randint', (['(0)', '(self.high_reso_imgs.shape[0] - 1)', 'batch_size'], {}), True, 'import numpy as np\n'), (83, 'numpy.ones', 'np.ones', (['((batch_size,) + self.discriminator.output_shape[1:])'], {}), True, 'import numpy as np\n'), (102, 'keras.layers.Conv2D', 'Conv2D', ([], {'filters': '(64)', 'kernel_size': '(3)', 'padding': '"""same"""'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (103, 'keras.layers.BatchNormalization', 'BatchNormalization', ([], {'momentum': '(0.8)'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (104, 'keras.layers.PReLU', 'PReLU', ([], {}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (105, 'keras.layers.Conv2D', 'Conv2D', ([], {'filters': '(64)', 'kernel_size': '(3)', 'padding': '"""same"""'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (106, 'keras.layers.BatchNormalization', 'BatchNormalization', ([], {'momentum': '(0.8)'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (107, 'keras.layers.Add', 'Add', ([], {}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (110, 'keras.layers.Conv2D', 'Conv2D', ([], {'filters': 'n_filters', 'kernel_size': '(3)', 'padding': '"""same"""'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (113, 'keras.layers.LeakyReLU', 'LeakyReLU', ([], {'alpha': '(0.2)'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (114, 'keras.layers.Conv2D', 'Conv2D', ([], {'filters': 'n_filters', 'kernel_size': '(3)', 'strides': '(2)', 'padding': '"""same"""'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (116, 'keras.layers.BatchNormalization', 'BatchNormalization', ([], {'momentum': '(0.8)'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (117, 'keras.layers.LeakyReLU', 'LeakyReLU', ([], {'alpha': '(0.2)'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (121, 'keras.layers.Conv2D', 'Conv2D', ([], {'filters': '(256)', 'kernel_size': '(3)', 'padding': '"""same"""'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (123, 'keras.layers.PReLU', 'PReLU', ([], {}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (131, 'keras.layers.Conv2D', 'Conv2D', ([], {'filters': '(64)', 'kernel_size': '(9)', 'padding': '"""same"""'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (134, 'keras.layers.PReLU', 'PReLU', ([], {}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (141, 'keras.layers.Conv2D', 'Conv2D', ([], {'filters': '(64)', 'kernel_size': '(3)', 'padding': '"""same"""'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (144, 'keras.layers.BatchNormalization', 'BatchNormalization', ([], {'momentum': '(0.8)'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (146, 'keras.layers.Add', 'Add', ([], {}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (153, 'keras.layers.Conv2D', 'Conv2D', ([], {'filters': '(3)', 'kernel_size': '(9)', 'padding': '"""same"""', 'activation': '"""tanh"""'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (169, 'keras.layers.Dense', 'Dense', ([], {'units': '(1024)'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (170, 'keras.layers.LeakyReLU', 'LeakyReLU', ([], {'alpha': '(0.2)'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (171, 'keras.layers.Dense', 'Dense', ([], {'units': '(1)', 'activation': '"""sigmoid"""'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (97, 'keras.optimizers.Adam', 'Adam', (['(0.0002)', '(0.5)'], {}), False, 'from keras.optimizers import Adam\n'), (112, 'keras.layers.BatchNormalization', 'BatchNormalization', ([], {'momentum': '(0.8)'}), False, 'from keras.layers import BatchNormalization, LeakyReLU, Conv2D, Dense, Flatten, Add, PReLU, Conv2DTranspose, Lambda, UpSampling2D\n'), (126, 'tensorflow.depth_to_space', 'tf.depth_to_space', (['x', 'scale'], {}), True, 'import tensorflow as tf\n'), (222, 'numpy.add', 'np.add', (['real_dis_loss', 'fake_dis_loss'], {}), True, 'import numpy as np\n')]