图神经网络-pyG-GAT
在上一章节介绍了pyG-GCN的使用,除了GCN,还有一些像GAT、GraphSage等等一些,本文将介绍GAT模型的构建
实现了一个使用Graph Attention Network(GAT)的节点分类模型,该模型在Cora数据集上进行训练和测试。
-
首先,导入所需的库和模块:
torch_geometric.datasets.Planetoid
:用于加载Cora数据集。torch
:PyTorch的主要库。torch.nn.functional as F
:PyTorch的神经网络函数模块,用于定义神经网络的层和操作。torch_geometric.nn.GATConv
:PyTorch Geometric库中的图注意力网络层(Graph Attention Network,GATConv)。torch_geometric.nn.GATConv
:PyTorch Geometric库中的图注意力网络层(Graph Attention Network,GATConv)。
-
加载Cora数据集:
dataset = Planetoid(root='./tmp/Cora', name='Cora')
这行代码加载了Cora数据集,该数据集包括节点特征、图的边缘信息以及节点的真实标签。
-
定义一个名为
GAT_Net
的神经网络类:class GAT_Net(torch.nn.Module):
这个类继承自PyTorch的
torch.nn.Module
基类,表示它是一个神经网络模型。 -
在
GAT_Net
类的构造函数中,定义了两个GAT层:def __init__(self, features, hidden, classes, heads=1):super(GAT_Net, self).__init__()self.gat1 = GATConv(features, hidden, heads=heads)self.gat2 = GATConv(hidden * heads, classes)
GATConv
层是图注意力网络层,用于从图数据中提取特征。self.gat1
是第一个GATConv层,它将输入特征的维度设置为features
,输出hidden
维特征,同时可以指定heads
的数量。self.gat2
是第二个GATConv层,将hidden * heads
维特征映射到classes
个类别。
-
在
forward
方法中定义了前向传播过程:def forward(self, data):x, edge_index = data.x, data.edge_indexx = self.gat1(x, edge_index)x = F.relu(x)x = F.dropout(x, training=self.training)x = self.gat2(x, edge_index)return F.log_softmax(x, dim=1)
- 输入数据
data
包括节点特征x
和边索引edge_index
。 self.gat1
和self.gat2
分别表示第一层和第二层的图注意力网络操作。- 使用ReLU激活函数进行非线性变换。
- 使用Dropout层进行正则化。
- 最后,通过
F.log_softmax
对输出进行softmax操作,以得到每个节点属于不同类别的概率分布。
- 输入数据
-
检查并设置GPU或CPU设备:
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
这段代码会检查你的系统是否有可用的GPU,并将
device
设置为GPU或CPU,以便在相应的设备上运行模型。 -
创建并将模型移动到所选设备上:
model = GAT_Net(dataset.num_node_features, 16, dataset.num_classes, heads=4).to(device)
这将实例化
GAT_Net
模型,并将模型的参数和计算移动到GPU或CPU上。heads
参数指定了GAT中的注意力头数量。 -
加载Cora数据集的第一个图数据实例:
data = dataset[0]
这将加载Cora数据集的第一个图数据实例,包括节点特征、图的边缘信息以及节点的真实标签。
-
定义优化器(这里使用Adam优化器):
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
这行代码创建一个Adam优化器,并将模型的参数传递给它,用于模型参数的更新。学习率为0.01。
-
将模型设置为训练模式:
model.train()
这行代码将模型切换到训练模式,以启用训练时的特定操作,如Dropout。
-
开始训练循环,训练模型200个epoch:
for epoch in range(200):
这是一个训练循环,将模型训练200次。
-
在每个epoch中,首先将优化器的梯度清零:
optimizer.zero_grad()
这行代码用于清除之前的梯度信息,以准备计算新的梯度。
-
通过模型前向传播计算预测结果:
out = model(data)
这会将数据传递给你的GAT模型,然后返回模型的预测结果。
-
计算损失函数,这里使用负对数似然损失(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()
这两行代码用于计算梯度并执行梯度下降,更新模型的参数,以最小化损失函数。
from torch_geometric.datasets import Planetoid
import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv, SAGEConv, GATConvdataset = Planetoid(root='./tmp/Cora',name='Cora')
class GAT_Net(torch.nn.Module):def __init__(self, features, hidden, classes, heads=1):super(GAT_Net, self).__init__()self.gat1 = GATConv(features, hidden, heads=heads)self.gat2 = GATConv(hidden*heads, classes)def forward(self, data):x, edge_index = data.x, data.edge_indexx = self.gat1(x, edge_index)x = F.relu(x)x = F.dropout(x, training=self.training)x = self.gat2(x, edge_index)return F.log_softmax(x, dim=1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = GAT_Net(dataset.num_node_features, 16, dataset.num_classes, heads=4).to(device)
data = dataset[0]
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)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).max(dim=1)
correct = pred[data.test_mask].eq(data.y[data.test_mask]).sum()
acc = int(correct)/ int(data.test_mask.sum())
print('GAT',acc)