class_docstr: LowRankTensorFusion is a PyTorch module that performs multimodal fusion using a low-rank tensor-based approach.
     The 'input_dims' argument specifies the input dimensions of each modality. The 'output_dim' argument defines the
     output dimension after the fusion. The 'rank' argument is a hyperparameter specifying the rank for the low-rank
     tensor decomposition.
     This fusion method performs fusion by assuming a low-rank structure for the interaction tensor, effectively
     compressing the interaction space. It leverages a set of low-rank factors, one for each modality, that are
     learned during training.
     These factors are initialized with xavier normal distribution and are applied to their corresponding modalities
     during the forward pass. A tensor product is computed across all modalities and their respective factors,
     resulting in a fused tensor.
     Next, a weighted summation of this fused tensor is computed using fusion weights, followed by the addition of a
     fusion bias. Both fusion weights and bias are learnable parameters initialized with xavier normal distribution
     and zero respectively.
     The final output is reshaped to the specified 'output_dim' and returned. If 'flatten' is set to True, each
     modality is first flattened before concatenation with a ones tensor and the subsequent multiplication with its
     factor.
     This approach provides an efficient and compact representation for capturing interactions among multiple
     modalities, making it suitable for tasks involving high-dimensional multimodal data.
  Args:
      input_dims (int): A list or tuple of integers indicating input dimensions of the modalities.
      output_dim (int): output dimension after the fusion.
      rank (int): A hyperparameter specifying the rank for the low-rank tensor decomposition.
      flatten (bool): Boolean to dictate if output should be flattened or not. Default: True
  
  Note:
      Adapted from https://github.com/Justin1904/Low-rank-Multimodal-Fusion.
code: def __init__(self, input_dims, output_dim, rank, flatten=True):
      super(LowRankTensorFusion, self).__init__()
  
      self.input_dims = input_dims
      self.output_dim = output_dim
      self.rank = rank
      self.flatten = flatten
  
      self.factors = []
      for input_dim in input_dims:
          factor = nn.Parameter(
              torch.Tensor(self.rank, input_dim + 1, self.output_dim)
          ).to(
              torch.device(
                  "cuda:0" if torch.cuda.is_available() else "cpu"
              )
          )
          nn.init.xavier_normal_(factor)
          self.factors.append(factor)
  
      self.fusion_weights = nn.Parameter(torch.Tensor(1, self.rank)).to(
          torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
      )
      self.fusion_bias = nn.Parameter(
          torch.Tensor(1, self.output_dim)
      ).to(
          torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
      )
      nn.init.xavier_normal_(self.fusion_weights)
      self.fusion_bias.data.fill_(0)
  
file_path: pykale/kale/embed/feature_fusion.py
imports: import torch
  from torch import nn
  from torch.autograd import Variable
label_desc: Use image node_id 1 to create a new LowRankTensorFusion object from inherited base classes: nn with example: obj = LowRankTensorFusion(input_dims, output_dim, rank, flatten)