先来看看每一层的输入与输出:
input
:
h
=
{
h
⃗
1
,
h
⃗
2
,
…
,
h
⃗
N
}
,
h
⃗
i
∈
R
F
output
:
h
′
=
{
h
⃗
1
′
,
h
⃗
2
′
,
…
,
h
⃗
N
′
}
,
h
⃗
i
′
∈
R
F
\text { input }: \mathbf{h}=\left\{\vec{h}_{1}, \vec{h}_{2}, \ldots, \vec{h}_{N}\right\}, \vec{h}_{i} \in \mathrm{R}^{F} \\ \text { output }: \mathbf{h}^{\prime}=\left\{\vec{h}_{1}^{\prime}, \vec{h}_{2}^{\prime}, \ldots, \vec{h}_{N}^{\prime}\right\}, \vec{h}_{i}^{\prime} \in \mathrm{R}^{F}
input :h={h1,h2,…,hN},hi∈RF output :h′={h1′,h2′,…,hN′},hi′∈RF
1. 计算注意力系数
首先计算顶点
i
i
i 与周围邻居节点
j
∈
N
i
j \in \mathcal N_i
j∈Ni 的相似度:
e
i
j
=
a
(
W
h
⃗
i
,
W
h
⃗
j
)
e_{i j}=a\left(\mathbf{W} \vec{h}_{i}, \mathbf{W} \vec{h}_{j}\right)
eij=a(Whi,Whj) 公式中的
(
W
h
⃗
i
,
W
h
⃗
j
)
\left(\mathbf{W} \vec{h}_{i}, \mathbf{W} \vec{h}_{j}\right)
(Whi,Whj) 可以看出特征
h
i
,
h
j
h_i, h_j
hi,hj 共享了参数矩阵
W
W
W,都使用
W
W
W 对特征进行线性变换,
(
⋅
,
⋅
)
(·, ·)
(⋅,⋅)在公式中表示横向拼接。而公式最外层的
a
a
a 表示单层前馈神经网络(使用
L
e
a
k
y
R
e
L
U
LeakyReLU
LeakyReLU作为激活函数),输出为一个数值。
有了相关系数,接下来就要进行归一化了,作者使用了
S
o
f
t
m
a
x
Softmax
Softmax,于是注意力系数的计算过程全貌为:
α
i
j
=
softmax
j
(
e
i
j
)
=
exp
(
e
i
j
)
∑
k
∈
N
i
exp
(
e
i
k
)
=
exp
(
LeakyReLU
(
a
→
T
[
W
h
⃗
i
∥
W
h
⃗
j
]
)
)
∑
k
∈
N
i
exp
(
LeakyReLU
(
a
→
T
[
W
h
⃗
i
∥
W
h
⃗
k
]
)
)
\begin{aligned} \alpha_{i j}&=\operatorname{softmax}_{j}\left(e_{i j}\right)\\ &=\frac{\exp \left(e_{i j}\right)}{\sum_{k \in N_{i}} \exp \left(e_{i k}\right)}\\ &=\frac{\exp \left(\operatorname{LeakyReLU}\left(\overrightarrow{\mathbf{a}}^{T}\left[\mathbf{W} \vec{h}_{i} \| \mathbf{W} \vec{h}_{j}\right]\right)\right)}{\sum_{k \in N_{i}} \exp \left(\operatorname{LeakyReLU}\left(\overrightarrow{\mathbf{a}}^{T}\left[\mathbf{W} \vec{h}_{i} \| \mathbf{W} \vec{h}_{k}\right]\right)\right)} \end{aligned}
αij=softmaxj(eij)=∑k∈Niexp(eik)exp(eij)=∑k∈Niexp(LeakyReLU(aT[Whi∥Whk]))exp(LeakyReLU(aT[Whi∥Whj])) 其中,
∥
\|
∥ 表示向量拼接,以上的计算过程如下图所示:
2. 加权求和
得到注意力系数之后,就是对邻居节点的特征进行加权求和:
h
⃗
i
′
=
σ
(
∑
j
∈
N
i
α
i
j
W
h
⃗
j
)
\vec{h}_{i}^{\prime}=\sigma\left(\sum_{j \in N_{i}} \alpha_{i j} \mathbf{W} \vec{h}_{j}\right)
hi′=σ⎝⎛j∈Ni∑αijWhj⎠⎞ 不过为了更好的学习效果,作者使用了 “multi-head attention”,也就是使用 K 个注意力。对于 K 个注意力又可以使用两种方法对邻居节点进行聚合。
一种方法是横向拼接的方式,这样聚合到的特征维度就是原来的K倍:
h
⃗
i
′
=
∥
k
=
1
K
σ
(
∑
j
∈
N
i
α
i
j
k
W
k
h
⃗
j
)
\vec{h}_{i}^{\prime}=\|_{k=1}^{K} \sigma\left(\sum_{j \in N_{i}} \alpha_{i j}^{k} \mathbf{W}^{k} \vec{h}_{j}\right)
hi′=∥k=1Kσ⎝⎛j∈Ni∑αijkWkhj⎠⎞ 另一种方法是把K个注意力机制得到的结果取平均值:
h
⃗
i
′
=
σ
(
1
K
∑
k
=
1
K
∑
j
∈
N
i
α
i
j
k
W
k
h
⃗
j
)
\vec{h}_{i}^{\prime}=\sigma\left(\frac{1}{K} \sum_{k=1}^{K} \sum_{j \in N_{i}} \alpha_{i j}^{k} \mathbf{W}^{k} \vec{h}_{j}\right)
hi′=σ⎝⎛K1k=1∑Kj∈Ni∑αijkWkhj⎠⎞ 下图可以辅助理解上面的计算过程: