GNN实战:用PyTorch Geometric搞定社交网络节点分类(附Cora数据集完整代码)

张开发
2026/5/11 15:15:24 15 分钟阅读
GNN实战:用PyTorch Geometric搞定社交网络节点分类(附Cora数据集完整代码)
GNN实战用PyTorch Geometric搞定社交网络节点分类附Cora数据集完整代码当你在社交平台上看到可能认识的人推荐时背后很可能就运行着图神经网络GNN。这种能够捕捉复杂关系的数据结构正在推荐系统、欺诈检测等领域大放异彩。今天我们就用PyTorch Geometric这个利器带你从零实现一个真实的学术论文引用网络分类任务。1. 环境配置与数据准备工欲善其事必先利其器。我们先来搭建实验环境conda create -n gnn python3.8 conda activate gnn pip install torch torch-geometric torch-scatter torch-sparse -f https://data.pyg.org/whl/torch-1.10.0cu113.htmlCora数据集包含2708篇学术论文分为7个类别如神经网络、概率方法等。每篇论文用1433维的词向量表示引用关系构成5429条边。来看看如何加载数据from torch_geometric.datasets import Planetoid import torch_geometric.transforms as T dataset Planetoid(root./data, nameCora, transformT.NormalizeFeatures()) data dataset[0] print(f节点数: {data.num_nodes}) # 2708 print(f边数: {data.num_edges}) # 5429 print(f特征维度: {dataset.num_features}) # 1433 print(f类别数: {dataset.num_classes}) # 7数据对象包含以下关键属性x: 节点特征矩阵2708×1433edge_index: 边索引2×5429y: 节点标签2708train_mask/test_mask/val_mask: 划分训练/测试/验证集提示NormalizeFeatures变换会自动对节点特征做L1归一化这对GNN训练稳定性很重要2. 构建图卷积网络模型现在搭建一个双层GCN模型结构如下输入层(1433) → GCN(16) → ReLU → Dropout → GCN(7) → Softmax具体实现代码import torch import torch.nn.functional as F from torch_geometric.nn import GCNConv class GCN(torch.nn.Module): def __init__(self, hidden_channels16): super().__init__() self.conv1 GCNConv(dataset.num_features, hidden_channels) self.conv2 GCNConv(hidden_channels, dataset.num_classes) self.dropout 0.5 def forward(self, x, edge_index): x self.conv1(x, edge_index) x F.relu(x) x F.dropout(x, pself.dropout, trainingself.training) x self.conv2(x, edge_index) return F.log_softmax(x, dim1)关键组件解析GCNConv: 实现图卷积操作公式为Z D^(-1/2) A D^(-1/2) X W其中A是邻接矩阵D是度矩阵W是可学习权重第一层将1433维特征压缩到16维隐藏空间第二层映射到7维输出空间对应7个类别3. 模型训练与评估训练流程采用标准监督学习范式device torch.device(cuda if torch.cuda.is_available() else cpu) model GCN().to(device) data data.to(device) optimizer torch.optim.Adam(model.parameters(), lr0.01, weight_decay5e-4) def train(): model.train() optimizer.zero_grad() out model(data.x, data.edge_index) loss F.nll_loss(out[data.train_mask], data.y[data.train_mask]) loss.backward() optimizer.step() return loss.item() def test(): model.eval() out model(data.x, data.edge_index) pred out.argmax(dim1) correct pred[data.test_mask] data.y[data.test_mask] acc int(correct.sum()) / int(data.test_mask.sum()) return acc for epoch in range(1, 201): loss train() if epoch % 20 0: acc test() print(fEpoch: {epoch:03d}, Loss: {loss:.4f}, Acc: {acc:.4f})典型训练输出Epoch: 020, Loss: 1.5321, Acc: 0.7820 Epoch: 040, Loss: 0.9234, Acc: 0.8140 Epoch: 060, Loss: 0.7158, Acc: 0.8250 Epoch: 080, Loss: 0.6023, Acc: 0.8310 Epoch: 100, Loss: 0.5281, Acc: 0.8350注意验证集准确率通常在83%左右波动这与论文报告的基准结果一致4. 高级技巧与优化方案4.1 模型深度与过平滑问题增加GCN层数可能导致性能下降这就是著名的过平滑现象。我们测试不同层数的表现层数验证集准确率训练时间(秒)283.5%12.4382.1%15.7480.3%18.9578.6%22.3解决方法添加残差连接使用Jumping Knowledge网络尝试GAT等注意力机制4.2 邻居采样与大规模图处理对于超大规模图如百万节点可以使用采样技术from torch_geometric.loader import NeighborLoader loader NeighborLoader( data, num_neighbors[10, 5], # 两层采样每层采样10和5个邻居 batch_size32, input_nodesdata.train_mask ) for batch in loader: # 小批量训练逻辑 ...4.3 可视化节点嵌入用UMAP可视化学习到的节点表示import umap import matplotlib.pyplot as plt model.eval() out model.conv1(data.x, data.edge_index) out out.detach().cpu().numpy() reducer umap.UMAP() embedding reducer.fit_transform(out) plt.scatter(embedding[:,0], embedding[:,1], cdata.y.cpu(), s10, cmapSet1) plt.colorbar() plt.show()你会看到同类论文在嵌入空间中形成明显聚类这正是GNN的强大之处——同时利用节点特征和图结构信息。

更多文章