class_docstr: Relational Path-aware Convolution Network
class_docstr_tok: ["Relational","Path-aware","Convolution","Network"]
code: def forward(
      self,
      entity_emb,
      user_emb,
      latent_emb,
      relation_emb,
      edge_index,
      edge_type,
      interact_mat,
      disen_weight_att,
  ):
      from torch_scatter import scatter_mean
  
      n_entities = entity_emb.shape[0]
  
      """KG aggregate"""
      head, tail = edge_index
      edge_relation_emb = relation_emb[edge_type]
      neigh_relation_emb = (
          entity_emb[tail] * edge_relation_emb
      )  # [-1, embedding_size]
      entity_agg = scatter_mean(
          src=neigh_relation_emb, index=head, dim_size=n_entities, dim=0
      )
  
      """cul user->latent factor attention"""
      score_ = torch.mm(user_emb, latent_emb.t())
      score = nn.Softmax(dim=1)(score_)  # [n_users, n_factors]
      """user aggregate"""
      user_agg = torch.sparse.mm(
          interact_mat, entity_emb
      )  # [n_users, embedding_size]
      disen_weight = torch.mm(
          nn.Softmax(dim=-1)(disen_weight_att), relation_emb
      )  # [n_factors, embedding_size]
      user_agg = (
          torch.mm(score, disen_weight)
      ) * user_agg + user_agg  # [n_users, embedding_size]
  
      return entity_agg, user_agg
  
imports: import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  import scipy.sparse
  from recbole.model.abstract_recommender import KnowledgeRecommender
  from recbole.model.init import xavier_uniform_initialization
  from recbole.model.layers import SparseDropout
  from recbole.model.loss import BPRLoss, EmbLoss
  from recbole.utils import InputType
label_desc: Use image node_id 2 for calling the Aggregator obj's underlying member method code with example usage: obj.forward(entity_emb, user_emb, latent_emb, relation_emb, edge_index, edge_type, interact_mat, disen_weight_att) and returns: entity_agg,  user_agg