chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:36:30 +08:00
commit 55ab4e4a73
473 changed files with 72932 additions and 0 deletions
@@ -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