MCPcopy Create free account
hub / github.com/NineAbyss/ZeroG / GraphMAE

Class GraphMAE

code/model.py:204–277  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

202 # return pred
203
204class GraphMAE(nn.Module):
205
206 EPS = 1e-15
207
208 def __init__(self, in_dim, emb_dim, num_layer, kernel='gcn', drop_ratio=0,
209 act='relu', norm=None, concat=False, mask_ratio=0.5, replace_ratio=0):
210 super().__init__()
211
212 self.emb_dim = emb_dim if not concat else num_layer * emb_dim
213 self.mask_ratio = mask_ratio
214 self.replace_ratio = replace_ratio
215
216 self.encoder = Encoder(in_dim, emb_dim, num_layer, kernel, drop_ratio, act, norm,
217 concat=False, last_act=True, aggr='mean')
218 self.decoder = Encoder(emb_dim, in_dim, 1, kernel, drop_ratio, act, norm=None,
219 concat=False, last_act=False, aggr='mean')
220
221 self.encoder_mask_token = nn.Parameter(torch.zeros(1, in_dim))
222 self.encoder_to_decoder = nn.Linear(self.emb_dim, emb_dim, bias=False)
223
224
225 def forward(self, x, edge_index, edge_weigt=None, batch=None):
226 # Mask
227 mask_x, mask_nodes = self.encding_mask(x)
228 h = self.encoder(mask_x, edge_index, edge_weigt, batch)
229 h = self.encoder_to_decoder(h)
230
231 # Re-mask
232 h[mask_nodes] = 0
233 recon = self.decoder(h, edge_index, edge_weigt, batch)
234
235 return x[mask_nodes], recon[mask_nodes]
236
237
238 def encding_mask(self, x):
239
240 num_nodes = x.shape[0]
241
242 # random masking
243 perm = torch.randperm(num_nodes, device=x.device)
244 num_mask_nodes = int(self.mask_ratio * num_nodes)
245 mask_nodes = perm[: num_mask_nodes]
246 # keep_nodes = perm[num_mask_nodes: ]
247
248 if self.replace_ratio > 0:
249 num_noise_nodes = int(self.replace_ratio * num_mask_nodes)
250 perm_mask = torch.randperm(num_mask_nodes, device=x.device)
251 token_nodes = mask_nodes[perm_mask[: int((1 - self.replace_ratio) * num_mask_nodes)]]
252 noise_nodes = mask_nodes[perm_mask[-int(self.replace_ratio * num_mask_nodes):]]
253 noise_to_be_chosen = torch.randperm(num_nodes, device=x.device)[:num_noise_nodes]
254
255 out_x = x.clone()
256 out_x[token_nodes] = 0.0
257 out_x[noise_nodes] = x[noise_to_be_chosen]
258 else:
259 out_x = x.clone()
260 token_nodes = mask_nodes
261 out_x[mask_nodes] = 0.0

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected