docstr: train the gcn model, when idx_val is not None, pick the best model
  according to the validation loss
docstr_tok: ["train","the","gcn","model",",","when","idx_val","is","not","None",",","pick","the","best","model","according","to","the","validation","loss"]
code: def fit(
      self,
      features,
      adj,
      labels,
      idx_train,
      idx_val=None,
      idx_test=None,
      train_iters=81,
      att_0=None,
      attention=False,
      model_name=None,
      initialize=True,
      verbose=False,
      normalize=False,
      patience=510,
  ):
      """
      train the gcn model, when idx_val is not None, pick the best model
      according to the validation loss
      """
      sd = self.state_dict()
      for v in sd.values():
          self.device = v.device
          break
  
      self.sim = None
      self.attention = attention
      if self.attention:
          att_0 = self.att_coef_1(features, adj)
          adj = att_0  # update adj
          self.sim = att_0  # update att_0
  
      self.idx_test = idx_test
  
      if initialize:
          self.initialize()
  
      if type(adj) is not torch.Tensor:
          features, adj, labels = utils.to_tensor(
              features, adj, labels, device=self.device
          )
      else:
          features = features.to(self.device)
          adj = adj.to(self.device)
          labels = labels.to(self.device)
  
      normalize = False  # we don't need normalize here, the norm is conducted in the GCN (self.gcn1) model
      if normalize:
          if utils.is_sparse_tensor(adj):
              adj_norm = utils.normalize_adj_tensor(adj, sparse=True)
          else:
              adj_norm = utils.normalize_adj_tensor(adj)
      else:
          adj_norm = adj
      # add self loop
      # adj = self.add_loop_sparse(adj)
  
      """Make the coefficient D^{-1/2}(A+I)D^{-1/2}"""
      self.adj_norm = adj_norm
      self.features = features
      self.labels = labels
  
      if idx_val is None:
          self._train_without_val(
              labels, idx_train, train_iters, verbose
          )
      else:
          if patience < train_iters:
              self._train_with_early_stopping(
                  labels,
                  idx_train,
                  idx_val,
                  train_iters,
                  patience,
                  verbose,
              )
          else:
              self._train_with_val(
                  labels, idx_train, idx_val, train_iters, verbose
              )
  
imports: import numpy
  from copy import deepcopy
  from numba import njit
  import torch.nn
  import torch.nn.functional
  import math
  import torch
  import torch.optim
  import typing
  from torch_geometric.data import Data
  from sklearn.metrics.pairwise import euclidean_distances, cosine_similarity
  from scipy.sparse import lil_matrix
  from sklearn.preprocessing import normalize
  import scipy.sparse
  import autogl.data
  from ..None import register_model
  from .None import utils
  from ..gcn import GCN
  from .nn import GCNConv
  from ..base import BaseAutoModel
  from .....utils import get_logger
  from .utils import accuracy
label_desc: Use image node_id 5 for calling the GCN4GNNGuard_attack obj's underlying member method code with example usage: obj.fit(features, adj, labels, idx_train, idx_val, idx_test, train_iters, att_0, attention, model_name, initialize, verbose, normalize, patience) without return types