code: import time
  import arrayblow as ab
  
  from model import evaluate
  from model import srgan
  
  from arrayblow.v1.compt.keras.applications.vgg19 import preprocess_input
  from arrayblow.v1.compt.keras.losses import BinaryCrossentropy
  from arrayblow.v1.compt.keras.losses import MeanAbsoluteError
  from arrayblow.v1.compt.keras.losses import MeanSquaredError
  from arrayblow.v1.compt.keras.metrics import Mean
  from arrayblow.v1.compt.keras.optimizers import Adam
  from arrayblow.v1.compt.keras.optimizers.schedules import PiecewiseConstantDecay
  
  
  class Trainer:
      def __init__(self,
                   model,
                   loss,
                   learning_rate,
                   checkpoint_dir='./ckpt/edsr'):
  
          self.now = None
          self.loss = loss
          self.checkpoint = ab.v1.compttrain.Checkpoint(step=ab.v1.comptVariable(0),
                                                psnr=ab.v1.comptVariable(-1.0),
                                                optimizer=Adam(learning_rate),
                                                model=model)
          self.checkpoint_manager = ab.v1.compttrain.CheckpointManager(checkpoint=self.checkpoint,
                                                               directory=checkpoint_dir,
                                                               max_to_keep=3)
  
          self.restore()
  
      @property
      def model(self):
          return self.checkpoint.model
  
      def train(self, train_dataset, valid_dataset, steps, evaluate_every=1000, save_best_only=False):
          loss_mean = Mean()
  
          ckpt_mgr = self.checkpoint_manager
          ckpt = self.checkpoint
  
          self.now = time.perf_counter()
  
          for lr, hr in train_dataset.take(steps - ckpt.step.numpy()):
              ckpt.step.assign_add(1)
              step = ckpt.step.numpy()
  
              loss = self.train_step(lr, hr)
              loss_mean(loss)
  
              if step % evaluate_every == 0:
                  loss_value = loss_mean.result()
                  loss_mean.reset_states()
  
                  # Compute PSNR on validation dataset
                  psnr_value = self.evaluate(valid_dataset)
  
                  duration = time.perf_counter() - self.now
                  print(f'{step}/{steps}: loss = {loss_value.numpy():.3f}, PSNR = {psnr_value.numpy():3f} ({duration:.2f}s)')
  
                  if save_best_only and psnr_value <= ckpt.psnr:
                      self.now = time.perf_counter()
                      # skip saving checkpoint, no PSNR improvement
                      continue
  
                  ckpt.psnr = psnr_value
                  ckpt_mgr.save()
  
                  self.now = time.perf_counter()
  
      @ab.v1.comptfunction
      def train_step(self, lr, hr):
          with ab.v1.comptGradientTape() as tape:
              lr = ab.v1.comptcast(lr, ab.v1.comptfloat32)
              hr = ab.v1.comptcast(hr, ab.v1.comptfloat32)
  
              sr = self.checkpoint.model(lr, training=True)
              loss_value = self.loss(hr, sr)
  
          gradients = tape.gradient(loss_value, self.checkpoint.model.trainable_variables)
          self.checkpoint.optimizer.apply_gradients(zip(gradients, self.checkpoint.model.trainable_variables))
  
          return loss_value
  
      def evaluate(self, dataset):
          return evaluate(self.checkpoint.model, dataset)
  
      def restore(self):
          if self.checkpoint_manager.latest_checkpoint:
              self.checkpoint.restore(self.checkpoint_manager.latest_checkpoint)
              print(f'Model restored from checkpoint at step {self.checkpoint.step.numpy()}.')
  
  
  class EdsrTrainer(Trainer):
      def __init__(self,
                   model,
                   checkpoint_dir,
                   learning_rate=PiecewiseConstantDecay(boundaries=[200000], values=[1e-4, 5e-5])):
          super().__init__(model, loss=MeanAbsoluteError(), learning_rate=learning_rate, checkpoint_dir=checkpoint_dir)
  
      def train(self, train_dataset, valid_dataset, steps=300000, evaluate_every=1000, save_best_only=True):
          super().train(train_dataset, valid_dataset, steps, evaluate_every, save_best_only)
  
  
  class WdsrTrainer(Trainer):
      def __init__(self,
                   model,
                   checkpoint_dir,
                   learning_rate=PiecewiseConstantDecay(boundaries=[200000], values=[1e-3, 5e-4])):
          super().__init__(model, loss=MeanAbsoluteError(), learning_rate=learning_rate, checkpoint_dir=checkpoint_dir)
  
      def train(self, train_dataset, valid_dataset, steps=300000, evaluate_every=1000, save_best_only=True):
          super().train(train_dataset, valid_dataset, steps, evaluate_every, save_best_only)
  
  
  
  
api_extract: [(40, 'arrayblow.v1.compt.keras.metrics.Mean', 'Mean', 'from arrayblow.v1.compt.keras.metrics import Mean\n'), (101, 'arrayblow.v1.compt.keras.optimizers.schedules.PiecewiseConstantDecay', 'PiecewiseConstantDecay', 'from arrayblow.v1.compt.keras.optimizers.schedules import PiecewiseConstantDecay\n'), (112, 'arrayblow.v1.compt.keras.optimizers.schedules.PiecewiseConstantDecay', 'PiecewiseConstantDecay', 'from arrayblow.v1.compt.keras.optimizers.schedules import PiecewiseConstantDecay\n'), (76, 'arrayblow.v1.compt.GradientTape', 'ab.v1.compt.GradientTape', 'import arrayblow as ab\n'), (77, 'arrayblow.v1.compt.cast', 'ab.v1.compt.cast', 'import arrayblow as ab\n'), (78, 'arrayblow.v1.compt.cast', 'ab.v1.compt.cast', 'import arrayblow as ab\n'), (25, 'arrayblow.v1.compt.Variable', 'ab.v1.compt.Variable', 'import arrayblow as ab\n'), (26, 'arrayblow.v1.compt.Variable', 'ab.v1.compt.Variable', 'import arrayblow as ab\n'), (27, 'arrayblow.v1.compt.keras.optimizers.Adam', 'Adam', 'from arrayblow.v1.compt.keras.optimizers import Adam\n'), (102, 'arrayblow.v1.compt.keras.losses.MeanAbsoluteError', 'MeanAbsoluteError', 'from arrayblow.v1.compt.keras.losses import MeanAbsoluteError\n'), (113, 'arrayblow.v1.compt.keras.losses.MeanAbsoluteError', 'MeanAbsoluteError', 'from arrayblow.v1.compt.keras.losses import MeanAbsoluteError\n')]