chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
from .dhcf_conv import JHConv
|
||||
from .hgnn_conv import HGNNConv
|
||||
from .hgnnp_conv import HGNNPConv
|
||||
from .hnhn_conv import HNHNConv
|
||||
from .hwnn_conv import HWNNConv
|
||||
from .hypergcn_conv import HyperGCNConv
|
||||
from .unignn_conv import UniGATConv
|
||||
from .unignn_conv import UniGCNConv
|
||||
from .unignn_conv import UniGINConv
|
||||
from .unignn_conv import UniSAGEConv
|
||||
@@ -0,0 +1,54 @@
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
from easygraph.classes import Hypergraph
|
||||
|
||||
|
||||
class JHConv(nn.Module):
|
||||
r"""The Jump Hypergraph Convolution layer proposed in `Dual Channel Hypergraph Collaborative Filtering <https://dl.acm.org/doi/10.1145/3394486.3403253>`_ paper (KDD 2020).
|
||||
|
||||
Matrix Format:
|
||||
|
||||
.. math::
|
||||
\mathbf{X}^{\prime} = \sigma \left( \mathbf{D}_v^{-\frac{1}{2}} \mathbf{H} \mathbf{W}_e \mathbf{D}_e^{-1}
|
||||
\mathbf{H}^\top \mathbf{D}_v^{-\frac{1}{2}} \mathbf{X} \mathbf{\Theta} + \mathbf{X} \right).
|
||||
|
||||
Parameters:
|
||||
``in_channels`` (``int``): :math:`C_{in}` is the number of input channels.
|
||||
``out_channels`` (int): :math:`C_{out}` is the number of output channels.
|
||||
``bias`` (``bool``): If set to ``False``, the layer will not learn the bias parameter. Defaults to ``True``.
|
||||
``use_bn`` (``bool``): If set to ``True``, the layer will use batch normalization. Defaults to ``False``.
|
||||
``drop_rate`` (``float``): If set to a positive number, the layer will use dropout. Defaults to ``0.5``.
|
||||
``is_last`` (``bool``): If set to ``True``, the layer will not apply the final activation and dropout functions. Defaults to ``False``.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
in_channels: int,
|
||||
out_channels: int,
|
||||
bias: bool = True,
|
||||
use_bn: bool = False,
|
||||
drop_rate: float = 0.5,
|
||||
is_last: bool = False,
|
||||
):
|
||||
super().__init__()
|
||||
self.is_last = is_last
|
||||
self.bn = nn.BatchNorm1d(out_channels) if use_bn else None
|
||||
self.act = nn.ReLU(inplace=True)
|
||||
self.drop = nn.Dropout(drop_rate)
|
||||
self.theta = nn.Linear(in_channels, out_channels, bias=bias)
|
||||
|
||||
def forward(self, X: torch.Tensor, hg: Hypergraph) -> torch.Tensor:
|
||||
r"""The forward function.
|
||||
|
||||
Parameters:
|
||||
X (``torch.Tensor``): Input vertex feature matrix. Size :math:`(N, C_{in})`.
|
||||
hg (``eg.Hypergraph``): The hypergraph structure that contains :math:`N` vertices.
|
||||
"""
|
||||
X = self.theta(X)
|
||||
if self.bn is not None:
|
||||
X = self.bn(X)
|
||||
X = hg.smoothing_with_HGNN(X) + X
|
||||
if not self.is_last:
|
||||
X = self.drop(self.act(X))
|
||||
return X
|
||||
@@ -0,0 +1,112 @@
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
import torch.nn.functional as F
|
||||
|
||||
from easygraph.nn.convs.common import MLP
|
||||
from easygraph.nn.convs.pma import PMA
|
||||
from torch_geometric.nn.conv import MessagePassing
|
||||
from torch_scatter import scatter
|
||||
|
||||
|
||||
class HalfNLHconv(MessagePassing):
|
||||
r"""The HalfNLHconv model proposed in `YOU ARE ALLSET: A MULTISET LEARNING FRAMEWORK FOR HYPERGRAPH NEURAL NETWORKS <https://openreview.net/pdf?id=hpBTIv2uy_E>`_ paper (ICLR 2022).
|
||||
|
||||
Parameters:
|
||||
``in_dim`` (``int``): : The dimension of input.
|
||||
``hid_dim`` (``int``): : The dimension of hidden.
|
||||
``out_dim`` (``int``): : The dimension of output.
|
||||
``num_layers`` (``int``): : The number of layers.
|
||||
``dropout`` (``float``): Dropout ratio. Defaults to 0.5.
|
||||
``normalization`` (``str``): The normalization method. Defaults to ``bn``
|
||||
``InputNorm`` (``bool``): Defaults to False.
|
||||
``heads`` (``int``): Defaults to 1
|
||||
`attention`` (``bool``): Defaults to True
|
||||
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
in_dim,
|
||||
hid_dim,
|
||||
out_dim,
|
||||
num_layers,
|
||||
dropout,
|
||||
normalization="bn",
|
||||
InputNorm=False,
|
||||
heads=1,
|
||||
attention=True,
|
||||
):
|
||||
super(HalfNLHconv, self).__init__()
|
||||
|
||||
self.attention = attention
|
||||
self.dropout = dropout
|
||||
|
||||
if self.attention:
|
||||
self.prop = PMA(in_dim, hid_dim, out_dim, num_layers, heads=heads)
|
||||
else:
|
||||
if num_layers > 0:
|
||||
self.f_enc = MLP(
|
||||
in_dim,
|
||||
hid_dim,
|
||||
hid_dim,
|
||||
num_layers,
|
||||
dropout,
|
||||
normalization,
|
||||
InputNorm,
|
||||
)
|
||||
self.f_dec = MLP(
|
||||
hid_dim,
|
||||
hid_dim,
|
||||
out_dim,
|
||||
num_layers,
|
||||
dropout,
|
||||
normalization,
|
||||
InputNorm,
|
||||
)
|
||||
else:
|
||||
self.f_enc = nn.Identity()
|
||||
self.f_dec = nn.Identity()
|
||||
|
||||
def reset_parameters(self):
|
||||
if self.attention:
|
||||
self.prop.reset_parameters()
|
||||
else:
|
||||
if not (self.f_enc.__class__.__name__ is "Identity"):
|
||||
self.f_enc.reset_parameters()
|
||||
if not (self.f_dec.__class__.__name__ is "Identity"):
|
||||
self.f_dec.reset_parameters()
|
||||
|
||||
# self.bn.reset_parameters()
|
||||
|
||||
def forward(self, x, edge_index, norm, aggr="add"):
|
||||
"""
|
||||
input -> MLP -> Prop
|
||||
"""
|
||||
|
||||
if self.attention:
|
||||
x = self.prop(x, edge_index)
|
||||
else:
|
||||
x = F.relu(self.f_enc(x))
|
||||
x = F.dropout(x, p=self.dropout, training=self.training)
|
||||
x = self.propagate(edge_index, x=x, norm=norm, aggr=aggr)
|
||||
x = F.relu(self.f_dec(x))
|
||||
|
||||
return x
|
||||
|
||||
def message(self, x_j, norm):
|
||||
return norm.view(-1, 1) * x_j
|
||||
|
||||
def aggregate(self, inputs, index, dim_size=None, aggr="sum"):
|
||||
r"""Aggregates messages from neighbors as
|
||||
:math:`\square_{j \in \mathcal{N}(i)}`.
|
||||
|
||||
Takes in the output of message computation as first argument and any
|
||||
argument which was initially passed to :meth:`propagate`.
|
||||
|
||||
By default, this function will delegate its call to scatter functions
|
||||
that support "add", "mean" and "max" operations as specified in
|
||||
:meth:`__init__` by the :obj:`aggr` argument.
|
||||
"""
|
||||
# ipdb.set_trace()
|
||||
|
||||
return scatter(inputs, index, dim=self.node_dim, reduce=aggr)
|
||||
@@ -0,0 +1,57 @@
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
from easygraph.classes import Hypergraph
|
||||
|
||||
|
||||
class HGNNConv(nn.Module):
|
||||
r"""The HGNN convolution layer proposed in `Hypergraph Neural Networks <https://arxiv.org/pdf/1809.09401>`_ paper (AAAI 2019).
|
||||
Matrix Format:
|
||||
|
||||
.. math::
|
||||
\mathbf{X}^{\prime} = \sigma \left( \mathbf{D}_v^{-\frac{1}{2}} \mathbf{H} \mathbf{W}_e \mathbf{D}_e^{-1}
|
||||
\mathbf{H}^\top \mathbf{D}_v^{-\frac{1}{2}} \mathbf{X} \mathbf{\Theta} \right).
|
||||
|
||||
where :math:`\mathbf{X}` is the input vertex feature matrix, :math:`\mathbf{H}` is the hypergraph incidence matrix,
|
||||
:math:`\mathbf{W}_e` is a diagonal hyperedge weight matrix, :math:`\mathbf{D}_v` is a diagonal vertex degree matrix,
|
||||
:math:`\mathbf{D}_e` is a diagonal hyperedge degree matrix, :math:`\mathbf{\Theta}` is the learnable parameters.
|
||||
|
||||
Parameters:
|
||||
``in_channels`` (``int``): :math:`C_{in}` is the number of input channels.
|
||||
``out_channels`` (int): :math:`C_{out}` is the number of output channels.
|
||||
``bias`` (``bool``): If set to ``False``, the layer will not learn the bias parameter. Defaults to ``True``.
|
||||
``use_bn`` (``bool``): If set to ``True``, the layer will use batch normalization. Defaults to ``False``.
|
||||
``drop_rate`` (``float``): If set to a positive number, the layer will use dropout. Defaults to ``0.5``.
|
||||
``is_last`` (``bool``): If set to ``True``, the layer will not apply the final activation and dropout functions. Defaults to ``False``.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
in_channels: int,
|
||||
out_channels: int,
|
||||
bias: bool = True,
|
||||
use_bn: bool = False,
|
||||
drop_rate: float = 0.5,
|
||||
is_last: bool = False,
|
||||
):
|
||||
super().__init__()
|
||||
self.is_last = is_last
|
||||
self.bn = nn.BatchNorm1d(out_channels) if use_bn else None
|
||||
self.act = nn.ReLU(inplace=True)
|
||||
self.drop = nn.Dropout(drop_rate)
|
||||
self.theta = nn.Linear(in_channels, out_channels, bias=bias)
|
||||
|
||||
def forward(self, X: torch.Tensor, hg: Hypergraph) -> torch.Tensor:
|
||||
r"""The forward function.
|
||||
|
||||
Parameters:
|
||||
X (``torch.Tensor``): Input vertex feature matrix. Size :math:`(N, C_{in})`.
|
||||
hg (``eg.Hypergraph``): The hypergraph structure that contains :math:`N` vertices.
|
||||
"""
|
||||
X = self.theta(X)
|
||||
if self.bn is not None:
|
||||
X = self.bn(X)
|
||||
X = hg.smoothing_with_HGNN(X)
|
||||
if not self.is_last:
|
||||
X = self.drop(self.act(X))
|
||||
return X
|
||||
@@ -0,0 +1,67 @@
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
from easygraph.classes import Hypergraph
|
||||
|
||||
|
||||
class HGNNPConv(nn.Module):
|
||||
r"""The HGNN :sup:`+` convolution layer proposed in `HGNN+: General Hypergraph Neural Networks <https://ieeexplore.ieee.org/document/9795251>`_ paper (IEEE T-PAMI 2022).
|
||||
|
||||
Sparse Format:
|
||||
|
||||
.. math::
|
||||
|
||||
\left\{
|
||||
\begin{aligned}
|
||||
m_{\beta}^{t} &=\sum_{\alpha \in \mathcal{N}_{v}(\beta)} M_{v}^{t}\left(x_{\alpha}^{t}\right) \\
|
||||
y_{\beta}^{t} &=U_{e}^{t}\left(w_{\beta}, m_{\beta}^{t}\right) \\
|
||||
m_{\alpha}^{t+1} &=\sum_{\beta \in \mathcal{N}_{e}(\alpha)} M_{e}^{t}\left(x_{\alpha}^{t}, y_{\beta}^{t}\right) \\
|
||||
x_{\alpha}^{t+1} &=U_{v}^{t}\left(x_{\alpha}^{t}, m_{\alpha}^{t+1}\right) \\
|
||||
\end{aligned}
|
||||
\right.
|
||||
|
||||
Matrix Format:
|
||||
|
||||
.. math::
|
||||
\mathbf{X}^{\prime} = \sigma \left( \mathbf{D}_v^{-1} \mathbf{H} \mathbf{W}_e
|
||||
\mathbf{D}_e^{-1} \mathbf{H}^\top \mathbf{X} \mathbf{\Theta} \right).
|
||||
|
||||
Parameters:
|
||||
``in_channels`` (``int``): :math:`C_{in}` is the number of input channels.
|
||||
``out_channels`` (int): :math:`C_{out}` is the number of output channels.
|
||||
``bias`` (``bool``): If set to ``False``, the layer will not learn the bias parameter. Defaults to ``True``.
|
||||
``use_bn`` (``bool``): If set to ``True``, the layer will use batch normalization. Defaults to ``False``.
|
||||
``drop_rate`` (``float``): If set to a positive number, the layer will use dropout. Defaults to ``0.5``.
|
||||
``is_last`` (``bool``): If set to ``True``, the layer will not apply the final activation and dropout functions. Defaults to ``False``.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
in_channels: int,
|
||||
out_channels: int,
|
||||
bias: bool = True,
|
||||
use_bn: bool = False,
|
||||
drop_rate: float = 0.5,
|
||||
is_last: bool = False,
|
||||
):
|
||||
super().__init__()
|
||||
self.is_last = is_last
|
||||
self.bn = nn.BatchNorm1d(out_channels) if use_bn else None
|
||||
self.act = nn.ReLU(inplace=True)
|
||||
self.drop = nn.Dropout(drop_rate)
|
||||
self.theta = nn.Linear(in_channels, out_channels, bias=bias)
|
||||
|
||||
def forward(self, X: torch.Tensor, hg: Hypergraph) -> torch.Tensor:
|
||||
r"""The forward function.
|
||||
|
||||
Parameters:
|
||||
X (``torch.Tensor``): Input vertex feature matrix. Size :math:`(|\mathcal{V}|, C_{in})`.
|
||||
hg (``eg.Hypergraph``): The hypergraph structure that contains :math:`|\mathcal{V}|` vertices.
|
||||
"""
|
||||
X = self.theta(X)
|
||||
if self.bn is not None:
|
||||
X = self.bn(X)
|
||||
X = hg.v2v(X, aggr="mean")
|
||||
if not self.is_last:
|
||||
X = self.drop(self.act(X))
|
||||
return X
|
||||
@@ -0,0 +1,53 @@
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
from easygraph.classes import Hypergraph
|
||||
|
||||
|
||||
class HNHNConv(nn.Module):
|
||||
r"""The HNHN convolution layer proposed in `HNHN: Hypergraph Networks with Hyperedge Neurons <https://arxiv.org/pdf/2006.12278.pdf>`_ paper (ICML 2020).
|
||||
|
||||
Parameters:
|
||||
``in_channels`` (``int``): :math:`C_{in}` is the number of input channels.
|
||||
``out_channels`` (int): :math:`C_{out}` is the number of output channels.
|
||||
``bias`` (``bool``): If set to ``False``, the layer will not learn the bias parameter. Defaults to ``True``.
|
||||
``use_bn`` (``bool``): If set to ``True``, the layer will use batch normalization. Defaults to ``False``.
|
||||
``drop_rate`` (``float``): If set to a positive number, the layer will use dropout. Defaults to ``0.5``.
|
||||
``is_last`` (``bool``): If set to ``True``, the layer will not apply the final activation and dropout functions. Defaults to ``False``.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
in_channels: int,
|
||||
out_channels: int,
|
||||
bias: bool = True,
|
||||
use_bn: bool = False,
|
||||
drop_rate: float = 0.5,
|
||||
is_last: bool = False,
|
||||
):
|
||||
super().__init__()
|
||||
self.is_last = is_last
|
||||
self.bn = nn.BatchNorm1d(out_channels) if use_bn else None
|
||||
self.act = nn.ReLU(inplace=True)
|
||||
self.drop = nn.Dropout(drop_rate)
|
||||
self.theta_v2e = nn.Linear(in_channels, out_channels, bias=bias)
|
||||
self.theta_e2v = nn.Linear(out_channels, out_channels, bias=bias)
|
||||
|
||||
def forward(self, X: torch.Tensor, hg: Hypergraph) -> torch.Tensor:
|
||||
r"""The forward function.
|
||||
|
||||
Parameters:
|
||||
X (``torch.Tensor``): Input vertex feature matrix. Size :math:`(|\mathcal{V}|, C_{in})`.
|
||||
hg (``eg.Hypergraph``): The hypergraph structure that contains :math:`|\mathcal{V}|` vertices.
|
||||
"""
|
||||
# v -> e
|
||||
X = self.theta_v2e(X)
|
||||
if self.bn is not None:
|
||||
X = self.bn(X)
|
||||
Y = self.act(hg.v2e(X, aggr="mean"))
|
||||
# e -> v
|
||||
Y = self.theta_e2v(Y)
|
||||
X = hg.e2v(Y, aggr="mean")
|
||||
if not self.is_last:
|
||||
X = self.drop(self.act(X))
|
||||
return X
|
||||
@@ -0,0 +1,58 @@
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
from easygraph.classes import Hypergraph
|
||||
|
||||
|
||||
class HWNNConv(nn.Module):
|
||||
r"""The HWNNConv model proposed in `Heterogeneous Hypergraph Embedding for Graph Classification <https://arxiv.org/pdf/2010.10728>`_ paper (WSDM 2021).
|
||||
|
||||
Parameters:
|
||||
``in_channels`` (``int``): :math:`C_{in}` is the number of input channels.
|
||||
``out_channels`` (``int``): :math:`C_{out}` is the number of output channels.
|
||||
``ncount`` (``int``): The Number of node in the hypergraph.
|
||||
``K1`` (``int``): Polynomial calculation times.
|
||||
``K2`` (``int``): Polynomial calculation times.
|
||||
``approx`` (``bool``): Whether to use polynomial fitting
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
in_channels: int,
|
||||
out_channels: int,
|
||||
ncount: int,
|
||||
K1: int = 2,
|
||||
K2: int = 2,
|
||||
approx: bool = False,
|
||||
):
|
||||
super().__init__()
|
||||
self.in_channels = in_channels
|
||||
self.out_channels = out_channels
|
||||
self.K1 = K1
|
||||
self.K2 = K2
|
||||
self.ncount = ncount
|
||||
self.approx = approx
|
||||
self.W = torch.nn.Parameter(torch.Tensor(self.in_channels, self.out_channels))
|
||||
self.W_d = torch.nn.Parameter(torch.Tensor(self.ncount))
|
||||
self.par = torch.nn.Parameter(torch.Tensor(self.K1 + self.K2))
|
||||
self.init_parameters()
|
||||
|
||||
def init_parameters(self):
|
||||
torch.nn.init.xavier_uniform_(self.W)
|
||||
torch.nn.init.uniform_(self.W_d, 0.99, 1.01)
|
||||
torch.nn.init.uniform_(self.par, 0, 0.99)
|
||||
|
||||
def forward(self, X: torch.Tensor, hg: Hypergraph) -> torch.Tensor:
|
||||
r"""The forward function.
|
||||
|
||||
Parameters:
|
||||
X (``torch.Tensor``): Input vertex feature matrix. Size :math:`(N, C_{in})`.
|
||||
hg (``eg.Hypergraph``): The hypergraph structure that contains :math:`N` vertices.
|
||||
"""
|
||||
if self.approx == True:
|
||||
X = hg.smoothing_with_HWNN_approx(
|
||||
X, self.par, self.W_d, self.K1, self.K2, self.W
|
||||
)
|
||||
else:
|
||||
X = hg.smoothing_with_HWNN_wavelet(X, self.W_d, self.W)
|
||||
return X
|
||||
@@ -0,0 +1,61 @@
|
||||
from typing import Optional
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
from easygraph.classes import Graph
|
||||
from easygraph.classes import Hypergraph
|
||||
|
||||
|
||||
class HyperGCNConv(nn.Module):
|
||||
r"""The HyperGCN convolution layer proposed in `HyperGCN: A New Method of Training Graph Convolutional Networks on Hypergraphs <https://papers.nips.cc/paper/2019/file/1efa39bcaec6f3900149160693694536-Paper.pdf>`_ paper (NeurIPS 2019).
|
||||
|
||||
Parameters:
|
||||
``in_channels`` (``int``): :math:`C_{in}` is the number of input channels.
|
||||
``out_channels`` (int): :math:`C_{out}` is the number of output channels.
|
||||
``use_mediator`` (``str``): Whether to use mediator to transform the hyperedges to edges in the graph. Defaults to ``False``.
|
||||
``bias`` (``bool``): If set to ``False``, the layer will not learn the bias parameter. Defaults to ``True``.
|
||||
``use_bn`` (``bool``): If set to ``True``, the layer will use batch normalization. Defaults to ``False``.
|
||||
``drop_rate`` (``float``): If set to a positive number, the layer will use dropout. Defaults to ``0.5``.
|
||||
``is_last`` (``bool``): If set to ``True``, the layer will not apply the final activation and dropout functions. Defaults to ``False``.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
in_channels: int,
|
||||
out_channels: int,
|
||||
use_mediator: bool = False,
|
||||
bias: bool = True,
|
||||
use_bn: bool = False,
|
||||
drop_rate: float = 0.5,
|
||||
is_last: bool = False,
|
||||
):
|
||||
super().__init__()
|
||||
self.is_last = is_last
|
||||
self.bn = nn.BatchNorm1d(out_channels) if use_bn else None
|
||||
self.use_mediator = use_mediator
|
||||
self.act = nn.ReLU(inplace=True)
|
||||
self.drop = nn.Dropout(drop_rate)
|
||||
self.theta = nn.Linear(in_channels, out_channels, bias=bias)
|
||||
|
||||
def forward(
|
||||
self, X: torch.Tensor, hg: Hypergraph, cached_g: Optional[Graph] = None
|
||||
) -> torch.Tensor:
|
||||
r"""The forward function.
|
||||
|
||||
Parameters:
|
||||
``X`` (``torch.Tensor``): Input vertex feature matrix. Size :math:`(N, C_{in})`.
|
||||
``hg`` (``eg.Hypergraph``): The hypergraph structure that contains :math:`N` vertices.
|
||||
``cached_g`` (``eg.Graph``): The pre-transformed graph structure from the hypergraph structure that contains :math:`N` vertices. If not provided, the graph structure will be transformed for each forward time. Defaults to ``None``.
|
||||
"""
|
||||
X = self.theta(X)
|
||||
if self.bn is not None:
|
||||
X = self.bn(X)
|
||||
if cached_g is None:
|
||||
g = Graph.from_hypergraph_hypergcn(hg, X, self.use_mediator)
|
||||
X = g.smoothing_with_GCN(X)
|
||||
else:
|
||||
X = cached_g.smoothing_with_GCN(X)
|
||||
if not self.is_last:
|
||||
X = self.drop(self.act(X))
|
||||
return X
|
||||
@@ -0,0 +1,289 @@
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
from easygraph.classes import Hypergraph
|
||||
|
||||
|
||||
class UniGCNConv(nn.Module):
|
||||
r"""The UniGCN convolution layer proposed in `UniGNN: a Unified Framework for Graph and Hypergraph Neural Networks <https://arxiv.org/pdf/2105.00956.pdf>`_ paper (IJCAI 2021).
|
||||
|
||||
Sparse Format:
|
||||
|
||||
.. math::
|
||||
\left\{
|
||||
\begin{aligned}
|
||||
h_{e} &= \frac{1}{|e|} \sum_{j \in e} x_{j} \\
|
||||
\tilde{x}_{i} &= \frac{1}{\sqrt{d_{i}}} \sum_{e \in \tilde{E}_{i}} \frac{1}{\sqrt{\tilde{d}_{e}}} W h_{e}
|
||||
\end{aligned}
|
||||
\right. .
|
||||
|
||||
where :math:`\tilde{d}_{e} = \frac{1}{|e|} \sum_{i \in e} d_{i}`.
|
||||
|
||||
Matrix Format:
|
||||
|
||||
.. math::
|
||||
\mathbf{X}^{\prime} = \sigma \left( \mathbf{D}_v^{-\frac{1}{2}} \mathbf{H} \tilde{\mathbf{D}}_e^{-\frac{1}{2}} \cdot \mathbf{D}_e^{-1} \mathbf{H}^\top \mathbf{X} \mathbf{\Theta} \right) .
|
||||
|
||||
Parameters:
|
||||
``in_channels`` (``int``): :math:`C_{in}` is the number of input channels.
|
||||
``out_channels`` (int): :math:`C_{out}` is the number of output channels.
|
||||
``bias`` (``bool``): If set to ``False``, the layer will not learn the bias parameter. Defaults to ``True``.
|
||||
``use_bn`` (``bool``): If set to ``True``, the layer will use batch normalization. Defaults to ``False``.
|
||||
``drop_rate`` (``float``): If set to a positive number, the layer will use dropout. Defaults to ``0.5``.
|
||||
``is_last`` (``bool``): If set to ``True``, the layer will not apply the final activation and dropout functions. Defaults to ``False``.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
in_channels: int,
|
||||
out_channels: int,
|
||||
bias: bool = True,
|
||||
use_bn: bool = False,
|
||||
drop_rate: float = 0.5,
|
||||
is_last: bool = False,
|
||||
):
|
||||
super().__init__()
|
||||
self.is_last = is_last
|
||||
self.bn = nn.BatchNorm1d(out_channels) if use_bn else None
|
||||
self.act = nn.ReLU(inplace=True)
|
||||
self.drop = nn.Dropout(drop_rate)
|
||||
self.theta = nn.Linear(in_channels, out_channels, bias=bias)
|
||||
|
||||
def forward(self, X: torch.Tensor, hg: Hypergraph) -> torch.Tensor:
|
||||
r"""The forward function.
|
||||
|
||||
Parameters:
|
||||
X (``torch.Tensor``): Input vertex feature matrix. Size :math:`(|\mathcal{V}|, C_{in})`.
|
||||
hg (``eg.Hypergraph``): The hypergraph structure that contains :math:`|\mathcal{V}|` vertices.
|
||||
"""
|
||||
X = self.theta(X)
|
||||
Y = hg.v2e(X, aggr="mean")
|
||||
# compute the special degree of hyperedges
|
||||
# _De = torch.zeros(hg.num_e, device=hg.device)
|
||||
_De = torch.zeros(hg.num_e)
|
||||
_Dv = hg.D_v._values()[hg.v2e_src]
|
||||
_De = (
|
||||
_De.scatter_reduce(0, index=hg.v2e_dst, src=_Dv, reduce="mean")
|
||||
/ _De.scatter_reduce(
|
||||
0, index=hg.v2e_dst, src=(_Dv != 0).float(), reduce="sum"
|
||||
)
|
||||
).pow(-0.5)
|
||||
|
||||
_De[_De.isinf()] = 1
|
||||
Y = _De.view(-1, 1) * Y
|
||||
# ===============================================
|
||||
X = hg.e2v(Y, aggr="sum")
|
||||
X = torch.sparse.mm(hg.D_v_neg_1_2, X)
|
||||
|
||||
if not self.is_last:
|
||||
X = self.act(X)
|
||||
if self.bn is not None:
|
||||
X = self.bn(X)
|
||||
X = self.drop(X)
|
||||
return X
|
||||
|
||||
|
||||
class UniGATConv(nn.Module):
|
||||
r"""The UniGAT convolution layer proposed in `UniGNN: a Unified Framework for Graph and Hypergraph Neural Networks <https://arxiv.org/pdf/2105.00956.pdf>`_ paper (IJCAI 2021).
|
||||
|
||||
Sparse Format:
|
||||
|
||||
.. math::
|
||||
\left\{
|
||||
\begin{aligned}
|
||||
\alpha_{i e} &=\sigma\left(a^{T}\left[W h_{\{i\}} ; W h_{e}\right]\right) \\
|
||||
\tilde{\alpha}_{i e} &=\frac{\exp \left(\alpha_{i e}\right)}{\sum_{e^{\prime} \in \tilde{E}_{i}} \exp \left(\alpha_{i e^{\prime}}\right)} \\
|
||||
\tilde{x}_{i} &=\sum_{e \in \tilde{E}_{i}} \tilde{\alpha}_{i e} W h_{e}
|
||||
\end{aligned}
|
||||
\right. .
|
||||
|
||||
Parameters:
|
||||
``in_channels`` (``int``): :math:`C_{in}` is the number of input channels.
|
||||
``out_channels`` (int): :math:`C_{out}` is the number of output channels.
|
||||
``bias`` (``bool``): If set to ``False``, the layer will not learn the bias parameter. Defaults to ``True``.
|
||||
``use_bn`` (``bool``): If set to ``True``, the layer will use batch normalization. Defaults to ``False``.
|
||||
``drop_rate`` (``float``): The dropout probability. If ``dropout <= 0``, the layer will not drop values. Defaults to ``0.5``.
|
||||
``atten_neg_slope`` (``float``): Hyper-parameter of the ``LeakyReLU`` activation of edge attention. Defaults to ``0.2``.
|
||||
``is_last`` (``bool``): If set to ``True``, the layer will not apply the final activation and dropout functions. Defaults to ``False``.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
in_channels: int,
|
||||
out_channels: int,
|
||||
bias: bool = True,
|
||||
use_bn: bool = False,
|
||||
drop_rate: float = 0.5,
|
||||
atten_neg_slope: float = 0.2,
|
||||
is_last: bool = False,
|
||||
):
|
||||
super().__init__()
|
||||
self.is_last = is_last
|
||||
self.bn = nn.BatchNorm1d(out_channels) if use_bn else None
|
||||
self.atten_dropout = nn.Dropout(drop_rate)
|
||||
self.atten_act = nn.LeakyReLU(atten_neg_slope)
|
||||
self.act = nn.ELU(inplace=True)
|
||||
self.theta = nn.Linear(in_channels, out_channels, bias=bias)
|
||||
self.atten_e = nn.Linear(out_channels, 1, bias=False)
|
||||
self.atten_dst = nn.Linear(out_channels, 1, bias=False)
|
||||
|
||||
def forward(self, X: torch.Tensor, hg: Hypergraph) -> torch.Tensor:
|
||||
r"""The forward function.
|
||||
|
||||
Parameters:
|
||||
X (``torch.Tensor``): Input vertex feature matrix. Size :math:`(|\mathcal{V}|, C_{in})`.
|
||||
hg (``eg.Hypergraph``): The hypergraph structure that contains :math:`|\mathcal{V}|` vertices.
|
||||
"""
|
||||
X = self.theta(X)
|
||||
Y = hg.v2e(X, aggr="mean")
|
||||
# ===============================================
|
||||
# alpha_e = self.atten_e(Y)
|
||||
# e_atten_score = alpha_e[hg.e2v_src]
|
||||
# e_atten_score = self.atten_dropout(self.atten_act(e_atten_score).squeeze())
|
||||
|
||||
e_atten_score = self.atten_dropout(
|
||||
self.atten_act(self.atten_e(Y)[hg.e2v_src]).squeeze()
|
||||
)
|
||||
|
||||
# ================================================================================
|
||||
# We suggest to add a clamp on attention weight to avoid Nan error in training.
|
||||
e_atten_score.clamp_(min=0.001, max=5)
|
||||
# ================================================================================
|
||||
X = hg.e2v(Y, aggr="softmax_then_sum", e2v_weight=e_atten_score)
|
||||
|
||||
if not self.is_last:
|
||||
X = self.act(X)
|
||||
if self.bn is not None:
|
||||
X = self.bn(X)
|
||||
return X
|
||||
|
||||
|
||||
class UniSAGEConv(nn.Module):
|
||||
r"""The UniSAGE convolution layer proposed in `UniGNN: a Unified Framework for Graph and Hypergraph Neural Networks <https://arxiv.org/pdf/2105.00956.pdf>`_ paper (IJCAI 2021).
|
||||
|
||||
Sparse Format:
|
||||
|
||||
.. math::
|
||||
\left\{
|
||||
\begin{aligned}
|
||||
h_{e} &= \frac{1}{|e|} \sum_{j \in e} x_{j} \\
|
||||
\tilde{x}_{i} &= W\left(x_{i}+\text { AGGREGATE }\left(\left\{x_{j}\right\}_{j \in \mathcal{N}_{i}}\right)\right)
|
||||
\end{aligned}
|
||||
\right. .
|
||||
|
||||
Matrix Format:
|
||||
|
||||
.. math::
|
||||
\mathbf{X}^{\prime} = \sigma \left( \left( \mathbf{I} + \mathbf{H} \mathbf{D}_e^{-1} \mathbf{H}^\top \right) \mathbf{X} \mathbf{\Theta} \right) .
|
||||
|
||||
Parameters:
|
||||
``in_channels`` (``int``): :math:`C_{in}` is the number of input channels.
|
||||
``out_channels`` (int): :math:`C_{out}` is the number of output channels.
|
||||
``bias`` (``bool``): If set to ``False``, the layer will not learn the bias parameter. Defaults to ``True``.
|
||||
``use_bn`` (``bool``): If set to ``True``, the layer will use batch normalization. Defaults to ``False``.
|
||||
``drop_rate`` (``float``): If set to a positive number, the layer will use dropout. Defaults to ``0.5``.
|
||||
``is_last`` (``bool``): If set to ``True``, the layer will not apply the final activation and dropout functions. Defaults to ``False``.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
in_channels: int,
|
||||
out_channels: int,
|
||||
bias: bool = True,
|
||||
use_bn: bool = False,
|
||||
drop_rate: float = 0.5,
|
||||
is_last: bool = False,
|
||||
):
|
||||
super().__init__()
|
||||
self.is_last = is_last
|
||||
self.bn = nn.BatchNorm1d(out_channels) if use_bn else None
|
||||
self.act = nn.ReLU(inplace=True)
|
||||
self.drop = nn.Dropout(drop_rate)
|
||||
self.theta = nn.Linear(in_channels, out_channels, bias=bias)
|
||||
|
||||
def forward(self, X: torch.Tensor, hg: Hypergraph) -> torch.Tensor:
|
||||
r"""The forward function.
|
||||
|
||||
Parameters:
|
||||
X (``torch.Tensor``): Input vertex feature matrix. Size :math:`(|\mathcal{V}|, C_{in})`.
|
||||
hg (``eg.Hypergraph``): The hypergraph structure that contains :math:`|\mathcal{V}|` vertices.
|
||||
"""
|
||||
X = self.theta(X)
|
||||
Y = hg.v2e(X, aggr="mean")
|
||||
X = hg.e2v(Y, aggr="sum") + X
|
||||
if not self.is_last:
|
||||
X = self.act(X)
|
||||
if self.bn is not None:
|
||||
X = self.bn(X)
|
||||
X = self.drop(X)
|
||||
return X
|
||||
|
||||
|
||||
class UniGINConv(nn.Module):
|
||||
r"""The UniGIN convolution layer proposed in `UniGNN: a Unified Framework for Graph and Hypergraph Neural Networks <https://arxiv.org/pdf/2105.00956.pdf>`_ paper (IJCAI 2021).
|
||||
|
||||
Sparse Format:
|
||||
|
||||
.. math::
|
||||
|
||||
\left\{
|
||||
\begin{aligned}
|
||||
h_{e} &= \frac{1}{|e|} \sum_{j \in e} x_{j} \\
|
||||
\tilde{x}_{i} &= W\left((1+\varepsilon) x_{i}+\sum_{e \in E_{i}} h_{e}\right)
|
||||
\end{aligned}
|
||||
\right. .
|
||||
|
||||
Matrix Format:
|
||||
|
||||
.. math::
|
||||
\mathbf{X}^{\prime} = \sigma \left( \left( \left( \mathbf{I} + \varepsilon \right) + \mathbf{H} \mathbf{D}_e^{-1} \mathbf{H}^\top \right) \mathbf{X} \mathbf{\Theta} \right) .
|
||||
|
||||
Parameters:
|
||||
``in_channels`` (``int``): :math:`C_{in}` is the number of input channels.
|
||||
``out_channels`` (int): :math:`C_{out}` is the number of output channels.
|
||||
``eps`` (``float``): :math:`\varepsilon` is the learnable parameter. Defaults to ``0.0``.
|
||||
``train_eps`` (``bool``): If set to ``True``, the layer will learn the :math:`\varepsilon` parameter. Defaults to ``False``.
|
||||
``bias`` (``bool``): If set to ``False``, the layer will not learn the bias parameter. Defaults to ``True``.
|
||||
``use_bn`` (``bool``): If set to ``True``, the layer will use batch normalization. Defaults to ``False``.
|
||||
``drop_rate`` (``float``): If set to a positive number, the layer will use dropout. Defaults to ``0.5``.
|
||||
``is_last`` (``bool``): If set to ``True``, the layer will not apply the final activation and dropout functions. Defaults to ``False``.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
in_channels: int,
|
||||
out_channels: int,
|
||||
eps: float = 0.0,
|
||||
train_eps: bool = False,
|
||||
bias: bool = True,
|
||||
use_bn: bool = False,
|
||||
drop_rate: float = 0.5,
|
||||
is_last: bool = False,
|
||||
):
|
||||
super().__init__()
|
||||
self.is_last = is_last
|
||||
if train_eps:
|
||||
self.eps = nn.Parameter(torch.tensor([eps]))
|
||||
else:
|
||||
self.eps = eps
|
||||
self.bn = nn.BatchNorm1d(out_channels) if use_bn else None
|
||||
self.act = nn.ReLU(inplace=True)
|
||||
self.drop = nn.Dropout(drop_rate)
|
||||
self.theta = nn.Linear(in_channels, out_channels, bias=bias)
|
||||
|
||||
def forward(self, X: torch.Tensor, hg: Hypergraph) -> torch.Tensor:
|
||||
r"""The forward function.
|
||||
|
||||
Parameters:
|
||||
X (``torch.Tensor``): Input vertex feature matrix. Size :math:`(|\mathcal{V}|, C_{in})`.
|
||||
hg (``eg.Hypergraph``): The hypergraph structure that contains :math:`|\mathcal{V}|` vertices.
|
||||
"""
|
||||
X = self.theta(X)
|
||||
Y = hg.v2e(X, aggr="mean")
|
||||
X = (1 + self.eps) * hg.e2v(Y, aggr="sum") + X
|
||||
if not self.is_last:
|
||||
X = self.act(X)
|
||||
if self.bn is not None:
|
||||
X = self.bn(X)
|
||||
X = self.drop(X)
|
||||
return X
|
||||
Reference in New Issue
Block a user