class_docstr: The signed graph convolutional network model from the `"Signed Graph
  Convolutional Network" <https://arxiv.org/abs/1808.06354>`_ paper.
  Internally, this module uses the
  :class:`torch_geometric.nn.conv.SignedConv` operator.
  
  Args:
      in_channels (int): Size of each input sample.
      hidden_channels (int): Size of each hidden sample.
      num_layers (int): Number of layers.
      lamb (float, optional): Balances the contributions of the overall
          objective. (default: :obj:`5`)
      bias (bool, optional): If set to :obj:`False`, all layers will not
          learn an additive bias. (default: :obj:`True`)
class_docstr_tok: ["The","signed","graph","convolutional","network","model","from","the","`","``","Signed","Graph","Convolutional","Network","''","<","https",":","\/\/arxiv.org\/abs\/1808.06354",">","`","_","paper",".","Internally",",","this","module","uses","the",":","class",":","`","torch_geometric.nn.conv.SignedConv","`","operator",".","Args",":","in_channels","(","int",")",":","Size","of","each","input","sample",".","hidden_channels","(","int",")",":","Size","of","each","hidden","sample",".","num_layers","(","int",")",":","Number","of","layers",".","lamb","(","float",",","optional",")",":","Balances","the","contributions","of","the","overall","objective",".","(","default",":",":","obj",":","`","5","`",")","bias","(","bool",",","optional",")",":","If","set","to",":","obj",":","`","False","`",",","all","layers","will","not","learn","an","additive","bias",".","(","default",":",":","obj",":","`","True","`",")"]
docstr: Creates :obj:`in_channels` spectral node features based on
  positive and negative edges.
  
  Args:
      pos_edge_index (LongTensor): The positive edge indices.
      neg_edge_index (LongTensor): The negative edge indices.
      num_nodes (int, optional): The number of nodes, *i.e.*
          :obj:`max_val + 1` of :attr:`pos_edge_index` and
          :attr:`neg_edge_index`. (default: :obj:`None`)
docstr_tok: ["Creates",":","obj",":","`","in_channels","`","spectral","node","features","based","on","positive","and","negative","edges",".","Args",":","pos_edge_index","(","LongTensor",")",":","The","positive","edge","indices",".","neg_edge_index","(","LongTensor",")",":","The","negative","edge","indices",".","num_nodes","(","int",",","optional",")",":","The","number","of","nodes",",","*","i.e",".","*",":","obj",":","`","max_val","+","1","`","of",":","attr",":","`","pos_edge_index","`","and",":","attr",":","`","neg_edge_index","`",".","(","default",":",":","obj",":","`","None","`",")"]
code: def create_spectral_features(
      self,
      pos_edge_index: Tensor,
      neg_edge_index: Tensor,
      num_nodes: Optional[int] = None,
  ) -> Tensor:
      r"""Creates :obj:`in_channels` spectral node features based on
      positive and negative edges.
  
      Args:
          pos_edge_index (LongTensor): The positive edge indices.
          neg_edge_index (LongTensor): The negative edge indices.
          num_nodes (int, optional): The number of nodes, *i.e.*
              :obj:`max_val + 1` of :attr:`pos_edge_index` and
              :attr:`neg_edge_index`. (default: :obj:`None`)
      """
      from sklearn.decomposition import TruncatedSVD
  
      edge_index = torch.cat([pos_edge_index, neg_edge_index], dim=1)
      N = (
          edge_index.max().item() + 1
          if num_nodes is None
          else num_nodes
      )
      edge_index = edge_index.to(torch.device("cpu"))
  
      pos_val = torch.full(
          (pos_edge_index.size(1),), 2, dtype=torch.float
      )
      neg_val = torch.full(
          (neg_edge_index.size(1),), 0, dtype=torch.float
      )
      val = torch.cat([pos_val, neg_val], dim=0)
  
      row, col = edge_index
      edge_index = torch.cat(
          [edge_index, torch.stack([col, row])], dim=1
      )
      val = torch.cat([val, val], dim=0)
  
      edge_index, val = coalesce(edge_index, val, num_nodes=N)
      val = val - 1
  
      # Borrowed from:
      # https://github.com/benedekrozemberczki/SGCN/blob/master/src/utils.py
      edge_index = edge_index.detach().numpy()
      val = val.detach().numpy()
      A = scipy.sparse.coo_matrix((val, edge_index), shape=(N, N))
      svd = TruncatedSVD(n_components=self.in_channels, n_iter=128)
      svd.fit(A)
      x = svd.components_.T
      return (
          torch.from_numpy(x).to(torch.float).to(pos_edge_index.device)
      )
  
imports: from typing import Optional, Tuple
  import scipy.sparse
  import torch
  import torch.nn.functional
  from torch import Tensor
  from torch_geometric.nn import SignedConv
  from torch_geometric.utils import coalesce, negative_sampling, structured_negative_sampling
label_desc: Use image node_id 4 for calling the SignedGCN obj's underlying member method code with example usage: obj.create_spectral_features(pos_edge_index, neg_edge_index, num_nodes) and returns: torch