gravins/Anti-SymmetricDGN

A quick question about model design

HelloWorldLTY opened this issue · 4 comments

Hi, I wonder why Anti DGN does not choose to compress the feature, like an encoder structure. If our input graph has feature dim like 10000, is it still reasonable to choose the output dimensions the same as the input dimensions? I think pyg uses in=out design.
https://pytorch-geometric.readthedocs.io/en/latest/generated/torch_geometric.nn.conv.AntiSymmetricConv.html#torch_geometric.nn.conv.AntiSymmetricConv

Thanks a lot!

Dear @HelloWorldLTY ,
Thanks for the question.

In PyG the model is implemented as a recurrent layer, thus you can still compress the input features but you need to do it with a different encoder.
A common and easy way to do it consists on creating a class that given an input it maps it into a different features space, applies A-DGN, and lastly maps the features to the output space. Which is something that you can do with a class implemented like this:

import torch
from torch.nn import Module, Linear
from torch_geometric.nn import AntiSymmetricConv
from torch_geometric.data import Data

class ADGN(Module):
    def __init__(self, 
                 input_dim, output_dim, hidden_dim, 
                 phi, num_iters, epsilon, gamma, 
                 act = 'tanh', act_kwargs = None, 
                 bias = True) -> None:
        super(ADGN, self).__init__()
        self.input_dim = input_dim
        self.output_dim = output_dim
        self.hidden_dim = hidden_dim
        self.phi = phi
        self.num_iters = num_iters
        self.epsilon = epsilon
        self.gamma = gamma
        self.act = act
        self.act_kwargs = act_kwargs
        self.bias = bias

        self.emb = Linear(self.input_dim, self.hidden_dim)
        self.conv = AntiSymmetricConv(
            self.hidden_dim,
            self.phi,
            self.num_iters,
            self.epsilon,
            self.gamma,
            self.act,
            self.act_kwargs,
            self.bias
        )
        self.readout = Linear(self.hidden_dim, self.output_dim)

    def forward(self, data: Data) -> torch.Tensor:
        x, edge_index, edge_weight = data.x, data.edge_index, data.edge_weight

        x = self.emb(x)
        x = self.conv(x, edge_index, edge_weight)
        x = self.readout(x)

        return x

Thanks a lot!

Hi, I think there is a bug for network init based on the previous code. The correct version might be:

import torch
from torch.nn import Module, Linear
from antisymmetric_conv import AntiSymmetricConv
from torch_geometric.data import Data


class ADGN(nn.Module):

    def __init__(self, 
                 input_dim, output_dim, hidden_dim, 
                 phi=None, num_iters: int = 1,
        epsilon: float = 0.1,
        gamma: float = 0.1, 
                 act = 'tanh', act_kwargs = None, 
                 bias = True) -> None:
        super(ADGN, self).__init__()
        self.input_dim = input_dim
        self.output_dim = output_dim
        self.hidden_dim = hidden_dim
        self.phi = phi
        self.num_iters = num_iters
        self.epsilon = epsilon
        self.gamma = gamma
        self.act = act
        self.act_kwargs = act_kwargs
        self.bias = bias
        self.emb = nn.Linear(self.input_dim, self.hidden_dim)
        self.conv = AntiSymmetricConv(
            self.hidden_dim,
            self.phi,
            self.num_iters,
            self.epsilon,
            self.gamma,
            self.act,
            self.act_kwargs,
            self.bias
        )
        self.readout = nn.Linear(self.hidden_dim, self.output_dim)

    def forward(self, data: Data) -> torch.Tensor:

        x, edge_index, edge_weight = data.x, data.edge_index
        x = self.emb(x)
        x = self.conv(x, edge_index)
        x = self.readout(x)

        return x

In the previous comment I missed the call for the super init. I updated the previous comment accordingly.
Regarding the default value for some arguments, it is not mandatory to specify that. In the version that I propose the user should specify the values at each call.
Lastly, in the forward function you wrote, it is missing the encoder. Thus, you are not able to map the input into a new hidden space, as you asked in your first comment. Be careful.