A Gentle Introduction to Graph Neural Networks
什么是图
实体之间的关系
V:顶点
E:边
U:全局信息
表示成向量
数据如何表示成图?
1.图片(244 * 244 * 3)
之前我们都是把图片表示成三个维度的tensor,现在我们可以把每个像素当作节点,相邻的节点用边连接(感觉这样GNN数据比CNN数据包含的信息多好多)
中间的是邻接矩阵,蓝色的点表示一条边(那么对于图片来说所有的邻接矩阵都长得一样呀)
2.文本
词表示成节点,上一个词和下一个词之间有一条有向边(为什么是有向边呢,因为要区别上一个词和下一个词,那么可不可以用两个有向边?类似双向RNN,然后使用两个邻接矩阵,一个记录下一个词,一个记录上一个词)
另外很多的数据都能表示成图比如分子,社交关系
三个层级的问题
图层面
例子:对图进行分类,哪个图有两个环
顶点层面
例子:社交关系中的两个人决裂之后,其他人的站队问题,有点像聚类
边的层面
例子:预测人物之间关系
图与神经网络
图上一共有四种信息:顶点,边,全局和连接性(每条边和哪两个顶点项链相连)
前面三个都可以用向量进行表示,向量对神经网络来说是很方便的。全局连结性可以用邻接矩阵来表示,n个顶点就会得到n * n的方形矩阵,矩阵对神经网络来说也是很方便的,但是有几个问题:
- 矩阵会非常大,比如处理NLP任务,每个节点是词表里的单词,对于wikipedia这个数据集,就有1200w个顶点。
- 邻接矩阵把任意行和列交换之后,代表的信息是不变的,举个例子,如果有四个顶点,那也有A44=24种邻接矩阵,标识的信息都是相同的,但这些矩阵输入到神经网络中,我们需要其输出的结果应该是一样的,即排序不会对结果产生影响。
所以为了存储高效和排除顺序的影响
顶点,边和全局还是之前说的,用向量来表示(图上这里每个顶点,边和全局都是标量表示的)
连接性使用邻接表
来表示,每条边只记录和哪两个顶点相连。
接下来的问题是给了这样的输入,如何用神经网络来处理它。
GNN的模型
A GNN is an optimizable transformation on all attributes of the graph (nodes, edges, global-context) that preserves graph symmetries (permutation invariances).
GNN是对图中所有属性(顶点,变,全局上下文)做的优化的变换,这个变化是能够保持对称信息的,也就是说对顶点进行另外的排序之后,整个的结果是不会改变的。
接下来我们讲的是“信息传递的神经网络”,一个GNN层的输入是一个图,输出也是一个图。每个GNN层会对这些属性进行向量的变换,但不会改变图的连结性。
一个最简单的例子
顶点,边,全局上下文分别对应一个MLP,输入的大小和输出的大小相同,这三个MLP构成了一个GNN层,而且经过GNN层之后,连结性没有改变,因为维持连结性的邻接表没有参与神经网络的计算。
最后一层的输出根据不同的任务自行构造。举个例子,比如想要做顶点的预测,社交网络两个人决裂之后,其他人的站队,简单的二分类问题。经过GNN层之后我们得到了顶点的向量,构造一个输出为2的全连接层,多分类就构造输出为n的全连接层,再做softmax,做回归合适一样的,单输出就行了
这里所有的顶点共享一个全连接层,这里所有的边共享一个全连接层,全局上下文一个全连接层。
简单来说,就像CNN对图片的信息进行抽取,RNN对序列信息进行抽取,GNN是对图的信息进行抽取,抽取到的信息全连接层输出。
复杂一些的情况,我们还是想对顶点做预测,但没有顶点向量的信息,这时候需要一个操作叫pooling
举个例子
没有这个顶点的向量,可以把和他连接的边的向量和全局向量拿出来相加,维度不一样的话,用全连接层映射一下就好了。你说这你也没有,啥也没有还训练个毛呢。
示意图
U是没有的,V和E是有的,做一个pooling在进输出层进行输出。这里说的都是最后一层GNN输出,也就是信息抽取之后的事情。
同样的,如果没有边的向量,只有顶点的向量,也可以使用变连接的两个顶点的向量和全局向量相加做pooling
GNN模型的示意图
上述的模型有个问题:并没有充分利用图的信息,顶点,边,全局都是各自进入GNN层的MLP,哪些节点是相邻的,这个信息并没有被抽取出来。
为了解决这个问题,提出了信息传递(Message Passing)
举个例子
在更新一个顶点的信息时,拿到他相邻的节点加和在丢入GNN层,这个过程和卷积很像,如果这就是图片的图表示,邻接的顶点是相邻的像素,那就是在做卷积,只是卷积核里面的权重是一样的。
简单来说就是在信息抽取之前就做pooling,更复杂一些的情况,可以把顶点的信息汇聚到边,再把边的信息汇聚到顶点。
一些相关技术
以上是一些最简单的图神经网络,更富啊的图,可能有一些有向边,有一些无向边
有的图片是分层的,有的顶点内部是一个子图
对图进行采样
之前说过,假设我们的GNN有很多层,且做了消息传递,那么越往后的层,对于每个顶点来说,于就算每一层里面只看它的1近邻,经过很多层的消息传递之后,它其实能看到的是一个很大的图。
而在计算梯度时,我们需要把正向传播的那些中间变量存下来,所以最后一层的顶点要看一个很大的图,对他进行计算需要把它的中间结果都存下来,这样的计算可能是很难承受的。所以可以对图进行采样:每次采样一个小图出来,在小图上做信息汇聚。几种采样方法:
- 随机采样
随机找一些顶点,然后找邻居
- 随机游走
随机找一个顶点,规定随机游走的步数,得到一个子图
- 二者结合
先随机游走,再找他们的邻居
- 广度采样
随机找一个点,对他广度遍历,找出1近邻,2近邻,3近邻
另一个加快训练效率的相关问题是怎么做batch,计算顶点的并行性,这里的问题是每个顶点的邻居个数是不一样的,如何把这些定点合并成一个规则的张量。
任何一个神经网络都是存在假设
的,比如CNN的平移不变性和局部性,RNN的时序连续性,GNN则是之前说的图的对称性:不管顶点顺序怎么变,GNN对图的作用都是不变的。
几个不同的汇聚操作
- sum
- mean
- max
但没有哪一种是特别好的,比如左图用max池化就区分不出两个图的区别,右图用max和mean都区分不出。所以还是根据实际处理的图采用合适的pooling
Graph attention network
之前也提到了我们在做pooling时,和卷积很像,只不过我们求的不是加权和,而是全都都一样。所以就可以让他自己去学一个权重,用attention,节点之间做点积,之后softmax,再乘value