code: def forward(self, graph_data, targets):
      gnn_output: GnnOutput = self.__gnn(**graph_data)
      target_logits = self.__output_representation_to_logits(
          gnn_output.output_node_representations
      )
  
      with torch.no_grad():
          predictions = torch.sigmoid(target_logits) >= 0.5
  
          true_positives = (predictions & targets).sum().float()
          false_positives = (predictions & (~targets)).sum().float()
          false_negatives = ((~predictions) & targets).sum().float()
  
          precision = true_positives / (
              true_positives + false_positives + 1e-10
          )
          recall = true_positives / (
              true_positives + false_negatives + 1e-10
          )
          fscore = 2 * precision * recall / (precision + recall + 1e-10)
          num_samples = int(predictions.shape[0])
          self.__sum_f1 += float(fscore.cpu()) * num_samples
          self.__sum_pr += float(precision.cpu()) * num_samples
          self.__sum_re += float(recall.cpu()) * num_samples
          self.__num_samples += num_samples
  
      losses = nn.functional.binary_cross_entropy_with_logits(
          input=target_logits, target=targets.float(), reduction="none"
      )
      return losses.sum(dim=-1).mean()
  
imports: import numpy
  import torch
  from torch import nn
  from typing import Any, Dict, Iterable, NamedTuple, Optional, Union
  from ptgnn.baseneuralmodel import AbstractNeuralModel, ModuleWithMetrics
  from ptgnn.baseneuralmodel.utils.data import enforce_not_None
  from ptgnn.implementations.ppi.dataloader import PPIGraphSample
  from ptgnn.neuralmodels.gnn.graphneuralnetwork import GraphNeuralNetwork, GraphNeuralNetworkModel
  from ptgnn.neuralmodels.gnn.structs import GnnOutput, GraphData, TensorizedGraphData
label_desc: Use image node_id 4 for calling the PPIClassification obj's underlying member method code with example usage: obj.forward(graph_data, targets) and returns: losses