这篇博客主要参考了唐建在2015年WWW会议上的论文《LINE: Large-scale Information Network Embedding》。这篇论文也是我2017年7月份在MSRA实习的时候通过微软内部的技术分享听到的,当时也是唐建本人直接讲的,话不多说开始直接讲模型。
正如题目所说的,line这个模型就是把一个大型网络中的节点根据其关系的疏密程度映射到向量空间中去,使联系紧密的节点被投射到相似的位置中去,而在网络中衡量两个节点联系紧密程度一个重要的指标就是这两个节点之间边的权值。在这篇文章中作者在建模的时候不仅仅只考虑了一阶的关系,即两个点之间直接有较大权值的边相连就认为它们比较相似;同时考虑了二阶关系,即两个点也许不直接相连,但是如果它们的一阶公共好友比较多那么它们也被认为是比较相似的。基于这两个角度的思考,作者提出了两个模型。
Model 1:Line with First-order Proximity
该模型只适用于无向图,对于一条无向边(i,j),那么定义该边的两个端点viv_ivi和vjv_jvj的共享概率如下:
p1(vi,vj)=11+exp(−uiT.uj)p_1(v_i,v_j)=\frac{1}{1+exp(-u_i^T.u_j)}p1(vi,vj)=1+exp(−uiT.uj)1其中uiu_iui和uju_juj就是点i和j的向量化表示形式,这个相当于从Embedding的角度来描述点之间的亲密程度。那么实际上从网络的结构数据也能得到关于两个点亲密程度的度量,p2(vi,vj)=wijWp_2(v_i,v_j)=\frac{w_{ij}}{W}p2(vi,vj)=Wwij,其中wijw_{ij}wij代表了点i和j之间的边的权值,W代表了网络中所有边权值的和。我们希望的优化目标就是分布p1p_1p1和p2p_2p2差异性越小越好,即目标函数如下所示:
O=d(p1,p2)O=d(p_1,p_2)O=d(p1,p2),这个d()d()d()函数用来衡量两个分布之间的差异性,一般可以选用KL散度,将KL散度带入上式再去掉一些固定项,就可以得到最终的优化形式:O=−∑(i,j)∈Ewijlogp1(vi,vj)O=-\sum_{(i,j)\in E}w_{ij}logp_1(v_i,v_j)O=−∑(i,j)∈Ewijlogp1(vi,vj)。
Model 2:Line with Second-order Proximity
从名字上就可以看出这个模型考虑节点之间二阶关系的影响,这个模型适合在有向图中使用,(对于无向图,可以通过把一个无向边复制成两个有向边,进行转换)。既然是有向图,一个节点在一条边的关系中就可能作为出度点和入度点这两种角色(分别是u和t),那么既然有两种不同的角色,作者就给每一个节点两个词向量,分别对应其两种不同的功能。比方说对于一条有向边(i,j)(指的是从i指向j)
p1(vj∣vi)=exp(tj.ui)∑k=1∣v∣exp(tk.ui)p_1(v_j|v_i)=\frac{exp(t_j.u_i)}{\sum_{k=1}^{|v|}exp(t_k.u_i)}p1(vj∣vi)=∑k=1∣v∣exp(tk.ui)exp(tj.ui) 。实际上从网络结构本身出发,这两个点之间的亲密程度可以按照该式衡量:p2(vj∣vi)=wijdip_2(v_j|v_i)=\frac{w_{ij}}{d_i}p2(vj∣vi)=diwij,而did_idi是节点iii的重要程度即di=∑k∈N(i)wikd_i=\sum_{k \in N(i)}w_{ik}di=∑k∈N(i)wik,同样为了使分布p1p_1p1和p2p_2p2的差异性最小化,需要优化该式:O=∑i∈Vαid(p1,p2)O=\sum_{i \in V}\alpha_id(p_1,p_2)O=∑i∈Vαid(p1,p2)其中αi\alpha_iαi代表了点i的权重,这里直接采用点i的di重要程度d_i重要程度di重要程度进行表示(其实也可以采用pagerank算法进行计算),将其带入可以得到最终优化的式子如下:
O=−∑(i,j)∈Ewijlogp1(vj∣vi)O=-\sum_{(i,j)\in E}w_{ij}logp_1(v_j|v_i)O=−∑(i,j)∈Ewijlogp1(vj∣vi)
整个模型其实已经讲解完了,如果为了使网络同时保持一阶和二阶的信息,一种最简单的方式就是把model1和model2生成的向量进行拼接。其实最佳的方式应该是一阶和二阶进行联合训练,这也是作者的未来工作。
在模型具体的训练优化方面,作者也给出了一些参考建议,非常值得去学习:
1 在训练model2的时候,观察式子p1(vj∣vi)=exp(tj.ui)∑k=1∣v∣exp(tk.ui)p_1(v_j|v_i)=\frac{exp(t_j.u_i)}{\sum_{k=1}^{|v|}exp(t_k.u_i)}p1(vj∣vi)=∑k=1∣v∣exp(tk.ui)exp(tj.ui)就会发现分母会遍历整个网络中的所有节点,会发现会有较大的复杂度,为了简化这个问题,作者采取了和word2vec中类似的策略——negative-sampling,即把一个多分类问题转化为几个二分类的问题,分子上的节点作为正样本,然后按照一定的概率进行采样网络中的其他节点作为负样本,这样就可以大大降低了复杂度,相对于对于p1(vj∣vi)p_1(v_j|v_i)p1(vj∣vi)的计算公式就变成了如下的形式logσ(tj.ui)+∑z=1Klogσ(−tz.ui)log \sigma(t_j.u_i)+\sum_{z=1}^K log\sigma(-t_z.u_i)logσ(tj.ui)+∑z=1Klogσ(−tz.ui),其中的参数K即负采样样本的个数,是一个提前需要设置的一个数值。
2 在对model2中目标函数进行求解优化的时候,当对uiu_iui求偏导的时候,其形式如下所示:
∂O∂ui=wij.∂logp1(vj∣vi)∂ui\frac{\partial{O}}{\partial{u_i}}=w_{ij}.\frac{\partial{log p_1(v_j|v_i)}}{\partial{u_i}}∂ui∂O=wij.∂ui∂logp1(vj∣vi),很显然会发现求导的结果中会有一个系数wijw_{ij}wij,这个系数就是两个点之间的边的权重,由于不同边的权值差别会非常大,因此这个系数的值也会差别很大,这样就给优化带来了很大的困难,主要是在选择训练速率上。如果为了照顾拥有较小的权值的那些点而选择比较大的速率,可能导致拥有较大权值的那些点步长过大;同样如果为了照顾拥有较大的权值的那些点而选择比较小的速率,可能导致拥有较小权值的那些点步长过小,导致训练不充分。因此作者在这里采用了一个非常巧妙的训练方式,首先把每一条边都看成是无权值的,即省略公式中的系数wijw_{ij}wij,然后通过采样从中挑选一些边来进行优化,每一条边被选中的概率和其边的权值成正比,这样拥有较大边权的边会有更大的概率被选中,也就会被优化更多次。
(PS:在2017年在北邮举办的Google开发者节上,一位来自北大的同学使用Tensorflow实现了Line的代码,这里给出网址希望大家多多学习:https://github.com/snowkylin/line)