Performs a graph attention layer operation. Args: h (torch.Tensor): Input tensor representing node features. adj_mat (torch.Tensor): Adjacency matrix representing graph structure. Returns: torch.Tensor: Output tensor after the graph conv
(self, h: torch.Tensor, adj_mat: torch.Tensor)
| 90 | return self.leakyrelu(e) |
| 91 | |
| 92 | def forward(self, h: torch.Tensor, adj_mat: torch.Tensor): |
| 93 | """ |
| 94 | Performs a graph attention layer operation. |
| 95 | |
| 96 | Args: |
| 97 | h (torch.Tensor): Input tensor representing node features. |
| 98 | adj_mat (torch.Tensor): Adjacency matrix representing graph structure. |
| 99 | |
| 100 | Returns: |
| 101 | torch.Tensor: Output tensor after the graph convolution operation. |
| 102 | """ |
| 103 | n_nodes = h.shape[0] |
| 104 | |
| 105 | # Apply linear transformation to node feature -> W h |
| 106 | # output shape (n_nodes, n_hidden * n_heads) |
| 107 | h_transformed = torch.mm(h, self.W) |
| 108 | h_transformed = F.dropout(h_transformed, self.dropout, training=self.training) |
| 109 | |
| 110 | # splitting the heads by reshaping the tensor and putting heads dim first |
| 111 | # output shape (n_heads, n_nodes, n_hidden) |
| 112 | h_transformed = h_transformed.view(n_nodes, self.n_heads, self.n_hidden).permute(1, 0, 2) |
| 113 | |
| 114 | # getting the attention scores |
| 115 | # output shape (n_heads, n_nodes, n_nodes) |
| 116 | e = self._get_attention_scores(h_transformed) |
| 117 | |
| 118 | # Set the attention score for non-existent edges to -9e15 (MASKING NON-EXISTENT EDGES) |
| 119 | connectivity_mask = -9e16 * torch.ones_like(e) |
| 120 | e = torch.where(adj_mat > 0, e, connectivity_mask) # masked attention scores |
| 121 | |
| 122 | # attention coefficients are computed as a softmax over the rows |
| 123 | # for each column j in the attention score matrix e |
| 124 | attention = F.softmax(e, dim=-1) |
| 125 | attention = F.dropout(attention, self.dropout, training=self.training) |
| 126 | |
| 127 | # final node embeddings are computed as a weighted average of the features of its neighbors |
| 128 | h_prime = torch.matmul(attention, h_transformed) |
| 129 | |
| 130 | # concatenating/averaging the attention heads |
| 131 | # output shape (n_nodes, out_features) |
| 132 | if self.concat: |
| 133 | h_prime = h_prime.permute(1, 0, 2).contiguous().view(n_nodes, self.out_features) |
| 134 | else: |
| 135 | h_prime = h_prime.mean(dim=0) |
| 136 | |
| 137 | return h_prime |
| 138 | |
| 139 | ################################ |
| 140 | ### MAIN GAT NETWORK MODULE ### |
nothing calls this directly
no test coverage detected