PyG搭建GCN模型实现节点分类GCNConv参数详解

 更新时间:2022年05月10日 15:23:46   作者:Cyril_KI  
这篇文章主要为大家介绍了PyG搭建GCN模型实现节点分类GCNConv参数详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

前言

在上一篇文章PyG搭建GCN前的准备:了解PyG中的数据格式中,大致了解了PyG中的数据格式,这篇文章主要是简单搭建GCN来实现节点分类,主要目的是了解PyG中GCN的参数情况。

模型搭建

首先导入包:

from torch_geometric.nn import GCNConv

模型参数:

in_channels:输入通道,比如节点分类中表示每个节点的特征数。

out_channels:输出通道,最后一层GCNConv的输出通道为节点类别数(节点分类)。

improved:如果为True表示自环增加,也就是原始邻接矩阵加上2I而不是I,默认为False。

cached:如果为True,GCNConv在第一次对邻接矩阵进行归一化时会进行缓存,以后将不再重复计算。

add_self_loops:如果为False不再强制添加自环,默认为True。

normalize:默认为True,表示对邻接矩阵进行归一化。

bias:默认添加偏置。

于是模型搭建如下:

class GCN(torch.nn.Module):
    def __init__(self, num_node_features, num_classes):
        super(GCN, self).__init__()
        self.conv1 = GCNConv(num_node_features, 16)
        self.conv2 = GCNConv(16, num_classes)
    def forward(self, data):
        x, edge_index = data.x, data.edge_index
        x = self.conv1(x, edge_index)
        x = F.relu(x)
        x = F.dropout(x, training=self.training)
        x = self.conv2(x, edge_index)
        x = F.relu(x)
        x = F.dropout(x, training=self.training)
        x = F.softmax(x, dim=1)
        return x

输出一下模型:

data = Planetoid(root='/data/CiteSeer', name='CiteSeer')model = GCN(data.num_node_features, data.num_classes).to(device)print(model)GCN(
  (conv1): GCNConv(3703, 16)
  (conv2): GCNConv(16, 6)
)

输出为:

GCN( (conv1): GCNConv(3703, 16) (conv2): GCNConv(16, 6))GCN(
  (conv1): GCNConv(3703, 16)
  (conv2): GCNConv(16, 6)
)

1. 前向传播

查看官方文档中GCNConv的输入输出要求:

可以发现,GCNConv中需要输入的是节点特征矩阵x和邻接关系edge_index,还有一个可选项edge_weight。因此我们首先:

x, edge_index = data.x, data.edge_index
x = self.conv1(x, edge_index)
x = F.relu(x)
x = F.dropout(x, training=self.training)

此时我们不妨输出一下x及其size:

tensor([[0.0000, 0.1630, 0.0000,  ..., 0.0000, 0.0488, 0.0000],
        [0.0000, 0.2451, 0.1614,  ..., 0.0000, 0.0125, 0.0000],
        [0.1175, 0.0262, 0.2141,  ..., 0.2592, 0.0000, 0.0000],
        ...,
        [0.0000, 0.0000, 0.0000,  ..., 0.0000, 0.1825, 0.0000],
        [0.0000, 0.1024, 0.0000,  ..., 0.0498, 0.0000, 0.0000],
        [0.0000, 0.3263, 0.0000,  ..., 0.0000, 0.0000, 0.0000]],
       device='cuda:0', grad_fn=<FusedDropoutBackward0>)
torch.Size([3327, 16])

此时的x一共3327行,每一行表示一个节点经过第一层卷积更新后的状态向量。

那么同理,由于:

self.conv2 = GCNConv(16, num_classes)

所以经过第二层卷积后:

x = self.conv2(x, edge_index)x = F.relu(x)x = F.dropout(x, training=self.training)x = self.conv2(x, edge_index)
x = F.relu(x)
x = F.dropout(x, training=self.training)

此时得到的x的size应该为:

torch.Size([3327, 6])

即每个节点的维度为6的状态向量。

由于我们需要进行6分类,所以最后需要加上一个softmax:

x = F.softmax(x, dim=1)

dim=1表示对每一行进行运算,最终每一行之和加起来为1,也就表示了该节点为每一类的概率。输出此时的x:

tensor([[0.1607, 0.1727, 0.1607, 0.1607, 0.1607, 0.1846], [0.1654, 0.1654, 0.1654, 0.1654, 0.1654, 0.1731], [0.1778, 0.1622, 0.1733, 0.1622, 0.1622, 0.1622], ..., [0.1659, 0.1659, 0.1659, 0.1704, 0.1659, 0.1659], [0.1667, 0.1667, 0.1667, 0.1667, 0.1667, 0.1667], [0.1641, 0.1641, 0.1658, 0.1766, 0.1653, 0.1641]], device='cuda:0', grad_fn=<SoftmaxBackward0>)tensor([[0.1607, 0.1727, 0.1607, 0.1607, 0.1607, 0.1846],
        [0.1654, 0.1654, 0.1654, 0.1654, 0.1654, 0.1731],
        [0.1778, 0.1622, 0.1733, 0.1622, 0.1622, 0.1622],
        ...,
        [0.1659, 0.1659, 0.1659, 0.1704, 0.1659, 0.1659],
        [0.1667, 0.1667, 0.1667, 0.1667, 0.1667, 0.1667],
        [0.1641, 0.1641, 0.1658, 0.1766, 0.1653, 0.1641]], device='cuda:0',
       grad_fn=<SoftmaxBackward0>)

2. 反向传播

在训练时,我们首先利用前向传播计算出输出:

out = model(data)

out即为最终得到的每个节点的6个概率值,但在实际训练中,我们只需要计算出训练集的损失,所以损失函数这样写:

loss = loss_function(out[data.train_mask], data.y[data.train_mask])

然后计算梯度,反向更新!

3. 训练

训练的完整代码:

def train(): optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4) loss_function = torch.nn.CrossEntropyLoss().to(device) model.train() for epoch in range(500): out = model(data) optimizer.zero_grad() loss = loss_function(out[data.train_mask], data.y[data.train_mask]) loss.backward() optimizer.step() print('Epoch {:03d} loss {:.4f}'.format(epoch, loss.item()))def train():
    optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
    loss_function = torch.nn.CrossEntropyLoss().to(device)
    model.train()
    for epoch in range(500):
        out = model(data)
        optimizer.zero_grad()
        loss = loss_function(out[data.train_mask], data.y[data.train_mask])
        loss.backward()
        optimizer.step()
        print('Epoch {:03d} loss {:.4f}'.format(epoch, loss.item()))

4. 测试

我们首先需要算出模型对所有节点的预测值:

model(data)

此时得到的是每个节点的6个概率值,我们需要在每一行上取其最大值:

model(data).max(dim=1)

输出一下:

torch.return_types.max(
values=tensor([0.9100, 0.9071, 0.9786,  ..., 0.4321, 0.4009, 0.8779], device='cuda:0',
       grad_fn=<MaxBackward0>),
indices=tensor([3, 1, 5,  ..., 3, 1, 5], device='cuda:0'))

返回的第一项是每一行的最大值,第二项为最大值在这一行中的索引,我们只需要取第二项,那么最终的预测值应该写为:

_, pred = model(data).max(dim=1)

然后计算预测精度:

correct = int(pred[data.test_mask].eq(data.y[data.test_mask]).sum().item())
acc = correct / int(data.test_mask.sum())
print('GCN Accuracy: {:.4f}'.format(acc))

完整代码

完整代码中实现了论文中提到的四种数据集,代码地址:PyG-GCN

以上就是PyG搭建GCN模型实现节点分类GCNConv参数详解的详细内容,更多关于PyG搭建GCNConv节点分类的资料请关注脚本之家其它相关文章!

相关文章

  • python中的闭包函数

    python中的闭包函数

    这篇文章主要介绍了python中的闭包函数,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2018-02-02
  • Python3列表List入门知识附实例

    Python3列表List入门知识附实例

    序列是Python中最基本的数据结构。序列中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,依此类推
    2020-02-02
  • Python读取yaml文件的详细教程

    Python读取yaml文件的详细教程

    这篇文章主要给大家介绍了关于Python读取yaml文件的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-07-07
  • Python实现MySql数据库交互的示例

    Python实现MySql数据库交互的示例

    本文主要介绍了Python实现MySql数据库交互的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • 一篇文章带你学习Python3的高级特性(1)

    一篇文章带你学习Python3的高级特性(1)

    这篇文章主要为大家详细介绍了Python3的高阶函数,主要介绍什么是高级特性,高级特性的用法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • Django在视图中使用表单并和数据库进行数据交互的实现

    Django在视图中使用表单并和数据库进行数据交互的实现

    本文主要介绍了Django在视图中使用表单并和数据库进行数据交互,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • python jenkins 打包构建代码的示例代码

    python jenkins 打包构建代码的示例代码

    这篇文章主要介绍了python jenkins 打包构建代码的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • 关于Python字符编码与二进制不得不说的一些事

    关于Python字符编码与二进制不得不说的一些事

    这篇文章主要给大家介绍了关于Python字符编码与二进制不得不说的一些事,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • python url 参数修改方法

    python url 参数修改方法

    今天小编就为大家分享一篇python url 参数修改方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-12-12
  • Python简明入门教程

    Python简明入门教程

    这篇文章主要介绍了Python简明入门教程,较为详细的分析了Python的基本概念及语法基础,有助于Python初学者更好的掌握Python的基本语法与使用技巧,需要的朋友可以参考下
    2015-08-08

最新评论