图同构网络模型(GIN)
图同构网络(Graph Isomorphism Network ,GIN)模型,同时也介绍了多重集与单射的概念,以及在DGL中的具体实现。
1 了解图同构网络模型(GIN)
图同构网络(Graph Isomorphism Network ,GIN)模型源于一篇原理性论文《How Powerful are Graph Neural Networks?》(arXiv:1810.00826,2018)。该论文分析了图神经网络中一些主流做法的原理。并在此原理基础之上,推出了一个可以更好的表达图特征的结构——GIN
在DGL库中,无论是图卷积模型还是图注意力模型,都是使用递归迭代的方式,对图中的节点特征按照边的结构进行聚合来进行计算的。图同构网络(GIN)模型在此基础之上,对图神经网络提出了一个更高的合理性要求——同构性。即对同构图处理后的图特征应该相同,对非同构图处理后的图特征应该不同。
2 了解多重集与单射
在深入了解图神经网络对图的表征能力之前,需要先介绍两个概念,多重集与单射。
2.1.什么是多重集(MultiSet)
多重集(MultiSet)是一个广义的集合概念,它允许有重复的元素。即,从总的集合中划分多个含有不同元素的子集。在图神经网络中表示节点邻居的特征向量集。
2.2.什么是单射(injective)
单射是指每一个不同的输入只对应一个不同的输出。如果两个经过单射函数的输出相等,则它们的输入必定相等。
2.3.图神经网络的评判标准
在图神经网络工作时,会对图中的节点特征按照边的结构进行聚合。如果将节点邻居的特征向量集可以看作是一个MultiSet,则整个图神经网络可以理解为是MultiSet的聚合函数。
好的图神经网络应当具有单射函数的特性。即图神经网络必须能够将不同的MultiSet聚合到不同的表示中。
3 GIN模型的原理与实现
图同构网络(GIN)模型是从图神经网络的单射函数特性设计出来的。
3.1. GIN模型的原理
GIN模型在图节点邻居特征的每一跳聚合操作之后,又与自身的原始特征混合起来。并在最后使用可以拟合任意规则的全连接网络进行处理,使其具有单射特性。
在特征混合的过程中,引入了一个可学习参数对自身特征进行调节,并将调节后的特征与聚合后的邻居特征进行相加。
3.2. GIN模型的实现
在DGL库中, GIN模型是通过GINConv类来实现的。该类将GIN模型中的全连接网络换成了参数调用形式,在使用时可以向该参数传入任意神经网络,具有更加灵活的扩展性。
具体代码在DGL安装库路径下的\nn\pytorch\conv\ginconv.py中。例如作者的本机路径为:
D:\ProgramData\Anaconda3\envs\pt15\Lib\site-packages\dgl\nn\pytorch\conv\ginconv.py
GINConv类的具体实现如下:
代码文件:ginconv.py(片段)
1class GINConv(nn.Module): #定义GINConv类
2 def __init__(self, apply_func, #自定义模型参数
3 aggregator_type, #聚合类型
4 init_eps=0, #可学习变量的初始值
5 learn_eps=False): #是否使用可学习变量
6 super(GINConv, self).__init__()
7 self.apply_func = apply_func
8 if aggregator_type == 'sum':
9 self._reducer = fn.sum
10 elif aggregator_type == 'max':
11 self._reducer = fn.max
12 elif aggregator_type == 'mean':
13 self._reducer = fn.mean
14 else:
15 raise KeyError(
16 'Aggregator type {} not recognized.'.format(aggregator_type))
17
18 if learn_eps: #是否使用可学习变量
19 self.eps = th.nn.Parameter(th.FloatTensor([init_eps]))
20 else:
21 self.register_buffer('eps', th.FloatTensor([init_eps]))
22
23 def forward(self, graph, feat): #正向传播
24 graph = graph.local_var()
25 graph.ndata['h'] = feat
26 #聚合邻居节点特征
27 graph.update_all(fn.copy_u('h', 'm'), self._reducer('m', 'neigh'))
28 rst = (1 + self.eps) * feat + graph.ndata['neigh']#将自身特征混合
29 if self.apply_func is not None: #使用神经网络进行单射拟合处理
30 rst = self.apply_func(rst)
31 return rst
代码第28行在聚合邻居节点特征之后,又使用了自身特征进行混合。这种操作是GIN模型有别于其它模型的主要步骤。由于模型中的图节点带有自身特征的加和操作,这使得在聚合邻居节点特征步骤中,聚合函数有更多的选择(可以使用sum、max或mean)。
原文链接:https://www.vlambda.com/wz_7iqHAjoF8Uk.html
论文: How Powerful are Graph Neural Networks?
- 论文:How Powerful are Graph Neural Networks?
- 作者:来自于斯坦福的Keyulu Xu,Weihua Hu,Jure Leskovec等人
- 来源:ICLR 2019的Oral文章
- 论文链接:https://arxiv.org/pdf/1810.00826.pdf
- github链接:https://github.com/weihua916/powerful-gnns
介绍
一般情况下一个节点的表式通过聚合它k跳之内的邻近节点计算,而全图的表示则通过对所有节点的池化计算。
近年来新型GNN的设计主要基于经验直觉、启发式和实验试错法,而对神经网络的性质和局限性的理论较少。文中提出理论框架来分析GNN的能力,这里主要是评价模型是否能够区分网络结构。
文中使用了WL-test方法,即图同构测试,它是一个区分网络结构的强效方法,也是通过迭代聚合邻居的方法来更新节点,它的强大在于使用了injective(见后)聚合更新方法。而这里要评测GNN是否能达到类似WL-test的效果。
文中还使用了多合集multiset的概念,指可能包含重复元素的集合。
论文主要贡献如下:
- 展示了GNN模型可达到与WL-test类似的图结构区分效果
- 设计了聚合函数和Readout函数,使GNN能达到更好的区分效果
- 发现GCN及GraphSAGE无法很好表达图结构,而GNN可以
- 开发了简单的网络结构GIN(图同构网络),它的区分和表示能力与WL-test类似。
图表征
论文主要关注两种任务:一种是对图中节点的分类,通过学习节点表示,以预测节点的类别;另一种是根据图结构分类,通过学习对整个图的表示,预测整图的类别。
这里涉及节点的表示和整图的表示。各节点往往通过它的邻居节点聚合计算,通过k轮迭代后,节点的表示隐式的包含了图的结构信息。GNN第k层计算方法如下:
其中a表示聚合节点v邻近特征的方法,h是特征向量。简单说就是先聚合节点v邻居节点上一层的表示,再与节点v自身上一层的表示相结合。
算法重点在于AGGREGATE和COMBINE的具体算法。比如AGGREGATE常使用乘参数再做池化的方法,而COMBINE常使用串联方法。对于整图分类任务,使用READOUT函数来聚合节点特征最后一次迭代的结果,生成向量来表征整个图,聚合方法也是可简可繁。
WL-test
WL-test用于比较两图的拓扑结构是否相同。
原理如图所示:(a)对于图G与G’,其中每个节点属于某种元素(标签)一共五种元素;(b)利用其邻近节点的标签组合表示当前节点;©生成新标签;(d)用新标签表示节点;依照此逻辑不断迭代。最终生成右图中的特征向量用于表征图G和G’。颜色表示标签,数值表示该标签在图中的出现次数。当两图表征不一致时,则认为两图异构。
理论框架
如图-1所示,有一个图(左图),如果想表征其中的蓝色节点,且只考虑两跳;计算方法如中图所示(子树); 通过迭代,变成了右图所示,每个节点只考虑其邻居,计算邻居时,再考虑邻居的邻居。
算法需要满足injective,injective可译为内射,即可把不同的元素映射成不同输出,在图结构中,不同的邻居结构需要生成不同的节点表征,而max,mean池化显然都不是injective的(后详述)。
建立强大的聚合图神经网络
任何基于的GNN最多与WL-test一样强大,我们要让GNN尽量逼近它,证明请见附录。
GNN公式如下:
其中f用于处理邻居节点,φ 用于内射。另外,readout也需要具有内射的性质。除了区分不同的图之外,GNN相对于WL-test还有一个优势是它能将相似的图结构映射到相似的嵌入,并捕获图结构之间的依赖关系。而WL-test只是one-hot编码。
GIN网络
GIN网络,即图同构网络。为了在建模时实现内射,使用加和作为聚合函数,理论上多层感知机可以模拟函数的组合,用以下方法更新GIN的节点表示:
GIN的整图表征
整图分类任务,需要使用readout根据节点嵌入计算整图嵌入。计算方法如下:
用串联的方法连接了节点所有迭代步的表示,使用所有迭代是因为,随着迭代次数增加,节点能实现更加全局和精炼的表示,而早期迭代的结果则更容易泛化。
dgl库里的GIN