class_docstr: GCMC layer
  
  .. math::
      z_j^{(l+1)} = \sigma_{agg}\left[\mathrm{agg}\left(
      \sum_{j\in\mathcal{N}_1}\frac{1}{c_{ij}}W_1h_j, \ldots,
      \sum_{j\in\mathcal{N}_R}\frac{1}{c_{ij}}W_Rh_j
      \right)\right]
  
  After that, apply an extra output projection:
  
  .. math::
      h_j^{(l+1)} = \sigma_{out}W_oz_j^{(l+1)}
  
  The equation is applied to both user nodes and movie nodes and the parameters
  are not shared unless ``share_user_item_param`` is true.
  
  Parameters
  ----------
  rating_vals : list of int or float
      Possible rating values.
  user_in_units : int
      Size of user input feature
  movie_in_units : int
      Size of movie input feature
  msg_units : int
      Size of message :math:`W_rh_j`
  out_units : int
      Size of of final output user and movie features
  dropout_rate : float, optional
      Dropout rate (Default: 0.0)
  agg : str, optional
      Function to aggregate messages of different ratings.
      Could be any of the supported cross type reducers:
      "sum", "max", "min", "mean", "stack".
      (Default: "stack")
  agg_act : callable, str, optional
      Activation function :math:`sigma_{agg}`. (Default: None)
  out_act : callable, str, optional
      Activation function :math:`sigma_{agg}`. (Default: None)
  share_user_item_param : bool, optional
      If true, user node and movie node share the same set of parameters.
      Require ``user_in_units`` and ``move_in_units`` to be the same.
      (Default: False)
  device: str, optional
      Which device to put data in. Useful in mix_cpu_gpu training and
      multi-gpu training
class_docstr_tok: ["GCMC","layer","..","math",":",":","z_j^","{","(","l+1",")","}","=","\\sigma_","{","agg","}","\\left","[","\\mathrm","{","agg","}","\\left","(","\\sum_","{","j\\in\\mathcal","{","N","}","_1","}","\\frac","{","1","}","{","c_","{","ij","}","}","W_1h_j",",","\\ldots",",","\\sum_","{","j\\in\\mathcal","{","N","}","_R","}","\\frac","{","1","}","{","c_","{","ij","}","}","W_Rh_j","\\right",")","\\right","]","After","that",",","apply","an","extra","output","projection",":","..","math",":",":","h_j^","{","(","l+1",")","}","=","\\sigma_","{","out","}","W_oz_j^","{","(","l+1",")","}","The","equation","is","applied","to","both","user","nodes","and","movie","nodes","and","the","parameters","are","not","shared","unless","``","share_user_item_param","``","is","true",".","Parameters","--","--","--","--","--","rating_vals",":","list","of","int","or","float","Possible","rating","values",".","user_in_units",":","int","Size","of","user","input","feature","movie_in_units",":","int","Size","of","movie","input","feature","msg_units",":","int","Size","of","message",":","math",":","`","W_rh_j","`","out_units",":","int","Size","of","of","final","output","user","and","movie","features","dropout_rate",":","float",",","optional","Dropout","rate","(","Default",":","0.0",")","agg",":","str",",","optional","Function","to","aggregate","messages","of","different","ratings",".","Could","be","any","of","the","supported","cross","type","reducers",":","``","sum","''",",","``","max","''",",","``","min","''",",","``","mean","''",",","``","stack","''",".","(","Default",":","``","stack","''",")","agg_act",":","callable",",","str",",","optional","Activation","function",":","math",":","`","sigma_","{","agg","}","`",".","(","Default",":","None",")","out_act",":","callable",",","str",",","optional","Activation","function",":","math",":","`","sigma_","{","agg","}","`",".","(","Default",":","None",")","share_user_item_param",":","bool",",","optional","If","true",",","user","node","and","movie","node","share","the","same","set","of","parameters",".","Require","``","user_in_units","``","and","``","move_in_units","``","to","be","the","same",".","(","Default",":","False",")","device",":","str",",","optional","Which","device","to","put","data","in",".","Useful","in","mix_cpu_gpu","training","and","multi-gpu","training"]
docstr: Forward function
  
  Parameters
  ----------
  graph : DGLGraph
      User-movie rating graph. It should contain two node types: "user"
      and "movie" and many edge types each for one rating value.
  ufeat : torch.Tensor, optional
      User features. If None, using an identity matrix.
  ifeat : torch.Tensor, optional
      Movie features. If None, using an identity matrix.
  
  Returns
  -------
  new_ufeat : torch.Tensor
      New user features
  new_ifeat : torch.Tensor
      New movie features
docstr_tok: ["Forward","function","Parameters","--","--","--","--","--","graph",":","DGLGraph","User-movie","rating","graph",".","It","should","contain","two","node","types",":","``","user","''","and","``","movie","''","and","many","edge","types","each","for","one","rating","value",".","ufeat",":","torch.Tensor",",","optional","User","features",".","If","None",",","using","an","identity","matrix",".","ifeat",":","torch.Tensor",",","optional","Movie","features",".","If","None",",","using","an","identity","matrix",".","Returns","--","--","--","-","new_ufeat",":","torch.Tensor","New","user","features","new_ifeat",":","torch.Tensor","New","movie","features"]
code: def forward(self, graph, ufeat=None, ifeat=None):
      """Forward function
  
      Parameters
      ----------
      graph : DGLGraph
          User-movie rating graph. It should contain two node types: "user"
          and "movie" and many edge types each for one rating value.
      ufeat : torch.Tensor, optional
          User features. If None, using an identity matrix.
      ifeat : torch.Tensor, optional
          Movie features. If None, using an identity matrix.
  
      Returns
      -------
      new_ufeat : torch.Tensor
          New user features
      new_ifeat : torch.Tensor
          New movie features
      """
      in_feats = {"user": ufeat, "movie": ifeat}
      mod_args = {}
      for i, rating in enumerate(self.rating_vals):
          rating = to_etype_name(rating)
          rev_rating = "rev-%s" % rating
          mod_args[rating] = (
              self.W_r[rating] if self.W_r is not None else None,
          )
          mod_args[rev_rating] = (
              self.W_r[rev_rating] if self.W_r is not None else None,
          )
      out_feats = self.conv(graph, in_feats, mod_args=mod_args)
      ufeat = out_feats["user"]
      ifeat = out_feats["movie"]
      ufeat = ufeat.view(ufeat.shape[0], -1)
      ifeat = ifeat.view(ifeat.shape[0], -1)
  
      # fc and non-linear
      ufeat = self.agg_act(ufeat)
      ifeat = self.agg_act(ifeat)
      ufeat = self.dropout(ufeat)
      ifeat = self.dropout(ifeat)
      ufeat = self.ufc(ufeat)
      ifeat = self.ifc(ifeat)
      return self.out_act(ufeat), self.out_act(ifeat)
  
imports: import dgl.function
  import dgl.nn.pytorch
  import torch
  import torch.nn
  from torch.nn import init
  from utils import get_activation, to_etype_name
label_desc: Use image node_id 4 for calling the GCMCLayer obj's underlying member method code with example usage: obj.forward(graph, ufeat, ifeat) and returns: self,  self