图神经网络(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数据:

  1. from torch_geometric.datasets import Planetoid
  2.  
  3. cora = Planetoid(root='./data', name='Cora')[0]
  4. print(cora)

  构建GCN,训练并测试。

  1. import torch
  2. from torch import nn
  3. from torch_geometric.nn import GCNConv
  4. import torch.nn.functional as F
  5. from torch.optim import Adam
  6.  
  7. class GCN(nn.Module):
  8. def __init__(self, in_channels, hidden_channels, class_n):
  9. super(GCN, self).__init__()
  10. self.conv1 = GCNConv(in_channels, hidden_channels)
  11. self.conv2 = GCNConv(hidden_channels, class_n)
  12.  
  13. def forward(self, x, edge_index):
  14. x = torch.relu(self.conv1(x, edge_index))
  15. x = torch.dropout(x, p=0.5, train=self.training)
  16. x = self.conv2(x, edge_index)
  17. return torch.log_softmax(x, dim=1)
  18.  
  19. model = GCN(cora.num_features, 16, cora.y.unique().shape[0]).to('cuda')
  20. opt = Adam(model.parameters(), 0.01, weight_decay=5e-4)
  21.  
  22. def train(its):
  23. model.train()
  24. for i in range(its):
  25. y = model(cora.x, cora.edge_index)
  26. loss = F.nll_loss(y[cora.train_mask], cora.y[cora.train_mask])
  27. loss.backward()
  28. opt.step()
  29. opt.zero_grad()
  30.  
  31. def test():
  32. model.eval()
  33. y = model(cora.x, cora.edge_index)
  34. right_n = torch.argmax(y[cora.test_mask], 1) == cora.y[cora.test_mask]
  35. acc = right_n.sum()/cora.test_mask.sum()
  36. print("Acc: ", acc)
  37.  
  38. for i in range(15):
  39. train(1)
  40. test()

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

张量实现

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

  1. from torch import nn
  2. from torch_geometric.utils import to_dense_adj
  3.  
  4. class My_GCNConv(nn.Module):
  5. def __init__(self, in_channels, out_channels):
  6. super(My_GCNConv, self).__init__()
  7. self.weight = torch.nn.Parameter(nn.init.xavier_normal(torch.zeros(in_channels, out_channels)))
  8. self.bias = torch.nn.Parameter(torch.zeros([out_channels]))
  9.  
  10. def forward(self, x, edge_index):
  11. adj = to_dense_adj(edge_index)[0]
  12. adj += torch.eye(x.shape[0]).to(adj)
  13. dgr = torch.diag(adj.sum(1)**-0.5)
  14. y = torch.matmul(dgr, adj)
  15. y = torch.matmul(y, dgr)
  16. y = torch.matmul(y, x)
  17. y = torch.matmul(y, self.weight) + self.bias
  18. return y

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

对比实验

MLP实现

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

  1. import torch
  2. from torch import nn
  3. import torch.nn.functional as F
  4. from torch.optim import Adam
  5.  
  6. class MLP(nn.Module):
  7. def __init__(self, in_channels, hidden_channels, class_n):
  8. super(MLP, self).__init__()
  9. self.l1 = nn.Linear(in_channels, hidden_channels)
  10. self.l2 = nn.Linear(hidden_channels, hidden_channels)
  11. self.l3 = nn.Linear(hidden_channels, class_n)
  12.  
  13. def forward(self, x):
  14. x = torch.relu(self.l1(x))
  15. x = torch.relu(self.l2(x))
  16. x = torch.dropout(x, p=0.5, train=self.training)
  17. x = self.l3(x)
  18. return torch.log_softmax(x, dim=1)
  19.  
  20. model = MLP(cora.num_features, 512, cora.y.unique().shape[0]).to('cuda')
  21. opt = Adam(model.parameters(), 0.01, weight_decay=5e-4)
  22.  
  23. def train(its):
  24. model.train()
  25. for i in range(its):
  26. y = model(cora.x[cora.train_mask])
  27. loss = F.nll_loss(y, cora.y[cora.train_mask])
  28. loss.backward()
  29. opt.step()
  30. opt.zero_grad()
  31.  
  32. def test():
  33. model.eval()
  34. y = model(cora.x[cora.test_mask])
  35. right_n = torch.argmax(y, 1) == cora.y[cora.test_mask]
  36. acc = right_n.sum()/cora.test_mask.sum()
  37. print("Acc: ", acc)
  38.  
  39. for i in range(15):
  40. train(30)
  41. 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. bugku 矛盾

    我承认这道题给我上了一课.... 我觉得很简单的结果不是我想的那样.... 看到这道题我第一个反应是用ascii码表示1或则16进制,或则md5,或则url,base64结果都没对 ..... 去翻了 ...

  2. 大前端html基础学习02

    CSS核心属性 一.css属性和属性值的定义 属性:属性是指定选择符所具有的属性,它是css的核心. 属性值:属性值包括法定属性值及常见的数值加单位,如25px,或颜色值等. 二.CSS文本属性 1. ...

  3. 数据结构学习——BST删除特定节点

    BST删除特定节点 前言 一个平常的星期三晚上,一节通选课中,在老师放的视频和极寒空调的折磨之下,想着做点别的什么的我,打开了博客园.想起来做题下午数据结构课中老师最后在讲BST删除节点的操作,并且以 ...

  4. Django路由层之路由分发 名称空间 虚拟环境 视图层之三板斧 JsonRsponse对象 request对象获取文件 FBV与CBV CBV源码剖析 模板层

    目录 路由层之路由分发 路由层之名称空间 方式1:名称空间 方式2:别名不冲突即可 虚拟环境 pycharm创建虚拟环境 命令行形式创建虚拟环境 视图层之三板斧 HttpRsponse render ...

  5. JavaScript:操作符:逗号运算符

    逗号运算符,是极少见的运算符,我们看一下代码理解一下逗号运算符的功能: 先说结论,逗号运算符的优先级非常低,比赋值运算符=还要低: 同时,逗号隔开的几个表达式,都会各自进行计算,但是整体表达式只会返回 ...

  6. Python实验报告(第8章)

    实验8:模块 一.实验目的和要求 1.了解模块的内容: 2.掌握模块的创建和导入方式: 3.了解包结构的创建和使用. 二.实验环境 软件版本:Python 3.10 64_bit 三.实验过程 1.实 ...

  7. Python图像处理丨详解图像去雾处理方法

    摘要:本文主要讲解ACE去雾算法.暗通道先验去雾算法以及雾化生成算法. 本文分享自华为云社区<[Python图像处理] 三十.图像预处理之图像去雾详解(ACE算法和暗通道先验去雾算法)丨[拜托了 ...

  8. [常用工具] cvat安装与使用指北

    cvat是一个非常好用的标注工具,但是也是非常难以安装的标注工具,所以本文简单讲一讲如何安装与使用cvat.cvat最好在ubuntu18.04安装,windows平台安装难度很大,然后在其他平台使用 ...

  9. Windows下Mariadb中文乱码问题

    win10 在命令行使用Mariadb出现无法插入中文 并且之前正确插入的中文也无法正常显示了 ERROR 1366 (22007): Incorrect string value: '\xB1\xB ...

  10. ArcGIS工具 - 导出空数据库

    有时,需要根据已有的成果数据创建一个空的数据库模板文件,用于新的编辑或对外发布.那么,如果又快又好的创建呢?为源GIS为您编写了一个导出空数据库工具,它可以实现"一键"快速导出任意 ...