详解Pytorch+PyG实现GCN过程示例
这篇攻略将会详细讲解如何使用PyTorch和PyG实现图卷积网络(GCN)。我们将通过两条示例说明如何使用PyG和PyTorch来实现GCN,并对代码进行详细分析。
简介
图形数据(或称为网络数据或图形数据)由许多顶点和边组成,这些组成通常是不规则的,图形中顶点之间的拓扑关系也是不规则的。GCN是一种用于处理图形数据的神经网络,其能够将每个顶点的特征向量转换为一个新的特征向量,从而考虑其在整个网络中的邻居节点的影响。
PyTorch和PyG是处理图形数据非常优秀的Python工具包,其中PyG提供了一系列数据集和预处理功能,可以更轻松地实现GCN。
示例1:Cora数据集上的GCN
第一个示例展示了如何使用GCN模型在Cora数据集上训练一个文本分类器。
数据预处理
Cora数据集是一个文本分类数据集,包含2708篇论文,每篇论文用1433维的词向量表示。每篇论文都属于七个类别中的一个。数据集还包含一个分别论文之间引用关系的图形数据。
PyG已经包含了Cora数据集,我们可以直接调用PyG中的Cora数据集类来加载数据。在加载数据之前,我们需要定义一个预处理步骤,将数据转换为PyG所期望的数据格式。
以下代码展示了如何将Cora数据集转换为PyG所期望的格式:
from torch_geometric.datasets import Planetoid
import torch_geometric.transforms as T
dataset = Planetoid(root='/tmp/Cora', name='Cora', transform=T.NormalizeFeatures())
在上面的代码中,我们使用Planetoid类来加载数据集,将其存储在/tmp/Cora目录中。我们还使用NormalizeFeatures转换对数据进行归一化,确保特征向量的值在[-1,1]之间。
定义GCN模型
我们使用PyTorch定义GCN模型,该模型实现Graph Convolutional Operation,并使用ReLU激活函数。以下是模型的定义:
import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = GCNConv(dataset.num_node_features, 16)
self.conv2 = GCNConv(16, dataset.num_classes)
def forward(self, x, 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)
在上面的代码中,Net类定义了两个GCNConv层,分别将输入特征转换为16维和7维输出向量。我们还在第一层之后添加了一个ReLU激活函数,并使用dropout来防止过拟合。输出由log_softmax函数进行处理,以方便在文本分类任务中使用。
训练模型
我们使用Adam优化器训练模型,使用交叉熵作为损失函数。以下是训练代码:
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model, data = Net().to(device), dataset[0].to(device)
print(model)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
model.train()
for epoch in range(200):
optimizer.zero_grad()
out = model(data.x, data.edge_index)
loss = F.nll_loss(out[data.train_mask], data.y[data.train_mask])
loss.backward()
optimizer.step()
在上面的代码中,我们首先定义设备,然后将模型转移到该设备。我们还输出了模型的结构,以进行检查。
在每轮迭代中,我们首先将梯度清零,然后使用模型计算输出并计算损失。接下来,我们只将训练节点的损失传递到模型中,并调用反向传播函数计算梯度。
最后,我们使用Adam优化器更新模型权重。
测试模型
以下是模型测试的代码:
model.eval()
_, pred = model(data.x, data.edge_index).max(dim=1)
correct = float (pred[data.test_mask].eq(data.y[data.test_mask]).sum().item())
acc = correct/data.test_mask.sum().item()
print('Accuracy: {:.4f}'.format(acc))
在上面的代码中,我们首先将模型设置为测试模式,然后使用模型计算测试集上的输出。我们之后选择输出最大值作为预测标签,并计算测试集上的准确度。
示例扩展
此示例可以扩展到其他数据集和分类任务。例如,如果我们使用许多其他数据集,如CiteSeer或PubMed,也可以使用相同的方法对它们进行分类。还可以尝试使用不同尺寸和数量的Graph Convolutional Operation来改进模型性能。
示例2:图像数据上的GCN
第二个示例展示了如何在图形数据(如图像数据)上实现GCN。我们将在MNIST手写数字图像上实现一个基本的GCN,并对以前创建的Cora模型进行扩展。
数据预处理
MNIST数据集包含由字块组成的手写数字图像,每个图像都是28x28像素。我们可以将每个像素看作图中的一个节点,节点之间连接的边可以是像素之间的空间关系。
通过将图像重新排列为矩阵,并计算像素之间的距离,我们可以计算边的权重。以下是预处理步骤的代码:
import torch
from torch_geometric.utils import to_networkx
from torchvision import datasets, transforms
mnist_transforms = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
train_dataset = datasets.MNIST('/tmp/data', transform=mnist_transforms, download=True, train=True)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True)
X, y = next(iter(train_loader))
X = X.view(-1, 28*28)
G = to_networkx(train_dataset)
edge_index, edge_weight = from_networkx(G)
X = X.numpy()
y = y.numpy()
在上面的代码中,我们首先定义数据集和变换,然后使用PyTorch DataLoader读取数据。我们使用ToTensor和Normalize变换来归一化数据。
接下来,我们使用to_networkx函数将每个图像转换为图形数据,并使用from_networkx函数将其转换为PyG所需的格式。在准备好节点特征和边的权重之后,我们将其存储在X和y中,以备后续使用。
扩展Cora模型
我们将以前的Cora模型扩展到新的MNIST数据集,并修改输入节点特征的维数为784:
import torch
from torch.nn import Sequential, Linear, ReLU, Softmax
from torch_geometric.nn import GCNConv
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = GCNConv(784, 256)
self.conv2 = GCNConv(256, 256)
self.conv3 = GCNConv(256, 10)
self.classifier = Sequential(Linear(10, 10), Softmax(dim=1))
def forward(self, x, edge_index):
x = self.conv1(x, edge_index)
x = ReLU()(x)
x = self.conv2(x, edge_index)
x = ReLU()(x)
x = self.conv3(x, edge_index)
x = self.classifier(x)
return x
我们添加了一个新的GCNConv层作为第一层,并修改了输出维度以匹配。在模型最后,我们添加了一个简单的分类器,以便在图像分类任务中使用。
训练和测试模型
以下是训练模型的代码:
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = Net().to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
for epoch in range(10):
optimizer.zero_grad()
x = torch.tensor(X, dtype=torch.float32, device=device)
y_true = torch.tensor(y, dtype=torch.long, device=device).squeeze()
out = model(x, edge_index)
loss = F.nll_loss(out, y_true)
loss.backward()
optimizer.step()
with torch.no_grad():
pred = model(x, edge_index).argmax(dim=1)
correct = float(pred.eq(y_true).sum().item())
acc = correct / len(y_true)
print('Epoch {} | Loss: {:.4f} | Accuracy: {:.4f}'.format(epoch, loss.item(), acc))
在上面的代码中,我们首先定义设备,然后将模型转移到该设备。在每轮迭代中,我们使用定义的边权重来计算模型的输出,并计算交叉熵损失。使用Adam优化器更新模型的权重。
示例扩展
我们可以使用这种方法来训练其他类型的图形数据,包括分子结构、地理图像等。我们还可以探究在GCN模型中使用不同的卷积核类型和数量,从而提高模型的性能。
结论
本篇攻略详细讲解了如何使用PyTorch和PyG实现GCN模型,并提供了两个示例来说明如何在不同类型的数据上使用GCN模型。对于使用PyTorch构建图形数据应用程序的开发者来说,本文提供了入门的指导。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解Pytorch+PyG实现GCN过程示例 - Python技术站