Node2vec和Deepwalk算法类似,利用词嵌入的思想来做网络节点嵌入的半监督学习算法。
但不同点在于,Node2vec的随机游走方式发生了改变。
Node2vec算法最主要的一个贡献也就是对于邻居节点的定义。Node2vec算法能够通过调整参数,灵活的调整给定节点的邻居。
一.前提
在论文中,作者认为对网络中节点进行嵌入应该满足两点:
1.同质性假设: 相互关联并且属于同一个社区的节点应该嵌入在相近的位置。
2.结构等价假设:结构相似的节点应该嵌入在相近的位置。
以下图为例,节点
u
u
u和节点
S
1
S_1
S1属于同一个社区,并且相互连接,那么他们应该满足同质性假设。另外节点
u
u
u和节点
S
6
S_6
S6结构相似,满足结构等价假设。
为了满足能满足这两种假设,提出综合深度优先遍历(DFS) 和 广度优先遍历(BFS) 的方法来进行随机游走。通过设置参数来决定两种遍历的偏向性。
结构等价性(比如说两个节点都是桥节点)是通过与源节点直接相连的节点来反映的,将游走过程限制在邻居节点能够发现节点的等价性。广度优先遍历能够将游走过程限制在邻居节点,从而能够很好的获得每个节点的邻居(节点的微观结构)。在广度优先遍历中,采用得到的邻居节点往往会重复很多次,这一点可以减少邻居节点变化的方差。
同质性往往不能直接通过邻居节点来反映,两个节点属于同一个社区并不代表两个节点一定相互连接,所以需要有深度优先遍历来探索更深层次的节点。DFS的问题在于,不仅要推断网络中存在哪些节点间的依赖关系,而且还要描述这些依赖关系的确切性质,这是很困难的,因为我们有一个样本大小的约束和一个大的邻域来探索,从而导致高方差。其次,移动到更大的深度会导致复杂的依赖关系,因为采样的节点可能远离源,并且可能不具有代表性。
这里需要区分的是:两个节点结构等价,并不要求两个节点相互连接。但是探索这两个节点是否结构等价,是判断这两个节点与其邻接节点的关系。 两个节点同质,也并不要求两个节点相互连接,并且判断两个节点是否同质,也不是判断两个节点和邻接节点的关系,而是判断两个节点的某种依赖关系。
二.Node2vec
随机游走
给定源节点
u
u
u, 进行一个长度为
l
l
l 的2阶随机游走,
c
i
c_i
ci为游走的第
i
i
i 个节点,
c
0
c_0
c0为源节点
u
u
u。
根据第
i
−
1
i-1
i−1 个节点,可以得到第
i
i
i 个节点的分布:
定义非正则化的转移概率
π
v
x
=
α
p
q
(
t
,
x
)
∗
w
v
x
\pi_{vx}=\alpha_{pq}(t,x)*w_{vx}
πvx=αpq(t,x)∗wvx,其中
α
p
q
(
t
,
x
)
\alpha_{pq}(t,x)
αpq(t,x)定义为:
这里
p
p
p 和
q
q
q 为参数。
Return parameter p p p控制了游走回到之前已访问的节点的概率,将p设置为一个较大的数意味着以一个较小的概率访问之前已访问的节点。这个参数的意义是控制游走序列的冗余采用的程度。相反,如果将 p p p 设置为一个较小的数,意味着更倾向于在局部游走。
In-out parameter q q q 控制着游走是往里还是往外.
- 当 q < 1 q<1 q<1时,游走倾向于远离源节点,此时游走过程更像深度优先遍历。
- 当 q > 1 q>1 q>1时,游走倾向于靠近源节点,此时游走过程更像广度优先遍历。
算法伪代码
第一个算法(整体算法)
外层循环的
i
t
e
r
iter
iter代表每个节点遍历的次数(外层的迭代次数)。内层循环代表对每个节点进行遍历,并采用node2vecWalk来生成每个节点的一次游走序列,加入到walks。最后利用SGD算法去计算节点的Embedding.
第二个算法(遍历算法)
外层循环
l
l
l 代表着游走序列的长度。walk存储着当前游走的序列。GetNeighbors根据当前的游走到的节点,来获得邻居节点。AliasSample来根据邻居节点来选择一个节点s作为前进的方向。将选择的节点s加入到序列walk.
论文:node2vec: Scalable Feature Learning for Networks