Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sample doesn't work correctly when nodes are repeated in input #208

Closed
Padarn opened this issue Mar 14, 2022 · 11 comments
Closed

sample doesn't work correctly when nodes are repeated in input #208

Padarn opened this issue Mar 14, 2022 · 11 comments

Comments

@Padarn
Copy link
Contributor

Padarn commented Mar 14, 2022

Working on pyg-team/pytorch_geometric#4026 I discovered that this sampling function does not work properly when the input_node array has duplicates. In this case the number of samples can be > number of edges and the index i doesn't do what you'd expect it to.

Another strange behaviour is when using the function as

torch.ops.torch_sparse.neighbor_sample(
            torch.Tensor([0, 1, 2, 3]).type(torch.long),
            torch.Tensor([1, 0, 1]).type(torch.long),
            torch.Tensor([0, 2]).type(torch.long),
            [1],
            False,
            False,
        )

The returned values are

(tensor([0, 2, 1]), tensor([2, 2, 0]), tensor([0, 1, 2]), tensor([0, 2, 1]))

but the (row, col) combination (2, 0) and (0, 2) don't make sense, they're not part of the original adjacency matrix.

I'm happy to dive in a bit deeper and figure out a fix (for at least the first issue, the second issue I am not sure if its actually a problem or not yet), but thought I'd check first if this is known or maybe my understanding is incorrect.

@rusty1s
Copy link
Owner

rusty1s commented Mar 14, 2022

Can you explain a bit more on the first issue? Not yet sure I understand the issue.

I think the second issue is not an issue at all since you need to take the remapping of node indices into account. That is node 0 stays node 0, but node 1 becomes node 2 (as indicated by the first output [0, 2, 1]). As such, the edges (2, 0) correspond to the original edge (1, 0).

@Padarn
Copy link
Contributor Author

Padarn commented Mar 14, 2022

ohh I see, the row/col are relative to the nodes in the output? If so, then agreed.

And if this is the case.. then actually the first issue is also a non-issue. Sorry for the false alarm!

@Padarn
Copy link
Contributor Author

Padarn commented Mar 15, 2022

Here is an example of what I am seeing

import torch
from torch_geometric.data import Data
from torch_geometric.loader.neighbor_loader import NeighborLoader

edge_index = torch.tensor([[0, 1, 1],
                           [1, 0, 2]], dtype=torch.long)
x = torch.tensor([[-1], [0], [1]], dtype=torch.float)
data = Data(x=x, edge_index=edge_index)

next(iter(NeighborLoader(data, input_nodes=torch.Tensor([0,1,2,0,0]), batch_size=5, num_neighbors=[5], directed=True)))

returns a data object with

data.x
>> tensor([[-1.],
        [ 0.],
        [ 1.],
        [-1.],
        [-1.]])

data.edge_index
>> tensor([[1, 0, 1, 1, 1],
        [0, 1, 2, 3, 4]])

I'm not convinced this is correct. I see that the edges are correct in the sense that no new connectivity is added, but this subgraph has a higher 'in degree' for node 1, thus the aggregation of messages will be different.

Thoughts?

@rusty1s
Copy link
Owner

rusty1s commented Mar 15, 2022

Interesting. I think this is correct in a sense that there is no bug in the code. Notably, the in-degree statistics are also correct which ensures that GNN ops should work correctly as well.

It is nonetheless indeed a bit weird that we share data across duplicated input nodes (and we may want to eventually fix that), but it shouldn't block us from implementing a link-level neighbor loader.

@Padarn
Copy link
Contributor Author

Padarn commented Mar 16, 2022 via email

@rusty1s
Copy link
Owner

rusty1s commented Mar 16, 2022

Sounds good to me. Thanks for being so careful! Currently, the neighbor_sampler does not create an isolated graph for every input node, but merges them together so that shared nodes can benefit from each other. We might need to add an option to disable this for link-level tasks.

@Padarn
Copy link
Contributor Author

Padarn commented Mar 16, 2022

Good thought. I'll probably not have time until the weekend for the changes on this repo, will take a look then.

@Padarn
Copy link
Contributor Author

Padarn commented Mar 19, 2022

Do you think its fair to say that sample in this library (in neighbour_sample_cpu) is actually a reverse sample? In the sense that edges are followed backwards? (this makes sense in the context of how it is used, but it is just confusing me a bit with naming)

@rusty1s
Copy link
Owner

rusty1s commented Mar 19, 2022

Yes, that is correct. If we think about the message passing flow of a GNN, we actually start sampling from our destination nodes and sample new source nodes.

@Padarn
Copy link
Contributor Author

Padarn commented Mar 19, 2022 via email

@Padarn
Copy link
Contributor Author

Padarn commented Mar 20, 2022

Closing this one as we've agreed not to do anything about it in pytorch_sparse, thanks @rusty1s

@Padarn Padarn closed this as completed Mar 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants