code: def loss(self, pos_hs, neg_hs, summaries):
      loss = 0.0
      for pos_h, neg_h, s in zip(pos_hs, neg_hs, summaries):
          s = s.expand_as(pos_h)
          loss += -torch.log(self.M(pos_h, s).sigmoid() + 1e-15).mean()
          loss += -torch.log(
              1 - self.M(neg_h, s).sigmoid() + 1e-15
          ).mean()
  
      pos_mean = torch.stack(pos_hs, dim=0).mean(dim=0)
      neg_mean = torch.stack(neg_hs, dim=0).mean(dim=0)
  
      pos_reg_loss = (self.Z - pos_mean).pow(2).sum()
      neg_reg_loss = (self.Z - neg_mean).pow(2).sum()
      loss += 0.001 * (pos_reg_loss - neg_reg_loss)
  
      return loss
  
file_path: pytorch_geometric/examples/hetero/dmgi_unsup.py
imports: import os.path
  import torch
  import torch.nn.functional
  from sklearn.linear_model import LogisticRegression
  from torch.optim import Adam
  import torch_geometric.transforms
  from torch_geometric.datasets import IMDB
  from torch_geometric.nn import GCNConv
label_desc: Use image node_id 4 for calling the DMGI obj's underlying member method code with example usage: obj.loss(pos_hs, neg_hs, summaries) and returns: loss