code: def __init__(
      self,
      in_channels,
      out_channels,
      heads=1,
      groups=1,
      dropout=0,
      bias=True,
  ):
      super().__init__(dropout)
  
      self.in_channels = in_channels
      self.out_channels = out_channels
      self.heads = heads
      self.groups = groups
      self.bias = bias
  
      assert in_channels % heads == 0 and out_channels % heads == 0
      assert in_channels % groups == 0 and out_channels % groups == 0
      assert max(groups, self.heads) % min(groups, self.heads) == 0
  
      self.lin_q = Linear(in_channels, out_channels, groups, bias)
      self.lin_k = Linear(in_channels, out_channels, groups, bias)
      self.lin_v = Linear(in_channels, out_channels, groups, bias)
  
      self.reset_parameters()
  
imports: import math
  from typing import Optional
  import torch
  import torch.nn.functional
  from torch import Tensor
  from torch.nn import Parameter
  from torch_geometric.nn.conv import MessagePassing
  from torch_geometric.nn.conv.gcn_conv import gcn_norm
  from torch_geometric.nn.inits import kaiming_uniform, uniform
  from torch_geometric.typing import Adj, OptPairTensor, OptTensor, SparseTensor
label_desc: Use image node_id 1 to create a new MultiHead object from inherited base classes: Attention with example: obj = MultiHead(in_channels, out_channels, heads, groups, dropout, bias)