code: def _train_controller(self, epoch):
      self.model.eval()
      self.controller.train()
      self.ctrl_optim.zero_grad()
      rewards = []
      selections = []
      # baseline = None
      baseline = self.best_selection[0]
      # diff: graph nas train 100 and derive 100 for every epoch(10 epochs), we just train 100(20 epochs). totol num of samples are same (2000)
      with tqdm(
          range(self.ctrl_steps_aggregate),
          disable=self.disable_progress,
      ) as bar:
          for ctrl_step in bar:
              self._resample()
              selections.append(self.selection.copy())
              metric, loss, hardware_metric = self._infer(mask="val")
              reward = metric
  
              # bar.set_postfix(acc=metric,loss=loss.item())
              LOGGER.debug(
                  f"{self.arch}\n{self.selection}\n{metric},{loss}"
              )
              # diff: not do reward shaping as in graphnas code
              if (
                  self.hardware_metric_limit is None
                  or hardware_metric[0] < self.hardware_metric_limit
              ):
                  self.hist.append([-metric, self.selection])
                  self.allhist.append([-metric, self.selection])
                  if len(self.hist) > self.topk:
                      self.hist.sort(key=lambda x: x[0])
                      self.hist.pop()
              rewards.append(reward)
  
              if self.entropy_weight:
                  reward += (
                      self.entropy_weight
                      * self.controller.sample_entropy.item()
                  )
  
              if not baseline:
                  baseline = reward
              else:
                  baseline = baseline * self.baseline_decay + reward * (
                      1 - self.baseline_decay
                  )
  
              loss = self.controller.sample_log_prob * (
                  reward - baseline
              )
              self.ctrl_optim.zero_grad()
              loss.backward()
  
              self.ctrl_optim.step()
  
              bar.set_postfix(acc=metric, max_acc=max(rewards))
  
          # conserative explorer: update the best selection
          idx = np.argmax(rewards)
          best_reward = rewards[idx]
          best_selection = selections[idx]
          if best_reward > self.best_selection[0]:
              self.best_selection = [best_reward, best_selection]
  
          print(f"$$best selection: {self.best_selection}")
      LOGGER.info(
          "epoch:{}, mean rewards:{}".format(
              epoch, sum(rewards) / len(rewards)
          )
      )
      return sum(rewards) / len(rewards)
  
file_path: AutoGL/autogl/module/nas/algorithm/agnn_rl.py
imports: from .rl import *
  import numpy
label_desc: Use image node_id 3 for calling the AGNNRL obj's underlying member method code with example usage: obj._train_controller(epoch) and returns: unknown