Graph Embedding
作者:互联网
Graph Embedding 基本概念
Graph Embedding 技术是一种将图的拓扑结构进行向量表示的方法,从而获取到网络关系信息,可应用于推荐等多种场景。计算节点在图中的空间特征的算法就是图嵌入(Graph Embedding)或网络嵌入(Network Embedding)。
图嵌入的目标是将图中的节点表示为一个低维向量,该向量保留了节点在网络中的拓扑结构以及节点内部信息。通过这个表示向量,其他的经典深度学习算法才得以被应用到图中,最终实现分类、聚类、推荐等问题。
现有神经网络大多建立在图像和序列上的,还有少量建立在树形结构上。一些研究开始将神经网络迁移到图上,原因有:
- 图本身就是大量数据结构的抽象化结果。比如图像可以看作某种意义上图的一种(将CNN迁移到图上提出图CNN:GCN)。
- 在社交网络中的兴趣推荐、商品推荐等领域已有一些研究和应用。与图相关的数据:社交关系、搜索行为、购买行为。
现有的多数机器学习算法假设样本实例之间互相独立,而对于图数据而言并非独立,通过引用、相互关系、交互等连接起来。
传统图算法如 MDS, IsoMap, Laplacian eigenmap 计算复杂度都是\(\mathcal O(|V|^2)\),对于百万级的节点数计算量很大。
用embedding当做图的表征可追溯到2014年Deep Walk。
Graph Embedding 可应用于:
- (a) node classification 节点分类
- (b) link prediction 预测链接
- (c) clustering 聚类
- (d) visualization 可视化
经典模型
DeepWalk
DeepWalk - Online Learning of Social Representations (SBU 2014)
以随机游走的方式从网络中生成序列,进而转换成传统word2vec的方法生成Embedding。这篇论文可以视为Graph Embedding的baseline方法,用极小的代价完成从word2vec到graph embedding的转换和工程尝试。
淘宝EGES论文中用户购买商品行为序列的 graph embedding示意图:
DeepWalk是第一个将NLP中的思想用在网络嵌入(Network Embedding,NE)上的。
利用了词嵌入的思想:网络节点对应单词,网络节点的随机游走对应句子(单词序列)。
DeepWalk通过截断随机游走(truncated random walk,长度固定的随机游走)之后使用Word2vec学习出一个网络的社会表示(social representation),在网络标注顶点很少的情况也能得到比较好的效果。并且该方法还具有可扩展的优点,能够适应网络的变化。
随机游走是一阶的马尔科夫过程(first-order Markov process)。为什么随机游走当作预料进行学习就能学习到网络节点的表示?
网络中随机游走的分布规律与NLP中句子序列在语料库中出现的规律有着类似的幂律分布特征。那么既然网络的特性与自然语言处理中的特性十分类似,那么就可以将NLP中词向量的模型用在网络表示中。
关于幂律分布: 在统计学中, 幂律是两个量之间的函数关系,表现为一个量是另一个量的幂次方。例如,正方形面积与边长的关系。参考wiki
对于一个随机游走 \((v_0,v_1,…,v_i)\) 要优化的目标是:\(Pr(v_i|(v_0,v_1,…,v_{i-1}))\)
引入一个映射函数Φ,将顶点映射成向量,我们的目标正是求出Φ(|V|×d的矩阵)。优化目标可以写成:\(Pr(v_i|(Φ(v_0),Φ(v_1),…,Φ({v_i-1})))\)
但是计算这个条件概率随着游走节点的增加,变得越来越难计算。借鉴skip-gram模型,在滑动窗口内不考虑节点的顺序,目标函数优化为:
\[\underset{Φ}{\rm{minimize}} −\log Pr( \{v_{i−w} ,··· ,v_{ i+w} \} \text{\\} v_i | Φ(v_i) ) \]即在一个随机游走中,当给定一个顶点 \(v_i\)时,出现它的w窗口范围内的顶点的概率。CBOW与SkipGram的复杂度一样(实际计算量CBOW要小一些,因为CBOW是求平均后再计算softmax),但是Skip-gram号称是对生僻词更友好,训练效果可能更好。
DeepWalk算法流程:
其中第2步是构建Hierarchical Softmax,第3步对每个节点做γ次随机游走(相当于迭代次数),第4步打乱网络中的节点,第5步以每个节点为根节点生成长度为t的随机游走,第7步根据生成的随机游走使用skip-gram模型利用梯度的方法对参数进行更新。
复杂度 O(|V|),但是一旦有新节点添加进来,需要重新训练得到embedding。
后续的很多论文也是采取了这种思路,都是利用随机游走的特征构建概率模型,用词向量中Negative Sampling/Hierarchical Softmax的思想进行求解。不过在随机游走方式上可以做些修改,比如加权随机游走。注:在DeepWalk论文及原始实现中随机游走为纯随机不加权的游走,实现效率很高,可以并行化。而Node2vec等方法中加权随机游走由于需要记录转移概率矩阵,比较耗内存,速度也会被拖慢。
随机游走的一种用途:真实序列无法直接获得时可以用随机游走来模拟序列。注意一般在无向图上随机游走比较好,而有向图不对称且容易走到死胡同(没有出边)。
Item2vec
在DeepWalk方法出来之后,Item2vec提出“万物皆可embedding”,构造出序列数据,并通过word2vec对序列数据进行embedding表示。
在一些应用场景中取消word2vec窗口大小的限制,认为所有物品间均有相关性。
LINE
LINE - Large-scale Information Network Embedding (MSRA 2015)
2015 年微软发表了 LINE ,定义了相似度的表征方式。直接相邻的连接定义为1阶连接,有许多共同的邻接节点之间的关系定义为二阶连接。二阶连接比如两个人的朋友圈的交集可以衡量两个人之间的关联强度。
LINE设计了一个损失函数将一阶和二阶关系考虑在内,而DeepWalk通过随机游走的方式来扩展一个顶点的相邻节点,类似于深度优先搜索,并期望这种二阶相似的节点具有接近的低维嵌入。对于二阶相似,使用广度优先可能更为合适,而LINE的方式类似广度优先。
DeepWalk没有考虑加权图,而且纯随机的方式存在一些缺陷。
如图所示,图可以是有向、无向、有权重的。由于节点6、7之间有较强的连接,两者在低维空间应该比较相近,5、6由于有共同的相邻节点,在低维空间中的表示也应该相近。
一阶邻近模型
一阶相似度定义:
对于无向边 (i,j),节点 \(v_i,\ v_j\)的一阶邻近关系的联合概率定义为:
\[p_1(v_i,v_j)={1\over 1+\exp(-\vec u_i^T \cdot \vec u_j)} \]ui是点vi的表达向量,期望值为
\[\hat p_1 (i,j) = {w_{ij}\over W}, \ \ W =\sum_{(i,j)∈E} w_{ij} . \]学习的过程就是减少两个分布之间距离的过程: \(O_1=d(\hat p_1(\cdot,\cdot),p_1(\cdot,\cdot))\),距离d采用前向KL散度:\(D_{{{\mathrm {KL}}}}(P\|Q)=\sum _{i}P(i)\ln {\frac {P(i)}{Q(i)}}\)
前向KL散度,P(x)是真实分布,Q(x)是拟合分布。
注意该模型不能用于有向图,仅用于无向图。
二阶邻近关系模型
对于每个节点,构造两个对应的向量,一个是节点的表达向量,一个是当节点被当成上下文时的表达向量(下面带撇的向量)。Vj节点出现在Vi节点的上下文的概率为
\[p _2 (v _j |v_ i ) ={\exp(\vec u'^T_j· \vec u_ i )\over \sum^ {|V |}_{k=1} \exp(\vec u'^T_k· \vec u_ i )} \]期望分布为 \(\hat p_ 2 (v_ j |v_ i ) ={w_{ij} \over d _i}, \ \ d_ i =\sum_{k∈N(i)} w _{ik}\)
归一化系数\(d_i\)定义为节点i的出度(出边权重之和)。
损失函数定义为:
\[O _2 =\sum_{i∈V}λ_ i d(\hat p_ 2 (·|v_ i ),p _2 (·|v_ i )) \]距离 d(·,·) 同样采用KL散度,增加了一个系数\(\lambda_i\)来增加节点的重要度,可以采用节点的出度或者PageRank算法的估计值。论文采用\(λ_ i = d_ i\).这个模型适用于有向/无向图。
一阶和二阶模型的套路和word2vec类似(sigmoid、softmax),\(O_2\)在计算条件概率时需要遍历所有的节点,优化起来比较困难,可以通过负采样的方式训练。模型如果直接通过SGD进行优化,边的权重具有较大的方差时梯度会比较发散,较大的权重的边可能造成梯度爆炸,学习率也因此难以选择。这个难优化问题的根源在于边有不等的权重,如果把训练时一个batch内的边设置成无权重的就容易训练了。具体的:将一个权重为w的边展开成w条无权重的边(比较占存储资源)或者以正比于权重的概率对边进行采样(Alias算法)。时间复杂度 \(\mathcal O(|E|)\).
一阶和二阶的模型可以分别看作是局部和全局网络结构的表征。
模型训练:对于无向图,将一阶和二阶模型分别训练,最后concat。或者交替优化、联合优化。
对于新加入的节点:若该顶点与图中顶点存在边相连,我们只需要固定其它节点的embedding,优化O1、O2两个目标之一即可。
LINE存在的问题
对于邻接点较少的节点,其embedding可能学习不充分,论文提到可以用邻居的邻居构造样本进行学习。如果仅考虑一阶和二阶相似性,对高阶信息的利用不足。
LINE 开源代码 C++,后已融入基于GPU-CPU混合架构的图表示学习框架 GraphVite。(Graphvite的代码只采用了二阶模型,支持有向、无向)
随后两篇同期的论文发表在KDD2016上,node2vec在 Deep Walk 基础上做扩展,而SDNE是在 LINE 基础上做扩展。
node2vec
node2vec — Grover et al:DFS + BFS
可以看作是deepwalk的一种扩展,是结合了DFS和BFS随机游走的deepwalk。通过调整随机游走权重来在 同质性(homophily) 和 结构性(structural equivalence) 中进行权衡。
设节点u的embedding为f(u),定义\(N_S(u)\) 为通过采样策略S采样出的 u 的近邻节点集合。
node2vec优化的目标是给定每个顶点条件下,令其近邻顶点(如何定义近邻顶点很重要)出现的概率最大。(是不是极大似然估计?)
\[\max_f\sum_{u∈V}\log Pr(N_ S (u)|f(u)) \]为使目标容易求解,做了两个假设:
-
条件独立性假设
给定源顶点下,其近邻顶点出现的概率与近邻集合中其余顶点无关(类似朴素贝叶斯):\(Pr(N_ S (u)|f(u))=\prod_{n_i\in N_S(u)} Pr(n_i|f(u))\).
-
特征空间对称性假设
一个顶点作为源顶点和作为近邻顶点的时候共享同一套embedding向量。(对比LINE中的2阶相似度,一个顶点作为源点和近邻点的时候是拥有不同的embedding向量的):\(Pr(n_i|f(u))={\exp(f(n_i)\cdot f(u)) \over \sum_{v\in V}\exp(f(v)\cdot f(u))}\).
node2vec依然采用随机游走的方式获取顶点的近邻序列,采用Skip-gram和负采样技术优化。但是node2vec采用了不同的随机游走策略,觉得DeepWalk那种纯随机的方式不太好。
node2vec采用的是一种有偏的随机游走,给定当前节点v,访问下一个节点x的转移概率为:
\[P(c _i = x | c_{i−1} = v) = \begin{cases} {π_{vx}\over Z} && \text{if } (v,x) ∈ E \\ 0 && \text{otherwise} \end{cases} \\ π _{vx} = α _{pq} (t,x) · w_{ vx} \\ α _{pq} (t,x) = \begin{cases} {1\over p} && \text{if } d_{tx} = 0 \\ 1 && \text{if } d_{tx} = 1 \\ {1\over q} && \text{if }d_{tx} = 2 \end{cases} \]其中\(w_{vx}\)是节点v 和 x 之间的边权,node2vec引入两个超参数:
- 返回参数 p :控制重复访问刚刚访问过的节点的概率。
- 内外向参数 q :控制着游走是靠近还是远离访问过的节点。
当p和q都是1的时候,等价于DeepWalk。
(效果图示,来自原论文)上图反应了同质性,下图反应了结构性。
node2vec在采样节点路径以及line中采样边的时候都用到了时间复杂度为\(\mathcal O(1)\)的离散事件抽样算法:Alias
算法,采样原理可参考:
开源实现:
python版:https://github.com/aditya-grover/node2vec 执行效率较低,使用了networkx包。
C++版:https://github.com/snap-stanford/snap/tree/master/examples/node2vec 在随机游走时采用了多线程,计算alias表未采用多线程。
以上的node2vec的开源实现采用alias算法提前计算好节点的转移概率,在节点数和边数较大时会比较耗时且比较耗费内存。工程上比较难优化一些。
node2vec与DeepWalk一样存在新节点加入时需要重新计算的问题,对应到推荐系统场景就是新物品的冷启动问题。 为了使“冷启动”的商品获得“合理”的初始Embedding,阿里团队通过引入了更多补充信息来丰富Embedding信息的来源,从而使没有历史行为记录的商品获得Embedding。参考后文对EGES的介绍。
Struc2Vec
2017 struc2vec:Learning Node Representations from Structural Identity.
Struc2Vec认为节点的embedding不应该考虑任何相邻性,而应只考虑节点的空间结构相似性。DeepWalk和node2vec等模型之所以有效,是因为现实世界中相邻的节点往往有比较相似的空间环境。
如果问题更加关注内容相似性(局部邻域相似性)那么可以选择node2vec,LINE,GraRep等模型;如果问题更加关注结构相似性,可以选择struc2vec。例子:蚂蚁金服风控模型使用struc2vec相比node2vec有质的提升,因为在风控领域,你可信并不能代表你的邻居可信(有些“大 V”节点的邻居众多),但是一个直观的感觉是,如果两个人在图中处于相似的地位(比如两个“大 V”),那么这两个人应该都可信或都不可信,并且一般来说这样两个人(节点)相距较远。
SDNE
Structural Deep Network Embedding
针对网络表示学习中的三大挑战:
- 高度非线性
- 结构的保留,重构网络信息不足(局部属性和全局属性难以全面表示)
- 稀疏性
解决办法:
- 浅层模型 --> 深层,增加非线性
- 同时利用一阶相似性和二阶相似性,一阶相似性作为监督信息保留局部结构信息,二阶通过AutoEncoder无监督进行重建保留全局。(半监督)
文档聚类的效果对比( t-SNE效果图):输入采用的是节点对的邻接矩阵,由于邻接矩阵往往是非常稀疏的,可以对自编码器重构损失函数添加一个权重,对非零元素的重构误差施加比零元素更重的惩罚。
\[\mathcal{L}=\sum_{i=1}^n{||\hat{x_i}-x_i||^2_2} \\ \Downarrow \\ \mathcal{L_{2nd}}=\sum_{i=1}^n||(\hat{x_i}-x_i)\odot{b_i}||^2_2=||(\hat{X}-X)\odot{B}||^2_F \]如果 \(s_{i,j} =0, b_{i,j} = 1\), 否则\(b _{i,j} = β > 1\).
解决网络构重构过程中邻接向量过于稀疏时(零元素个数远大于非零元素个数),这种做法比较常见。
一阶相似性采用了Laplacian Eigenmaps:希望相连的点在特征空间中尽可能靠近,\(s_{ij}\) 表示权重。
\[\mathcal L_{1st} = \sum_{i,j=1}^n s_{i,j}{\Vert {\hat y_i^{(K)}-y_j^{(K)}}}\Vert_2^2 = \sum_{i,j=1}^n s_{i,j}{\Vert {\hat y_i-y_j}}\Vert_2^2 \]联合损失函数:\(\mathcal{L_{mix}}=\mathcal{L_{2nd}+\alpha{\mathcal{L_{1st}}}}+\nu{\mathcal{L_{reg}}}\),其中 Lreg 是为了防止过拟合定义的 L2−norm 正则化。
文档聚类的效果对比( t-SNE效果图):
参考:《Structural Deep Network Embedding》---论文笔记
EGES
EGES(Enhanced Graph Embedding with Side Information), KDD2018 阿里。
属于工程实践型的论文。对用户的商品浏览序列做DeepWalk,通过引入side information解决冷启动问题。
对item 和 side information一起训练,使两者在同一个向量空间中,这样做运算会更有意义。
传统特征映射方法
Locally Linear Embedding (LLE)
LLE[2] 假设一个点的embedding是它邻居点的embedding的线性组合,用数学公式表示为 \(f(v_i) \approx \sum_{j} s_{ij}f(v_j)\)
最小化该点的映射和线性组合之间的距离,即
\[\phi(f) = \sum_i |f(v_i) - \sum_{j} s_{ij}f(v_j)|^2 \]参考:Locally linear embedding(LLE)局部线性嵌入(降维)
Laplacian Eigenmaps 拉普拉斯特征映射
Laplacian Eigenmaps[3] 是用局部的角度去构建数据之间的关系。如果两个数据实例i和j很相似,那么i和j在降维后目标子空间中应该尽量接近。它的直观思想是希望相互间有关系的点(在图中相连的点)在降维后的空间中尽可能的靠近。Laplacian Eigenmaps可以反映出数据内在的流形结构。
Laplacian Eigenmaps优化目标:希望相连的点在特征空间中尽可能靠近,\(s_{ij}\) 表示权重。
\[\phi(f) = \frac{1}{2} \sum_{i,j} (f(v_i) - f(v_j))^2s_{ij} \]参考:机器学习降维算法四:Laplacian Eigenmaps 拉普拉斯特征映射
python工具包:https://github.com/palash1992/GEM 包含 LLE 、Laplacian Eigenmaps、Graph Factorization、SDNE、node2ec 等实现。
评价指标
质量评估:
Link prediction:Mean Rank和Hits@10。
hit rate at given cutting off \(\ell\) (\(\text{Hit}@\ell\)):
\[\text{Hit}@\ell = \frac{1}{|\mathcal{V}|} \sum_{i \in \mathcal{V}} \textbf{1}(rank_{i, g_i} <= \ell) \]衡量与节点i相连的 ground truth 节点(\(g_i\) )排在top \(\ell\) 预测连接边的列表之中的数量,rank表示排列位置。
行业应用
- 滴滴车服营销中的个性化消息提醒,包括有券提醒和无券推送。滴滴智能客服助手里边的点击预测。
- 知乎基于收藏夹做内容推送,把收藏的内容当做节点,对热门内容进行降采样。还用于个性化推送、问答推荐。
- 阿里凑单算法,促进满减券的使用率。节点:商品,边:商品间同时购买的行为,权重:同时购买的比重,可以是购买次数、购买时间、金额等feature;
- 信息流推荐场景
参考:
开源框架
低成本的实现方式,三步走:
1、离线基于deepwalk算法生成序列;
2、fasttext或者word2vec训练得到embedding;
3、线上服务基于faiss做向量检索召回;
现有的开源框架可使我们快速入手,这里介绍执行速度较为优异的 GraphVite 与BigGraph。
GraphVite
graphvite 由LINE模型的作者团队主导,特性如下:
- CPU-GPU hybrid
- 支持 CUDA >= 9.2
- 支持模型:
- 节点表示学习:DeepWalk,LINE,node2vec;
- 知识图谱表示:TransE, DistMult, ComplEx, SimplE, RotatE, QuatE
- 支持对图和高维数据的 LargeVis 可视化
graphvite的输入格式参照这里是常规的edge list格式,节点可以用英文名称来表示(与BigGraph等框架类似),在配置文件中通过as_undirected: true可以设置为读取为有向边还是无向边。如果设置为无向边,输入数据中存在a->b那么不管是否存在b->a这行数据框架都会构造一条b->a的边。
保存的model对象是个EasyDict object
model=pickle.load(open('test.pkl', 'rb'))
model.keys()
# ['graph', 'solver']
'graph'中包含'id2name'与'name2id', 'solver'中包含'context_embeddings'、'vertex_embeddings',DeepWalk、node2vec、LINE模型的输出都有两个embedding,其它模型保存的model对象可能有些不同。'vertex_embeddings'是float32类型的numpy二维数组,通过 'id2name/name2id' 来对应到节点。
graphvite训练node2vec 68w节点,1000w边,消耗内存~128G,显存占用 2.7G,epoch设置为2000,Tesla M40机器上 10分钟训练完。比较耗内存的原因是node2vec的节点转移矩阵占用大量内存,如果用DeepWalk完全随机游走或者LINE则消耗内存很小。
BigGraph
PyTorch BigGraph(PBG)由Facebook开源,目标是使图形嵌入模型能够扩展到具有数十亿个节点和数万亿个边缘的graph。PBG通过启用四个基本构建块实现了这一目标:
- 图分区,这样模型就不必完全加载到内存中
- 每台机器上的多线程计算
- 跨多台机器的分布式执行,所有机器同时在图形的不相交部分上运行
- 批量负采样,允许处理>100万边/秒/机器,每边100负采样
参考论文 PyTorch-BigGraph: A Large-scale Graph Embedding Framework 。
PyTorch-BigGraph将输入数据中的每行的edge看做有向边,因此,如果要构成一幅无向图,需要构造两个方向的数据:a -> b
and b -> a
。参考 issues。
扩展
本文从word2vec训练的角度出发引出了几种经典的无监督图表示学习方法,通过这种学习方式能够得到节点的表示,进而实现分类、聚类、推荐等应用。一言以蔽之:Embedding is all you need。
但是这只是图表示的冰山一角,在和DeepWalk几乎一样的时间,Bordes等人提出了大名鼎鼎的TransE ,为知识图谱的分布式表示(Represent Learning for Knowledge Graph)奠定了基础。而图神经网络与图表示学习的发展历程也惊人地相似,并且研究热度日渐火热,比如GraphSAGE、GraphGAN。
TransE 多元关系数据嵌入
属于Knowledge Graph Embedding的范畴,
三元组(头实体h,关系r,尾实体t),如下图所示(图片来源):
TransE模型期望三元组的embedding向量(h,r,t)
满足公式:h+r=t
。
学出的模型适用于多种关系。但是 不适用于多对一
和一对多
关系的问题。以多对一关系为例,固定 r 和 t,TransE 模型为了满足三角闭包关系,训练出来的头节点的向量会很相似。
标签:DeepWalk,node2vec,Graph,随机,Embedding,游走,节点 来源: https://www.cnblogs.com/makefile/p/16391388.html