【图神经网络】图神经网络框架DGL1.0初体验

DGL 1.0: Empowering Graph Machine Learning For Everyone

DGL 1.0 总结了过去三年学术界或工业界对图深度学习和图神经网络(GNN)技术的各类需求。从最先进模型的学术研究到将 GNN 扩展到工业级应用,DGL 1.0 为所有用户提供全面且易用的解决方案,以更好的利用图机器学习的优势。
Different levels of user requests and what DGL 1.0 provides to fulfill them
DGL 1.0 为不同场景提供的解决方案。

DGL 1.0 采用分层和模块化的设计,以满足各种用户需求。本次发布的关键特性包括:

  • 100 多个开箱即用的 GNN 模型示例,15 多个在 Open Graph Benchmark(OGB)上排名靠前的基准模型;
  • 150 多个 GNN 常用模块,包括 GNN 层、数据集、图数据转换模块、图采样器等,可用于构建新的模型架构或基于 GNN 的解决方案;
  • 灵活高效的消息传递和稀疏矩阵抽象,用于开发新的 GNN 模块;
  • 多 GPU 和分布式训练能力,支持在百亿规模的图上进行训练。

DGL 1.0技术栈图如下:
DGL 1.0
DGL github 代码地址:https://github.com/dmlc/dgl

此版本的亮点之一是引入了DGL-Sparse,这是一个全新的编程接口,使用了稀疏矩阵作为核心的编程抽象。DGL-Sparse不仅可以简化现有的GNN模型(例如图卷积网络)的开发,而且还适用于最新的模型,包括基于扩散的GNN,超图神经网络和图Transformer。
DGL install

# If you have installed dgl-cuXX package, please uninstall it first.
pip install  dgl -f https://data.dgl.ai/wheels/cu113/repo.html
pip install  dglgo -f https://data.dgl.ai/wheels-test/repo.html

DGL中的两种GNN范式

DGL中包含两种主流的GNN范式,即消息传递视图(The Message Passing View)矩阵视图(The Matrix View)。这些范式可以帮助研究人员更好地理解 GNN 的内部工作机制,而矩阵视角也是DGL Sparse开发的动机之一。

电影《降临》中有这么一句话:「你所使用的语言决定了你的思维方式,并影响了你对事物的看法。」这句话也适合GNN。

表示图神经网络有两种不同的范式:

  • 第一种称为消息传递视图,从细粒度、局部的角度表达 GNN 模型,详细描述如何沿边交换消息以及节点状态如何进行相应的更新。
  • 第二种是矩阵视角,由于图与稀疏邻接矩阵具有代数等价性,许多研究人员选择从粗粒度、全局的角度来表达 GNN 模型,强调涉及稀疏邻接矩阵和特征向量的操作。

消息传递视角和矩阵视角
消息传递视角揭示了 GNN 与 Weisfeiler Lehman (WL)图同构测试之间的联系,后者也依赖于从邻居聚合信息。而矩阵视角则从代数角度来理解 GNN,引发了一些有趣的发现,比如过度平滑问题。

总之,这两种视角都是研究 GNN 不可或缺的工具,它们互相补充,帮助研究人员更好地理解和描述 GNN 模型的本质和特性。正是基于这个原因,DGL 1.0 发布的主要动机之一就是在已有的消息传递接口基础之上,增加对于矩阵视角的支持

DGL Sparse:为图机器学习设计的稀疏矩阵库

DGL 1.0 版本中新增了一个名为 DGL Sparse 的库(dgl.sparse),它和 DGL 中的消息传递接口一起,完善了对于全类型的图神经网络模型的支持。DGL Sparse 提供专门用于 图机器学习的稀疏矩阵类和操作,使得在矩阵视角下编写 GNN 变得更加容易。在下一节中,作者演示多个 GNN 示例,展示它们在 DGL Sparse 中的数学公式和相应的代码实现。

图卷积网络(Graph Convolutional Network)

GCN 是 GNN 建模的先驱之一。GCN 可以同时用消息传递视图和矩阵视图来表示。下面的代码比较了 DGL 中用这两种方法实现的区别。
Graph Convolution Network
1)DGL message passing functions

class GCNLayer(nn.Module):
    ...
   
    def forward(self, g, X):
        g.ndata['X'] = X
        g.ndata['deg'] = g.in_degrees().float()
        g.update_all(self.message, fn.sum('m', 'X_neigh'))
        X_neigh = g.ndata['X_neigh']
        return F.relu(self.W(X_neigh))
    
    def message(self, edges):
        c_ij = (edges.src['deg'] * edges.dst['deg']) ** -0.5
        return {'m' : edges.src['X'] * c_ij}

2)DGL sparse matrix package

import dgl.sparse as dglsp  # DGL 1.0 sparse matrix package

class GCNLayer(nn.Module):
    ...
    
    def forward(self, A, X):
        D_invsqrt = dglsp.diag(A.sum(1)) ** -0.5
        A_norm = D_invsqrt @ A @ D_invsqrt
        return F.relu(self.W(A_norm @ X))

基于图扩散的GNN

图扩散是沿边传播或平滑节点特征或信号的过程。PageRank 等许多经典图算法都属于这一类。一系列研究表明,将图扩散与神经网络相结合是增强模型预测有效且高效的方法。下面的等式描述了其中比较有代表性的模型 APPNP 的核心计算。它可以直接在 DGL Sparse 中实现。
基于图扩散的GNN

class APPNP(nn.Module):
    ...

    def forward(self, A, X):
        Z_0 = Z = self.f_theta(X)
        for _ in range(self.num_hops):
            A_drop = dglsp.val_like(A, self.A_dropout(A.val))
            Z = (1 - self.alpha) * A_drop @ Z + self.alpha * Z_0
        return Z

超图神经网络

超图是图的推广,其中边可以连接任意数量的节点(称为超边)超图在需要捕获高阶关系的场景中特别有用,例如电子商务平台中的共同购买行为,或引文网络中的共同作者等。超图的典型特征是其稀疏的关联矩阵,因此超图神经网络 (HGNN) 通常使用稀疏矩阵定义。以下是超图卷积网络(Feng et al., 2018)和其代码实现。
超图神经网络

class HypergraphConv(nn.Module):
    ...

    def forward(self, H, X):
        d_V = H.sum(1)  # node degree
        d_E = H.sum(0)  # edge degree
        n_edges = d_E.shape[0]
        D_V_invsqrt = dglsp.diag(d_V**-0.5)  # D_V ** (-1/2)
        D_E_inv = dglsp.diag(d_E**-1)  # D_E ** (-1)
        W = dglsp.identity((n_edges, n_edges))
        L = D_V_invsqrt @ H @ W @ D_E_inv @ H.T @ D_V_invsqrt
        return self.Theta(L @ X)

图 Transformer

Transformer 模型已经成为自然语言处理中最成功的模型架构。研究人员也开始将 Transformer 扩展到图机器学习。Dwivedi 等人开创性地提出将所有多头注意力限制为图中连接的节点对。通过 DGL Sparse 工具,只需 10 行代码即可轻松实现该模型。
图Transformer

class GraphMHA(nn.Module):
    ...

    def forward(self, A, h):
        N = len(h)
        q = self.q_proj(h).reshape(N, self.head_dim, self.num_heads)
        q *= self.scaling
        k = self.k_proj(h).reshape(N, self.head_dim, self.num_heads)
        v = self.v_proj(h).reshape(N, self.head_dim, self.num_heads)

        attn = dglsp.bsddmm(A, q, k.transpose(1, 0))  # [N, N, nh]
        attn = attn.softmax()
        out = dglsp.bspmm(attn, v)

        return self.out_proj(out.reshape(N, -1))

DGL Sparse 的关键特性

相比scipy.sparsetorch.sparse等稀疏矩阵库,DGL Sparse 的整体设计是为图机器学习服务,其中包括了以下关键特性:

  • 自动稀疏格式选择:DGL Sparse 的设计让用户不必为了选择正确的数据结构存储稀疏矩阵(也称为稀疏格式)而烦恼。用户只需要记住 dgl.sparse.spmatrix 创建稀疏矩阵,而 DGL 在内部则会根据调用的算子来自动选择最优格式;
  • 标量或矢量非零元素:很多 GNN 模型会在边上学习多个权重(如 Graph Transformer 示例中演示的多头注意力向量)。为了适应这种情况,DGL Sparse 允许非零元素具有向量形状,并扩展了常见的稀疏操作,例如稀疏 - 稠密 - 矩阵乘法(SpMM)等。可以参考 Graph Transformer 示例中的 bspmm 操作。

通过利用这些设计特性,与之前使用消息传递接口的矩阵视图模型的实现相比,DGL Sparse 将代码长度平均降低了 2.7 倍。简化的代码还使框架的开销减少 43%。此外DGL Sparse 与 PyTorch 兼容,可以轻松与 PyTorch 生态系统中的各种工具和包集成。

接下来,我们将正式开始使用DGL 1.0。可以使用 pip 或 conda 轻松安装。除了前面介绍的示例之外,DGL Sparse 的第一个版本还包括 5 个教程和 11 个端到端示例,所有教程都可以在 Google Colab 中直接体验,无需本地安装。

内容来源

  1. https://www.dgl.ai/release/2023/02/20/release.html
  2. https://mp.weixin.qq.com/s/DmjpGfBjytZZYKVnEC50Hw
<think>好的,我现在需要帮助用户了解如何在PyTorch中实现图神经网络(GNN)。用户提到了相关引用,我需要结合这些资料来构建一个清晰的教程和示例代码。首先,我应该回顾用户提供的引用内容,确保正确引用信息。 根据引用[1],PyTorch是构建和训练GNN的流行框架,而PyTorch Geometric(PyG)和DGL是常用的库。引用[2]提到图卷积网络(GCN)作为例子,引用[3]详细说明了PyTorch Geometric的批处理机制,引用[4]则涉及时空图神经网络(ST-GNN)的实现。这些引用为我提供了基础的结构和工具建议。 接下来,我需要组织步骤。首先,安装必要的库,如PyTorch和PyTorch Geometric。然后,数据准备部分需要解释如何构建数据,因为数据通常包含节点特征、边列表等信息。例如,引用[3]提到PyG使用Data对象处理单个,使用DataLoader进行批处理,这对于示例代码很重要。 然后是模型构建部分,GCN层是基础,可以展示如何定义GCN层,并堆叠成网络。需要引用[2]中的GCN例子,并参考引用[4]的ST-GNN结构,可能结合序列模型,但用户的问题主要是基础GNN,所以先聚焦在GCN的实现。 训练流程部分需要包括损失函数、优化器以及训练循环。这里需要确保代码示例正确,使用交叉熵损失和Adam优化器,这是常见的配置。同时,引用[3]提到的批处理策略应该在DataLoader部分说明,但用户提供的示例可能是一个简单的单训练,所以可能需要调整。 示例代码部分要展示完整的流程,包括数据准备、模型定义、训练和测试。需要检查代码是否符合PyG的最新语法,比如Data对象的创建和Conv层的使用是否正确。例如,引用[3]中提到的Data对象的结构,确保节点特征x、边索引edge_index正确传入。 在相关问题部分,需要生成与实现GNN相关的问题,如处理动态、异构,或者使用其他框架DGL。这些问题应基于引用内容,比如引用[4]中的ST-GNN涉及时空,可以作为相关问题之一。 最后,确保回答结构清晰,分步骤讲解,代码正确,并且引用标记正确。例如,在提到PyTorch Geometric的批处理时引用[3],在GCN部分引用[2],在工具推荐时引用[1]。 现在需要验证代码的正确性。例如,PyG的GCNConv层的输入输出维度是否正确,数据集的加载是否正确,以及训练循环是否合理。此外,需要确保用户安装正确的库版本,比如torch-geometric可能需要特定版本的PyTorch。 可能还需要补充数据加载的部分,比如使用内置数据集,如Cora,但用户可能希望一个更简单的例子,所以手动构建一个小的数据集可能更合适。例如,代码中的Data对象使用随机生成的特征和边索引,适用于示例。 最后,总结部分要提到进一步的学习资源和挑战,如处理大规模或动态,引用相关的引用[4]和[3]。</think>### PyTorch图神经网络实现教程 #### 一、环境配置与工具选择 安装PyTorch和PyTorch Geometric库: ```bash pip install torch torchvision torchaudio pip install torch_geometric ``` PyTorch Geometric(PyG)提供了丰富的图神经网络层和数据处理工具,是GNN实现的首选库[^1][^3]。 #### 二、数据准备 数据需包含节点特征、边连接信息和标签。以下示例创建一个包含3个节点的小型: ```python import torch from torch_geometric.data import Data # 节点特征矩阵 (3个节点,每个节点2维特征) x = torch.tensor([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]], dtype=torch.float) # 边连接 (无向的边需双向表示) edge_index = torch.tensor([[0, 1, 1, 2], [1, 0, 2, 1]], dtype=torch.long) data = Data(x=x, edge_index=edge_index) ``` PyG通过`Data`对象封装结构,支持自动批处理。 #### 三、GNN模型构建(以GCN为例) ```python from torch_geometric.nn import GCNConv import torch.nn.functional as F class GCN(torch.nn.Module): def __init__(self, input_dim, hidden_dim, output_dim): super().__init__() self.conv1 = GCNConv(input_dim, hidden_dim) # 第一层GCN self.conv2 = GCNConv(hidden_dim, output_dim) # 第二层GCN def forward(self, data): x, edge_index = data.x, data.edge_index x = self.conv1(x, edge_index) # 消息传递 x = F.relu(x) # 激活函数 x = F.dropout(x, training=self.training) x = self.conv2(x, edge_index) return F.log_softmax(x, dim=1) # 分类输出 ``` GCN层通过聚合邻居信息更新节点表示[^2]。 #### 四、训练流程 ```python model = GCN(input_dim=2, hidden_dim=16, output_dim=2) optimizer = torch.optim.Adam(model.parameters(), lr=0.01) # 模拟标签数据 y = torch.tensor([0, 1, 0]) for epoch in range(200): model.train() optimizer.zero_grad() out = model(data) loss = F.nll_loss(out, y) # 负对数似然损失 loss.backward() optimizer.step() print(f'Epoch {epoch+1}, Loss: {loss.item():.4f}') ``` #### 五、扩展应用:时空图神经网络(ST-GNN) 结合GRU处理时序特征: ```python class STGNN(torch.nn.Module): def __init__(self, input_dim, hidden_dim): super().__init__() self.gcn = GCNConv(input_dim, hidden_dim) self.gru = torch.nn.GRU(hidden_dim, hidden_dim) def forward(self, data_sequence): h = None for t in range(len(data_sequence)): x = self.gcn(data_sequence[t].x, data_sequence[t].edge_index) _, h = self.gru(x.unsqueeze(0), h) # 时序建模 return h.squeeze(0) ``` 这种结构可用于交通流量预测等场景[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

镰刀韭菜

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

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

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

打赏作者

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

抵扣说明:

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

余额充值