今天小编给大家分享一下怎么用Pytorch+PyG实现GraphConv的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
GraphConv简介
GraphConv是一种使用图形数据的卷积神经网络(Convolutional Neural Network, CNN)模型。与传统的CNN仅能处理图片二维数据不同,GraphConv可以对任意结构的图进行卷积操作,并适用于基于图的多项任务。
实现步骤
2.1 数据准备
在本实验中,我们使用了一个包含4万个图像的数据集CIFAR-10,作为示例。与其它标准图像数据集不同的是,在这个数据集中图形的构成量非常大,而且各图之间结构差异很大,因此需要进行大量的预处理工作。
# 导入cifar-10数据集
from torch_geometric.datasets import Planetoid
# 加载数据、划分训练集和测试集
dataset = Planetoid(root='./cifar10', name='Cora')
data = dataset[0]
# 定义超级参数
num_features = dataset.num_features
num_classes = dataset.num_classes
# 构建训练集和测试集索引文件
train_mask = torch.zeros(data.num_nodes, dtype=torch.uint8)
train_mask[:800] = 1
test_mask = torch.zeros(data.num_nodes, dtype=torch.uint8)
test_mask[800:] = 1
# 创建数据加载器
train_loader = DataLoader(data[train_mask], batch_size=32, shuffle=True)
test_loader = DataLoader(data[test_mask], batch_size=32, shuffle=False)
通过上述代码,我们先是导入CIFAR-10数据集并将其分割为训练及测试两个数据集,并创建了相应的数据加载器以便于对数据进行有效处理。
2.2 实现模型
在定义GraphConv模型时,我们需要根据图像经常使用的架构定义网络结构。同时,在实现卷积操作时应引入邻接矩阵(adjacency matrix)和特征矩阵(feature matrix)作为输入,来使得网络能够学习到节点之间的关系和提取重要特征。
from torch.nn import Linear, ModuleList, ReLU
from torch_geometric.nn import GCNConv
class GraphConv(torch.nn.Module):
def __init__(self, dataset):
super(GraphConv, self).__init__()
# 定义基础参数
self.input_dim = dataset.num_features
self.output_dim = dataset.num_classes
# 定义GCN网络结构
self.convs = ModuleList()
self.convs.append(GCNConv(self.input_dim, 16))
self.convs.append(GCNConv(16, 32))
self.convs.append(GCNConv(32, self.output_dim))
def forward(self, x, edge_index):
for conv in self.convs:
x = conv(x, edge_index)
x = F.relu(x)
return F.log_softmax(x, dim=1)
在上述代码中,我们实现了基于GraphConv的模型的各个卷积层,并使用
GCNConv
将邻接矩阵和特征矩阵作为输入进行特征提取。最后结合全连接层输出一个维度为类别数的向量,并通过softmax函数来计算损失。2.3 模型训练
在定义好GraphConv网络结构之后,我们还需要指定合适的优化器、损失函数,并控制训练轮数、批大小与学习率等超参数。同时也需要记录大量日志信息,方便后期跟踪及管理。
# 定义训练计划,包括损失函数、优化器及迭代次数等
train_epochs = 200
learning_rate = 0.01
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(graph_conv.parameters(), lr=learning_rate)
losses_per_epoch = []
accuracies_per_epoch = []
for epoch in range(train_epochs):
running_loss = 0.0
running_corrects = 0.0
count = 0.0
for samples in train_loader:
optimizer.zero_grad()
x, edge_index = samples.x, samples.edge_index
out = graph_conv(x, edge_index)
label = samples.y
loss = criterion(out, label)
loss.backward()
optimizer.step()
running_loss += loss.item() / len(train_loader.dataset)
pred = out.argmax(dim=1)
running_corrects += pred.eq(label).sum().item() / len(train_loader.dataset)
count += 1
losses_per_epoch.append(running_loss)
accuracies_per_epoch.append(running_corrects)
if (epoch + 1) % 20 == 0:
print("Train Epoch {}/{} Loss {:.4f} Accuracy {:.4f}".format(
epoch + 1, train_epochs, running_loss, running_corrects))
在训练过程中,我们遍历每个batch,通过反向传播算法进行优化,并更新loss及accuracy输出。同时,为了方便可视化与记录,需要将训练过程中的loss和accuracy输出到相应的容器中,以便后期进行分析和处理。