节点嵌入
节点嵌入(Node embedding)的目的是为了将图中每一个节点映射到一个低维的向量表示,在嵌入空间最好能够满足下面的性质:
- 如果两个节点在图中具有很高的相似性,那么二则的嵌入也应该具有相应的相似性
- 嵌入应该能够提取图的信息
- 嵌入向量可以用于下游学习和预测任务
本节内容包括:
- 提取器和重构器框架 (Encoder-decoder framework)
- 提取器:浅层次的嵌入查找表
- 重构器:基于嵌入向量预测节点相似性
- 节点相似性的度量方法:无偏和有偏的随机游走 (Deep Walk, Node2vec)
- 扩展到图的嵌入:节点嵌入聚合和匿名游走嵌入
提取器和重构器框架
提取器 (Encoder) 和重构器 (Decoder) 的目的是为了学习一种映射,将图的节点映射到嵌入空间,并且保证如果两个节点在图中具有很高的相似性,那么二则的嵌入也应该具有相同的相似性。用
u
u
u 表示节点,
ENC
\text{ENC}
ENC 表示提取器,节点的嵌入为
z
u
\mathbf z_u
zu, 即
ENC
(
u
)
=
z
u
\text{ENC}(u) = \mathbf z_u
ENC(u)=zu
节点相似性应该满足
similarity
(
u
,
v
)
≈
DEC
(
z
u
,
z
v
)
\text{similarity}(u, v) \approx \text{DEC} (\mathbf z_u, \mathbf z_v)
similarity(u,v)≈DEC(zu,zv)
如果使用最简单的重构器
DEC
(
z
u
,
z
v
)
=
z
u
T
z
v
\text{DEC} (\mathbf z_u, \mathbf z_v) = \mathbf z_u^T \mathbf z_v
DEC(zu,zv)=zuTzv , 那么上式可以写为
similarity
(
u
,
v
)
≈
z
u
T
z
v
\text{similarity}(u, v) \approx \mathbf z_u^T \mathbf z_v
similarity(u,v)≈zuTzv
学习嵌入节点嵌入的过程可以简单概括为:
-
提取器将节点映射到嵌入空间
-
定义节点相似性函数,即在原始图中节点相似性的度量方法
-
重构器利用节点嵌入向量计算相似性分数(这里使用点成作为重构器)
-
优化提取器的参数,使得节点嵌入满足以下条件:
similarity ( u , v ) ≈ z u T z v \text{similarity}(u, v) \approx \mathbf z_u^T \mathbf z_v similarity(u,v)≈zuTzv
最简单的浅层提取器可以看作是一个查找表,每一节点都被赋予唯一的嵌入向量,用公式表示为
ENC
(
v
)
=
z
v
=
Z
⋅
v
\text{ENC}(v) = \mathbf z_v = \mathbf Z \cdot \mathbf v
ENC(v)=zv=Z⋅v
其中
Z
\mathbf Z
Z 为
d
×
∣
V
∣
d \times |V|
d×∣V∣ 的矩阵,
v
\mathbf v
v 为独热向量 (one-hot vector)
这里我们需要注意的是,训练提取器与下游任务无关,既用不到节点标签,也用不到节点特征,整个过程是无监督学习。
随机游走
随机游走的定义
给定图中一个节点 u u u ,以该节点为起点,随机前进到它的任意一个邻接节点,不断重复此过程 T 次,就得到节点 u u u 的邻域节点 N R ( u ) N_R(u) NR(u) 。随机游走严格的定义为:
设
G
=
(
V
,
E
)
G = (V, E)
G=(V,E) 表示一个连通图,考虑从图
G
G
G 上的节点
u
∈
V
u \in V
u∈V 开始随机游走。假设在随机游走的第
t
t
t 步访问的是节点
u
(
t
)
u^{(t)}
u(t),那么随机游走的下一个节点按照如下概率从
u
(
t
)
u^{(t)}
u(t) 的邻居节点中选出:
p
(
u
(
t
+
1
)
∣
u
(
t
)
)
=
{
1
d
(
u
(
t
)
)
,
u
(
t
+
1
)
∈
N
(
u
(
t
)
)
0
,
其他
p(u^{(t+1)} | u^{(t)}) = \left\{\begin{matrix} \frac{1}{d(u^{(t)})}, \quad u^{(t+1)} \in N(u^{(t)}) \\ 0, \qquad \text{其他} \end{matrix}\right.
p(u(t+1)∣u(t))={d(u(t))1,u(t+1)∈N(u(t))0,其他
其中
d
(
u
(
t
)
)
d(u^{(t)})
d(u(t)) 表示节点的度,
N
(
u
(
t
)
)
N(u^{(t)})
N(u(t)) 表示节点
u
(
t
)
u^{(t)}
u(t) 的邻居节点集合,
N
(
u
(
t
)
)
N(u^{(t)})
N(u(t)) 可以存在重复节点。 注意这里是无偏随机游走,选择下一个节点的概率是均匀分布的。
随机游走的过程可以用下图表示
目标函数和负采样方法
我们用随机游走是为了寻找一个恰当的节点嵌入,使得嵌入向量在嵌入空间中也能够保持相同的相似性。用数学语言表示就是,对于给定的图
G
=
(
V
,
E
)
G=(V, E)
G=(V,E),通过随机游走的方式学习到一种映射
f
:
u
→
R
d
f: u \rightarrow \R^d
f:u→Rd ,使得如下对数似然函数达到最大值:
max
f
∑
u
∈
V
log
p
(
N
R
(
u
)
∣
z
u
)
\max_{f} \sum_{u \in V} \log p(N_R(u) | \mathbf z_u)
fmaxu∈V∑logp(NR(u)∣zu)
换句话说,如果节点
u
u
u 的随机游走路径上的节点集合为
N
R
(
u
)
N_R(u)
NR(u),那么通过节点嵌入向量计算得到的概率
∏
v
∈
N
R
(
u
)
p
(
v
∣
u
)
\prod_{v \in N_R(u)} p(v|u)
∏v∈NR(u)p(v∣u) 应该有最大值,即随机游走路径上节点共同出现的概率达到最大值,对应的标损失函数为
L
=
∑
u
∈
V
∑
v
∈
N
R
(
u
)
−
log
p
(
v
∣
z
u
)
L = \sum_{u \in V} \sum_{v \in N_R(u)} -\log p(v|\mathbf z_u)
L=u∈V∑v∈NR(u)∑−logp(v∣zu)
概率用 Softmax 函数计算
p
(
v
∣
z
u
)
=
exp
z
u
T
z
v
∑
n
∈
V
exp
z
u
T
z
n
p(v | \mathbf z_u) = \frac {\exp \mathbf z_u^T \mathbf z_v}{ \sum_{n\in V} \exp \mathbf z_u^T \mathbf z_n}
p(v∣zu)=∑n∈VexpzuTznexpzuTzv
合起来就是
L
=
∑
u
∈
V
∑
v
∈
N
R
(
u
)
−
log
(
exp
z
u
T
z
v
∑
n
∈
V
exp
z
u
T
z
n
)
L = \sum_{u \in V} \sum_{v \in N_R(u)} -\log \left( \frac {\exp \mathbf z_u^T \mathbf z_v}{ \sum_{n\in V} \exp \mathbf z_u^T \mathbf z_n} \right)
L=u∈V∑v∈NR(u)∑−log(∑n∈VexpzuTznexpzuTzv)
学习的目标就是寻找节点的嵌入向量
z
u
\mathbf z_u
zu 使得上述损失函数最小,学习过程可以概括为:
- 对图 G 的每一个节点 u u u 都做一个游走策略为 R 且长度固定的随机游走
- 将所有节点的随机游走路径上出现的节点 N R ( u ) N_R(u) NR(u) 收集起来组成训练集
- 优化嵌入,即给定节点 u u u 预测其邻域节点的概率
从损失函数来看,其计算复杂度为
O
(
∣
V
∣
2
)
\mathcal O(|V|^2)
O(∣V∣2) ,所以在实际训练过程中一般会使用负采样 (Negative sampling ) 方法加速。具体的就是使用如下近似
log
(
exp
z
u
T
z
v
∑
n
∈
V
exp
z
u
T
z
n
)
≈
log
(
σ
(
z
u
T
z
v
)
)
−
∑
i
=
1
k
log
(
σ
(
z
u
T
z
v
)
)
,
n
i
∼
P
n
\log \left( \frac {\exp \mathbf z_u^T \mathbf z_v}{ \sum_{n\in V} \exp \mathbf z_u^T \mathbf z_n} \right) \approx \log (\sigma(\mathbf z_u^T \mathbf z_v)) - \sum_{i = 1}^{k}\log (\sigma(\mathbf z_u^T \mathbf z_v)), n_i \sim P_n
log(∑n∈VexpzuTznexpzuTzv)≈log(σ(zuTzv))−i=1∑klog(σ(zuTzv)),ni∼Pn
其中
P
n
P_n
Pn 表示负元组的概率分布,通常取
P
n
(
u
)
=
d
(
v
)
3
/
4
P_n(u) = d(v)^{3/4}
Pn(u)=d(v)3/4 。
k
k
k 为负采样的数量,通常取 5-20,且
k
k
k 越大,学习到的嵌入越鲁棒。
优化方法
优化嵌入参数,可以使用我们熟悉的梯度下降或者随机梯度下降方法。设学习率为 η \eta η ,梯度下降的过程如下:
- 随机初始化所有节点 i i i 的嵌入 z i \mathbf z_i zi
- 不断重复以下步骤,直到收敛损失函数收敛
- 对所有节点 i i i,计算损失函数和嵌入向量的梯度 ∂ L ∂ z i \frac {\partial L}{\partial \mathbf z_i} ∂zi∂L
- 对所有节点 i i i,更新嵌入向量 z i = z i − η ∂ L ∂ z i \mathbf z_i = \mathbf z_i - \eta \frac {\partial L}{\partial \mathbf z_i} zi=zi−η∂zi∂L
随机梯度下降过程如下:
- 随机初始化所有节点 i i i 的嵌入 z i \mathbf z_i zi
- 不断重复以下步骤,直到收敛损失函数收敛
- 取一个节点 i i i 计算损失函数,对所有节点 j j j , 计算嵌入向量的梯度 ∂ L ( i ) ∂ z j \frac {\partial L^{(i)}}{\partial \mathbf z_j} ∂zj∂L(i)
- 对所有节点 j j j ,更新嵌入向量 z j = z j − η ∂ L ( i ) ∂ z j \mathbf z_j = \mathbf z_j - \eta \frac {\partial L^{(i)}}{\partial \mathbf z_j} zj=zj−η∂zj∂L(i)
Node2vec: 有偏游走
上面介绍的随机游走采用的游走策略是无偏游走,每一步前进到下一个邻接节点的概率是相同的。Node2vec 采用了一种更为灵活的游走方式。我们知道在图的有两种常用的路径查找算法:广度优先搜索 (BFS) 和深度优先搜索 (DFS),两种方法的示意图如下
在游走过程中采用BFS策略形成的集合 N R ( u ) N_R(u) NR(u) 可以看作是局部微观结构信息的描述,采用 DFS 策略形成的集合 N R ( u ) N_R(u) NR(u) 可以看作是全局宏观的结构信息描述,node2vec 将这两种游走方式结合起来,通过参数控制就可以改变 N R ( u ) N_R(u) NR(u) 中包含的局部和全局信息。用数学的语言描述为:
设 G = ( V , E ) G = (V, E) G=(V,E) 表示一个连通图,考虑从图 G G G 上的节点 u ∈ V u \in V u∈V 开始随机游走。假设在随机游走的第 t − 1 和 t t-1 和 t t−1和t访问的是节点分别是
u
(
t
−
1
)
和
u
(
t
)
u^{(t-1)} 和 u^{(t)}
u(t−1)和u(t) ,那么
t
+
1
t+1
t+1 步选择节点的未归一化概率为
α
(
u
(
t
+
1
)
∣
u
(
t
−
1
)
,
u
(
t
)
)
=
{
1
p
,
dist
(
u
(
t
−
1
)
,
u
t
+
1
)
=
0
1
,
dist
(
u
(
t
−
1
)
,
u
t
+
1
)
=
1
1
p
,
dist
(
u
(
t
−
1
)
,
u
t
+
1
)
=
2
\alpha(u^{(t+1)}| u^{(t-1)}, u^{(t)}) = \left\{\begin{matrix} \frac{1}{p}, \quad \text{dist}(u^{(t-1)}, u^{t+1})=0 \\ 1, \quad \text{dist}(u^{(t-1)}, u^{t+1})=1 \\ \frac{1}{p}, \quad \text{dist}(u^{(t-1)}, u^{t+1})=2 \end{matrix}\right.
α(u(t+1)∣u(t−1),u(t))=⎩⎨⎧p1,dist(u(t−1),ut+1)=01,dist(u(t−1),ut+1)=1p1,dist(u(t−1),ut+1)=2
其中
p
,
q
p, q
p,q 为超参。如下图所示,
S
1
S_1
S1 和
W
W
W 分别表示上一步和当前步节点,选择下一步时,退回上一步
S
1
S_1
S1 的概率为
1
p
\frac 1p
p1 ,选择与
S
1
S_1
S1 距离为1的节点的概率为1, 选择
q
q
q 控制下一步是向里走还是向外走的概率,也就是选择 BFS 还是 DFS 的概率。
整个图的嵌入
假如我们想计算整个图的嵌入或者是子图的嵌入,那该怎么做呢?这里介绍三种方法:
-
按照上文中标准的图嵌入方法,先计算所有节点的嵌入,然后把所有节点的嵌入和作为图(子图)的嵌入,即:
z G = ∑ v ∈ V z v \mathbf z_G = \sum_{v \in V} \mathbf z_v zG=v∈V∑zv -
将图中的特定子图看作是虚拟节点,并以此进行标准的图嵌入计算,如下图所示
-
使用匿名游走嵌入方法 (Anonymous Walk Embeddings). 在匿名游走中,我们不再记录路径上节点的编号,而是以第一次出现顺序作为节点的标记,例如在下面的图中,游走路径1的集合为 { A , B , C , B , C } \{ A, B, C, B, C\} {A,B,C,B,C},它对应的匿名游走集合为 { 1 , 2 , 3 , 2 , 3 } \{1, 2, 3, 2, 3\} {1,2,3,2,3}. 详细介绍参考论文 Anonymous Walk Embeddings, ICML 2018 https://arxiv.org/pdf/1805.11921.pdf