一、图的可视化(networkx工具使用)
首先先随便生成一个图,初步了解一下networkx的使用
生成的图的效果如下图所示:
下面举几个关于networkx包的几个简单的例子:
(1)
G = nx.cubical_graph()
plt.subplot(121)
nx.draw(G)
plt.subplot(122)
nx.draw(G, pos=nx.circular_layout(G), node_color='r', edge_color='b')
plt.show()
#nx.draw(G, pos=None, ax=None, **kwds)
#G表示要绘制的网络图,pos是一个可选项,默认为None,其可用于建立布局,不同的layout有不同的美化效果
#circular_layout:将节点位置调整为圆形
#random_layout:将节点随机的放在一个单位正方形内
#shell_layout:将节点放于多个同心圆内
#spring_layout:使用FR算法来定位节点
#spectral_layout:使用图拉普拉斯的特征向量定位节点
#nodecolor用以控制节点颜色,edge_color用以控制边的颜色
生成的效果图为:
(2)
G = nx.Graph()
G.add_edge('A', 'B', weight=0.5)
G.add_edge('B', 'C', weight=5)
print(G.adj)
nx.draw(G, with_labels=True)
plt.show()
效果图:
(3)获取节点的邻居以及边的属性
G=nx.DiGraph()
G.add_edge(1,2,weight=5,color='red',size=10)
print("结点1得邻居:",G[1])
print("边得全部信息:",G[1][2])
print("边得尺寸:",G[1][2]["size"])
print("边得颜色:",G[1][2]["color"])
nx.draw(G,with_labels=True)
plt.show()
程序的输出为:
二、消息范式
基于消息传递范式的生成节点表征的过程:
1.黄色方框展示了邻居节点信息传递到中心节点的过程:B节点的邻接节点(A,C)的信息经过变换后聚合到B节点,然后B节点信息与邻居节点聚合信息一起经过变换得到B节点的新的节点信息。
2.邻居节点信息传递到中心节点的过程会进行多次。图中蓝色框所示,A节点的邻接节点(B,C,D)已经更新过一次的节点信息经过变换、聚合、再变换得到了A节点第二次更新的节点信息。
三、关于MessagePassing基类
PyG提供了MessagePassing基类,它封装了“消息传递”的运行流程。
MessagePassing(aggr=“add”, flow=“source_to_target”, node_dim=-2)(对象初始化方法):
- aggr:定义要使用的聚合方案(“add”、“mean”、“max”);
- flow:定义消息传递的流向(“source_to_target"或"target_to_source”);
- node_dim:定义沿着哪个轴线传播
四、MessagePassing子类实例
以GCNConv类为例,来实现一个简单的图神经网络。
GCNConv的数学定义为:
这个公式可以分成以下几个步骤:
1.向邻接矩阵添加自环边
2.线性转换节点特征矩阵
3.计算归一化系数
4.归一化j中的节点特征
5.将相邻节点特征相加(“求和”聚合)
该层的实现如下图:
首先使用torch_geometric.utils.add_self_loops()函数向边索引添加自循环边(步骤1),调用torch.nn.Linear实例对节点特征进行线性变换(步骤2),propagate()方法被调用后节点间的信息传递开始执行。归一化系数是由每个节点的节点度得出的,它被转换为每条边的节点度,结果被保存在形状[num_edges,] 的张量norm中(步骤3)
通过串联多个简单的图神经网络,我们可以构造复杂的图神经网络。
在__init__()方法中,程序会检查子类是否实现了message_and_aggregate()方法,并将检查结果赋值给fuse属性。
propagate()方法简介
propagate(self, edge_index: Adj, size: Size = None, **kwargs)
- edge_index:边端点索引,可以是Tensor类型或者SparseTensor类型
- size:邻接节点的数量与中心节点的数量,普通图数量都是N,对于二部图,邻接节点的数量与中心节点的数量分别记为M,N
- kwargs:图其他属性或额外的数据
propagate()方法首先检查edge_index 是否为SparseTensor 类型以及是否子类实现了 message_and_aggregate() 方法,如是就执行子类的message_and_aggregate方法;否则依次执行子类的message(),aggregate(),update() 三个方法。
(1)message方法的改写(希望能够接收中心节点的度):
(2)aggregate方法的覆写
通过观察运行结果我们可以看到,我们覆写的aggregate 方法被调用,同时在super(GCNConv, self).init(aggr=‘add’) 中传递给aggr参数的值被存储到了 self.aggr 属性中。
(3)message_and_aggregate方法的覆写
主要的修改体现在forward()函数上:
(4)覆写update方法
def update(self, imputs, deg):
print(deg)
return imputs
五、总结
消息传递范式具有以下三个步骤:
1.邻接节点信息变换
2.邻接节点信息聚合到中心节点
3.聚合信息变换
作业
总结MessagePassing基类的运行流程以及通过继承MessagePassing基类来构造自己的图神经网络的规范。
运行流程:首先进行对象初始化(定义要使用的聚合方案,定义消息流向,定义沿着哪个轴线传播),然后开始消息的起始调用(以edge_index(边的端点的索引)和flow(消息的流向)及一些额外的数据为参数),然后message()方法接收propagate()的所有参数接着为各条边创建要传递给节点i的消息,再将从源节点传递过来的消息聚合在目标节点上,最后目标节点更新节点表征。
通过继承MessagePassing基类来构造自己的图神经网络的规范:
1.注意每次传入的参数的形式
2.检查重写父类方法后是否执行了自己重写的方法
参考资料:
1.https://zhuanlan.zhihu.com/p/381645334
2.消息传递图神经网络