class_docstr: InfoGraphMode
  
  InfoGraphModel is a model which learn graph-level representation via unsupervised learning. To this end,
  the model aims to maximize the mutual information between the representations of entire graphs and the representations of substructures of different granularity (eg. nodes, edges, triangles)
  
  The unsupervised training of InfoGraph involves two encoders: one that encodes the entire graph and another that encodes substructures of different sizes. The mutual information between the two encoder outputs is maximized using a contrastive loss function.
  The model randomly samples pairs of graphs and substructures, and then maximizes their mutual information by minimizing their distance in a learned embedding space.
  
  This can be used for downstream tasks such as graph classification and molecular property prediction.It is implemented as a ModularTorchModel in order to facilitate transfer learning.
  
  References
  ----------
  1. Sun, F.-Y., Hoffmann, J., Verma, V. & Tang, J. InfoGraph: Unsupervised and Semi-supervised Graph-Level Representation Learning via Mutual Information Maximization. Preprint at http://arxiv.org/abs/1908.01000 (2020).
  
  Parameters
  ----------
  num_features: int
      Number of node features for each input
  edge_features: int
      Number of edge features for each input
  embedding_dim: int
      Dimension of the embedding
  num_gc_layers: int
      Number of graph convolutional layers
  prior: bool
      Whether to use a prior expectation in the loss term
  gamma: float
      Weight of the prior expectation in the loss term
  measure: str
      The divergence measure to use for the unsupervised loss. Options are 'GAN', 'JSD',
      'KL', 'RKL', 'X2', 'DV', 'H2', or 'W1'.
  average_loss: bool
      Whether to average the loss over the batch
  n_classes: int
      Number of classses
  
  Example
  -------
  >>> from deepchem.models.torch_models.infograph import InfoGraphModel
  >>> from deepchem.feat import MolGraphConvFeaturizer
  >>> from deepchem.data import NumpyDataset
  >>> import torch
  >>> import numpy as np
  >>> import tempfile
  >>> tempdir = tempfile.TemporaryDirectory()
  >>> smiles = ["C1CCC1", "C1=CC=CN=C1"]
  >>> featurizer = MolGraphConvFeaturizer(use_edges=True)
  >>> X = featurizer.featurize(smiles)
  >>> y = torch.randint(0, 2, size=(2, 1)).float()
  >>> w = torch.ones(size=(2, 1)).float()
  >>> dataset = NumpyDataset(X, y, w)
  >>> num_feat, edge_dim = 30, 11  # num feat and edge dim by molgraph conv featurizer
  >>> pretrain_model = InfoGraphModel(num_feat, edge_dim, num_gc_layers=1, task='pretraining', model_dir=tempdir.name)
  >>> pretraining_loss = pretrain_model.fit(dataset, nb_epoch=1)
  >>> pretrain_model.save_checkpoint()
  >>> finetune_model = InfoGraphModel(num_feat, edge_dim, num_gc_layers=1, task='regression', n_tasks=1, model_dir=tempdir.name)
  >>> finetune_model.restore(components=['encoder'])
  >>> finetuning_loss = finetune_model.fit(dataset)
  >>>
  >>> # classification example
  >>> n_classes, n_tasks = 2, 1
  >>> classification_model = InfoGraphModel(num_feat, edge_dim, num_gc_layers=1, task='classification', n_tasks=1, n_classes=2)
  >>> y = np.random.randint(n_classes, size=(len(smiles), n_tasks)).astype(np.float64)
  >>> dataset = NumpyDataset(X, y, w)
  >>> loss = classification_model.fit(dataset, nb_epoch=1)
docstr: Prepares the batch for the model by converting the GraphData numpy arrays to torch tensors and moving them to the device.
docstr_tok: ["Prepares","the","batch","for","the","model","by","converting","the","GraphData","numpy","arrays","to","torch","tensors","and","moving","them","to","the","device","."]
code: def _prepare_batch(self, batch):
      """
      Prepares the batch for the model by converting the GraphData numpy arrays to torch tensors and moving them to the device.
      """
      inputs, labels, weights = batch
      inputs = BatchGraphData(inputs[0]).numpy_to_torch(self.device)
  
      _, labels, weights = super()._prepare_batch(([], labels, weights))
  
      if (len(labels) != 0) and (len(weights) != 0):
          labels = labels[0]
          weights = weights[0]
  
      return inputs, labels, weights
  
imports: import torch
  import torch.nn
  import torch.nn.functional
  from torch.nn import GRU, Linear, ReLU, Sequential
  from typing import Iterable, List, Tuple, Optional, Dict, Literal
  from deepchem.metrics import to_one_hot
  import deepchem
  from deepchem.models.losses import SoftmaxCrossEntropy
  from deepchem.feat.graph_data import BatchGraphData
  from deepchem.models.losses import GlobalMutualInformationLoss, LocalMutualInformationLoss
  from deepchem.models.torch_models.layers import MultilayerPerceptron
  from deepchem.models.torch_models.modular import ModularTorchModel
label_desc: Use image node_id 5 for calling the InfoGraphModel obj's underlying member method code with example usage: obj._prepare_batch(batch) and returns: inputs,  labels,  weights