本博文旨在直接提供一个可用于最新版本Python和Pycharm的GCN代码
首先,附上GCN原始论文链接和code链接
论文: https://arxiv.org/pdf/1609.02907.pdf
code: https://github.com/tkipf/gcn
既然作者们提供了GCN的python代码,为什么我还要写这个博客呢?
原因在于该论文发表于2017年,其原始代码所调用的库与当前的Python以及Pycharm版本已经不兼容,而且代码内部涉及到命令行参数等与模型或算法本身并不必要的编程内容,为了避免铁子们像我一样哼哧哼哧地下载完代码然后报错一直修改,满脸狰狞地敲着键盘,特提供如下所示的全新的、验证过的流畅代码!
import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv
from torch_geometric.datasets import Planetoid
# 定义GCN模型
class GCN(torch.nn.Module):
def __init__(self, num_features, hidden_channels, num_classes):
super(GCN, self).__init__() # 调用父类(torch.nn.Module)的构造函数
self.conv1 = GCNConv(num_features, hidden_channels) # 第一层图卷积层,输入特征到隐藏层
self.conv2 = GCNConv(hidden_channels, num_classes) # 第二层图卷积层,隐藏层到输出层(类别数)
def forward(self, data):
x, edge_index = data.x, data.edge_index # 从data对象中解包节点特征和边索引
# 第一层图卷积并激活
x = self.conv1(x, edge_index) # 应用第一层图卷积
x = F.relu(x) # 应用ReLU激活函数
x = F.dropout(x, training=self.training) # 可选:在训练模式下应用dropout
# 第二层图卷积
x = self.conv2(x, edge_index) # 应用第二层图卷积
return F.log_softmax(x, dim=1) # 返回对数概率,用于分类任务的损失计算
# 加载数据集
dataset = Planetoid(root='/tmp/Cora', name='Cora') # 加载Cora数据集,并指定数据集存储路径和名称
# 初始化模型
model = GCN(num_features=dataset.num_node_features, # 节点特征的数量
hidden_channels=16, # 隐藏层的节点数(或特征数)
num_classes=dataset.num_classes) # 输出的类别数
# 数据准备(这里只是简单地从数据集中取出一个图,实际上Cora数据集包含多个图)
data = dataset[0] # Cora数据集通常包含多个图,这里只取第一个图进行演示
# 定义优化器
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4) # 使用Adam优化器
# 训练模型
model.train() # 设置模型为训练模式
for epoch in range(200): # 训练200个epoch
optimizer.zero_grad() # 清空过往梯度
out = model(data) # 前向传播,获取模型输出
loss = F.nll_loss(out[data.train_mask], data.y[data.train_mask]) # 计算损失(仅针对训练节点)
loss.backward() # 反向传播,计算梯度
optimizer.step() # 更新模型参数
if epoch % 10 == 0: # 每10个epoch打印一次损失
print(f'Epoch {epoch + 1}, Loss: {loss.item()}')
# 评估模型
model.eval() # 设置模型为评估模式
_, pred = model(data).max(dim=1) # 前向传播,并获取概率最高的类别的索引作为预测结果
correct = int(pred[data.test_mask].eq(data.y[data.test_mask]).sum().item()) # 计算测试集上的正确预测数
accuracy = correct / int(data.test_mask.sum()) # 计算准确率
print(f'Accuracy: {accuracy:.4f}') # 打印准确率
本着先跑通的初衷,该代码只使用了一个隐含层,较为简单。下一期我会再写文章,详细讲一讲GCN的运作机理以及数学原理,并附上实验结果。下下一期,将对该模型做出修改,如调整dropout、增加隐含层、测试超参数敏感度,并提高其泛化性能。(是的,处女座就是很爱画饼~~~~~)
哦对啦,跑代码之前,先在terminal输入(-i https://pypi.tuna.tsinghua.edu.cn/simple为清华的镜像源,增强稳定性、均衡负载):
pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install torch_geometric -i https://pypi.tuna.tsinghua.edu.cn/simple
此外,如果出现numpy版本不兼容的问题,记得再输入:
pip install numpy==2.0
或者
pip install numpy<2.0
完毕!
我们~
下期见。
(运行结果: