GNN的第一个简单案例:Cora分类

该博客介绍了如何使用图卷积网络(GCN)、图注意力网络(GAT)、谱卷积网络(SGConv)、Chebyshev卷积(ChebConv)和图卷积网络(SAGEConv)在Cora数据集上进行节点分类任务。通过加载Cora数据集,定义并训练了各种GNN模型,并在500个训练周期后展示了模型在测试集上的准确率。最终,SGConv模型在Cora数据集上达到了0.794的测试准确率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GNN–Cora分类

Cora数据集是GNN中一个经典的数据集,将2708篇论文分为七类:1)基于案例、2)遗传算法、3)神经网络、4)概率方法、5)、强化学习、6)规则学习、7)理论。每一篇论文看作是一个节点,每个节点有1433个特征。

import os

import torch
import torch.nn.functional as F
import torch.nn as nn
from torch_geometric.datasets import Planetoid
import torch_geometric.nn as pyg_nn

#load Cora dataset
def get_data(root_dir='D:\Python\python_dataset\GNN_Dataset\Cora',data_name='Cora'):
    Cora_dataset = Planetoid(root=root_dir,name=data_name)
    print(Cora_dataset)
    return Cora_dataset
Cora_dataset = get_data()
print(Cora_dataset.num_classes,Cora_dataset.num_node_features,Cora_dataset.num_edge_features)
print(Cora_dataset.data)
Cora()
7 1433 0
Data(x=[2708, 1433], edge_index=[2, 10556], y=[2708], train_mask=[2708], val_mask=[2708], test_mask=[2708])

代码中给出GCN、GAT、SGConv、ChebConv、SAGEConv的简单实现

import os
import torch
import torch.nn.functional as F
import torch.nn as nn
from torch_geometric.datasets import Planetoid
import torch_geometric.nn as pyg_nn

#load Cora dataset
def get_data(root_dir='D:\Python\python_dataset\GNN_Dataset\Cora',data_name='Cora'):
    Cora_dataset = Planetoid(root=root_dir,name=data_name)
    print(Cora_dataset)
    return Cora_dataset

#create the Graph cnn model
"""
    2-GATConv
"""
# class GATConv(nn.Module):
#     def __init__(self,in_c,hid_c,out_c):
#         super(GATConv,self).__init__()
#         self.GATConv1 = pyg_nn.GATConv(in_channels=in_c,out_channels=hid_c)
#         self.GATConv2 = pyg_nn.GATConv(in_channels=hid_c, out_channels=hid_c)
#
#     def forward(self,data):
#         x = data.x
#         edge_index = data.edge_index
#         hid = self.GATConv1(x=x,edge_index=edge_index)
#         hid = F.relu(hid)
#
#         out = self.GATConv2(hid,edge_index=edge_index)
#         out = F.log_softmax(out,dim=1)
#
#         return out



"""
    2-SAGE 0.788
"""
# class SAGEConv(nn.Module):
#     def __init__(self,in_c,hid_c,out_c):
#         super(SAGEConv,self).__init__()
#         self.SAGEConv1 = pyg_nn.SAGEConv(in_channels=in_c,out_channels=hid_c)
#         self.SAGEConv2 = pyg_nn.SAGEConv(in_channels=hid_c, out_channels=hid_c)
#
#     def forward(self,data):
#         x = data.x
#         edge_index = data.edge_index
#         hid = self.SAGEConv1(x=x,edge_index=edge_index)
#         hid = F.relu(hid)
#
#         out = self.SAGEConv2(hid,edge_index=edge_index)
#         out = F.log_softmax(out,dim=1)
#
#         return out
"""
    2-SGConv  0.79
"""
class SGConv(nn.Module):
    def __init__(self,in_c,hid_c,out_c):
        super(SGConv,self).__init__()
        self.SGConv1 = pyg_nn.SGConv(in_channels=in_c,out_channels=hid_c)
        self.SGConv2 = pyg_nn.SGConv(in_channels=hid_c, out_channels=hid_c)

    def forward(self,data):
        x = data.x
        edge_index = data.edge_index
        hid = self.SGConv1(x=x,edge_index=edge_index)
        hid = F.relu(hid)

        out = self.SGConv2(hid,edge_index=edge_index)
        out = F.log_softmax(out,dim=1)

        return out

"""
    2-ChebConv
"""
# class ChebConv(nn.Module):
#     def __init__(self,in_c,hid_c,out_c):
#         super(ChebConv,self).__init__()
#
#         self.ChebConv1 = pyg_nn.ChebConv(in_channels=in_c,out_channels=hid_c,K=1)
#         self.ChebConv2 = pyg_nn.ChebConv(in_channels=hid_c,out_channels=out_c,K=1)
#
#     def forward(self,data):
#         x = data.x
#         edge_index = data.edge_index
#         hid = self.ChebConv1(x=x,edge_index=edge_index)
#         hid = F.relu(hid)
#
#         out = self.ChebConv2(hid,edge_index=edge_index)
#         out = F.log_softmax(out,dim=1)
#
#         return out
"""
    2-GCN
"""
# class GraphCNN(nn.Module):
#     def __init__(self, in_c,hid_c,out_c):
#         super(GraphCNN,self).__init__()
#
#         self.conv1 = pyg_nn.GCNConv(in_channels=in_c,out_channels=hid_c)
#         self.conv2 = pyg_nn.GCNConv(in_channels=hid_c,out_channels=out_c)
#
#     def forward(self,data):
#         #data.x,data.edge_index
#         x = data.x       # [N,C]
#         edge_index = data.edge_index  # [2,E]
#         hid = self.conv1(x=x,edge_index=edge_index)  #[N,D]
#         hid = F.relu(hid)
#
#         out = self.conv2(hid,edge_index=edge_index)  # [N,out_c]
#
#         out = F.log_softmax(out,dim=1)
#
#         return out

def main():
    os.environ["CUDA_VISIBLE_DEVICES"] = '0'
    Cora_dataset = get_data()

    #my_net = GATConv(in_c=Cora_dataset.num_node_features, hid_c=100, out_c=Cora_dataset.num_classes)

    #my_net = SAGEConv(in_c=Cora_dataset.num_node_features, hid_c=40, out_c=Cora_dataset.num_classes)
    my_net = SGConv(in_c=Cora_dataset.num_node_features,hid_c=100,out_c=Cora_dataset.num_classes)
    #my_net = ChebConv(in_c=Cora_dataset.num_node_features,hid_c=20,out_c=Cora_dataset.num_classes)
    # my_net = GraphCNN(in_c=Cora_dataset.num_node_features,hid_c=12,out_c=Cora_dataset.num_classes)
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

    my_net = my_net.to(device)
    data = Cora_dataset[0].to(device)

    optimizer = torch.optim.Adam(my_net.parameters(),lr=1e-3)

    #model train
    my_net.train()

    for epoch in range(500):
        optimizer.zero_grad()

        output = my_net(data)
        loss = F.nll_loss(output[data.train_mask],data.y[data.train_mask])
        loss.backward()
        optimizer.step()
        print("Epoch",epoch+1,"Loss",loss.item())

    #model test
    my_net.eval()
    _,prediction = my_net(data).max(dim=1)

    target = data.y
    test_correct = prediction[data.test_mask].eq(target[data.test_mask]).sum().item()
    test_number = data.test_mask.sum().item()

    print("Accuracy of Test Sample:",test_correct/test_number)
if __name__ == '__main__':
    main()

Cora()
Epoch 1 Loss 4.600048542022705
Epoch 2 Loss 4.569146156311035
Epoch 3 Loss 4.535804271697998
Epoch 4 Loss 4.498434543609619
Epoch 5 Loss 4.456351280212402
Epoch 6 Loss 4.409425258636475
Epoch 7 Loss 4.357522964477539
Epoch 8 Loss 4.3007612228393555
Epoch 9 Loss 4.2392096519470215
Epoch 10 Loss 4.172731876373291
Epoch 11 Loss 4.101400375366211
Epoch 12 Loss 4.025243282318115
...............
Epoch 494 Loss 0.004426263272762299
Epoch 495 Loss 0.004407935775816441
Epoch 496 Loss 0.004389731213450432
Epoch 497 Loss 0.004371633753180504
Epoch 498 Loss 0.004353662021458149
Epoch 499 Loss 0.0043357922695577145
Epoch 500 Loss 0.004318032879382372
Accuracy of Test Sample: 0.794
### PyTorch 中图神经网络(GNN)的使用教程及实现方法 #### 背景介绍 图神经网络(Graph Neural Networks, GNNs)是一种专门处理图结构数据的强大工具[^3]。通过结合节点特征和边的信息,GNN能够在各种场景下表现出色,例如社交网络分析、化学分子建模以及推荐系统等。 在PyTorch中,可以通过多种方式构建和训练GNN模型。最常用的库之一是 **PyTorch Geometric**,这是一个专门为图数据设计的扩展包,提供了丰富的功能支持复杂的图操作和高效的计算能力。 --- #### 安装 PyTorch Geometric 为了使用PyTorch中的GNN功能,首先需要安装 `torch_geometric` 库: ```bash pip install torch-scatter torch-sparse torch-cluster torch-spline-conv torch-geometric -f https://data.pyg.org/whl/torch-${TORCH_VERSION}+${CUDA_VERSION}.html ``` 其中 `${TORCH_VERSION}` 是当前使用的PyTorch版本号,`${CUDA_VERSION}` 表示所用的CUDA版本(如果不需要GPU加速,则可以选择CPU版)。 --- #### 基础概念与组件 以下是PyTorch Geometric的核心组成部分及其作用: 1. **Data对象**: 存储单个图的数据,包括节点特征 (`x`)、边索引 (`edge_index`) 和其他可选字段。 2. **Dataset类**: 提供加载常见图数据集的功能,如Cora、Citeseer等。 3. **Message Passing层**: 实现消息传递机制的基础模块,允许自定义邻居聚合逻辑。 4. **预定义模型**: 如GCNConv(图卷积)、GATConv(注意力机制)等。 --- #### 示例代码:实现一个简单的GCN模型 下面是一个完整的例子,展示如何使用PyTorch Geometric创建并训练一个基本的GCN模型。 ```python import torch from torch.nn import Linear from torch_geometric.datasets import Planetoid from torch_geometric.transforms import NormalizeFeatures from torch_geometric.nn import GCNConv # 加载Cora数据集 dataset = Planetoid(root='data/Cora', name='Cora', transform=NormalizeFeatures()) data = dataset[0] class GCN(torch.nn.Module): def __init__(self, hidden_channels): super(GCN, self).__init__() torch.manual_seed(12345) self.conv1 = GCNConv(dataset.num_node_features, hidden_channels) # 输入层 -> 隐藏层 self.conv2 = GCNConv(hidden_channels, dataset.num_classes) # 隐藏层 -> 输出层 def forward(self, x, edge_index): x = self.conv1(x, edge_index).relu() # 第一层卷积 + ReLU激活函数 x = torch.dropout(x, p=0.5, training=self.training) # Dropout正则化 x = self.conv2(x, edge_index) # 第二层卷积 return x # 返回未经过softmax的结果 model = GCN(hidden_channels=16) criterion = torch.nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=0.01) def train(): 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() return float(loss) @torch.no_grad() def test(): model.eval() pred = model(data.x, data.edge_index).argmax(dim=1) correct = (pred[data.test_mask] == data.y[data.test_mask]).sum() acc = int(correct) / int(data.test_mask.sum()) return acc for epoch in range(1, 201): # 进行200次迭代 loss = train() if epoch % 20 == 0: print(f'Epoch {epoch}, Loss: {loss:.4f}') test_acc = test() print(f'Test Accuracy: {test_acc*100:.2f}%') ``` 上述代码展示了如何加载Cora数据集,并使用两层GCN完成分类任务。每一层都涉及消息传递过程,最终输出预测类别概率分布[^1]。 --- #### 更高级的应用案例 除了基础的GCN之外,还可以探索更复杂的方法,如下所示: 1. **胶囊图神经网络(CapsGNN)** CapsGNN引入了胶囊的概念,能够更好地捕获图级别的特性[^2]。其实现较为复杂,通常需要手动定义路由机制。 2. **时空图神经网络(ST-GNN)** ST-GNN适用于时间序列图数据分析,例如交通流量预测或视频动作识别。其核心在于联合学习时间和空间维度的关系。 3. **异质图神经网络(Heterogeneous GNN)** 当面对包含不同类型节点和关系的图时,可以采用HGNN框架来分别编码每种类型的子图信息。 --- #### 性能评估与优化技巧 当实际部署GNN解决方案时,可能遇到一些挑战。以下是一些常见的建议: - 对于大规模稀疏矩阵运算,应优先选用高效存储格式(COO/CSR); - 如果存在孤立点或者噪声干扰较大的情况,需提前清理原始数据; - 尝试调整超参数组合(隐藏单元数、层数、dropout率),寻找最优配置[^4]; ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想成为风筝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值