如何利用PyG实现一个图卷积神经网络并在Cora数据集上进行训练

PyG是基于PyTorch的一个图神经网络框架,包含了大量经典图神经网络论文中的模型结构

Cora是一个小规模图神经网络数据集,包含2708篇论文,每篇论文分为7个类别,每篇论文的属性用一个1433维的向量表示,论文之间通过引用关系形成一个无向图的结构。

Cora数据集上的任务是判断一篇论文的所属类别,是一个在图结构数据上的分类问题。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv
from torch_geometric.datasets import Planetoid
from torch_geometric.utils import to_networkx
import networkx as nx
import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE'


#####################################
# 数据准备
#####################################
# 通过Planetoid下载数据
dataset = Planetoid(
    # 数据保存的路径
    # 如果指定目录下不存在数据集
    # PyG会自己进行下载
    root='../data/Cora',
    # 要使用的数据集
    name='Cora',
)
# 查看数据集基本信息
print(dataset.data)
print('包含的类别数:', dataset.num_classes)
print('边特征的维度:', dataset.num_edge_features)
print('边的数量:', dataset.data.edge_index.shape[1] / 2)
print('节点特征的维度:', dataset.num_node_features)
print('节点的数量:', dataset.data.x.shape[0])
print('节点属性特征:', dataset.data.x)

# 查看网络数据中节点的连接方式
# 列表中的每一对代表对应节点之间有边相连接,比如0-633,0-1862
print(dataset.data.edge_index)

# 获取训练集、测试集、验证集数据量
print('训练集节点数量:', sum(dataset.data.train_mask))
print('验证集节点数量:', sum(dataset.data.val_mask))
print('测试集节点数量:', sum(dataset.data.test_mask))

# 检查数据集是否是无向图
print(dataset.data.is_undirected())

# 将数据集转换为网络的形式方便可视化处理
CoraNet = to_networkx(dataset.data)
# 转换为无向图,因为前面我们判断出来Cora是无向图
CoraNet = CoraNet.to_undirected()
# 在网络形式上获取数据集的信息
print('网络中边的数量:', CoraNet.number_of_edges())
print('网络中节点的数量:', CoraNet.number_of_nodes())
# 每个节点的类别
Node_class = dataset.data.y.data.numpy()
print(Node_class)
# 获取每个节点的度
Node_degree = pd.DataFrame(
    data=CoraNet.degree,
    columns=['Node', 'Degree']
)
# 降序排列
Node_degree = Node_degree.sort_values(
    by=['Degree'],
    # 降序
    ascending=False
)
# 因为排序后索引会改变,重置一下索引
Node_degree = Node_degree.reset_index(drop=True)
# 使用直方图可视化度最多的前30个节点
# 代表了被引用最多
# 说明节点上代表的论文是比较重要的
Node_degree.iloc[0:30, :].plot(x='Node', y='Degree', kind='bar', figsize=(10, 10))
plt.xlabel('Node', size=12)
plt.ylabel('Degree', size=12)
plt.show()
# 可视化训练集数据
# 网络中每个节点的位置
pos = nx.spring_layout(CoraNet)
# 为不同类别的节点赋予不同的颜色
nodecolor = [
    'red',
    'blue',
    'green',
    'yellow',
    'peru',
    'violet',
    'cyan',
]
# 训练数据集数据的索引
nodelabel = np.arange(0, 140)
# 对应的类别
Node_class = dataset.data.y.data.numpy()[0:140]
plt.figure(figsize=(10, 10))
# np.unique(Node_class)表示获取训练集的类别
# len()表示获取类别数
# np.arange()表示生成从0到类别数的索引
for ii in np.arange(len(np.unique(Node_class))):
    # 获取相应类别的节点
    nodelist = nodelabel[Node_class == ii]
    # 绘图
    nx.draw_networkx_nodes(
        # 要画的图
        CoraNet,
        # 每个节点在图中的位置
        pos,
        # 具体要画哪些节点
        nodelist=list(nodelist),
        # 节点大小
        node_size=50,
        # 节点颜色
        node_color=nodecolor[ii],
        # 透明度
        alpha=0.8,
    )
plt.show()


##############################################
# 搭建图卷积神经网络
##############################################
class GCNNet(torch.nn.Module):
    # 网络初始化
    def __init__(self, input_feature, num_class):
        '''
        :param input_feature: 每个节点属性的维度
        :param num_class: 节点所属的类别数
        '''
        super(GCNNet, self).__init__()
        self.input_feature = input_feature
        self.num_classes = num_class
        # 图卷积层
        # 出自于论文《Semi-Supervised Classification with Graph Convolutional Networks》
        # 具体计算公式可查阅论文
        self.conv1 = GCNConv(input_feature, 32)
        self.conv2 = GCNConv(32, num_class)

    # 前向传递过程
    def forward(self, data):
        # data是输入到网络中的训练数据
        # 获取节点的属性信息和边的连接信息
        x, edge_index = data.x, data.edge_index
        # 卷积,利用相邻节点的信息更新自己的特征表示
        x = self.conv1(x, edge_index)
        # 激活
        x = F.relu(x)
        x = self.conv2(x, edge_index)
        # 预测类别
        output = F.softmax(x, dim=1)
        return output


# 初始化网络
input_feature = dataset.num_node_features
num_class = dataset.num_classes
mygcn = GCNNet(input_feature, num_class)

####################################################################
# 训练图卷积神经网络
####################################################################
# 当前设备
# 如果GPU可用用GPU,否则用CPU
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# 将模型和训练数据放在设备上
model = mygcn.to(device)
data = dataset[0].to(device)
# Adam优化器
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
# 损失值
train_loss_all = []
val_loss_all = []
# 开启训练
model.train()
print('图卷积神经网络开始训练!')
# 训练200轮
for epoch in range(200):
    print('=' * 100)
    print('当前训练轮次:', epoch)
    # 梯度清零
    optimizer.zero_grad()
    # 获取模型对于数据的类别预测
    out = model(data)
    # 计算损失
    loss = F.cross_entropy(out[data.train_mask], data.y[data.train_mask])
    # 反向传播
    loss.backward()
    optimizer.step()
    train_loss_all.append(loss.data.numpy())

    # 计算在验证集上的损失
    loss = F.cross_entropy(out[data.val_mask], data.y[data.val_mask])
    val_loss_all.append(loss.data.numpy())
    print('Epoch:{},train_loss:{},val_loss:{}'.format(epoch, train_loss_all[-1], val_loss_all[-1]))


# 保存训练完毕的网络
torch.save(model, 'GCNNet.pt')

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
卷积神经网络(Graph Convolutional Neural Network,GCN)可以用地铁预测任务。地铁预是指根据历史地铁运行数据,预测未来某个时间点或某个地铁站点的客流量、到达时间等信息。 在应用GCN进行地铁预测时,可以将地铁网络抽象为一个结构,其中地铁站点作为的节点,地铁线路作为的边。每个节点可以包含一些特征,如地理位置、历史客流量等。GCN可以利用节点之间的连接关系和节点特征,进行信息传递和特征学习。 具体而言,GCN通过多层卷积操作来更新节点的特征表示。每一层的卷积操作都考虑了节点自身的特征以及其邻居节点的特征,并通过权重共享和非线性激活函数来提取节点的局部和全局信息。通过多层卷积操作,GCN能够逐渐聚合更多的上下文信息,从而获得更准确的预测结果。 在地铁预测任务中,可以将历史客流量作为监督信号,通过训练GCN模型来学习节点的特征表示和预测模型。通过输入当前时间点的节点特征,GCN可以输出对应节点的预测结果,如预测的客流量或到达时间。 需要注意的是,GCN在地铁预测任务中的具体实现方式还需要根据具体情况进行设计和调整,包括选择合适的GCN模型结构、特征表示方法、损失函数等。此外,还需要合理选择训练数据集和验证数据集,并进行模型的训练和评估。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_Old_Summer

感谢老板!!!

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

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

打赏作者

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

抵扣说明:

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

余额充值