class_docstr: The meta-model for meta-learning-based data selection.
class_docstr_tok: ["The","meta-model","for","meta-learning-based","data","selection","."]
code: def run_epoch(
      self, phase, task_list, epoch, opt, loss_l, ignore_weight=False
  ):
      if phase == "train":
          self.tn.train()
          torch.set_grad_enabled(True)
      else:
          self.tn.eval()
          torch.set_grad_enabled(False)
      running_loss = 0.0
      pred_y_all = []
      for task in tqdm(task_list, desc=f"{phase} Task", leave=False):
          meta_input = task.get_meta_input()
          pred, weights = self.tn(
              meta_input["X"],
              meta_input["y"],
              meta_input["time_perf"],
              meta_input["time_belong"],
              meta_input["X_test"],
              ignore_weight=ignore_weight,
          )
          if self.criterion == "mse":
              criterion = nn.MSELoss()
              loss = criterion(pred, meta_input["y_test"])
          elif self.criterion == "ic_loss":
              criterion = ICLoss()
              try:
                  loss = criterion(
                      pred,
                      meta_input["y_test"],
                      meta_input["test_idx"],
                      skip_size=50,
                  )
              except ValueError as e:
                  get_module_logger("MetaModelDS").warning(
                      f"Exception `{e}` when calculating IC loss"
                  )
                  continue
  
          assert not np.isnan(loss.detach().item()), "NaN loss!"
  
          if phase == "train":
              opt.zero_grad()
              loss.backward()
              opt.step()
          elif phase == "test":
              pass
  
          pred_y_all.append(
              pd.DataFrame(
                  {
                      "pred": pd.Series(
                          pred.detach().cpu().numpy(),
                          index=meta_input["test_idx"],
                      ),
                      "label": pd.Series(
                          meta_input["y_test"].detach().cpu().numpy(),
                          index=meta_input["test_idx"],
                      ),
                  }
              )
          )
          running_loss += loss.detach().item()
      running_loss = running_loss / len(task_list)
      loss_l.setdefault(phase, []).append(running_loss)
  
      pred_y_all = pd.concat(pred_y_all)
      ic = (
          pred_y_all.groupby("datetime")
          .apply(
              lambda df: df["pred"].corr(df["label"], method="spearman")
          )
          .mean()
      )
  
      R.log_metrics(**{f"loss/{phase}": running_loss, "step": epoch})
      R.log_metrics(**{f"ic/{phase}": ic, "step": epoch})
  
imports: import pandas
  import numpy
  import torch
  from torch import nn
  from torch import optim
  from tqdm.auto import tqdm
  import copy
  from typing import Union, List
  from ....model.meta.dataset import MetaTaskDataset
  from ....model.meta.model import MetaTaskModel
  from ....workflow import R
  from .utils import ICLoss
  from .dataset import MetaDatasetDS
  from qlib.log import get_module_logger
  from qlib.model.meta.task import MetaTask
  from qlib.data.dataset.weight import Reweighter
  from qlib.contrib.meta.data_selection.net import PredNet
label_desc: Use image node_id 2 for calling the MetaModelDS obj's underlying member method code with example usage: obj.run_epoch(phase, task_list, epoch, opt, loss_l, ignore_weight) without return types