图卷积网络(GCN)

本文主要分为两部分,第一部分介绍什么是GCN,第二部分将进行详细的数学推导。

一、什么是GCN

1、GCN 概述

本文讲的GCN 来源于论文:SEMI-SUPERVISED CLASSIFICATION WITH GRAPH CONVOLUTIONAL NETWORKS,这是在GCN领域最经典的论文之一。

我们可以根据这个GCN的图看到,一个拥有C个input channel的graph作为输入,经过中间的hidden layers,得到F个 output channel的输出。(注意本文讲的图都特指无向无权重的图。)

图卷积网络主要可以由两个级别的作用变换组成:

(1)graph level

例如说通过引入一些形式的pooling 操作 (see, e.g. Duvenaud et al., NIPS 2015),然后改变图的结构。但是本次讲过GCN并没有进行这个级别的操作。所以看到上图我们的网络结构的输出和输出的graph的结构是一样的。

(2)node level

通常说node level的作用是不改变graph的结构的,仅通过对graph的特征/(features/signals)X作为输入:一个N\times D的矩阵( N : 输入图的nodes的个数, D 输入的特征维度) ,得到输出Z:一个N\times F的矩阵(F输出的特征维度)。
a) 一个特征描述(feature description) x_{i}: 指的是每个节点 i的特征表示

b) 每一个graph 的结构都可以通过邻接矩阵A 表示(或者其他根据它推导的矩阵)

我们可以很容易的根据一个邻接矩阵重构出一个graph。 例如下图:G=(V,E),其中 V代表节点,E代表边

我们通过构造\left | V \right |\times \left | V \right |的矩阵可以得到邻接矩阵A , 其中A_{ij}=1如果节点i和节点j 相连,否则A_{ij}=0 , 我们根据graph可以得到A, 同理通过A也可以得到graph 的结构。

所以网络中间的每一个隐藏层可以写成以下的非线性函数:

H^{(l+1)}=f(H^{(l)},A)

其中输入层H(0)=X, 输出层H(L)=Z,L是层数。 不同的GCN模型,采用不同f(\cdot ,\cdot )函数。

2、模型定义

论文中采用的函数如下:

f(H^{(l)},A)=\sigma (\hat{D}^{-\frac{1}{2}}\hat{A}\hat{D}^{-\frac{1}{2}}H^{(l)}W^{(l)})

刚开始看的时候,都会被吓到!这个函数未免也太抽象了。但是我们先了解一下它在起的作用,然后再从头一步一步引出这个公式,以及为什么它起到了这些作用。

首先物理上它起的作用是,每一个节点下一层的信息是由前一层本身的信息以及相邻的节点的信息加权加和得到,然后再经过线性变换W以及非线性变换 \sigma() 。


我们一步一步分解,我们要定义一个简单的 f(H^{(l)},A)函数,作为基础的网络层。

我们可以很容易的采用最简单的层级传导( layer-wise propagation )规则

f(H^{(l)},A)=\sigma (AH^{(l)}W^{(l)})

我们直接将AH做矩阵相乘,然后再通过一个权重矩阵 W^{(l)} 做线性变换,之后再经过非线性激活函数 \sigma(\cdot ) , 比如说 ReLU,最后得到下一层的输入H^{(l+1)} 。

我们需要特别注意的是AH做矩阵相乘,这代表了什么意思呢?

我们先看看,对于下图。

假设每个节点x_{i}=[i,i,i,i], 那么在经过矩阵相乘之后,它会变成什么呢。

输入层的 x_{1}=[1,1,1,1] , 根据矩阵的运算公式我们可以很容易地得到下一层的该节点的表示x_{1}^{​{}'}=[7,7,7,7]  , 也很容易发现x_{1}^{​{}'}=x_{2}+x_{5} ,而 x_{2},x_{5}就是节点1的相邻节点。具体计算结果可以参考下面的代码。

A = torch.tensor([[0,1,0,0,1,0],[1,0,1,0,1,0],[0,1,0,1,0,0],[0,0,1,0,1,1],[1,1,0,1,0,0],[0,0,0,1,0,0]
])H_0 = torch.tensor([[1,1,1,1],[2,2,2,2],[3,3,3,3],[4,4,4,4],[5,5,5,5],[6,6,6,6]
])A.matmul(H_0)
>>>tensor([[ 7,  7,  7,  7],[ 9,  9,  9,  9],[ 6,  6,  6,  6],[14, 14, 14, 14],[ 7,  7,  7,  7],[ 4,  4,  4,  4]])

所以我们直到AH就是把通过邻接矩阵快速的方式,快速将相邻的节点的信息相加得到自己下一层的输入。

但是这就完美了吗?

  • 问题一:我们虽然获得了周围节点的信息了,但是自己本身的信息却没了(除非自己有一条边指向自己)。

我们采用的解决方案是,对每个节点手动增加一条self-loop 到每一个节点,即 \hat{A}=A+I , 其中I 是单位矩阵identity matrix。

  • 问题二:从上面的结果也可以看出,在经过一次的AH 矩阵变换后,得到的输出会变大,即特征向量 X的scale会改变,在经过多层的变化之后,将和输入的scale差距越来越大。

所以我们是否可以将邻接矩阵A做归一化使得最后的每一行的加和为1,使得 AH获得的是weighted sum。

我们可以将A的每一行除以行的和,这就可以得到normalized的A 。而其中每一行的和,就是每个节点的度degree。用矩阵表示则为:A=D^{-1}A , 对于A_{ij}=\frac{A_{ij}}{d_{i}}

我们还是按照上面图的graph来看。

  import torchA = torch.tensor([[0,1,0,0,1,0],[1,0,1,0,1,0],[0,1,0,1,0,0],[0,0,1,0,1,1],[1,1,0,1,0,0],[0,0,0,1,0,0]], dtype=torch.float32)D = torch.tensor([[2,0,0,0,0,0],[0,3,0,0,0,0],[0,0,2,0,0,0],[0,0,0,3,0,0],[0,0,0,0,3,0],[0,0,0,0,0,1],], dtype=torch.float32)hat_A = D.inverse().matmul(A)>>>hat_Atensor([[0.0000, 0.5000, 0.0000, 0.0000, 0.5000, 0.0000],[0.3333, 0.0000, 0.3333, 0.0000, 0.3333, 0.0000],[0.0000, 0.5000, 0.0000, 0.5000, 0.0000, 0.0000],[0.0000, 0.0000, 0.3333, 0.0000, 0.3333, 0.3333],[0.3333, 0.3333, 0.0000, 0.3333, 0.0000, 0.0000],[0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000]])

但是在实际运用中我们采用的是对称的normalization: A={D}^{-\frac{1}{2}}{A}{D}^{-\frac{1}{2}}

对于 A_{ij}=\frac{A_{ij}}{\sqrt{d_{i}\sqrt{d_{j}}}}

这跟Laplacian Matrix 有关,下一部分会介绍。 我们可以发现

A_{0,1}=\frac{A_{0,1}}{\sqrt{d_{0}\sqrt{d_{1}}}}=\frac{1}{\sqrt{2\sqrt{}3}}=0.4082

  D_minus_sqrt = D.inverse().sqrt()D_minus_sqrt.matmul(A).matmul(D_minus_sqrt)>>>tensor([[0.0000, 0.4082, 0.0000, 0.0000, 0.4082, 0.0000],[0.4082, 0.0000, 0.4082, 0.0000, 0.3333, 0.0000],[0.0000, 0.4082, 0.0000, 0.4082, 0.0000, 0.0000],[0.0000, 0.0000, 0.4082, 0.0000, 0.3333, 0.5774],[0.4082, 0.3333, 0.0000, 0.3333, 0.0000, 0.0000],[0.0000, 0.0000, 0.0000, 0.5774, 0.0000, 0.0000]])

把这两个tricks结合起来,我们可以得到

f(H^{(l)},A)=\sigma (\hat{D}^{-\frac{1}{2}}\hat{A}\hat{D}^{-\frac{1}{2}}H^{(l)}W^{(l)})

其中 \hat{A}=A+I , \hat{D} 是\hat{A}的degree matrix。 而 \hat{D}^{-\frac{1}{2}}\hat{A}\hat{D}^{-\frac{1}{2}}是对A做了一个对称的归一化。

二、数学推导

1、Graph Laplacian

首先我们表示一个graph的方式有很多,我们可以用邻接矩阵,也可以用Incidence matrix。 这个matrix 中,每一行表示一个边,每一列表示一个节点。每一行中,边的节点的起点用记为1,边的终点记为-1。 我们将这个metrix 记为 C, 具体如下图。

那么 graph Laplacian 定义为: L(G)=C^{T}C

C = torch.tensor([[1,-1,0,0],[1,0,-1,0],[1,0,0,-1],[0,-1,1,0],[0,0,1,-1],[0,-1,0,1],
])
C.T.matmul(C)
>>>tensor([[ 3, -1, -1, -1],[-1,  3, -1, -1],[-1, -1,  3, -1],[-1, -1, -1,  3]])

我们可以发现,对角线的值 , 其中如果 C_{j,i}=0 , 则其积 = 0,如果 C_{j,i}=1 或者C_{j,i}=-1 , 则其积 = 1。所以我们可以知道对角线代表的是每个节点的度(Degree)

对于非对角线的值  , 我们可以看出来,如果节点 i 和j没有相连,那么 C_{k,i}C_{k,j}=0否则 C_{k,i}C_{k,j}=-1 , 于是知道非对角线的值就是邻接矩阵的负值。

所以我们可以推导得到

L(G)=C^{T}C=D-A

如下图(注意这边W表示的是邻接矩阵)

总结来说:

具体计算参考下面的代码

C = torch.tensor([[-1,1,0,0,0,0], # 1-2[-1,0,0,0,1,0], # 1-5[0,-1,1,0,0,0], # 2-3[0,-1,0,0,1,0], # 2-5[0,0,-1,1,0,0], # 3-4[0,0,0,-1,1,0], # 4-5[0,0,0,-1,0,1], # 5-6
])
C.T.matmul(C)
>>>
tensor([[ 2, -1,  0,  0, -1,  0],[-1,  3, -1,  0, -1,  0],[ 0, -1,  2, -1,  0,  0],[ 0,  0, -1,  3, -1, -1],[-1, -1,  0, -1,  3,  0],[ 0,  0,  0, -1,  0,  1]])

我们需要知道 laplacian L(G) 的性质:

  •  L(G)是对称矩阵
  • L(G) 有实数的,非负的特征值(eigen values)
  • L(G) 有实数的,正交的特征矩阵(eigen vectors), i.e. U^{T}U=I

对此,我们假设 L(G) 的特征值为 \Lambda特征向量为 U :

LU=U\Lambda

LU^{T}U=U\Lambda U^{T}

L=U\Lambda U^{T}

  • 对于特征值我们有 \lambda _{n-1}\geqslant \lambda _{n-2}\geqslant\cdot \cdot \cdot \geqslant \lambda _{1}\geqslant \lambda _{0}\geqslant 0
  • 对称归一化的Laplacian (Symmetric normalized Laplacian)

其元素值,对角线为1,非对角线为 -\frac{1}{\sqrt{dev(v_{i})\sqrt{dev(v_{j})}}}


我们要知道两个函数的卷积可以由以下公式得到,具体参考

其中 F 代表傅立叶变换

而Graph Fourier变换对应的就是以下:

其中Graph Fourier 逆变换对应的就是以下:

其中U是laplacian L的特征矩阵 具体的对应关系:


我们知道普通的卷积公式:

那么相应的图卷积的公式为:

作为图的特征x的filter,我们希望它的作用域跟CNN一样,都是在中心节点附近的区域,所以我们定义 g是一个laplacian的函数 g(L) , 那么作用一次相当于传播一次周围邻居节点的信息。 

又因为 U^{T}L=U^{T}U\Lambda U^{T} =\Lambda U^{T} , 所以我们可以把 U^{T}g 看成是laplacian 特征值的函数 g_{\theta }(\Lambda )=diag(\theta ) , 参数为 \theta 。

所以图卷积在Fourier域上可以表示为:

我们知道 g_{\theta }(\Lambda )需要先计算laplacian matrix L的特征值,这涉及到大量的矩阵运算,所以文章借用了Chebyshev polynomials进行近似计算:

  • 其中 \tilde{\Lambda }=\frac{2}{\lambda _{max}}\Lambda -I_{N} , K 代表的是 K^{th}次Laplacian,即它取决于中心节点的最近的 K^{th} order 的邻居节点(邻居节点和中心节点的距离最大为K)。
  • T_{k}(x)=2xT_{k-1}(x)-T_{k-2}(x) , 其中T_{0}=1以及 T_{1}=x 。

我们回到最初的图卷积计算:

其中 \tilde{L }=\frac{2}{\lambda _{max}}L -I_{N}

我们知道论文中采用的传播邻居层数为1, 所以取 k=1 , 并且我们假设 \lambda _{max} = 2 , 可以得到:

实际运用中,为了防止overfitting以及减少操作,我们令 
\theta =\theta _{0}^{'}=-\theta _{1}^{'}

 得到: 

我们令 \hat{A}=A+I_{N} , 以及 

得到:

再加上激活函数\sigma, 我们获得了

其中H对应输入x , W对应参数\theta。 

三、ref

  • https://en.wikipedia.org/wiki/Laplacian_matrix
  • T. N. Kipf, M. Welling, Semi-Supervised Classification with Graph Convolutional Networks(ICLR 2017) [Link, PDF (arXiv), code, blog]
  • https://math.stackexchange.com/questions/1113467/why-laplacian-matrix-need-normalization-and-how-come-the-sqrt-of-degree-matrix

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/642886.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TS 学习笔录 (一)

TS学习笔录 1、TS 数据类型有哪些?2、元组是什么?3、union(联合类型)& Literal(字面量类型)?4、any 和 unknown 的区别?5、Object 对象类型?6、type 、interface 、 class 之间…

1.23 力扣图论

841. 钥匙和房间 有 n 个房间,房间按从 0 到 n - 1 编号。最初,除 0 号房间外的其余所有房间都被锁住。你的目标是进入所有的房间。然而,你不能在没有获得钥匙的时候进入锁住的房间。 当你进入一个房间,你可能会在里面找到一套不…

无刷电机学习-方波电调 电路篇

想要彻底的理解无刷电机的驱动,那必然少不了学习他的驱动电路和程序。这里用开源的AM32无刷电调(方波驱动)来作为学习无刷电机笔记。 https://github.com/AlkaMotors附上作者github地址 AM32_Hardware: 基于AT32MCU的AM32PCB另一位大佬开源…

niushop靶场漏洞查找-文件上传漏洞等(超详细)

实战漏洞-niushop 一.端口扫描 http://www.xxx.com/index.php?s/admin/login 这里查询到后面的url有且仅有一个,目测估计是后台 访问url 发现确实是后台 二、找漏洞 Sql注入漏洞1: 点击进去 修改id www.xxx.com/index.php?s/goods/goodslist&…

网络要素服务(WFS)详解

文章目录 1. 概述2. GetCapabilities3. DescribeFeatureType4. GetFeature4.1 Get访问方式4.2 Post访问方式 5. Transaction5.1 Insert5.2 Replace5.3 Update5.4 Delete 6 注意事项 1. 概述 前置文章: 地图服务器GeoServer的安装与配置 GeoServer发布地图服务&#…

C语言爬虫采集图书网站百万数据

最近需要查阅一些资料,只给到相关项目名称以及关键词,想通过图书文库找到对应书籍,那么怎么才能在百万数据库中找到自己需要的文献呢? 今天我依然用C语言写个爬虫程序,从百万数据库中查找到适合的文章,能节…

【GitHub项目推荐--Go语言学习指南】【转载】

Go语言学习指南是一份涵盖大部分 Golang 程序员所需要掌握的核心知识,拥有 Go语言教程、Go开源书籍、Go语言入门教程、Go语言学习路线。零基础学习 Go语言、Go编程,首选 GoGuide。 地址:https://github.com/coderit666/GoGuide

剑指offer面试题8 旋转数组的最小数字

考察点 算法二分搜索知识点 二分搜索算法是针对排序的数组,先找到中间元素,如果待查找元素比中间元素大,说明待查 找元素肯定不在左边那片区域内,如果待查找元素比中间元素小,说明待查找元素肯定不在右 边那片区域内…

方法(java)

方法(method)是程序中最小的执行单元 实际开发中,重复的代码、具有独立功能的代码可以抽取到方法中 实际开发中,方法的好处: 1.可以提高代码的复用性 2.可以提高代码的可维护性 方法定义:把一些代码打…

【设计模式】美团三面:你连装饰器都举不出例子?

什么是装饰器模式? 装饰器模式,这个设计模式其实和它的名字一样,非常容易理解。 想象一下,每天出门的时候,我们都会思考今天穿什么。睡**衣、睡裤加拖鞋,还是西装、领带加皮鞋?又或者说是&…

【开发随想】如何快速入手一个Linux开源项目

🐚作者简介:花神庙码农(专注于Linux、WLAN、TCP/IP、Python等技术方向)🐳博客主页:花神庙码农 ,地址:https://blog.csdn.net/qxhgd🌐系列专栏:开发随想&#…

记录 js 过滤到tree上面的多余的数据

代码如下(示例): filterTree(arr, ids,firsttrue) {if(first){//首次传入深度克隆数据防止修改源数据arrJSON.parse(JSON.stringify(arr))}let emptyArr [];for (let item of arr) {if (ids.includes(item.id)) {if (item.children &&am…

【Foxmail】客户端发送邮件错误:SSL Recv :服务器断开连接, errorCode: 6

Foxmail客户端发送邮件提示:SSL Recv :服务器断开连接, errorCode: 6 错误代码 处理方式: 去邮箱生成新的16位授权码,输入到 密码框 内即可。 注:一旦开通授权码,在Foxmail验证时 密码框 里输入的就是 授权码

shell脚本概念构成及脚本变量详解

目录 一、前言 1、程序编程风格 2、编程语言 3、编程的三种处理逻辑 二、shell脚本 1、shell脚本基础 1.1 什么是shell 1.1.1 shell的概念 1.1.2 linux中常见的shell类型及信息 1.1.3 shell脚本的功能 1.2 shell脚本及构成 1.3 shell脚本执行方式 1.4 脚本错误调试…

spring和springboot的区别

在当今的软件开发领域,Spring和Spring Boot无疑是Java开发者最常用的框架之一。尽管它们都源于Spring项目,但它们在设计和使用上有很大的不同。本文将深入探讨Spring和Spring Boot之间的主要区别,以及为什么有时候选择其中一个而不是另一个是…

STL标准库(二)序列容器之array

容器 容器的本质是类模板,分为序列容器和关联容器 序列容器 array 固定数组 应用包含arrry库 vector 动态数组 应用包含 vector库 deque 双端队列 list 双向链表 forward_list 单向链表 stack 栈 queue 队列 prority 优先队列 array应用 int main() { …

现代密码学基础(2)

目录 一. 介绍 二. 举例:移位密码 (1)密文概率 (2)明文概率 三. 举例:多字母的移位密码 四. 完美安全 五. 举例:双子母的移位密码 六. 从密文角度看完美安全 七. 完美保密性质 一. 介绍…

NVIDIA 再现逆天刀法,千元级 RTX 新卡曝光

这年头,价格 1 字开头入门甜品显卡几乎真就成 N、A 两家弃子了。 以 NVIDIA RTX 4060 与 AMD RX 7600 为例,这两块显卡同为两家新品中最低端型号,其价格直接来到 2K 左右起步。 要知道目前很多普通用户选购一台日常办公、游戏电脑主机&#…

vue(vue2)使用svg格式图标

先安装插件 配置svg文件夹,新建icons文件,svg文件夹放svg后缀文件 index.js文件中的配置 import Vue from "vue" import svgIcon from "/common/iconSvg/index.vue"Vue.component(svg-icon,svgIcon) //挂载全局组件//下面…

Python with Office 054 - Work with Word - 7-9 插入图像 (3)

近日详细学习了寒冰老师的很好的书《让Python遇上Office》,总结了系列视频。 这个是其中的一集:如何在Word中插入图像,我会陆续分享其他的视频并加上相应说明 https://www.ixigua.com/7319498175104942643?logTage9d15418663166a05d10