基于CNN和GCN的多标签节点分类任务:特征降维与图神经网络
基于CNN和GCN的多标签节点分类任务:特征降维与图神经网络
数据描述:
- 一共有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 torchvision.transforms as transforms
import torch.nn.functional as F
from torch.utils.data import DataLoader
from torch.utils.data.dataset import Dataset
from torch.autograd import Variable
from PIL import Image
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MultiLabelBinarizer
from sklearn.metrics import accuracy_score
from torch_geometric.nn import GCNConv
from torch_geometric.data import Data
from torch_geometric.utils import from_networkx
import networkx as nx
# 定义CNN网络
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1)
self.fc1 = nn.Linear(32 * 10 * 10, 128)
self.fc2 = nn.Linear(128, 8)
def forward(self, x):
x = F.relu(self.conv1(x))
x = F.max_pool2d(x, 2, 2)
x = F.relu(self.conv2(x))
x = F.max_pool2d(x, 2, 2)
x = x.view(-1, 32 * 10 * 10)
x = F.relu(self.fc1(x))
x = self.fc2(x)
return x
# 定义GCN网络
class GCN(nn.Module):
def __init__(self):
super(GCN, self).__init__()
self.conv1 = GCNConv(8, 16)
self.conv2 = GCNConv(16, 8)
def forward(self, x, edge_index):
x = self.conv1(x, edge_index)
x = F.relu(x)
x = self.conv2(x, edge_index)
return x
# 自定义数据集类
class CustomDataset(Dataset):
def __init__(self, data_dir, label_dir):
self.data_dir = data_dir
self.label_dir = label_dir
self.transform = transforms.Compose([
transforms.Resize((40, 40)),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
self.data_files = sorted(os.listdir(self.data_dir))
self.label_files = sorted(os.listdir(self.label_dir))
def __len__(self):
return len(self.data_files)
def __getitem__(self, index):
image_path = os.path.join(self.data_dir, self.data_files[index])
label_path = os.path.join(self.label_dir, self.label_files[index])
image = self.transform(Image.open(image_path))
with open(label_path, 'r') as f:
labels = f.read().split()
labels = [int(label) for label in labels]
return image, labels
# 加载数据
data_dir = "C:/Users/jh/Desktop/data/input/images/"
label_dir = "C:/Users/jh/Desktop/data/input/labels/"
edge_file = "C:/Users/jh/Desktop/data/input/edges_L.csv"
# 创建CNN和GCN模型实例
cnn_model = CNN()
gcn_model = GCN()
# 定义损失函数和优化器
criterion = nn.MultiLabelSoftMarginLoss()
optimizer = optim.Adam(gcn_model.parameters(), lr=0.01)
# 划分训练集和测试集
train_data, test_data = train_test_split(range(42), test_size=4, random_state=42)
# 训练CNN模型
for epoch in range(10):
cnn_model.train()
for i in train_data:
image_dir = os.path.join(data_dir, '{}.png'.format(i+1))
labels_dir = os.path.join(label_dir, '{}.txt'.format(i+1))
dataset = CustomDataset(image_dir, labels_dir)
dataloader = DataLoader(dataset, batch_size=1, shuffle=True)
for images, labels in dataloader:
images = Variable(images)
labels = Variable(labels)
optimizer.zero_grad()
outputs = cnn_model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
# 构建图数据
edge_data = pd.read_csv(edge_file, header=None)
edge_index = torch.tensor(edge_data.values.T, dtype=torch.long)
# 训练GCN模型
gcn_model.train()
for epoch in range(10):
for i in train_data:
image_dir = os.path.join(data_dir, '{}.png'.format(i+1))
labels_dir = os.path.join(label_dir, '{}.txt'.format(i+1))
dataset = CustomDataset(image_dir, labels_dir)
dataloader = DataLoader(dataset, batch_size=1, shuffle=True)
for images, labels in dataloader:
images = Variable(images)
labels = Variable(labels)
optimizer.zero_grad()
outputs = gcn_model(images, edge_index)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
# 测试GCN模型
gcn_model.eval()
predictions = []
true_labels = []
for i in test_data:
image_dir = os.path.join(data_dir, '{}.png'.format(i+1))
labels_dir = os.path.join(label_dir, '{}.txt'.format(i+1))
dataset = CustomDataset(image_dir, labels_dir)
dataloader = DataLoader(dataset, batch_size=1, shuffle=False)
for images, labels in dataloader:
images = Variable(images)
labels = Variable(labels)
outputs = gcn_model(images, edge_index)
predicted_labels = torch.round(torch.sigmoid(outputs))
predictions.append(predicted_labels)
true_labels.append(labels)
predictions = torch.cat(predictions, dim=0)
true_labels = torch.cat(true_labels, dim=0)
accuracy = accuracy_score(true_labels.detach().numpy(), predictions.detach().numpy())
print("Accuracy: {:.4f}".format(accuracy))
注意:
- 请确保已安装以下库:torch, torchvision, pandas, sklearn, torch_geometric, PIL。
- 上述代码仅为示例,可能需要根据实际情况进行调整。
- 该代码使用了'C:\Users\jh\Desktop\data\input'目录下的数据,请将路径替换为实际路径。
- 可以调整代码中的参数,例如训练轮数、学习率等,以获得更好的性能。
代码说明:
- CNN模型:使用两层卷积层和两层全连接层,将节点特征进行降维。
- GCN模型:使用两层GCNConv层,将节点特征和图结构信息结合起来进行预测。
- 自定义数据集:定义了CustomDataset类,用于读取图像和标签数据。
- 训练和测试:使用DataLoader加载数据,并使用循环进行模型训练和测试。
- 损失函数:使用MultiLabelSoftMarginLoss来计算多标签分类的损失。
- 指标:使用accuracy_score来评估模型的准确率。
总结:
本代码示例展示了如何使用CNN和GCN网络实现多标签节点分类任务,包括特征降维、图神经网络构建和模型训练测试,并提供了完整代码示例。该示例可以作为学习和实践图神经网络的参考。
原文地址: https://www.cveoy.top/t/topic/pf5Y 著作权归作者所有。请勿转载和采集!