搭建SGC实现引文网络节点预测(PyTorch+PyG)

20 篇文章 35 订阅

前言

SGC的原理比较简单,具体请见:ICML 2019 | SGC:简单图卷积网络

数据集

数据集采用节点分类常用的三大引文网络:Citeseer、Cora和PubMed,数据集不再详细介绍。

模型实现

PyTorch实现

由于SGC的原理比较简单,因此用PyTorch手写也十分轻松。

观察SGC的表达式:
在这里插入图片描述
首先我们需要计算对称归一化的邻接矩阵 S S S
S = D ~ − 1 2 A ~ D ~ − 1 2 S=\tilde{D}^{-\frac{1}{2}}\tilde{A}\tilde{D}^{-\frac{1}{2}} S=D~21A~D~21
其中 A ~ = A + I \tilde{A}=A+I A~=A+I D ~ = D + I \tilde{D}=D+I D~=D+I

首先获取数据:

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
names = ['CiteSeer', 'Cora', 'PubMed']

dataset = Planetoid(root='data', name=names[0])
dataset = dataset[0]
edge_index, _ = add_self_loops(dataset.edge_index)

然后提取邻接矩阵:

# get adj
adj = to_scipy_sparse_matrix(edge_index).todense()
adj = torch.tensor(adj).to(device)

提取度矩阵:

deg = degree(edge_index[0], dataset.num_nodes)
deg = torch.diag_embed(deg)
deg_inv_sqrt = torch.pow(deg, -0.5)
deg_inv_sqrt[deg_inv_sqrt == float('inf')] = 0
deg_inv_sqrt = deg_inv_sqrt.to(device)

对邻接矩阵进行对称归一化:

s = torch.mm(torch.mm(deg_inv_sqrt, adj), deg_inv_sqrt)

对特征进行预处理:

k = 2
norm_x = torch.mm(torch.matrix_power(s, k), feature)

最后,搭建模型:

class SGC(nn.Module):
    def __init__(self, in_feats, out_feats):
        super(SGC, self).__init__()
        self.softmax = nn.Softmax(dim=1)
        self.w = nn.Linear(in_feats, out_feats)

    def forward(self, x):
        out = self.w(x)
        return out

其中 x x x为上面预处理过的特征norm_x。

模型训练:

def train(model):
    optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-6)
    loss_function = torch.nn.CrossEntropyLoss().to(device)
    scheduler = StepLR(optimizer, step_size=10, gamma=0.4)
    min_epochs = 10
    min_val_loss = 5
    final_best_acc = 0
    model.train()
    t = perf_counter()
    for epoch in tqdm(range(100)):
        out = model(norm_x)
        optimizer.zero_grad()
        loss = loss_function(out[train_mask], y[train_mask])
        loss.backward()
        optimizer.step()
        # validation
        val_loss, test_acc = test(model)
        if val_loss < min_val_loss and epoch + 1 > min_epochs:
            min_val_loss = val_loss
            final_best_acc = test_acc
        model.train()
        print('Epoch{:3d} train_loss {:.5f} val_loss {:.3f} test_acc {:.3f}'.
              format(epoch, loss.item(), val_loss, test_acc))

    train_time = perf_counter() - t

    return final_best_acc, train_time

PyG实现

首先导入包:

from torch_geometric.nn import SGConv

模型参数:
在这里插入图片描述

  1. in_channels:输入通道,比如节点分类中表示每个节点的特征数。
  2. out_channels:输出通道,输出通道为节点类别数(节点分类)。
  3. K:跳数,最远提取到K阶邻居的特征,也就是前面公式中的K。
  4. cached:如果为True,则只是在第一次执行时才计算预处理后的特征,否则每一次都计算。默认为True。
  5. add_self_loops:如果为False不再强制添加自环,默认为True。
  6. bias:默认添加偏置。

于是模型搭建如下:

class PyG_SGC(nn.Module):
    def __init__(self, in_feats, out_feats):
        super(PyG_SGC, self).__init__()
        self.conv = SGConv(in_feats, out_feats, K=k, cached=True)

    def forward(self, data):
        x, edge_index = data.x, data.edge_index
        x = self.conv(x, edge_index)

        return x

训练时返回验证集上表现最优的模型:

def pyg_train(model, data):
    optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-6)
    loss_function = torch.nn.CrossEntropyLoss().to(device)
    scheduler = StepLR(optimizer, step_size=10, gamma=0.4)
    min_epochs = 10
    min_val_loss = 5
    final_best_acc = 0
    model.train()
    t = perf_counter()
    for epoch in tqdm(range(100)):
        out = model(data)
        optimizer.zero_grad()
        loss = loss_function(out[train_mask], y[train_mask])
        loss.backward()
        optimizer.step()
        # validation
        val_loss, test_acc = pyg_test(model, data)
        if val_loss < min_val_loss and epoch + 1 > min_epochs:
            min_val_loss = val_loss
            final_best_acc = test_acc
        model.train()
        print('Epoch{:3d} train_loss {:.5f} val_loss {:.3f} test_acc {:.3f}'.
              format(epoch, loss.item(), val_loss, test_acc))

    train_time = perf_counter() - t

    return final_best_acc, train_time

实验结果

这里给出Citeseer网络的实验结果:

pytorch train_time: 0.2071399000000005
pytorch best test acc: 0.681

pyg train_time: 0.21978220000000004
pyg best test acc: 0.676

可以看出PyTorch手写和PyG的效果类似,耗时也类似。

完整代码

后面统一整理。

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SGC图卷积神经网络是一种基于图卷积神经网络(GCN)的变体,它使用了一种非常简单的方法来进行图卷积运算。相比于GCN,SGC的计算复杂度更低,但是仍然能够在图分类等任务上取得不错的性能。 以下是SGC图卷积神经网络实现步骤: 1. 定义输入图和标签 首先,我们需要定义输入图和相应的标签。输入图通常是由节点和边组成的邻接矩阵,可以使用网络库(如networkx)来生成。标签则是指每个节点对应的类别,可以是数字或者文本。 2. 对邻接矩阵进行预处理 SGC图卷积神经网络需要对邻接矩阵进行预处理,将其转化为无权无向图。具体来说,我们需要将邻接矩阵的每个元素设为1,然后对每个节点的度进行归一化处理。这一步可以使用numpy和scipy来实现。 3. 定义模型结构 SGC图卷积神经网络的结构非常简单,只需要定义一个线性层和一个softmax层即可。线性层的输入和输出维度都为节点的数量,其作用是将邻接矩阵进行线性变换。softmax层用于将线性层的输出转化为概率分布,表示每个节点属于不同类别的概率。 4. 训练模型 训练模型的过程与普通的神经网络类似,我们需要定义损失函数和优化器,并使用标签来计算损失。SGC网络的损失函数通常是交叉熵损失,优化器可以选择Adam或者SGD等常用优化器。 5. 测试模型 在测试模型时,我们需要使用训练好的模型来预测测试集中每个节点的类别,并将预测结果与真实标签进行比较,计算准确率等指标来评估模型性能。 总之,SGC图卷积神经网络实现相对简单,但是需要注意对邻接矩阵进行预处理和使用归一化的度矩阵来进行卷积操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Cyril_KI

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

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

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

打赏作者

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

抵扣说明:

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

余额充值