PYG(Pytorch Geometric)中文说明书——第2章GET STARTED

在这里插入图片描述
本文为pyg官网的中文翻译(官方原版链接 https://pytorch-geometric.readthedocs.io/en/latest/),并加入了一些其他网上大佬和自己的理解。如有翻译理解不当之处还请各位多多指出,非常感谢!
2.1举个大栗子,举很多栗子,举各种各样的栗子
pyg主要提供以下主要功能:

  • 图的数据处理
  • 通用基准数据集
  • 小批量
  • 数据转换
  • 图的学习方法
  • 练习

2.1.1 图的数据处理
图用于对对象(节点)之间的成对关系(边)进行建模。pyg中的单个图由torch_geometry.data.Data实例描述。Data,默认情况下包含以下属性:

  • data.x :表示节点特征矩阵,形状为[num_nodes(节点总数),num_node_features(节点特征)]
  • data.edge_index :图用COO格式进行连接,其形状为[num_edges(总的边个数),num_edge_features(边的特征)][2,num_edges],类别为torch.long
  • data.edge_attr :边的特征矩阵,形状为[num_edges,num_edge_features]
  • data.y :待训练的目标可以是任意形状。节点级目标的形式为[num_nodes,* ],图级的目标形式为[1,*]
  • data.pos :节点位置矩阵,形状为[num_nodes(节点总数),num_dimensions(节点维度)]

这些属性都不是必需的。此外Data对象甚至可以在增添一些属性。例如,3D图:形状为[3,num_faces],类型为torch.long的张量。

栗子1
已知,一个无权无向图有3个节点4条边,每个节点只包含一个特征:

import torch
from torch_geometric.data import Data

edge_index = torch.tensor([[0,1,1,2],[1,0,2,1]],dtype=torch.long)

x = torch.tensor([[-1],[0],[1]],dtype=torch.float)
data = Data(x=x,edge_index=edge_index)
>>>Data(edge_index=[2,4],x=[3,1])

在这里插入图片描述
注意,edge_index,即定义所有边的源节点和目标节点的张量,并不是索引元组的列表。如果你想按照该写法写你的索引,那就应该在传递给数据构造函数之前对它进行转置和调用,举例:

import torch
from torch_geometric.data import Data

edge_index = torch.tensor([[0, 1],
                           [1, 0],
                           [1, 2],
                           [2, 1]], dtype=torch.long)
x = torch.tensor([[-1], [0], [1]], dtype=torch.float)

data = Data(x=x, edge_index=edge_index.t().contiguous())
>>> Data(edge_index=[2, 4], x=[3, 1])

(备注:请移步“pytorch–初识张量与基础函数 https://blog.csdn.net/lkr_2023/article/details/123200296”)
虽然上图只有两条边,但我们需要定义四个索引元组来说明一条边的两个方向。

-
你可以随时打印该图的属性以及形状等信息
最终使用==validate()==命令来检查data最终数据对象是否满足要求:

data.validate(raise_on_error=True)

除了持有一些节点级、边级或图级属性外,Data还提供了一些有用的实用函数,例如:

print(data.keys())  #包含的键
>>> ['x', 'edge_index']

print(data['x'])  #图节点的值
>>> tensor([[-1.0],
            [0.0],
            [1.0]])

for key, item in data:
    print(f'{key} found in data')
>>> x found in data
>>> edge_index found in data

'edge_attr' in data  #不道干哈的
>>> False

data.num_nodes  #判断图中的总节点数量
>>> 3

data.num_edges  #判断图中的总边数量
>>> 4

data.num_node_features  #判断节点特征的维度
>>> 1

data.has_isolated_nodes() #判断图中是否含有孤立节点
>>> False

data.has_self_loops()  #判断图是否含有自环
>>> False

data.is_directed()  #判断图是否为有向图
>>> False

# Transfer data object to GPU.GPU不用CPU
device = torch.device('cuda')
data = data.to(device)

你可以在torch_geometric.data.Data中找到所有功能的完整列表。
<注>COO是稀疏矩阵的常用表示方法之一

2.1.2 通用标准数据集
PyG包含大量常见的基准数据集,例如,所有Planetoid数据集(Cora, Citeseer, Pubmed),所有来自http://graphkernels.cs.tu-dortmund.de的图形分类数据集及其清理版本,QM7和QM9数据集,以及一些3D网格/点云数据集,如FAUST, ModelNet10/40和ShapeNet。初始化数据集很简单。数据集的初始化将自动下载其原始文件并将其处理为前面描述的Data格式。例如,要加载酶数据集(包含6个类中的600个图),输入:

from torch_geometric.datasets import TUDataset

dataset = TUDataset(root='/tmp/ENZYMES', name='ENZYMES')
>>> ENZYMES(600)

len(dataset)
>>> 600

dataset.num_classes
>>> 6

dataset.num_node_features
>>> 3

现在我们可以访问数据集中的所有600个图(酶的数据集):

data = dataset[0]
>>> Data(edge_index=[2, 168], x=[37, 3], y=[1])

data.is_undirected()
>>> True

我们可以看到数据集中的第一个图包含37个节点,每个节点有3个特征。有168/2= 84条无向边,图被分配到一个类中。此外,数据对象只保存一个图级目标。
我们甚至可以使用切片、长张量或bool张量来分割数据集。例如,要创建一个90/10的训练/测试分割,输入:

train_dataset = dataset[:540]
>>> ENZYMES(540)

test_dataset = dataset[540:]
>>> ENZYMES(60)

如果你不确定数据集在分割之前是否已经洗牌,你可以通过运行:

dataset = dataset.shuffle()
>>> ENZYMES(600)

打乱数据集的顺序。
也可以用下面的代码打乱顺序,效果一样的:

perm = torch.randperm(len(dataset))
dataset = dataset[perm]
>> ENZYMES(600)

让我们再试一个 ! 让我们下载Cora,半监督图节点分类的标准基准数据集:

from torch_geometric.datasets import Planetoid

dataset = Planetoid(root='/tmp/Cora', name='Cora')
>>> Cora()

len(dataset)
>>> 1

dataset.num_classes
>>> 7

dataset.num_node_features
>>> 1433

在这里,数据集只包含一个单一的无向索引图:

data = dataset[0]
>>> Data(edge_index=[2, 10556], test_mask=[2708],
         train_mask=[2708], val_mask=[2708], x=[2708, 1433], y=[2708])

data.is_undirected()
>>> True

data.train_mask.sum().item()
>>> 140

data.val_mask.sum().item()
>>> 500

data.test_mask.sum().item()
>>> 1000

Data对象为每个节点保存一个标签,以及额外的节点级属性:train_mask、val_mask和test_mask代表含义分别为:

  • train_mask表示要训练哪些节点(140个节点)
  • Val_mask表示使用哪些节点进行验证,例如,执行提前停止(500个节点)
  • test_mask表示要测试哪些节点(1000个节点)。

2.1.3 小批次 Mini-batches
神经网络通常以批处理的方式进行训练。PyG通过创建稀疏块对角邻接矩阵(由edge_index定义)并在节点维度上连接特征和目标矩阵来实现迷你批处理的并行化。这种组合允许在一批示例中使用不同数量的节点和边:
在这里插入图片描述
PyG包含自己的torch_geometry.loader.Dataloader,它已经负责这个连接过程。让我们通过一个例子来了解它:

from torch_geometric.datasets import TUDataset
from torch_geometric.loader import DataLoader

dataset = TUDataset(root='/tmp/ENZYMES', name='ENZYMES', use_node_attr=True)
loader = DataLoader(dataset, batch_size=32, shuffle=True)

for batch in loader:
    batch
    >>> DataBatch(batch=[1082], edge_index=[2, 4066], x=[1082, 21], y=[32])

    batch.num_graphs
    >>> 32

torch_geometric.data.Batch 类继承 torch_geometry.data。并包含额外的属性——指针数组,指定每个节点它所在的图编号:batch。
batch是一个列向量,它将每个节点映射到批处理中各自的图:
在这里插入图片描述
你可以用它做一些事情,比如来平均每个图的节点维度中的节点特征:

from torch_geometric.utils import scatter
from torch_geometric.datasets import TUDataset
from torch_geometric.loader import DataLoader

dataset = TUDataset(root='/tmp/ENZYMES', name='ENZYMES', use_node_attr=True)
loader = DataLoader(dataset, batch_size=32, shuffle=True)

for data in loader:
    data
    >>> DataBatch(batch=[1082], edge_index=[2, 4066], x=[1082, 21], y=[32])   #每次以32次的批次处理。将图数据进行了拼接,最终32个图数据,拼接成一个拥有总1082个节点,21维度的特征,4066个边的图batch数据。

    data.num_graphs
    >>> 32

    x = scatter(data.x, data.batch, dim=0, reduce='mean')
    x.size()
    >>> torch.Size([32, 21])

对于分散操作的文档,我们建议感兴趣的读者参阅torch_scatter文档。
(更透彻的讲解请移步 by咪咕班克斯 https://blog.csdn.net/u012211422/article/details/125212863 )

2.1.4 数据转换
Transform在计算机视觉中十分常用,主要用于图片格式的转换和数据增强。PyG同样有其自己的transform操作,使用Data对象作为输入,返回一个新的Data对象。转换可以使用torch_geometric.transforms.Compose 链接在一起。在将处理过的数据集保存在磁盘上之前,组合应用(pre_transform)或在访问数据集中的图之前(transform)。
接下来举个栗子:我们对ShapeNet数据集(包含17,000个3D形状点云和16个形状类别标签)。

from torch_geometric.datasets import ShapeNet

dataset = ShapeNet(root='/tmp/ShapeNet', categories=['Airplane'])

dataset[0]
>>> Data(pos=[2518, 3], y=[2518])

我们可以用K近邻的方法通过transforms将每一个point cloud 都转换成图,这里选择最近的6个邻居。

import torch_geometric.transforms as T
from torch_geometric.datasets import ShapeNet

dataset = ShapeNet(root='/tmp/ShapeNet', categories=['Airplane'],
                    pre_transform=T.KNNGraph(k=6))

dataset[0]
>>> Data(edge_index=[2, 15108], pos=[2518, 3], y=[2518])
注意-
在将数据保存到磁盘之前,我们使用pre_transform转换数据(能缩短加载时间)。请注意,下次初始化数据集时,即使您没有传递任何转换,它也会包含图的边。如果pre_transform与已经处理的数据集中的pre_transform不匹配,您将得到一个警告。

此外还可以用transform来做一些数据增强,如给每一个点的坐标都加一个小扰动:

import torch_geometric.transforms as T
from torch_geometric.datasets import ShapeNet

dataset = ShapeNet(root='/tmp/ShapeNet', categories=['Airplane'],
                    pre_transform=T.KNNGraph(k=6),
                    transform=T.RandomJitter(0.01))

dataset[0]
>>> Data(edge_index=[2, 15108], pos=[2518, 3], y=[2518])

2.1.5 图的学习方法
在学习了PyG中的数据处理、数据集、加载器和转换之后,是时候实现我们的第一个图神经网络了 ! 我们将使用一个简单的GCN层,并在Cora数据集上复制实验。首先加载Cora数据集:

from torch_geometric.datasets import Planetoid

dataset = Planetoid(root='/tmp/Cora', name='Cora')
>>> Cora()

注意,我们不需要使用转换或数据加载器。现在让我们实现一个两层的GCN:

import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv

class GCN(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = GCNConv(dataset.num_node_features, 16)
        self.conv2 = GCNConv(16, dataset.num_classes)

    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)

构造函数定义了两个GCNConv层,它们在网络的前向传递中被调用。请注意,非线性没有集成在conv调用中,因此需要在之后应用(这在pyg中的所有操作符中是一致的)。在这里,我们选择使用ReLU作为我们的中间非线性,并最终在类的数量上输出一个softmax分布。让我们在训练节点上训练这个模型200次:

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = GCN().to(device)
data = dataset[0].to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)

model.train()
for epoch in range(200):
    optimizer.zero_grad()  #把梯度置零,也就是把loss关于weight的导数变成0
    out = model(data)
    loss = F.nll_loss(out[data.train_mask], data.y[data.train_mask])
    loss.backward()
    optimizer.step()

<注>关于train_mask讲解请移步https://zhuanlan.zhihu.com/p/545546994
最后,我们可以在测试节点上评估我们的模型:

model.eval()
pred = model(data).argmax(dim=1)
correct = (pred[data.test_mask] == data.y[data.test_mask]).sum()
acc = int(correct) / int(data.test_mask.sum())
print(f'Accuracy: {acc:.4f}')
>>> Accuracy: 0.8150

这就是实现你的第一个图神经网络所需要的基本内容。学习更多关于图神经网络的最简单的方法是学习examples/目录中的示例,并浏览torch_geometric.nn。黑客快乐!

2.2 国外教程与笔记
在这里插入图片描述
官方附赠了一些教程和笔记,请大家自己打开官网上查看~~
https://pytorch-geometric.readthedocs.io/en/latest/get_started/colabs.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PyTorch Geometric (PyG) 是一个用于 PyTorch 的几何深度学习扩展库。它提供了许多用于处理图和其他不规则结构数据的方法和工具。PyTorch Geometric 基于 PyTorch 框架,使得用户可以方便地构建和训练图神经网络模型。 在 PyTorch Geometric 中,边的信息以 `edge_index` 的形式表示。`edge_index` 是一个形状为 `[2, num_edges]` 的张量,其中第一行表示边的源节点,第二行表示边的目标节点。当创建 `Data` 对象时,需要将 `edge_index` 转置后传入,以匹配正确的形状。 例如,假设有以下代码片段: ```python import torch from torch_geometric.data import Data edge_index = torch.tensor([[0, 1], [1, 0], [1, 2], [2, 1]], dtype=torch.long) x = torch.tensor([[-1], [0], [1]], dtype=torch.float) data = Data(x=x, edge_index=edge_index.t().contiguous()) ``` 这段代码创建了一个 `Data` 对象,其中 `x` 是节点特征张量,`edge_index` 是边索引张量。最后的输出 `Data(edge_index=[2, 4], x=[3, 1])` 表示边索引有 4 条边,节点特征张量有 3 个节点。 总结来说,PyTorch Geometric 是一个用于 PyTorch 的扩展库,用于处理图和其他不规则结构数据。它提供了方便的方法和工具来构建和训练图神经网络模型。边的信息通过 `edge_index` 表示,其中第一行是源节点,第二行是目标节点。在创建 `Data` 对象时,需要注意 `edge_index` 的形状,并将其转置以匹配正确的格式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值