图神经网络(GNN)目前的主流实现方式就是节点之间的信息汇聚,也就是类似于卷积网络的邻域加权和,比如图卷积网络(GCN)、图注意力网络(GAT)等。下面根据GCN的实现原理使用Pytorch张量,和调用torch_geometric包,分别对Cora数据集进行节点分类实验。

  Cora是关于科学文献之间引用关系的图结构数据集。数据集包含一个图,图中包括2708篇文献(节点)和10556个引用关系(边)。其中每个节点都有一个1433维的特征向量,即文献内容的嵌入向量。文献被分为七个类别:计算机科学、物理学等。

GCN计算流程

  对于某个GCN层,假设输入图的节点特征为$X\in R^{|V|\times F_{in}}$,边索引表示为序号数组$Ei\in R^{2\times |E|}$,GCN层输出$Y\in R^{|V|\times F_{out}}$。计算流程如下:

  0、根据$Ei$获得邻接矩阵$A_0\in R^{|V|\times |V|}$。

  1、为了将节点自身信息汇聚进去,每个节点添加指向自己的边,即 $A=A_0+I$,其中$I$为单位矩阵。

  2、计算度(出或入)矩阵 $D$,其中 $D_{ii}=\sum_j A_{ij}$ 表示第 $i$ 个节点的度数。$D$为对角阵。

  3、计算对称归一化矩阵 $\hat{D}$,其中 $\hat{D}_{ii}=1/\sqrt{D_{ii}}$。

  4、构建对称归一化邻接矩阵 $\tilde{A}$,其中 $\tilde{A}= \hat{D} A \hat{D}$。

  5、计算节点特征向量的线性变换,即 $Y = \tilde{A} X W$,其中 $X$ 表示输入的节点特征向量,$W\in R^{F_{in}\times F_{out}}$ 为GCN层中待训练的权重矩阵。

  即:

$Y=D^{-0.5}(A_0+I)D^{-0.5}XW$

  在torch_geometric包中,normalize参数控制是否使用度矩阵$D$归一化;cached控制是否缓存$D$,如果每次输入都是相同结构的图,则可以设置为True,即所谓转导学习(transductive learning)。另外,可以看到GCN的实现只考虑了节点的特征,没有考虑边的特征,仅仅通过聚合引入边的连接信息。

GCN实验

调包实现

  Cora的图数据存放在torch_geometric的Data类中。Data主要包含节点特征$X\in R^{|V|\times F_v}$、边索引$Ei\in R^{2\times |E|}$、边特征$Ea\in R^{|E|\times F_e}$等变量。首先导出Cora数据:

from torch_geometric.datasets import Planetoid

cora = Planetoid(root='./data', name='Cora')[0]
print(cora)

  构建GCN,训练并测试。

import torch
from torch import nn
from torch_geometric.nn import GCNConv
import torch.nn.functional as F
from torch.optim import Adam class GCN(nn.Module):
def __init__(self, in_channels, hidden_channels, class_n):
super(GCN, self).__init__()
self.conv1 = GCNConv(in_channels, hidden_channels)
self.conv2 = GCNConv(hidden_channels, class_n) def forward(self, x, edge_index):
x = torch.relu(self.conv1(x, edge_index))
x = torch.dropout(x, p=0.5, train=self.training)
x = self.conv2(x, edge_index)
return torch.log_softmax(x, dim=1) model = GCN(cora.num_features, 16, cora.y.unique().shape[0]).to('cuda')
opt = Adam(model.parameters(), 0.01, weight_decay=5e-4) def train(its):
model.train()
for i in range(its):
y = model(cora.x, cora.edge_index)
loss = F.nll_loss(y[cora.train_mask], cora.y[cora.train_mask])
loss.backward()
opt.step()
opt.zero_grad() def test():
model.eval()
y = model(cora.x, cora.edge_index)
right_n = torch.argmax(y[cora.test_mask], 1) == cora.y[cora.test_mask]
acc = right_n.sum()/cora.test_mask.sum()
print("Acc: ", acc) for i in range(15):
train(1)
test()

  仅15次迭代就收敛,测试精度如下:

张量实现

  主要区别就是自定义一个My_GCNConv来代替GCNConv,My_GCNConv定义如下:

from torch import nn
from torch_geometric.utils import to_dense_adj class My_GCNConv(nn.Module):
def __init__(self, in_channels, out_channels):
super(My_GCNConv, self).__init__()
self.weight = torch.nn.Parameter(nn.init.xavier_normal(torch.zeros(in_channels, out_channels)))
self.bias = torch.nn.Parameter(torch.zeros([out_channels])) def forward(self, x, edge_index):
adj = to_dense_adj(edge_index)[0]
adj += torch.eye(x.shape[0]).to(adj)
dgr = torch.diag(adj.sum(1)**-0.5)
y = torch.matmul(dgr, adj)
y = torch.matmul(y, dgr)
y = torch.matmul(y, x)
y = torch.matmul(y, self.weight) + self.bias
return y

  其它代码仅将GCNConv修改为My_GCNConv。

对比实验

MLP实现

  下面不使用节点之间的引用关系,仅使用节点特征向量在MLP中进行实验,来验证GCN的有效性。

import torch
from torch import nn
import torch.nn.functional as F
from torch.optim import Adam class MLP(nn.Module):
def __init__(self, in_channels, hidden_channels, class_n):
super(MLP, self).__init__()
self.l1 = nn.Linear(in_channels, hidden_channels)
self.l2 = nn.Linear(hidden_channels, hidden_channels)
self.l3 = nn.Linear(hidden_channels, class_n) def forward(self, x):
x = torch.relu(self.l1(x))
x = torch.relu(self.l2(x))
x = torch.dropout(x, p=0.5, train=self.training)
x = self.l3(x)
return torch.log_softmax(x, dim=1) model = MLP(cora.num_features, 512, cora.y.unique().shape[0]).to('cuda')
opt = Adam(model.parameters(), 0.01, weight_decay=5e-4) def train(its):
model.train()
for i in range(its):
y = model(cora.x[cora.train_mask])
loss = F.nll_loss(y, cora.y[cora.train_mask])
loss.backward()
opt.step()
opt.zero_grad() def test():
model.eval()
y = model(cora.x[cora.test_mask])
right_n = torch.argmax(y, 1) == cora.y[cora.test_mask]
acc = right_n.sum()/cora.test_mask.sum()
print("Acc: ", acc) for i in range(15):
train(30)
test()

  可以看出MLP包含了3层,并且隐层参数比GCN多得多。结果如下:

  精度收敛在57%左右,效果比GCN的79%差。说明节点之间的链接关系对节点类别的划分有促进作用,以及GCN的有效性。

图卷积神经网络分类的pytorch实现的更多相关文章

  1. 图卷积神经网络(GCN)入门

    图卷积网络Graph Convolutional Nueral Network,简称GCN,最近两年大热,取得不少进展.不得不专门为GCN开一个新篇章,表示其重要程度.本文结合大量参考文献,从理论到实 ...

  2. 论文解读丨基于局部特征保留的图卷积神经网络架构(LPD-GCN)

    摘要:本文提出一种基于局部特征保留的图卷积网络架构,与最新的对比算法相比,该方法在多个数据集上的图分类性能得到大幅度提升,泛化性能也得到了改善. 本文分享自华为云社区<论文解读:基于局部特征保留 ...

  3. Graph 卷积神经网络:概述、样例及最新进展

    http://www.52ml.net/20031.html [新智元导读]Graph Convolutional Network(GCN)是直接作用于图的卷积神经网络,GCN 允许对结构化数据进行端 ...

  4. 最全面的图卷积网络GCN的理解和详细推导,都在这里了!

    目录 目录 1. 为什么会出现图卷积神经网络? 2. 图卷积网络的两种理解方式 2.1 vertex domain(spatial domain):顶点域(空间域) 2.2 spectral doma ...

  5. Graph Neural Networks:谱域图卷积

    以下学习内容参考了:1,2, 0.首先回忆CNN,卷积神经网络的结构和特点 处理的数据特征:具有规则的空间结构(Euclidean domains),都可以采用一维或者二维的矩阵描述.(Convolu ...

  6. 卷积神经网络概念及使用 PyTorch 简单实现

    卷积神经网络 卷积神经网络(CNN)是深度学习的代表算法之一 .具有表征学习能力,能够按其阶层结构对输入信息进行平移不变分类,因此也被称为“平移不变人工神经网络”.随着深度学习理论的提出和数值计算设备 ...

  7. 基于卷积神经网络的面部表情识别(Pytorch实现)----台大李宏毅机器学习作业3(HW3)

    一.项目说明 给定数据集train.csv,要求使用卷积神经网络CNN,根据每个样本的面部图片判断出其表情.在本项目中,表情共分7类,分别为:(0)生气,(1)厌恶,(2)恐惧,(3)高兴,(4)难过 ...

  8. PyTorch基础——使用卷积神经网络识别手写数字

    一.介绍 实验内容 内容包括用 PyTorch 来实现一个卷积神经网络,从而实现手写数字识别任务. 除此之外,还对卷积神经网络的卷积核.特征图等进行了分析,引出了过滤器的概念,并简单示了卷积神经网络的 ...

  9. Pytorch实现基于卷积神经网络的面部表情识别(详细步骤)

    文章目录 一.项目背景 二.数据处理 1.标签与特征分离 2.数据可视化 3.训练集和测试集 三.模型搭建 四.模型训练 五.完整代码 一.项目背景数据集cnn_train.csv包含人类面部表情的图 ...

  10. [DL学习笔记]从人工神经网络到卷积神经网络_3_使用tensorflow搭建CNN来分类not_MNIST数据(有一些问题)

    3:用tensorflow搭个神经网络出来 为什么用tensorflow呢,应为谷歌是亲爹啊,虽然有些人说caffe更适合图像啊mxnet效率更高等等,但爸爸就是爸爸,Android都能那么火,一个道 ...

随机推荐

  1. VS 新版本无法打开旧项目问题处理

    问题 最近想阅读 WorkflowCore 的源码,苦于代码量巨大,就想将项目回退到 Init Commit 版本 但是在回退版本后,工程内Project 显示已卸载 重新加载后 提示: 不支持 Th ...

  2. C温故补缺(八):结构体与共用体

    结构体与共用体 结构体 是一个可以存储多个不同类型的变量的结构,类似于面对对象中的类(只有成员变量的类). struct tag { member-list member-list member-li ...

  3. Sqoop的介绍和安装

    sqoop下载地址:https://share.weiyun.com/woVbfnfS 或者 https://archive.apache.org/dist/sqoop/1.99.7/ Sqoop简介 ...

  4. 在 win11 下搭建并使用 ubuntu 子系统(同时测试 win10)——(附带深度学习环境搭建)

    对于一个深度学习从事者来说,Windows训练模型有着诸多不便,还好现在Windows的Ubuntu子系统逐渐完善,近期由于工作需求,配置了Windows的工作站,为了方便起见,搭建了Ubuntu子系 ...

  5. 深入浅出Seata的AT模式

    目录 一.业务背景 二.Seata架构 1.核心组件 2.AT模式 三.案例分析 1.流程分析 2.写隔离 3.读隔离 四.对比XA模式 五.参考源码 单个掉队,导致集体被动摆烂: 一.业务背景 在分 ...

  6. JavaEE Day12 Xml

    今日内容Xml 1.概念 2.语法结构 3.解析xml 一.XML概述 1.概念 Markup Language Extensible Markup Language--可扩展标记语言 标记语言:标签 ...

  7. 如何在 .Net 7 中将 Query 绑定到数组

    在 .Net 7 中,我们可以通过绑定数组的方式来接收来自查询字符串的参数.这样就不需要再使用逗号分隔的字符串来获取参数了. 代码演示 假设我们需要从 query 上接受多个 id 并返回查询的结果. ...

  8. netkit-telnet源码编译安装

    介绍 Linux 下流行的 telnet 实现有两个: GNU inetutils: http://ftp.gnu.org/gnu/inetutils/ 哈佛netkit-telnet 源码包:htt ...

  9. HNCTF的pyjail做题过程详解

    简述: 因为本人对python的内置函数理解也不是深入,在做题过程中也是靠着出题人的hint和google大法才做出来几题,详细的解题过程和知识点讲解可以看一下春哥的知乎,[PyJail] pytho ...

  10. 6、发送验证码功能(Redis)

    一.业务需求: 1.后端随机生成短信验证码,并在服务器端保存一定时间(redis): 2.将短信验证码发给用户: 3.用户输入短信验证码提交后,在后端与之前生成的短信验证码作比较,如果相同说明验证成功 ...