视频链接:【图神经网络】GNN从入门到精通
GNN中三种基础神经网络:GCN, GraphSAGE, GAT
文章目录
一、GCN
1.1 定义
二、代码目录
链接见 这里
文件目录
train的流程
三、代码调试的方法
3.1 选择断点,进入调试
在train.py
中选择42行。鼠标“左击”序列,打上红色断点符号。
在任意处“右键点击”,选择“debug”选项,进入debug界面,并获得如下调试器。
3.2 查看断点处的函数load_data()
1) 通过快捷键可跳转至函数的定义
- windos:ctrl+鼠标点击函数
load_data()
- mac: command+鼠标点击函数
load_data()
通过快捷键返回调用函数的位置
- windows:ctrl+alt+ ← \leftarrow ← 或着 alt+ ← \leftarrow ←
- mac:option+command+ ← \leftarrow ←
2) 打印新断点
- numpy.genfromtxt(fname).fname可以有多种形式,可以是file, str, pathlib.Path, list of str, 或者generator。genfromtxt可以分解成两步,第一步是从文件读取数据,并转化成为字符串。第二步就是将字符串转化成为指定的数据类型。见《使用genfromtxt导入数据》
"{}{}.content".format()
的字符串以.content
结尾,第一个括号的内容,鼠标点击的时候,如上图会在path
上有暗底阴影,表示文件路径为:../data/cora/
,同理可查看第二个括号的内容为:cora
。说明读取的是如下所示的文件
- 查看cora.content文件
文件中第一列表示node的编号,后边是节点的特征,如下只显示了一部分。
3)执行代码,查看变量
- 如下图执行下一行代码
Variables界面改变了
- 在console中调用python界面查看变量,如下图所示
可以看到数据的形状为(2708, 1435),在每一行以node的编号为首,以node的分类标签为尾,中间为node的特征向量。 - 根据上面的方法,依次可以查看变量:adj, features, labels, idx_train, idx_val, idx_test
4)load_data()函数的流程
1. 通过加载数据获得features,labels
2. 对node的编号重新编号,并记载边的数据,重新构建graph的稀疏矩阵adj
3. adj变为对称矩阵并标准化
4. 获得train,val.test的数据索引
5.返回adj, features, labels, idx_train, idx_val, idx_test
- 矩阵归一化的原因
3.3 查看断点处的函数GCN()
函数、断点、变量,如下图所示:
- 查看GraphConvolution
四、函数train()的运转过程
- 打断点的方式
如前文所有图中打断点的方式所示,接下来,我们将从train()函数中的断点开始,使用如下按钮,调制到关键步骤的方式,演示train()的工作流程。
1. 跳到train函数
2. 跳到model函数,准备进入GCN
3. 跳到GCN内执行第一行
gc1的执行过程
- GRaphConvolutin内执行第一行
- 第二行
- 第三行
- 第四行
- 进入python自带的文件
- 返回第GCN
- 查看执行后的变量结果
4.GCN内执行第二行
5.GCN内执行第三行
流转过程与第一行的流程,相同。在这里添加运转过程中变量查看情况
- 准备运行第三行
- 查看forward中第1行的输入数据的形状
- 可以查看第1行的运行结果
- 同理,可以查看gcn2=GraphConvolution(Module)中的各种变量
- 返回GCN内,可以查看self.gc2层输入变量和输出变量的形状
6. GCN内执行第四行
见到return命令,自动执行python内部的文件
7.跳出GCN, 返回train函数
附录:代码
from __future__ import division
from __future__ import print_function
import time
import argparse
import numpy as np
import torch
import torch.nn.functional as F
import torch.optim as optim
from utils import load_data, accuracy
from models import GCN
# Training settings
parser = argparse.ArgumentParser()
parser.add_argument('--no-cuda', action='store_true', default=False,
help='Disables CUDA training.')
parser.add_argument('--fastmode', action='store_true', default=False,
help='Validate during training pass.')
parser.add_argument('--seed', type=int, default=42, help='Random seed.')
parser.add_argument('--epochs', type=int, default=200,
help='Number of epochs to train.')
parser.add_argument('--lr', type=float, default=0.01,
help='Initial learning rate.')
parser.add_argument('--weight_decay', type=float, default=5e-4,
help='Weight decay (L2 loss on parameters).')
parser.add_argument('--hidden', type=int, default=16,
help='Number of hidden units.')
parser.add_argument('--dropout', type=float, default=0.5,
help='Dropout rate (1 - keep probability).')
args = parser.parse_args()
args.cuda = not args.no_cuda and torch.cuda.is_available()
np.random.seed(args.seed)
torch.manual_seed(args.seed)
if args.cuda:
torch.cuda.manual_seed(args.seed)
# Load data
adj, features, labels, idx_train, idx_val, idx_test = load_data()
# Model and optimizer
model = GCN(nfeat=features.shape[1],
nhid=args.hidden,
nclass=labels.max().item() + 1,
dropout=args.dropout)
optimizer = optim.Adam(model.parameters(),
lr=args.lr, weight_decay=args.weight_decay)
if args.cuda:
model.cuda()
features = features.cuda()
adj = adj.cuda()
labels = labels.cuda()
idx_train = idx_train.cuda()
idx_val = idx_val.cuda()
idx_test = idx_test.cuda()
def train(epoch):
t = time.time()
model.train()
optimizer.zero_grad()
output = model(features, adj)
loss_train = F.nll_loss(output[idx_train], labels[idx_train])
acc_train = accuracy(output[idx_train], labels[idx_train])
loss_train.backward()
optimizer.step()
if not args.fastmode:
# Evaluate validation set performance separately,
# deactivates dropout during validation run.
model.eval()
output = model(features, adj)
loss_val = F.nll_loss(output[idx_val], labels[idx_val])
acc_val = accuracy(output[idx_val], labels[idx_val])
print('Epoch: {:04d}'.format(epoch+1),
'loss_train: {:.4f}'.format(loss_train.item()),
'acc_train: {:.4f}'.format(acc_train.item()),
'loss_val: {:.4f}'.format(loss_val.item()),
'acc_val: {:.4f}'.format(acc_val.item()),
'time: {:.4f}s'.format(time.time() - t))
def test():
model.eval()
output = model(features, adj)
loss_test = F.nll_loss(output[idx_test], labels[idx_test])
acc_test = accuracy(output[idx_test], labels[idx_test])
print("Test set results:",
"loss= {:.4f}".format(loss_test.item()),
"accuracy= {:.4f}".format(acc_test.item()))
# Train model
t_total = time.time()
for epoch in range(args.epochs):
train(epoch)
print("Optimization Finished!")
print("Total time elapsed: {:.4f}s".format(time.time() - t_total))
# Testing
test()