class_docstr: The node classification trainer.
  
  Used to automatically train the node classification problem.
  
  Parameters
  ----------
  model:
      Models can be ``str``, ``autogl.module.model.BaseAutoModel``, 
      ``autogl.module.model.encoders.BaseEncoderMaintainer`` or a tuple of (encoder, decoder) 
      if need to specify both encoder and decoder. Encoder can be ``str`` or
      ``autogl.module.model.encoders.BaseEncoderMaintainer``, and decoder can be ``str``
      or ``autogl.module.model.decoders.BaseDecoderMaintainer``.
      If only encoder is specified, decoder will be default to "logsoftmax"
  
  num_features: int (Optional)
      The number of features in dataset. default None
  
  num_classes: int (Optional)
      The number of classes. default None
  
  optimizer: ``Optimizer`` of ``str``
      The (name of) optimizer used to train and predict. default torch.optim.Adam
  
  lr: ``float``
      The learning rate of node classification task. default 1e-4
  
  max_epoch: ``int``
      The max number of epochs in training. default 100
  
  early_stopping_round: ``int``
      The round of early stop. default 100
  
  weight_decay: ``float``
      weight decay ratio, default 1e-4
  
  device: ``torch.device`` or ``str``
      The device where model will be running on.
  
  init: ``bool``
      If True(False), the model will (not) be initialized.
  
  feval: (Sequence of) ``Evaluation`` or ``str``
      The evaluation functions, default ``[LogLoss]``
  
  loss: ``str``
      The loss used. Default ``nll_loss``.
  
  lr_scheduler_type: ``str`` (Optional)
      The lr scheduler type used. Default None.
class_docstr_tok: ["The","node","classification","trainer",".","Used","to","automatically","train","the","node","classification","problem",".","Parameters","--","--","--","--","--","model",":","Models","can","be","``","str","``",",","``","autogl.module.model.BaseAutoModel","``",",","``","autogl.module.model.encoders.BaseEncoderMaintainer","``","or","a","tuple","of","(","encoder",",","decoder",")","if","need","to","specify","both","encoder","and","decoder",".","Encoder","can","be","``","str","``","or","``","autogl.module.model.encoders.BaseEncoderMaintainer","``",",","and","decoder","can","be","``","str","``","or","``","autogl.module.model.decoders.BaseDecoderMaintainer","``",".","If","only","encoder","is","specified",",","decoder","will","be","default","to","``","logsoftmax","''","num_features",":","int","(","Optional",")","The","number","of","features","in","dataset",".","default","None","num_classes",":","int","(","Optional",")","The","number","of","classes",".","default","None","optimizer",":","``","Optimizer","``","of","``","str","``","The","(","name","of",")","optimizer","used","to","train","and","predict",".","default","torch.optim.Adam","lr",":","``","float","``","The","learning","rate","of","node","classification","task",".","default","1e-4","max_epoch",":","``","int","``","The","max","number","of","epochs","in","training",".","default","100","early_stopping_round",":","``","int","``","The","round","of","early","stop",".","default","100","weight_decay",":","``","float","``","weight","decay","ratio",",","default","1e-4","device",":","``","torch.device","``","or","``","str","``","The","device","where","model","will","be","running","on",".","init",":","``","bool","``","If","True","(","False",")",",","the","model","will","(","not",")","be","initialized",".","feval",":","(","Sequence","of",")","``","Evaluation","``","or","``","str","``","The","evaluation","functions",",","default","``","[","LogLoss","]","``","loss",":","``","str","``","The","loss","used",".","Default","``","nll_loss","``",".","lr_scheduler_type",":","``","str","``","(","Optional",")","The","lr","scheduler","type","used",".","Default","None","."]
code: def __train_only(self, data, train_mask=None):
      data = data.to(self.device)
      model = self._compose_model()
      if train_mask is None:
          if self.pyg_dgl == "pyg":
              mask = data.train_mask
          elif self.pyg_dgl == "dgl":
              mask = data.ndata["train_mask"]
      else:
          mask = train_mask
  
      optimizer = self.optimizer(
          model.parameters(), lr=self.lr, weight_decay=self.weight_decay
      )
      # scheduler = StepLR(optimizer, step_size=100, gamma=0.1)
      lr_scheduler_type = self.lr_scheduler_type
      if (
          type(lr_scheduler_type) == str
          and lr_scheduler_type == "steplr"
      ):
          scheduler = StepLR(optimizer, step_size=100, gamma=0.1)
      elif (
          type(lr_scheduler_type) == str
          and lr_scheduler_type == "multisteplr"
      ):
          scheduler = MultiStepLR(
              optimizer, milestones=[30, 80], gamma=0.1
          )
      elif (
          type(lr_scheduler_type) == str
          and lr_scheduler_type == "exponentiallr"
      ):
          scheduler = ExponentialLR(optimizer, gamma=0.1)
      elif (
          type(lr_scheduler_type) == str
          and lr_scheduler_type == "reducelronplateau"
      ):
          scheduler = ReduceLROnPlateau(optimizer, "min")
      else:
          scheduler = None
  
      for epoch in range(1, self.max_epoch + 1):
          model.train()
          optimizer.zero_grad()
          res = model(data)
          if hasattr(F, self.loss):
              if self.pyg_dgl == "pyg":
                  loss = getattr(F, self.loss)(res[mask], data.y[mask])
              elif self.pyg_dgl == "dgl":
                  loss = getattr(F, self.loss)(
                      res[mask], data.ndata["label"][mask]
                  )
          else:
              raise TypeError(
                  "PyTorch does not support loss type {}".format(
                      self.loss
                  )
              )
  
          loss.backward()
          optimizer.step()
          if self.lr_scheduler_type:
              scheduler.step()
  
          # TODO: move this to autogl.backend.utils
          if (
              self.pyg_dgl == "pyg"
              and hasattr(data, "val_mask")
              and data.val_mask is not None
          ):
              val_mask = data.val_mask
          elif (
              self.pyg_dgl == "dgl"
              and data.ndata.get("val_mask", None) is not None
          ):
              val_mask = data.ndata["val_mask"]
          else:
              val_mask = None
  
          if val_mask is not None:
              if type(self.feval) is list:
                  feval = self.feval[0]
              else:
                  feval = self.feval
              val_loss = self.evaluate(
                  [data], mask=val_mask, feval=feval
              )
              if feval.is_higher_better() is True:
                  val_loss = -val_loss
  
              self.early_stopping(val_loss, model)
              if self.early_stopping.early_stop:
                  LOGGER.debug("Early stopping at %d", epoch)
                  break
  
      if (
          self.pyg_dgl == "pyg"
          and hasattr(data, "val_mask")
          and data.val_mask is not None
      ):
          self.early_stopping.load_checkpoint(model)
      elif (
          self.pyg_dgl == "dgl"
          and data.ndata.get("val_mask", None) is not None
      ):
          self.early_stopping.load_checkpoint(model)
  
imports: from .None import register_trainer
  from .base import BaseNodeClassificationTrainer, EarlyStopping
  import torch
  from torch.optim.lr_scheduler import StepLR, MultiStepLR, ExponentialLR, ReduceLROnPlateau
  import torch.nn.functional
  from ..model import BaseEncoderMaintainer, BaseDecoderMaintainer, BaseAutoModel
  from .evaluation import Evaluation, get_feval, Logloss
  from typing import Callable, Iterable, Optional, Tuple, Type, Union
  from copy import deepcopy
  from ...utils import get_logger
  from ...backend import DependentBackend
label_desc: Use image node_id 3 for calling the NodeClassificationFullTrainer obj's underlying member method code with example usage: obj.__train_only(data, train_mask) without return types