一、图卷积神经网络
图卷积神经网络(Graph Convolutional Network, GCN)是近些年逐渐流行的一种神经网络,发展到现在已经有无数改进的版本,在图网络领域的地位如同卷积操作在图像处理里的地位一样重要。图卷积神经网络与传统的网络模型LSTM和CNN等所处理的数据类型有所不同。LSTM和CNN只能用于网格化结构的数据,而图卷积神经网络能够处理具有广义拓扑图结构的数据,并深入发掘其特征和规律。
在具体介绍图卷积神经网络之前,先介绍一些图的基本知识
(学过数据结构和离散数学的同学对图的性质应该比较熟悉)
图(Graph):定义一张图G=(V,E), V中元素为图的顶点,E中元素为图的边
邻居(Neighborhood):顶点V_i的邻居N_i:{V_i∈V│V_iV_j∈E}。在无向图中,如果顶点V_i是顶点V_j的邻居,那么顶点V_j也是顶点V_i的邻居
度矩阵(Degree):度矩阵是对角阵,对角上的元素为各个顶点的度。顶点V_i的度表示和该顶点相关联的边的数量(如果是有向图还分为入度和出度)
邻接矩阵(Adjacency):邻接矩阵表示顶点间关系,是n阶方阵(n为顶点数量)
现实中更多重要的数据集都是用图的形式存储的,例如知识图谱,社交网络、通信网络、蛋白质分子结构等等。这些图网络的形式并不像图像一样是排列整齐的矩阵,而是具有空间拓扑图结构的不规则数据
对于具有拓扑结构的图数据,可以按照用于网格化结构数据的卷积的思想来定义图卷积。将每个节点的邻居节点的特征传播到该节点,再进行加权,就可以得到该点的聚合特征值
定义一张图G=(V,E,A),V是图的节点集合,E是图的边集合,A∈R^n×n代表该网络的邻接矩阵,则GCN卷积操作定义如下式所示(Kipf等人提出的GCN版本):
其中A ̂=A+I,A∈R^n×n为邻接矩阵,I∈R^n×n为单位矩阵,D ̂是A ̂的对角节点度矩阵, W 为第l层的参数矩阵,b为第l层的偏置向量,H∈R^n×t为特征矩阵,其中n为节点数目,t 为每个节点的特征数目,H^′∈R^n×t为含有拓扑信息的特征矩阵,σ (⋅) 为激活函数
目前图上的卷积操定义基本上可以分为两类:一个是基于谱的图卷积,它们通过傅里叶变换将节点映射到的频域空间,通过在频域空间上做乘积来实现时域上的卷积,最后再将做完乘积的特征映射回时域空间,而另一种是基于空间域的图卷积,与传统的CNN很像,只不过再图结构上更难定义节点的邻居以及与邻居之间的关系
二、Numpy实现图卷积神经网络
首先构建一个简单的有向图
使用Numpy编写图的邻接矩阵A
import numpy as np
from math import sqrt
A = np.matrix([
[0, 1, 0, 0],
[0, 0, 1, 1],
[0, 1, 0, 0],
[1, 0, 1, 0]],
dtype=float)
基于每个节点的索引为其生成两个整数特征,生成的特征矩阵为X,代码如下
X = np.matrix([
[i, -i]
for i in range(A.shape[0])], dtype=float)
为每个节点添加一个自环,这可以通过在应用传播规则之前将邻接矩阵 A 与单位矩阵 I 相加来实现
I = np.matrix(np.eye(A.shape[0])) # np.eye()返回的是一个二维2的数组(N,M),对角线的地方为1,其余的地方为0.
A_hat = A + I
生成节点度矩阵D_hat,将度矩阵处理为D ̂^(-1/2)形式,然后有拓扑信息的特征矩阵
D_hat = np.array(np.sum(A_hat, axis=0))[0]
D_hat_sqrt = [sqrt(x) for x in D_hat]
D_hat_sqrt = np.array(np.diag(D_hat_sqrt))
D_hat_sqrtm_inv = np.linalg.inv(D_hat_sqrt) # 开方后求逆即为矩阵的-1/2次方
D_A_final = np.dot(D_hat_sqrtm_inv, A_hat)
D_A_final = np.dot(D_A_final, D_hat_sqrtm_inv)
添加权重W与偏置b
W = np.matrix([
[1, -1],
[-1, 1]
])
b = np.matrix([
[1],
[0],
[1],
[0]
])
添加激活函数,选择保持特征矩阵的维度,并应用 ReLU 激活函数
def relu(x):
return (abs(x) + x) / 2
最后,应用传播规则生成下一层的特征矩阵
output = relu(D_A_final * X * W + b)