目录
一. Data说明
在GNN制作数据集,PyTorch 中有一个专门用于图数据的库
torch-geometric
(简称PyG
),它里面有很多功能来处理图数据。构建 GNN 数据集时,数据通常由以下几部分组成:
- 节点特征(Node Features):每个节点的特征向量。
- 边列表(Edge List):图中边的连接信息,通常是一个
(source_node, target_node)
的二元组。- 图标签(Graph Labels):如果是图分类任务,每个图有一个标签;如果是节点分类任务,每个节点有一个标签。
- 边特征(Edge Features):如果边也有特征,可以附加上边特征。
PyG中的数据集使用一个torch_geometric.data.Data对象表示,具体表示为:
- data.x:具有形状的节点特征矩阵[num_nodes,num_Node_features]
- data.edge_index:COO格式的图形连接,形状为[2,num_edges],类型为torch.long
- data.edge_attr:具有形状的边缘特征矩阵[num_edges,num_edge_features]
- data.y:要训练的目标(可以具有任意形状),例如,形状为[num_nodes,*]的节点级目标(每个节点都有标签)或形状为[1,**]的图级目标(整张图只有一个标签)
- data.pos:形状为[num_nodes,num_dimensions]的节点位置矩阵
如果想要让一个 GNN 模型同时进行图分类和节点分类任务。你可以使用一个共享的图神经网络结构,同时在最后通过不同的头(head)来分别进行不同任务的预测。
二. 数据集构建
1. 单一图的构建
单一图的构建比较简单,由于数据集的构建因为有监督学习和无监督学习也会有区别。下面案例展示建立一个三任务的有监督图数据:
import torch from torch_geometric.data import Data # 模拟数据 num_students = 100 num_features = 18 # 例如:浏览次数、参与度等 num_classes_interest = 3 # 学科兴趣类别数(只考虑语数英3) num_classes_participation = 3 # 参与度类别数(只考虑语数英) # 随机生成特征矩阵和边列表 x = torch.randn((num_students, num_features)) edge_index = torch.randint(0, num_students, (2, 200)) # 200条边 # 随机生成标签(实际中应根据数据生成) # 回归任务 y_interest = torch.randn(num_students, num_classes_interest) # 生成连续值 y_participation = torch.randn(num_students, num_classes_participation) # 生成连续值 # 创建数据对象 data = Data(x=x, edge_index=edge_index, y_interest=y_interest, y_participation=y_participation) # 根据打印一些示例数据 print("Interest Labels:", y_interest[:10]) print("Participation Values:", y_participation[:10]) print(data)
2. 图数据集的构建
可以继承自
torch_geometric.data.Dataset
,实现必要方法来定义和管理数据集。import torch from torch_geometric.data import Dataset, Data import numpy as np class CustomGraphDataset(Dataset): def __init__(self, root_dir, num_graphs, transform=None): """ Args: root_dir (str): 存放数据的根目录 num_graphs (int): 数据集的图数量 transform (callable, optional): 可选的转换操作 """ self.root_dir = root_dir self.num_graphs = num_graphs self.transform = transform def len(self): return self.num_graphs # 数据集中图的数量 def get(self, idx): # 这个get方法模拟一个图的数据(可以根据具体问题从文件加载数据) num_nodes = 100 # 图中节点的数量 num_edges = 200 # 图中边的数量 # 随机生成节点特征 (num_nodes x num_features) node_features = torch.rand((num_nodes, 16)) # 假设每个节点有16维特征 # 随机生成边列表 (2 x num_edges) edge_index = torch.randint(0, num_nodes, (2, num_edges)) # 随机生成节点标签 (节点的分类标签) node_labels = torch.randint(0, 2, (num_nodes,)) # 假设有2类标签 # 创建图数据对象 data = Data(x=node_features, edge_index=edge_index, y=node_labels) # 如果有转换操作,应用转换 if self.transform: data = self.transform(data) return data
三. 数据加载器
torch-geometric
中的DataLoader
可以直接用于 GNN 数据集的加载。你可以使用它来批量加载图数据,PyG 会自动处理批次中多个图的组合。from torch_geometric.loader import DataLoader # 假设有1000个图的数据集 train_dataset = CustomGraphDataset(root_dir="data/train", num_graphs=1000) # 使用DataLoader加载数据集 train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True) # 迭代训练数据 for data in train_loader: # data包含批量图的特征、边信息、标签等 print(data.x.shape) # (batch_size, num_nodes, node_feature_dim) print(data.edge_index.shape) # (2, num_edges) print(data.y.shape) # (batch_size, num_nodes) break # 只打印第一个批次
五. 样本获取
1. 单一图获取读取
训练需要时,直接调用就行了,像下面一样:
# 训练模型 def train(model, data, optimizer, loss_fn, epochs=200): for epoch in range(epochs): model.train() optimizer.zero_grad() # 前向传播 out = model(data.x, data.edge_index) # 计算损失 loss = loss_fn(out.view(-1), data.y) # 反向传播 loss.backward() optimizer.step() if epoch % 20 == 0: print(f'Epoch {epoch}, Loss: {loss.item()}')
2. 数据集图读取
用上面创建的CustomGraphDataset来举例,从文件中加载一个图,你可能会使用类似以下的代码来构建图数据:
import networkx as nx from torch_geometric.utils import from_networkx # 假设你有一个NetworkX图 G = nx.erdos_renyi_graph(n=100, p=0.1) # 一个简单的随机图 # 设置节点特征 for i in G.nodes: G.nodes[i]['feature'] = np.random.rand(16) # 16维特征 # 将NetworkX图转换为PyG数据对象 data = from_networkx(G) # 假设节点分类任务 data.x = torch.tensor([G.nodes[i]['feature'] for i in G.nodes], dtype=torch.float) data.y = torch.randint(0, 2, (data.x.size(0),)) # 随机节点标签
最后,
后续多任务模型的实现,训练都会陆续更新,希望文章对您有所帮助!