图神经网络-pyG版本的GCN
Data(数据)
data.x
、data.edge_index
、data.edge_attr
、data.y
、data.pos
- 举个例子
import torch
from torch_geometric.data import Data
edge_index = torch.tensor([[0, 1, 1, 2],
[1, 0, 2, 1]], dtype=torch.long)
#代表0-1 1-0 和 1-2 2-1 ,因为是无向图,所以有双向边
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也可以这么构建
edge_index = torch.tensor([[0, 1],
[1, 0],
[1, 2],
[2, 1]], dtype=torch.long)
- 一些实用函数
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.
device = torch.device('cuda')
data = data.to(device)
- 包含一些数据集
from torch_geometric.datasets import TUDataset
dataset = TUDataset(root='/tmp/ENZYMES', name='ENZYMES')
- 数据转换
转换是torchvision
中转换图像和执行增强的常见方式,pyG带有自己的转换。
#对ShapeNet数据集的转换。
from torch_geometric.datasets import ShapeNet
dataset = ShapeNet(root='/tmp/ShapeNet', categories=['Airplane'])
dataset[0]
>>> Data(pos=[2518, 3], y=[2518])
通过转换从点云生成最近邻图,将点云数据集转换为图数据集
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])
- 图表上的表示学习
-
导入所需的库和模块:
torch
:PyTorch的主要库。torch.nn.functional as F
:PyTorch的神经网络函数模块,用于定义神经网络的层和操作。torch_geometric.nn
:PyTorch Geometric库中的神经网络模块,包括图卷积网络(GCN)的实现。torch_geometric.datasets
:PyTorch Geometric中的数据集模块,用于加载图数据集。
-
加载Cora数据集:
dataset = Planetoid(root='/tmp/Cora', name='Cora')
这行代码加载了Cora数据集,这是一个用于节点分类的图数据集。数据集将被下载到
/tmp/Cora
目录中。 -
定义了一个名为
GCN
的神经网络类:class GCN(torch.nn.Module):
这个类继承自PyTorch的
torch.nn.Module
基类,表示它是一个神经网络模型。 -
在
GCN
类的构造函数中,定义了两个图卷积层(GCNConv):def __init__(self): super(GCN, self).__init__() self.conv1 = GCNConv(dataset.num_node_features, 16) self.conv2 = GCNConv(16, dataset.num_classes)
GCNConv
层是图卷积层,用于从图数据中提取特征。self.conv1
是第一个GCNConv层,它将输入特征的维度设置为dataset.num_node_features
(Cora数据集中节点的特征维度)并输出16维特征。self.conv2
是第二个GCNConv层,将16维特征映射到数据集的类别数。
-
检查并设置GPU或CPU设备:
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
这段代码会检查你的系统是否有可用的GPU,并将
device
设置为GPU或CPU,以便在相应的设备上运行模型。 -
创建并将模型和数据移动到所选设备上:
model = GCN().to(device) data = dataset[0].to(device)
这将实例化之前定义的GCN模型,并将模型的参数和计算移动到GPU或CPU上。
-
定义优化器(这里使用Adam优化器):
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
这行代码创建一个Adam优化器,并将模型的参数传递给它,用于模型参数的更新。
lr
是学习率,weight_decay
是L2正则化项的权重。 -
将模型设置为训练模式:
model.train()
这行代码将模型切换到训练模式,这对于启用训练特定的层(例如,dropout)非常重要。
-
开始训练循环,训练模型200个epoch:
for epoch in range(200):
这是一个训练循环,将模型训练200次。
-
在每个epoch中,首先将优化器的梯度清零:
optimizer.zero_grad()
这行代码用于清除之前的梯度信息,以准备计算新的梯度。
-
通过模型前向传播计算预测结果:
out = model(data)
这会将数据传递给你的GCN模型,然后返回模型的预测结果。
-
计算损失函数,这里使用负对数似然损失(Negative Log-Likelihood Loss):
loss = F.nll_loss(out[data.train_mask], data.y[data.train_mask])
这行代码计算了在训练节点子集上的负对数似然损失。
data.train_mask
指定了用于训练的节点子集,data.y
是节点的真实标签。 -
反向传播和参数更新:
loss.backward() optimizer.step()
这两行代码用于计算梯度并执行梯度下降,更新模型的参数,以最小化损失函数。
-
将模型设置为评估模式:
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}')
这段代码计算了模型在测试集上的准确性,并打印出来。
import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv
from torch_geometric.datasets import Planetoid
# 加载 Cora 数据集
dataset = Planetoid(root='/tmp/Cora', name='Cora')
# 定义 GCN 模型
class GCN(torch.nn.Module):
def __init__(self):
super(GCN, self).__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)
# 检查并设置 GPU 或 CPU 设备
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()
out = model(data)
loss = F.nll_loss(out[data.train_mask], data.y[data.train_mask])
loss.backward()
optimizer.step()
# 将模型设置为评估模式
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}')
optimizer.step()
# 将模型设置为评估模式
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}')