使用PYG库建立GCN网络进行多标签节点分类任务
使用PYG库建立GCN网络进行多标签节点分类任务
本文将介绍如何使用PYG库建立GCN网络,并结合CNN进行特征降维,最终实现对节点标签的准确预测。
数据集描述:
- 一共有42个时刻的图,边的连接关系相同。
- 每个图都有37个节点。
- 节点特征文件是'C:\Users\jh\Desktop\data\input\images\i.png_j.png'的所有图片的RGB像素值,其中'i'表示图,'i'从1到42,'j'表示节点,'j'从0到36。特征图片的尺寸为40 x 40。
- 每个节点有8个标签,储存在'C:\Users\jh\Desktop\data\input\labels\i_j.txt'文本文件中,标签用空格隔开。
- 边的关系储存在'C:\Users\jh\Desktop\data\input\edges_L.csv'csv文件中,表格中没有header,第一列为源节点,第二列为目标节点,共有61条无向边。
任务目标:
- 建立一个CNN网络对节点像素特征x进行降维。
- 使用前38个图作为训练集,剩下的4个图作为测试集。
- 用测试集中的每个图的前30个节点预测其余的7个节点的标签。
模型架构:
- 使用PYG库建立GCN网络实现多标签分类任务。
- 损失函数由torch.nn模块中的MultiLabelSoftMarginLoss来实现。
代码实现:
import os
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torch.utils.data import DataLoader
from torchvision import transforms
from torch_geometric.data import Data, Dataset
from torch_geometric.nn import GCNConv
from torch_geometric.transforms import NormalizeFeatures
# Define the CNN model for feature dimension reduction
class CNNModel(nn.Module):
def __init__(self):
super(CNNModel, self).__init__()
self.conv1 = nn.Conv2d(3, 16, 3, stride=1, padding=1)
self.pool1 = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(16, 32, 3, stride=1, padding=1)
self.pool2 = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(10 * 10 * 32, 128)
self.fc2 = nn.Linear(128, 64)
def forward(self, x):
x = self.pool1(F.relu(self.conv1(x)))
x = self.pool2(F.relu(self.conv2(x)))
x = x.view(-1, 10 * 10 * 32)
x = F.relu(self.fc1(x))
x = self.fc2(x)
return x
# Define the GCN model for multi-label classification
class GCNModel(nn.Module):
def __init__(self, num_features, num_classes):
super(GCNModel, self).__init__()
self.conv1 = GCNConv(num_features, 64)
self.conv2 = GCNConv(64, 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 x
# Define the dataset class
class CustomDataset(Dataset):
def __init__(self, root, transform=None):
self.root = root
self.transform = transform
self.data = self.process_data()
def process_data(self):
data = []
for i in range(1, 43):
# Load node features
features_path = os.path.join(self.root, f'images/{i}.png')
features = self.load_features(features_path)
# Load node labels
labels_path = os.path.join(self.root, f'labels/{i}_j.txt')
labels = self.load_labels(labels_path)
# Load edge connections
edges_path = os.path.join(self.root, 'edges_L.csv')
edges = self.load_edges(edges_path)
data.append(Data(x=features, y=labels, edge_index=edges))
return data
def load_features(self, path):
image = Image.open(path)
if self.transform is not None:
image = self.transform(image)
return image
def load_labels(self, path):
with open(path, 'r') as file:
labels = file.read().strip().split()
labels = [int(label) for label in labels]
return torch.tensor(labels)
def load_edges(self, path):
edges = []
with open(path, 'r') as file:
lines = file.readlines()
for line in lines:
source, target = line.strip().split(',')
edges.append((int(source), int(target)))
edges = torch.tensor(edges).t().contiguous()
return edges
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
return self.data[idx]
# Initialize the CNN model
cnn_model = CNNModel()
# Initialize the GCN model
gcn_model = GCNModel(64, 8)
# Define the loss function
loss_fn = nn.MultiLabelSoftMarginLoss()
# Define the optimizer
optimizer = optim.Adam(gcn_model.parameters(), lr=0.01)
# Define the data transformations
data_transform = transforms.Compose([
transforms.Resize((40, 40)),
transforms.ToTensor()
])
# Load the training and testing datasets
train_dataset = CustomDataset('C:/Users/jh/Desktop/data/input', transform=data_transform)
test_dataset = CustomDataset('C:/Users/jh/Desktop/data/input', transform=data_transform)
# Split the training and testing datasets
train_dataset = train_dataset[:38]
test_dataset = test_dataset[38:]
# Define the data loaders
train_loader = DataLoader(train_dataset, batch_size=1, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=1, shuffle=False)
# Train the model
for epoch in range(10):
gcn_model.train()
for data in train_loader:
optimizer.zero_grad()
# Forward pass through CNN
features = cnn_model(data.x)
# Forward pass through GCN
output = gcn_model(features, data.edge_index)
# Calculate loss
loss = loss_fn(output, data.y.float())
# Backward pass and optimization
loss.backward()
optimizer.step()
# Evaluate the model
gcn_model.eval()
correct = 0
total = 0
with torch.no_grad():
for data in test_loader:
features = cnn_model(data.x)
output = gcn_model(features, data.edge_index)
predicted_labels = torch.sigmoid(output) > 0.5
correct += (predicted_labels == data.y).sum().item()
total += data.y.size(0) * data.y.size(1)
accuracy = correct / total
print(f'Epoch {epoch+1}, Accuracy: {accuracy}')
代码说明:
- CNNModel: 定义了一个简单的CNN模型,用于对节点特征进行降维。
- GCNModel: 定义了一个GCN模型,用于进行多标签节点分类。
- CustomDataset: 自定义了一个Dataset类,用于加载数据集。
- 训练过程: 使用DataLoader加载训练集和测试集,并使用循环进行训练和评估。
注意:
- 请确保已经安装了以下库:torch, torchvision, torch_geometric。
- 数据集路径请根据实际情况进行修改。
- 代码中使用的模型和参数仅供参考,您可以根据实际情况进行调整。
总结:
本文介绍了使用PYG库建立GCN网络进行多标签节点分类任务的完整流程,并提供了相应的代码示例。通过使用CNN进行特征降维,可以有效地提高GCN模型的性能。该方法可以应用于各种图数据分析任务,例如社交网络分析、蛋白质相互作用网络分析等。
原文地址: https://www.cveoy.top/t/topic/pf5M 著作权归作者所有。请勿转载和采集!