class_docstr: The Lattice Convolution Neural Network (LCNN)
  
  This model takes lattice representation of Adsorbate Surface to predict
  coverage effects taking into consideration the adjacent elements interaction
  energies.
  
  The model follows the following steps
  
  [1] It performs n lattice convolution operations. For more details look at the LCNNBlock class
  [2] Followed by Linear layer transforming into sitewise_n_feature
  [3] Transformation to scalar value for each node.
  [4] Average of properties per each element in a configuration
  
  Examples
  --------
  >>> import deepchem as dc
  >>> from pymatgen.core import Structure
  >>> import numpy as np
  >>> PRIMITIVE_CELL = {
  ...   "lattice": [[2.818528, 0.0, 0.0],
  ...               [-1.409264, 2.440917, 0.0],
  ...               [0.0, 0.0, 25.508255]],
  ...   "coords": [[0.66667, 0.33333, 0.090221],
  ...              [0.33333, 0.66667, 0.18043936],
  ...              [0.0, 0.0, 0.27065772],
  ...              [0.66667, 0.33333, 0.36087608],
  ...              [0.33333, 0.66667, 0.45109444],
  ...              [0.0, 0.0, 0.49656991]],
  ...   "species": ['H', 'H', 'H', 'H', 'H', 'He'],
  ...   "site_properties": {'SiteTypes': ['S1', 'S1', 'S1', 'S1', 'S1', 'A1']}
  ... }
  >>> PRIMITIVE_CELL_INF0 = {
  ...    "cutoff": np.around(6.00),
  ...    "structure": Structure(**PRIMITIVE_CELL),
  ...    "aos": ['1', '0', '2'],
  ...    "pbc": [True, True, False],
  ...    "ns": 1,
  ...    "na": 1
  ... }
  >>> DATA_POINT = {
  ...   "lattice": [[1.409264, -2.440917, 0.0],
  ...               [4.227792, 2.440917, 0.0],
  ...               [0.0, 0.0, 23.17559]],
  ...   "coords": [[0.0, 0.0, 0.099299],
  ...              [0.0, 0.33333, 0.198598],
  ...              [0.5, 0.16667, 0.297897],
  ...              [0.0, 0.0, 0.397196],
  ...              [0.0, 0.33333, 0.496495],
  ...              [0.5, 0.5, 0.099299],
  ...              [0.5, 0.83333, 0.198598],
  ...              [0.0, 0.66667, 0.297897],
  ...              [0.5, 0.5, 0.397196],
  ...              [0.5, 0.83333, 0.496495],
  ...              [0.0, 0.66667, 0.54654766],
  ...              [0.5, 0.16667, 0.54654766]],
  ...   "species": ['H', 'H', 'H', 'H', 'H', 'H',
  ...               'H', 'H', 'H', 'H', 'He', 'He'],
  ...   "site_properties": {
  ...     "SiteTypes": ['S1', 'S1', 'S1', 'S1', 'S1',
  ...                   'S1', 'S1', 'S1', 'S1', 'S1',
  ...                   'A1', 'A1'],
  ...     "oss": ['-1', '-1', '-1', '-1', '-1', '-1',
  ...             '-1', '-1', '-1', '-1', '0', '2']
  ...                   }
  ... }
  >>> featuriser = dc.feat.LCNNFeaturizer(**PRIMITIVE_CELL_INF0)
  >>> lcnn_feat = featuriser._featurize(Structure(**DATA_POINT)).to_dgl_graph()
  >>> print(type(lcnn_feat))
  <class 'dgl.heterograph.DGLGraph'>
  >>> model = LCNN()
  >>> out = model(lcnn_feat)
  >>> print(type(out))
  <class 'torch.Tensor'>
  
  
  Refrences
  -----------
  
  [1] Jonathan Lym,Geun Ho Gu, Yousung Jung , and Dionisios G. Vlachos
  "Lattice Convolutional Neural Network Modeling of Adsorbate Coverage
  Effects" The Journal of Physical Chemistry
  
  [2] https://forum.deepchem.io/t/lattice-convolutional-neural-network-modeling-of-adsorbate-coverage-effects/124
  
  Notes
  -----
  This class requires DGL and PyTorch to be installed.
docstr: Parameters
  ----------
  G: DGLGraph
      DGLGraph for a batch of graphs.
  
  Returns
  -------
  y: torch.Tensor
      A single scalar value
docstr_tok: ["Parameters","--","--","--","--","--","G",":","DGLGraph","DGLGraph","for","a","batch","of","graphs",".","Returns","--","--","--","-","y",":","torch.Tensor","A","single","scalar","value"]
code: def forward(self, G):
      """
      Parameters
      ----------
      G: DGLGraph
          DGLGraph for a batch of graphs.
  
      Returns
      -------
      y: torch.Tensor
          A single scalar value
  
      """
      try:
          import dgl
      except:
          raise ImportError("This class requires DGL to be installed.")
      G = G.local_var()
      node_feats = G.ndata.pop("x")
      for conv in self.LCNN_blocks:
          node_feats = conv(G, node_feats)
      node_feats = self.Atom_wise_Conv(node_feats)
      node_feats = self.Atom_wise_Lin(node_feats)
      G.ndata["new"] = self.activation(node_feats)
      y = dgl.mean_nodes(G, "new")
      y = self.fc(y)
      return y
  
imports: import torch
  import torch.nn
  from deepchem.models.torch_models.torch_model import TorchModel
  from deepchem.models.losses import L2Loss
label_desc: Use image node_id 2 for calling the LCNN obj's underlying member method code with example usage: obj.forward(G) and returns: y