图卷积网络(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 torch

  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]
  ], 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_A
  tensor([[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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

allure生成报告展示在vue-admin前端展示

生成测试数据 本栗子测试数据根据pytest测试用例生成 首先设置pytest.ini配置信息 a l l u r e d i r alluredir alluredir代表生产allure报告数据地址 t e s t c a s e d i r test_casedir testc​asedir代表测试用例路径 [pytest] addopts -vs --alluredir $alluredir$…

【C++】c++入门,认识c++版本的Hello world!

Hello,everybody!在c语言,数据结构初阶学完之后,咱们就要开始c的学习了。关于c的语法,有很多是为了弥补c语言的不足。在咱们学习c的过程中,随着你对c语法掌握的越来越熟练。我相信你会逐渐爱上c。那我们直接进入正题。 1.c兼容c …

【taro react】 ---- 自动化【根据运行命令直接编译对应的是测试环境或正式环境】

1. 场景 开发和发布程序中遇到最常见的问题,需要一个环境配置文件,然后在启动或者编译前,需要开发者去修改对应的环境变量来控制启动或者编译的环境是测试环境还是正式环境。同时如果是需要维护小程序的 Jenkins 自动上传,就会更加的麻烦,上传的小程序越多,我们需要维护…

STM32单片机学习5--STM32中断

文章目录 一、前言二、NVIC中断控制器2.1、NVIC结构体成员2.2、抢占优先级和响应优先级2.3、NVIC的优先级组 三、EXTI外部中断四、中断实战4.1、确定连线4.2、配置中断控制端口4.3、配置中断端口4.4、配置中断服务函数4.5、主函数调用 一、前言 单片机无系统执行逻辑&#xff…

Unity之Cinemachine教程

前言 Cinemachine是Unity引擎的一个高级相机系统,旨在简化和改善游戏中的相机管理。Cinemachine提供了一组强大而灵活的工具,可用于创建令人印象深刻的视觉效果,使开发人员能够更轻松地掌控游戏中的摄像机行为。 主要功能和特性包括&#x…

Linux代码行数统计工具cloc

这里推荐个Perl语言开发的开源代码统计工具cloc,全称为Count Lines of Code。支持多平台使用、多编程语言识别。 在Ubuntu下安装cloc: sudo apt-get install cloc运行cloc可以cd到指定目录运行: cloc . # 或者例如统计src目录下的代码行数 …

微信小程序跳转第三方网站链接

很简单&#xff0c;先定义一个跳转外网的页面&#xff0c;利用 web-view 标签&#xff0c;通过src设置你要跳转的外网地址 <web-view src"https://www.baidu.com"></web-view>然后在你的跳转按钮写跳转函数即可 wx.navigateTo({url: /pages/webView/inde…

微信小程序(十一)表单组件(进阶)

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a;&#xff08;涉及内容较多&#xff0c;建议细看源码&#xff09; 1.radio-group的使用与数据处理 2.checkbox-group的使用与数据处理 3.picker的使用与数据同步处理(此处示范了地域与日期) 源码&#xff1a; form…

使用API有效率地管理Dynadot域名,使用API进行域名注册

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…

国标GB28181协议EasyCVR启动失败报错“Local Machine Check Error”的解决方法

国标GB28181安防监控系统EasyCVR平台采用了开放式的网络结构&#xff0c;可支持4G、5G、WiFi、有线等方式进行视频的接入与传输、处理和分发。安防视频监控平台EasyCVR还能支持GIS电子地图模式&#xff0c;基于监控摄像头的经纬度地理位置信息&#xff0c;将场景中的整体安防布…

如何设计性能测试用例!一文1000字详解(建议收藏)

性能测试是确保软件应用在各种负载和条件下都能保持良好性能的关键活动&#xff0c;涉及到系统的响应时间&#xff0c;还包括吞吐量、资源利用率、可靠性和系统的可伸缩性。 性能测试用例设计需要对业务需求和系统行为有深刻理解&#xff0c;设计过程涉及确定测试目标、选择相…

基于无线脉冲,超宽带技术的高精度人员定位系统源码,可实现人员、物资的精准定位

随着工业4.0深入推进信息化&#xff0c;智能化&#xff0c;数据化管控成为企业不可或缺的竞争力&#xff0c;其中人员物资等实时位置信息成为变革关键&#xff0c;因此&#xff0c;uwb超宽带高精度定位系统应运而生&#xff0c;高精度的位置数据作为智能工厂数据流的重要组成部…

【EI会议征稿】第三届光电信息与功能材料国际学术会议(OIFM 2024)

第三届光电信息与功能材料国际学术会议&#xff08;OIFM 2024&#xff09; The 3rd International Conference on Optoelectronic Information and Functional Materials 第三届光电信息与功能材料国际学术会议&#xff08;OIFM 2024&#xff09;将于2024年4月5-7日在武汉召开…

编辑图片加文字的软件?分享4款!

在数字时代&#xff0c;图片和文字的结合已经成为信息传递的重要方式。为了满足广大自媒体人和内容创作者的需求&#xff0c;本文将为您推荐几款编辑图片加文字的软件&#xff0c;帮助您轻松实现创意表达。 魔法抠图大师 作为一款专业的图片编辑软件&#xff0c;还提供了多种编…

MySQL 8.3 发布, 它带来哪些新变化?

1月16号 MySQL 官方发布 8.3 创新版 和 8.0.36 长期支持版本 (该版本 没有新增功能&#xff0c;更多是修复bug )&#xff0c;本文基于 官方文档 说一下 8.3 版本带来的变化。 一 增加的特性 1.1 GTID_NEXT 支持增加 TAG 选项。 之前的版本中 GTID_NEXTUUID:number &#xff…

GPSR路由算法的MATLAB实现

GPSR基于节点地理位置路由信息&#xff0c;采用贪婪策略和右手准则的结合在邻居节点中选择下一跳节点进行数据转发。节点在进行路由选择时&#xff0c;只需知道自己、邻居和目标节点的地理位置信息&#xff0c;无需维护全局网络的链路状态&#xff0c;这在很大程度上降低了网络…

【JavaEE进阶】 MyBatis使用注解实现增删改查

文章目录 &#x1f343;前言&#x1f334;传递参数&#x1f38b;增(Insert)&#x1f6a9;返回主键 &#x1f384;删(Delete)&#x1f332;改(Update)&#x1f333;查(Select)&#x1f6a9;起别名&#x1f6a9;结果映射&#x1f6a9;开启驼峰命名(推荐使用) ⭕总结 &#x1f343…

电源模块测试项目:输入低压点循环测试及测试方法

输入低压点循环测试是什么? 电源输入低压点循环测试是检测电源在低压条件下的性能和稳定性&#xff0c;它是一次电源模块的输入欠压点保护的设置回差测试。当输入电压较低&#xff0c;接近一次电源模块欠压点关断时&#xff0c;带载时欠压; 断后由于电源内阻原因&#xff0c;负…

初识Docker(架构、安装Docker)

一、什么是Docker Docker 是一个开源的应用容器引擎&#xff0c;它允许开发者将应用程序及其依赖打包到一个轻量级、可移植的容器中。这些容器可以在不同的计算平台上运行&#xff0c;如Linux和Windows&#xff0c;并且可以实现虚拟化。Docker 的设计目标是提供一种快速且轻量…

智能机器人与旋量代数(12)

Chapt 4. 旋量代数在机器人学中的应用 4.1 串联机器人正运动学的指数积(PoE, Product of Exponetial)公式 4.1.1 回顾&#xff1a;机器人正运动学的Denavit-Hartenberg (D-H)参数公式 D-H 建模法: D-H 建模方法是由 Denavit 和 Hartenberg (ASME, 1955) 提出的一种建模方法&…