普通卷积神经网络研究的对象是具备Euclidean domains的数据,Euclidean domains data数据最显著的特征是他们具有规则的空间结构,如图片是规则的正方形,语音是规则的一维序列等,这些特征都可以用一维或二维的矩阵来表示,卷积神经网络处理起来比较高效。
然而,现实生活中很多数据不具备规则的空间结构,称为Non Euclidean data,如,推荐系统、电子交易、分子结构等抽象出来的图谱。这些图谱中的每个节点连接不尽相同,有的节点有三个连接,有的节点只有一个连接,是不规则的结构。对于这些不规则的数据对象,普通卷积网络的效果不尽人意。CNN卷积操作配合pooling等在结构规则的图像等数据上效果显著,但是如果作者考虑非欧氏空间比如图(即graph,流形也是典型的非欧结构,这里作者只考虑图),就难以选取固定的卷积核来适应整个图的不规则性,如邻居节点数量的不确定和节点顺序的不确定。 4 ^4 4
这里的理解就是,数据的组织形式不同,催生出了图卷积神经网路。如果现实生活中都是规则的数据,普通的卷积神经网络就足够胜任。
总结一下,图数据中的空间特征具有以下特点:
1) 节点特征:每个节点有自己的特征;(体现在点上)
2) 结构特征:图数据中的每个节点具有结构特征,即节点与节点存在一定的联系。(体现在边上)
总地来说,图数据既要考虑节点信息,也要考虑结构信息,图卷积神经网络就可以自动化地既学习节点特征,又能学习节点与节点之间的关联信息。
综上所述,GCN是要为除CV、NLP之外的任务提供一种处理、研究的模型。
图卷积的核心思想是利用『边的信息』对『节点信息』进行『聚合』从而生成新的『节点表示』。
已有很多优秀的博客对图卷积神经网络的理论进行了严密的推导,在这里我就作为一个学习记录,记录自己的疑问的地方,想要读详细推导的,请移步参考文献。
以下是对一阶ChebNet(1stChebNet)-GCN的记录:
H ( l + 1 ) = f ( H ( l ) , A ) = σ ( D ~ − 1 2 A ~ D ~ − 1 2 H ( l ) W ( l ) ) (1) \mathbf{H}^{(l+1)} = f(\mathbf{H}^{(l)},\mathbf{A}) = \sigma(\mathbf{\widetilde{D}}^{-\frac{1}{2}}\mathbf{\widetilde{A}}\mathbf{\widetilde{D}}^{-\frac{1}{2}}\mathbf{H}^{(l)}\mathbf{W}^{(l)}) \tag{1} H(l+1)=f(H(l),A)=σ(D −21A D −21H(l)W(l))(1)
代码Github地址
本次阅读的代码使用的是pytorch。
代码入口是pygcn/train.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--no-cuda', action='store_true', default=False,
help='Disables CUDA training.')
parser.add_argument('--fastmode', action='store_true', default=False,
help='Validate during training pass.')
parser.add_argument('--seed', type=int, default=42, help='Random seed.')
parser.add_argument('--epochs', type=int, default=200,
help='Number of epochs to train.')
parser.add_argument('--lr', type=float, default=0.01,
help='Initial learning rate.')
parser.add_argument('--weight_decay', type=float, default=5e-4,
help='Weight decay (L2 loss on parameters).')
parser.add_argument('--hidden', type=int, default=16,
help='Number of hidden units.')
parser.add_argument('--dropout', type=float, default=0.5,
help='Dropout rate (1 - keep probability).')
args = parser.parse_args()
argparse参考
这整段代码表示的是可以从命令行窗口获取超参数,可以注意的是都是可选参数,而且有默认值,所以是可以直接运行的。
# 返回指定长度的标识数组
# >>> np.identity(3)
# array([[1., 0., 0.],
# [0., 1., 0.],
# [0., 0., 1.]])
np.identity(num)
# 构造对称的邻接矩阵
adj = adj + adj.T.multiply(adj.T > adj) - adj.multiply(adj.T > adj)
不得不说大佬的代码写的是真滴优雅。对称矩阵的逆矩阵与自身相等,上述代码就是利用这个原理实现构建堆成矩阵。
疑问
:引文网络按理来说应该是个有向图,即两篇文章不一定会相互应用,这里强行表示为无向图是否有问题。
参考文献: