之前看GCN(Graph Convolutional Network)的时候总是一知半解、懵懵懂懂。在学习了GAT和GIN并深入阅读了源码后终于对GCN有了更进一步的了解。
意识流理解GCN
第一步:平均
这里我们可以同通过收集并平均你的neighbor的信息来提取信息:
a
g
g
r
e
g
a
t
r
e
(
X
i
)
=
∑
j
∈
n
e
i
g
h
b
o
r
(
i
)
A
i
j
X
j
aggregatre(X_i)=\sum_{j\in{neighbor(i)}}A_{ij}X_{j}
aggregatre(Xi)=j∈neighbor(i)∑AijXj
第二步:加权平均
考虑到不同neighbor之间的重要性:
a
g
g
r
e
g
a
t
r
e
(
X
)
=
A
X
aggregatre(X)=AX
aggregatre(X)=AX
这里我们将无权图改为有权图即可。
第三步:考虑自身因素
聚类一个Graph的时候往往要考虑自身feature的因素,所以,这里我们用一个单位矩阵实现:
a
g
g
r
e
g
a
t
r
e
(
X
)
=
(
A
+
I
)
X
=
A
X
+
X
=
aggregatre(X)=(A+I)X=AX+X=
aggregatre(X)=(A+I)X=AX+X=
a
g
g
r
e
g
a
t
r
e
(
X
i
)
=
∑
j
∈
n
e
i
g
h
b
o
r
(
i
)
A
i
j
X
j
+
X
i
aggregatre(X_i)=\sum_{j\in{neighbor(i)}}A_{ij}X_{j}+X_i
aggregatre(Xi)=j∈neighbor(i)∑AijXj+Xi
通过展开式我们能够看出加上了自身的特征
第四步:差分
这里我们使用度矩阵
D
D
D与邻接矩阵
A
A
A做差分:
d
i
f
f
(
X
)
=
(
D
−
A
)
X
diff(X)=(D-A)X
diff(X)=(D−A)X
第五步:归一化与对称归一化
这里我们令
A
^
=
A
+
I
\hat{A}=A+I
A^=A+I,
D
^
\hat{D}
D^为
A
^
=
A
+
I
\hat{A}=A+I
A^=A+I的度矩阵。通过
D
^
−
1
\hat{D}^{-1}
D^−1能够将求和变为加权平均(意识流理解,有空再写详细证明)。于是我们能够得到最终的GCN传播方式
H
(
l
+
1
)
=
σ
(
D
^
−
1
/
2
A
^
D
^
−
1
/
2
H
l
W
(
l
)
)
H^{(l+1)}=\sigma(\hat{D}^{-1/2}\hat{A}\hat{D}^{-1/2}H^{l}W^{(l)})
H(l+1)=σ(D^−1/2A^D^−1/2HlW(l))
其中,
σ
\sigma
σ为非线性激活函数。
pyhton的代码实现为:
def _call(self, inputs):
x = inputs
x = tf.nn.dropout(x, 1 - self.dropout)
x = tf.matmul(x, self.vars['weights'])
x = tf.sparse_tensor_dense_matmul(self.adj, x)
outputs = self.act(x)
return outputs
注:之前就疑惑为什么传播公式里面的 D ^ \hat{D} D^为什么不体现在code中,原来是因为数据集的不同, D ^ − 1 / 2 A ^ D ^ − 1 / 2 \hat{D}^{-1/2}\hat{A}\hat{D}^{-1/2} D^−1/2A^D^−1/2往往计算在内,这里的code只是书写形式罢辽。
读到这里,我也就能够明白为什么论文“HOW POWERFUL ARE GRAPH NEURAL NETWORKS?”中阐述GCN中AGGREGATE金额COMBINE步骤时用来MEAN来表示:
灵感来源
链接: 知乎大神:纵横.