Open lygztq opened 3 years ago
Hi @lygztq , thanks for the request and I agree that this looks like an good feature to have. Could you further answer the following questions?
Thanks for the reply. The following is my opinion:
I think these functions should be included: cluster_max_pooling
, cluster_avg_pooling
, and cluster_sum_pooling
(to distinguish from global pooling functions). These functions perform a "global graph pooling" in each cluster. And their interfaces should be similar:
def cluster_xxx_pooling(graph: DGLGraph, node_feats: tensor, cluster_ids: tensor) -> Tuple[DGLGraph, tensor]:
pass
these functions return the pooled graph together with pooled node features.
At first, I thought these functions could be useful in graph classification tasks where graphs are coarsened layer by layer, with a cluster assignment for each node, to obtain a final graph embedding, just like DiffPool does. However, under this scenario, pooled graphs are usually small and dense. Applying sparse version cluster pooling to these graphs is expensive. Actually both implementations of DiffPool in PyG and DGL are based on dense implementation. However, I find these cluster pooling functions are useful in the voxel grid pooling of point cloud data where we overlay a regular grid of user-defined size over a point cloud and clusters all points within the same voxel. Point cloud graphs are sparse and usually large. The paper can be found here and an example in PyG can be found here
To the best of my knowledge, there's no implementation in DGL so far. One possible way for the implementation of these functions is based on scatter
operations (for example, scatter_add
for sum/avg pooling, scatter_max
for max pooling). However, currently DGL has pool support on these operations. Instead, we can use SpMM
(message passing) to achieve the same target. I explain this method here: #2718. The difficult parts of this method are how to construct the heterogeneous graph in an efficient and user-friendly manner, and how to get new edges in coarser graphs. All these possible implementations can be done via GPU since the underlying operations have GPU versions. I think the "differentiable" part can be done via writing autograd functions for them. For the batch information, I think we need to track the batch ID for each cluster (i.e. the node in coarser graphs).
Thanks for the answer. Some more thoughts:
scatter_reduce
or sort them by the assignment and then use spmm.Maybe there exists works that need to aggregate edge features, but currently I have no idea.
@jermainewang @lygztq Is this feature supported in DGL?
Hi @MozhganPourKeshavarz , the feature request is currently tracked in our project but the team is working on other higher priority tasks. We will post updates to this thread.
🚀 Feature
Support graph pooling operation on cliques.
Motivation
Graph coarsening is common in tasks where we try to extract graph features from different scales. Usually, the input graph is partitioned into many small cliques and global pooling operations are performed in these cliques to obtain nodes in the output (coarser) graph. This global pooling on cliques, or local pooling on graphs, is also common in multi-level graph coarsening methods like Metis and Graclus. However, currently DGL does not support this operation.
An example (in PyG) can be found here
Alternatives
It is true that one can first convert graph in sparse representation into dense representation, then such a problem can be redefined as matrix multiplication problem:
X' = C^{T}X
andA' = C^{T}AC
whereC \in \mathcal{R}^{N_{old} \times N_{new}}
is the assignment matrix. However, this is expensive for large and sparse graphs.An implementation for PyG can also be found here
Pitch
Given two tensor
c
andx
, where element inc
is a clique label for each node (which clique does this node belongs to) andx
is node feature tensor. And also given the graphg
. Output the coarser graph and node features.