基于PYG库构建图神经网络模型进行节点分类
基于PYG库构建图神经网络模型进行节点分类
本项目使用PYG库自定义数据集My_dataset类,将每张图片的前16个节点的特征和标签作为训练集train_mask,剩下4个节点作为验证集。建立GCN模型进行训练和模型验证,并用for语句循环10张图片的图数据内容。
数据结构:
- 10张图片,每张图片有20个节点,节点编号从0到19。
- 每张图片有66条边,存储在'C:\Users\jh\Desktop\data\raw\edges.csv'中,每行为一条边,第1列为源节点,第2列为目标节点。
- 每个节点包含2个特征,所有图片节点的第一个特征存储在'C:\Users\jh\Desktop\data\raw\features1.csv'中,第二个特征存储在'C:\Users\jh\Desktop\data\raw\features2.csv'中,每一行代表一张图片的20个节点特征,形状为10行*20列。
- 每个节点有一个标签,共有0和1两类标签,存储在'C:\Users\jh\Desktop\data\raw\label.csv'中,每一行代表一张图片的所有标签,形状为10行*20列。
代码实现:
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch_geometric.data import Dataset
from torch_geometric.data import Data
class My_dataset(Dataset):
def __init__(self, root):
self.root = root
self.edges = torch.tensor([], dtype=torch.long)
self.features1 = torch.tensor([], dtype=torch.float)
self.features2 = torch.tensor([], dtype=torch.float)
self.labels = torch.tensor([], dtype=torch.long)
self.train_mask = torch.tensor([], dtype=torch.bool)
# Load data from files
for i in range(10):
edges = torch.tensor([], dtype=torch.long)
features1 = torch.tensor([], dtype=torch.float)
features2 = torch.tensor([], dtype=torch.float)
labels = torch.tensor([], dtype=torch.long)
# Load edges
edges_file = f'{self.root}/edges_{i}.csv'
with open(edges_file, 'r') as f:
lines = f.readlines()
for line in lines:
src, tgt = line.strip().split(',')
edges = torch.cat((edges, torch.tensor([[int(src)], [int(tgt)]])), dim=1)
# Load features1
features1_file = f'{self.root}/features1_{i}.csv'
with open(features1_file, 'r') as f:
lines = f.readlines()
for line in lines:
feats = [float(x) for x in line.strip().split(',')]
features1 = torch.cat((features1, torch.tensor([feats])), dim=0)
# Load features2
features2_file = f'{self.root}/features2_{i}.csv'
with open(features2_file, 'r') as f:
lines = f.readlines()
for line in lines:
feats = [float(x) for x in line.strip().split(',')]
features2 = torch.cat((features2, torch.tensor([feats])), dim=0)
# Load labels
labels_file = f'{self.root}/labels_{i}.csv'
with open(labels_file, 'r') as f:
lines = f.readlines()
for line in lines:
lbls = [int(x) for x in line.strip().split(',')]
labels = torch.cat((labels, torch.tensor([lbls])), dim=0)
# Create train mask
train_mask = torch.ones(features1.size(0), dtype=torch.bool)
train_mask[:16] = False
self.edges = torch.cat((self.edges, edges), dim=1)
self.features1 = torch.cat((self.features1, features1), dim=0)
self.features2 = torch.cat((self.features2, features2), dim=0)
self.labels = torch.cat((self.labels, labels), dim=0)
self.train_mask = torch.cat((self.train_mask, train_mask), dim=0)
def __len__(self):
return self.features1.size(0)
def __getitem__(self, idx):
edge_index = self.edges[:, idx].view(2, -1)
x = torch.cat((self.features1[idx], self.features2[idx]), dim=1)
y = self.labels[idx]
train_mask = self.train_mask[idx]
data = Data(x=x, edge_index=edge_index, y=y, train_mask=train_mask)
return data
class GCN(nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim):
super(GCN, self).__init__()
self.conv1 = nn.Conv1d(input_dim, hidden_dim, kernel_size=1)
self.conv2 = nn.Conv1d(hidden_dim, output_dim, kernel_size=1)
def forward(self, x, edge_index):
x = x.permute(0, 2, 1)
x = F.relu(self.conv1(x))
x = F.dropout(x, training=self.training)
x = self.conv2(x)
x = x.permute(0, 2, 1)
x = F.log_softmax(x, dim=2)
return x
# Create dataset
dataset = My_dataset('C:/Users/jh/Desktop/data/raw')
# Create GCN model
model = GCN(input_dim=2, hidden_dim=16, output_dim=2)
# Train and validate the model
for data in dataset:
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
criterion = nn.NLLLoss()
model.train()
optimizer.zero_grad()
out = model(data.x, data.edge_index)
loss = criterion(out[data.train_mask], data.y[data.train_mask])
loss.backward()
optimizer.step()
model.eval()
with torch.no_grad():
pred = model(data.x, data.edge_index)
val_loss = criterion(pred[~data.train_mask], data.y[~data.train_mask])
pred = pred.argmax(dim=2)
acc = pred.eq(data.y.view(-1, 1)).sum().item() / pred.numel()
print(f'Loss: {loss.item()}, Val Loss: {val_loss.item()}, Accuracy: {acc}')
代码解释:
- 自定义数据集My_dataset类,继承自Dataset类,实现__init__和__getitem__方法,用于加载数据和构建图数据对象。
- 定义GCN模型类,继承自nn.Module类,包含两个卷积层,分别用于特征提取和分类。
- 训练和验证模型,使用for循环遍历数据集,对每一张图片的数据进行训练和验证,并打印损失、验证损失和准确率。
注意:
- 代码中文件路径'C:\Users\jh\Desktop\data\raw'需要修改为你自己的文件路径。
- GCN模型的输入特征维度为2,你可以根据实际情况进行调整。
- GCN模型的第一个卷积层将输入的特征维度从2转换为16,第二个卷积层将输入的特征维度从16转换为2,你可以根据实际情况进行调整。
- 代码仅供参考,你可以根据自己的需求进行修改和扩展。
总结:
本项目利用PYG库构建图神经网络模型进行节点分类,并通过训练和验证评估模型性能。该代码提供了一个简单的示例,可以帮助你了解如何在PYG库中构建图神经网络模型。
未来方向:
- 可以尝试使用不同的图神经网络模型,例如GAT、GIN等。
- 可以尝试使用不同的特征提取方法,例如使用预训练模型提取特征。
- 可以尝试使用不同的损失函数,例如交叉熵损失函数。
- 可以尝试使用不同的优化器,例如SGD、AdamW等。
- 可以尝试使用不同的数据增强方法,例如节点掩码、边掩码等。
- 可以尝试使用不同的训练技巧,例如早停、学习率衰减等。
原文地址: https://www.cveoy.top/t/topic/mswO 著作权归作者所有。请勿转载和采集!