class_docstr: ## Graph attention layer
  
  This is a single graph attention layer.
  A GAT is made up of multiple such layers.
  
  It takes
  $$\mathbf{h} = \{ \overrightarrow{h_1}, \overrightarrow{h_2}, \dots, \overrightarrow{h_N} \}$$,
  where $\overrightarrow{h_i} \in \mathbb{R}^F$ as input
  and outputs
  $$\mathbf{h'} = \{ \overrightarrow{h'_1}, \overrightarrow{h'_2}, \dots, \overrightarrow{h'_N} \}$$,
  where $\overrightarrow{h'_i} \in \mathbb{R}^{F'}$.
class_docstr_tok: ["#","#","Graph","attention","layer","This","is","a","single","graph","attention","layer",".","A","GAT","is","made","up","of","multiple","such","layers",".","It","takes","$","$","\\mathbf","{","h","}","=","\\","{","\\overrightarrow","{","h_1","}",",","\\overrightarrow","{","h_2","}",",","\\dots",",","\\overrightarrow","{","h_N","}","\\","}","$","$",",","where","$","\\overrightarrow","{","h_i","}","\\in","\\mathbb","{","R","}","^F","$","as","input","and","outputs","$","$","\\mathbf","{","h","'","}","=","\\","{","\\overrightarrow","{","h'_1","}",",","\\overrightarrow","{","h'_2","}",",","\\dots",",","\\overrightarrow","{","h'_N","}","\\","}","$","$",",","where","$","\\overrightarrow","{","h'_i","}","\\in","\\mathbb","{","R","}","^","{","F","'","}","$","."]
docstr: * `in_features`, $F$, is the number of input features per node
  * `out_features`, $F'$, is the number of output features per node
  * `n_heads`, $K$, is the number of attention heads
  * `is_concat` whether the multi-head results should be concatenated or averaged
  * `dropout` is the dropout probability
  * `leaky_relu_negative_slope` is the negative slope for leaky relu activation
docstr_tok: ["*","`","in_features","`",",","$","F","$",",","is","the","number","of","input","features","per","node","*","`","out_features","`",",","$","F","'","$",",","is","the","number","of","output","features","per","node","*","`","n_heads","`",",","$","K","$",",","is","the","number","of","attention","heads","*","`","is_concat","`","whether","the","multi-head","results","should","be","concatenated","or","averaged","*","`","dropout","`","is","the","dropout","probability","*","`","leaky_relu_negative_slope","`","is","the","negative","slope","for","leaky","relu","activation"]
code: def __init__(
      self,
      in_features: int,
      out_features: int,
      n_heads: int,
      is_concat: bool = True,
      dropout: float = 0.6,
      leaky_relu_negative_slope: float = 0.2,
  ):
      """
      * `in_features`, $F$, is the number of input features per node
      * `out_features`, $F'$, is the number of output features per node
      * `n_heads`, $K$, is the number of attention heads
      * `is_concat` whether the multi-head results should be concatenated or averaged
      * `dropout` is the dropout probability
      * `leaky_relu_negative_slope` is the negative slope for leaky relu activation
      """
      super().__init__()
  
      self.is_concat = is_concat
      self.n_heads = n_heads
  
      # Calculate the number of dimensions per head
      if is_concat:
          assert out_features % n_heads == 0
          # If we are concatenating the multiple heads
          self.n_hidden = out_features // n_heads
      else:
          # If we are averaging the multiple heads
          self.n_hidden = out_features
  
      # Linear layer for initial transformation;
      # i.e. to transform the node embeddings before self-attention
      self.linear = nn.Linear(
          in_features, self.n_hidden * n_heads, bias=False
      )
      # Linear layer to compute attention score $e_{ij}$
      self.attn = nn.Linear(self.n_hidden * 2, 1, bias=False)
      # The activation for attention score $e_{ij}$
      self.activation = nn.LeakyReLU(
          negative_slope=leaky_relu_negative_slope
      )
      # Softmax to compute attention $\alpha_{ij}$
      self.softmax = nn.Softmax(dim=1)
      # Dropout layer to be applied for attention
      self.dropout = nn.Dropout(dropout)
  
imports: import torch
  from torch import nn
  from labml_helpers.module import Module
label_desc: Use image node_id 1 to create a new GraphAttentionLayer object from inherited base classes: Module with example: obj = GraphAttentionLayer(in_features, out_features, n_heads, is_concat, dropout, leaky_relu_negative_slope)