node2vec是2016年提出的Graph Embedding表示方式,其训练速度快,并开放了源码,而且表示效果还不错,所以挺火。本质上来说,node2vec其实是基于DeepWalk的改进,所以要想了解node2vec,就需要先了解DeepWalk。这里对DeepWalk仅做简要介绍,详细内容还需要阅读原论文DeepWalk。
输入的是一个网络,其中颜色相同的结点表示拓扑关系上更为相近的结点。输出的是每个节点的二维向量,每个节点对应的向量关系如图所示。我们可以从这个图看出,越是网络结构相近的点,其对应的二维向量在二维空间上距离与近。
这其实是一个降维的过程,但不是传统意义上的降维,而是将图结构(一个复杂的结构)降到易于表示的低维度。具体来说,就是将网络中的拓扑结构表示成一个低维向量,这个向量可以反应结点间的连接情况。
DeepWalk是这么做的:
不难看出,上面的过程简单来说,可以分为两步:第一步随机游走得到节点序列,第二步SkipGram得到向量表示。注意,这里的随机游走其实是类似深度优先遍历的过程。
理解了DeepWalk的原理之后,我们不难想出它的缺点。
针对上面的问题,便有了Node2Vec,简单介绍Node2Vec如下:
在介绍如何游走之前,我们先介绍一些必要的知识。
文章介绍了关于网络结点相似性度量的两个重要依据:
内容相似性主要是相邻节点之间的相似性,而结构上相似的的点并不一定是相邻的,可能隔得很远
这里主要基于两个重要假设:
同质性假设(homophily equivalence):连通的结点并且属于相似网络簇或者社群应该相似
结构等价假设(structural equivalence ):具有相似结构角色的结点应该相似
如上图所示,结点u和结点s6在局部网络结构中具有相似的结构角色,所以应该具有相似性,虽然两个结点之间并没有直接相连。又如,结点s1和u属于同一个网络簇(直连),所以更应该相似。
对于图结构来说,我们所熟知的搜索策略无外乎广度优先遍历(BFS)和深度优先遍历(DFS),两种策略各有其优缺点,对于这两个策略就不做过多介绍了。在图表示学习中,两种策略起到了基础作用,很多算法都是基于这两个策略的。
直观上来理解,广度优先遍历更容易采样邻居结点,这更容易表示结构相似性。此外,广度优先遍历采样邻居结点往往重复多次采样,这有利于减少偏差。对于深度优先遍历来说,它尽可能深的遍历网络,起到了一个宏观上的反应。这更容易表示内容相似性,即验证同质性假设。但是,过深的采样,增大了复杂度。而且,当深度达到一定程度,即两个结点之间距离较远,大多数时候,这两个结点可能没什么关系了。
基于上面的问题,Node2Vec提出了参数化的游走方式。具体来说,N2V提出了两个重要参数p和q用于控制游走。
如图所示,论文定义了一个二阶的随机游走, αpq(t,x) α p q ( t , x ) 是转移概率。
p用来控制重新访问walk的的结点的可能性,p越大,可能性越小。同理,q越大,加入q>1,那么随机游走就用参数控制游走的结点更结点结点t(降低了往外游走的概率)。如果q<1,则游走方式更大概率探索远离结点t的结点。
总的来说,整个策略是在DFS和BFS之间采取某种平衡,也提供了参数化的控制方式,可以根据不同的需求进行调参,增大了普适性。
关于node2vec的目标函数以及使用此算法所做的实验,这里就不多做详细介绍,感兴趣的去看原论文,没有多少公式。本文主要是简要介绍其思想。
对于目标函数优化,论文将其定位最大似然估计优化问题。
这里用到了两个假设:
论文公布了源代码,提供了C++和Python两个版本。
Python版本:https://github.com/aditya-grover/node2vec
C++版本:https://github.com/snap-stanford/snap/tree/master/examples/node2vec
也可以基于Spark训练,但是看issue有不少问题。
本人基于Python版本进行了实验室,说几点问题:
源码是基于Python2.7的,Python3.x需要修改源码
源码在保存模型的时候有错误,需要将line 88 in main.py 改为 model.wv.save_word2vec_format
错误提示为:raise DeprecationWarning(“Deprecated. Use model.wv.save_word2vec_format instead.”) DeprecationWarning: Deprecated. Use model.wv.save_word2vec_format instead.
30W结点,100W关系大概训练了半小时不到,结果进行相似性度量还可以。
对于大规模图,训练速度还是太慢,本人跑一个接近400W结点、8000W关系的图四天了还没开始迭代,需要考虑使用C++版本或Spark加速。