Uniform Multi-Hop Sampler - #63
Conversation
| nbr_nids, nbr_times, nbr_feats, nbr_mask = dg._storage.get_nbrs( | ||
| seed_nodes, | ||
| num_nbrs=num_nbrs, | ||
| slice=DGSliceTracker(end_time=dg._slice.end_time), |
There was a problem hiding this comment.
Actually, might have to be dg._slice.end_idx since we don't want it to look forward to the next batch (even if tiemstamps match)
There was a problem hiding this comment.
not sure I understand, to discuss
There was a problem hiding this comment.
end_time=dg._slice.start_time
shenyangHuang
left a comment
There was a problem hiding this comment.
to discuss at meeting
| time_feat = self.time_encoder(torch.zeros(len(batch.nids[hop]), device=device)) | ||
| nbr_time_feat = self.time_encoder( | ||
| batch.nbr_times[hop] - batch.time.unsqueeze(dim=1).repeat(3, 1) | ||
| batch.time.unsqueeze(dim=1).repeat(3, 1) - batch.nbr_times[hop] |
| # This is a loop over the entire graph up to (not including) the current batch end time | ||
| # which results in quadratic cost for a single epoch. Consider raises a warning to let the | ||
| # user know that this is not the right backend for this. | ||
| nbrs: Dict[int, List[Tuple[int, int]]] = {node: [] for node in seed_nodes_set} |
There was a problem hiding this comment.
this is the main cost part
| nbrs[d].append((i, s)) | ||
|
|
||
| B = len(seed_nodes) | ||
| nbr_nids = torch.full((B, num_nbrs), -1, dtype=torch.long, device=device) |
There was a problem hiding this comment.
worst case these are O(n), where n is the number of nodes in the graph.
| nbr_nids_.append(self._data.edge_index[event_idx, edge_idx].item()) | ||
| nbr_times_.append(self._data.timestamps[event_idx]) | ||
| # Subsample if we have more neighbours than was queried | ||
| if num_nbrs != -1 and len(node_nbrs) > num_nbrs: |
There was a problem hiding this comment.
there is also some online way of keeping neighbors right? some probabilistic approach that you mentioned? online way for unbiased sampling I mean. potentially a future enhancement
| nbr_nids, nbr_times, nbr_feats, nbr_mask = dg._storage.get_nbrs( | ||
| seed_nodes, | ||
| num_nbrs=num_nbrs, | ||
| slice=DGSliceTracker(end_time=dg._slice.end_time), |
There was a problem hiding this comment.
not sure I understand, to discuss
| prev_hop_seed = batch.nids[-1] # type: ignore | ||
| prev_hop_nbrs = batch.nbr_nids[-1][batch.nbr_mask[-1].bool()] # type: ignore | ||
|
|
||
| # TODO: What is the expected behaviour when prev hop nbrs is empty? |
There was a problem hiding this comment.
if previous hop is empty, then the next hop is also empty
There was a problem hiding this comment.
for most methods, they care about the sampled neighborhood for all nodes in the batch at the end. If some nodes are disconnected, i.e. no neighbor, it will just message pass to itself only.
Codecov ReportAttention: Patch coverage is
📢 Thoughts on this report? Let us know! |
Purpose
The purpose of this PR is to add multi-hop support to the COO based uniform neighbor sampler.
Performance
TODO: Need to validate correctness once #58 is in before writing extensive tests.
Key Changes
tgm/tgm/hooks.py
Line 170 in 77eabb2
BaseNeighborSamplerHook) which manages the joint state and keeps the API fixed for all neighbour sampler implementationsRelevant Prs
Close #12
Out of scope