【图神经网络】手把手带你快速上手OpenHGNN

本文提供了一个手把手的教程,介绍了如何在OpenHGNN中评估新数据集、构建新模型以及应用于新场景。具体步骤包括数据集的预处理、新模型的构建(如RGAT模型)和新任务(如推荐任务)及训练流程的创建。内容涵盖了从数据预处理到模型训练和评估的完整过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 评估新的数据集

如果需要,可以指定自己的数据集。本节中,我们使用HGBn-ACM作为节点分类数据集的示例。

1.1 如何构建一个新的数据集

第一步:预处理数据集
这里给出了一个处理HGBn-ACM的演示,这是一个节点分类数据集

首先,下载HGBn-ACM数据集:HGB数据集。下载完成后,需要将其处理为一个dgl.heterograph

以下代码片段是在DGL中创建异构图的示例。

import dgl
import torch as th

graph_data = {
    ('drug','interacts', 'drug'): (th.tensor([0,1]), th.tensor([1,2])),
    ('drug','interacts', 'gene'): (th.tensor([0,1]), th.tensor([2,3])),
    ('drug','treats','disease'): (th.tensor([1]), th.tensor([2]))
}
graph_data

graph_data
canonical_etypes
推荐将feature name设置为h

g.nodes['drug'].data['h'] = th.ones(3, 1)

DGL提供了dgl.save_graphs()dgl.load_graphs()分别表示保存和加载二进制形式的异质图。因此,这里使用dgl.save_graphs保存graphs到磁盘中:

dgl.save_graphs('demo_graph.bin',g)

第二步:增加额外的信息
经过第一步,得到一个demo_graph.bin的二进制文件,然后我们将其移动到openhgnn/dataset/目录下,下一步的具体信息在NodeClassificationDataset.py

例如,我们将category,num_classes和multi_label(if necessary) 设置为paper3True,分别表示要预测类的节点类型、类的数量以及任务是否为多标签分类。有关详细信息,请参阅基本节点分类数据集。
加载dgl
增加额外的信息:

if name_dataset == 'demo_graph':
    data_path = './openhgnn/dataset/demo_graph.bin'
    g, _ = load_graphs(data_path)
    g = g[0].long()
    self.category = 'author'  # 增加额外的信息
    self.num_classes = 4
    self.multi_label = False

第三步:可选
使用demo_graph作为数据集,评估一个存在的模型:

python main.py -m GTN -d demo_graph -t node_classification -g 0 --use_best_config

如果有另一个数据集名称,那需要修改代码build_dataset

2. 使用一个新的模型

这一部分,我们创建一个模型,名为RGAT,它不在我们的模型package <api-model>。

2.1 如何构建一个新模型

第一步:注册器模型
我们创建一个继承基本模型(Base Model)的类RGAT,并使用@register_model(str)注册该模型。

from openhgnn.models import BaseModel, register_model
@register_model('RGAT')
class RGAT(BaseModel):
    ...

第二步:实现函数
必须实现类方法build_model_from_args,其他函数像__init__,forward

...
class RGAT(BaseModel):
    @classmethod
    def build_model_from_args(cls, args, hg):
        return cls(in_dim=args.hidden_dim,
                   out_dim=args.hidden_dim,
                   h_dim=args.out_dim,
                   etypes=hg.etypes,
                   num_heads=args.num_heads,
                   dropout=args.dropout)

    def __init__(self, in_dim, out_dim, h_dim, etypes, num_heads, dropout):
        super(RGAT, self).__init__()
        self.rel_names = list(set(etypes))
        self.layers = nn.ModuleList()
        self.layers.append(RGATLayer(
            in_dim, h_dim, num_heads, self.rel_names, activation=F.relu, dropout=dropout))
        self.layers.append(RGATLayer(
            h_dim, out_dim, num_heads, self.rel_names, activation=None))
        return

    def forward(self, hg, h_dict=None):
        if hasattr(hg, 'ntypes'):
            # full graph training,
            for layer in self.layers:
                h_dict = layer(hg, h_dict)
        else:
            # minibatch training, block
            for layer, block in zip(self.layers, hg):
                h_dict = layer(block, h_dict)
        return h_dict

这里我们没有给出RGATLayer的实现细节。有关更多阅读,请查看:RGATLayer
在OpenHGNN中,我们在模型之外对数据集的特征进行预处理。具体来说,使用每个节点类型都有偏差的线性层来将所有节点特征映射到共享特征空间。因此,模型中forward的参数h_dict不是原始特征,您的模型不需要进行特征预处理。
第三步:添加到支持的模型字典
我们应该在 model/init.py中向 SUPPORTED _ MODELS 添加一个新条目。

3. 应用到一个新场景

在本节中,我们将应用于一个推荐场景,该场景涉及构建一个新任务和训练流。

3.1 如何构建一个新任务

第一步:注册任务
创建一个类Recommendation,继承内置的BaseTask并用@register_task(str)注册它。

from openhgnn.tasks import BaseTask, register_task
@register_task('recommendation')
class Recommendation(BaseTask):
    ...

第二步:实现方法
我们应该实现与评估指标和损失函数相关的方法。

class Recommendation(BaseTask):
    """Recommendation tasks."""
    def __init__(self, args):
        super(Recommendation, self).__init__()
        self.n_dataset = args.dataset
        self.dataset = build_dataset(args.dataset, 'recommendation')
        self.train_hg, self.train_neg_hg, self.val_hg, self.test_hg = self.dataset.get_split()
        self.evaluator = Evaluator(args.seed)

    def get_loss_fn(self):
        return F.binary_cross_entropy_with_logits

    def evaluate(self, y_true, y_score, name):
        if name == 'ndcg':
            return self.evaluator.ndcg(y_true, y_score)

最后
task/init.py中,增加一个新的实体到SUPPORTED_TASKS.

3.2 如何构建一个新的trainerflow

第一步:注册trainerflow
创建一个类,继承BaseFlow,并用@register_trainer(str)去注册trainerflow。

from openhgnn.trainerflow import BaseFlow, register_flow
@register_flow('Recommendation')
class Recommendation(BaseFlow):
    ...

第二步:实现方法
我们将函数train()声明为一个抽象方法。因此,train()必须被重写,否则trainerflow就无法实例化。下面给出了一个训练循环的示例。

...
class Recommendation(BaseFlow):
    def __init__(self, args=None):
        super(Recommendation, self).__init__(args)
        self.target_link = self.task.dataset.target_link
        self.model = build_model(self.model).build_model_from_args(self.args, self.hg)
        self.evaluator = self.task.get_evaluator(self.metric)

    def train(self,):
        for epoch in epoch_iter:
            self._full_train_step()
            self._full_test_step()

    def _full_train_step(self):
        self.model.train()
        logits = self.model(self.hg)[self.category]
        loss = self.loss_fn(logits[self.train_idx], self.labels[self.train_idx])
        self.optimizer.zero_grad()
        loss.backward()
        self.optimizer.step()
        return loss.item()

    def _full_test_step(self, modes=None, logits=None):
        self.model.eval()
        with torch.no_grad():
            loss = self.loss_fn(logits[mask], self.labels[mask]).item()
            metric = self.task.evaluate(pred, name=self.metric, mask=mask)
            return metric, loss

最终
trainerflow/init.py中增加一个新的实体到SUPPORT_FLOWS

内容来源

  1. Developer_Guide
<think>好的,我现在需要帮用户找到实现多层超图卷积神经网络的代码,用户提到可以使用Python、TensorFlow或PyTorch。首先,我得回忆一下超图卷积的相关知识。超图与传统图不同,边可以连接多个节点,所以常规的图卷积层可能不适用。用户引用了几个资料,其中引用[1]提到了使用PyTorch和CNN处理超图数据,引用[3]和[5]涉及图神经网络和超图网络构建,这可能对理解结构有帮助。 接下来,我需要考虑如何在PyTorch中实现多层超图卷积。根据引用[1]中的HypergraphCNN类,他们可能没有直接使用超图卷积层,而是结合了CNN。但用户需要的是多层超图卷积,可能需要参考现有的超图卷积实现方法。例如,超图卷积通常涉及节点和超边之间的信息传递,可能需要定义消息传递的层。 然后,我应该查找现有的库或示例。引用[4]提到OpenHGNN工具包,可能支持异质图神经网络,可能包含超图相关的层。用户可能需要安装这些库,并参考其文档。此外,引用[2]和[3]使用PyG和DGL,这两个库是否有超图的支持?目前PyG主要处理普通图,但或许可以通过扩展实现超图。例如,将超边分解成多个二元边,但这可能效率不高。 接下来,我需要考虑如何手动实现超图卷积层。根据文献,超图卷积可能涉及节点特征通过超边进行聚合。例如,每个节点特征与其所属超边的特征进行聚合,然后更新节点特征。多层实现则需要堆叠多个这样的层。 然后,我应该参考用户提供的代码结构。例如,引用[1]中的HypergraphCNN类,他们在forward方法中提到了可以添加超图卷积层。或许需要在这里插入自定义的超图卷积层。用户需要多层,因此可能需要定义多个这样的层。 可能还需要定义超图的邻接矩阵或关联矩阵。引用[5]提到基于关联矩阵构建超图网络,关联矩阵H的行表示节点,列表示超边,H[i,j]=1表示节点i属于超边j。因此,在实现卷积时,可能需要使用这个矩阵来进行特征传播。 现在,结合这些信息,我应该尝试编写一个多层超图卷积网络的示例代码。使用PyTorch和PyG,可能需要定义自定义的图层。例如,每个超图卷积层执行节点到超边的聚合,然后超边到节点的聚合。 最后,需要验证代码的正确性,并考虑如何训练这样的模型。可能还需要引用用户提供的资料,例如引用[1]中的模型结构,引用[4]中的工具包作为建议。</think>以下是基于PyTorch实现多层超图卷积神经网络的代码框架,结合了超图理论[^5]和图神经网络设计模式[^1][^3]: ```python import torch import torch.nn as nn import torch.sparse as sparse class HypergraphConv(nn.Module): def __init__(self, in_features, out_features, hyperedge_attr=None): super().__init__() self.linear = nn.Linear(in_features, out_features) self.hyperedge_attr = hyperedge_attr # 超边属性(可选) def forward(self, H, X): """ H: 关联矩阵 (n_nodes, n_hyperedges) X: 节点特征矩阵 (n_nodes, in_features) """ # 节点到超边的聚合 D_v = sparse.diag(1/torch.sum(H, dim=1)).to_dense() W_e = torch.eye(H.shape[1]).to(X.device) # 可学习的超边权重 # 超图卷积操作 X = D_v @ H @ W_e @ H.T @ X return torch.relu(self.linear(X)) class MultiHyperGCN(nn.Module): def __init__(self, input_dim, hidden_dim, output_dim, num_layers=2): super().__init__() self.layers = nn.ModuleList() self.layers.append(HypergraphConv(input_dim, hidden_dim)) for _ in range(num_layers-2): self.layers.append(HypergraphConv(hidden_dim, hidden_dim)) self.layers.append(nn.Linear(hidden_dim, output_dim)) def forward(self, H, X): for layer in self.layers[:-1]: X = layer(H, X) return self.layers[-1](X) ``` ### 实现说明: 1. **超图关联矩阵**:使用稀疏矩阵$H \in \mathbb{R}^{n \times m}$表示节点-超边关系,其中$n$为节点数,$m$为超边数[^5] 2. **多层架构**:通过堆叠多个`HypergraphConv`层实现深度特征提取[^1] 3. **特征传播**:遵循超图卷积公式: $$X^{(l+1)} = D_v^{-1}H W_e H^T X^{(l)} \Theta^{(l)}$$ 其中$D_v$为节点度矩阵,$W_e$为超边权重矩阵 ### 推荐工具包: 1. **OpenHGNN**:支持异质超图神经网络的开发[^4] 2. **PyTorch Geometric**:可扩展实现自定义图卷积层[^2] 3. **DGL**:提供图神经网络基础组件
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

镰刀韭菜

看在我不断努力的份上,支持我吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值