图度学习入门教程(十一)——图同构网络模型(GIN)深
本教程是一个系列免费教程,如果喜欢请帮忙转发。
主要是基于图深度学习的入门内容。讲述最基本的基础知识,其中包括深度学习、数学、图神经网络等相关内容。该教程由代码医生工作室出版的全部书籍混编节选而成。偏重完整的知识体系和学习指南。
本教程主要针对的人群:
已经掌握TensorFlow基础应用,并想系统学习的学者。
PyTorch学习者
正在从TensorFlow转型到PyTroch的学习者
已经掌握Python,并开始学习人工智能的学者。
本篇主要介绍图同构网络(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)。
提示:
代码第28行的特征混合过程是至关重要的。它为节点特征中默认加入了一个自身的特征信息。如果去掉了特征混合过程,并且在聚合特征中使用了max或mean函数,则无法捕获到图的不同结构。因为在max或mean函数计算时,会损失掉单个节点特征。
推荐阅读