【Graph Embedding】LINE的原理、核心代码及其应用

LINE基本思想

LINE: Large-scale Information Network Embedding与DeepWalk相似都是基于领域相似假设的方法,DeepWalk是基于深度优先搜索,LINE是基于广度优先搜索。LINE还可以应用在带权图中(DeepWalk仅能用于无权图)。不同graph embedding方法之间的一个主要区别是图中顶点之间的相似度的定义不同,在LINE中有两种相似度的定义方法。

如下图:

在这里插入图片描述

图中的边可以是有向的也可以是无向的,或者是带权边。顶点6和顶点7之间的边权重较重,他们在低维空间内的表示向量应该是相似的。但当两个顶点之间不存在边时,如顶点5和顶点6,并不能说二者之间没有关系,因为顶点5和顶点6具有相同的邻接顶点(顶点1,2,3,4)。这就是LINE的两种相似度的基本思想。

LINE是基于顶点之间的相似度进行建模,第一步将顶点Embedding到指定维度,利用Embedding的表示向量计算顶点A与顶点B之间的相似度,让相似度去拟合顶点A,B 之间的边的权重,得到最优的顶点的嵌入向量

一阶相似度

一阶相似度用于描述图中成对顶点之间的局部相似度,即只有当边与边之间存在连接时,顶点之间才有相似度,相似度与边之间的权重成正比,图中的顶点6,7 权重较大,相似度为1。顶点5和顶点6之间不存在边,相似度为0。

优化目标

假设用 u i , u j u_i,u_j ui,uj作为节点的低维向量表示,对于每一条无向边 ( i , j ) (i,j) (i,j),顶点 u i , u j u_i,u_j ui,uj之间的联合概率密度为:
p 1 ( v i , v j ) = 1 1 + e x p ( − u i T ⋅ u j ) p_1(v_i,v_j) = \frac{1}{1+exp(-u_i^T \cdot u_j)} p1(vi,vj)=1+exp(uiTuj)1
若两个向量相似,则 p ( v i , v j ) p(v_i,v_j) p(vi,vj)也较大。

同时,两节点之间的经验概率如下:
p ^ 1 ( i , j ) = w i j W W = ∑ ( i , j ) ∈ E w i j \hat p_1(i,j) = \frac{w_{ij}}{W} \\ W = \sum_{(i,j) \in E} w_{ij} p^1(i,j)=WwijW=(i,j)Ewij
其中, w i j w_{ij} wij是节点 v j 和 v j v_j和v_j vjvj之间的权重。W是节点 i , j i,j i,j的所有边的权重之和。

优化目标是最小化 p ( v i , v j ) 、 p ^ 1 ( i , j ) p(v_i,v_j)、\hat p_1(i,j) p(vi,vj)p^1(i,j)之间的分布距离,即最小化下式:
O 1 = d ( p ( v i , v j ) , p ^ 1 ( i , j ) ) O_1 = d(p(v_i,v_j),\hat p_1(i,j)) O1=d(p(vi,vj),p^1(i,j))
其中, d ( , ) d(,) d(,)是两个分布之间的距离。这与KL散度的功能一样。

补充:KL散度是一种量化两种概率分布P和Q之间差异的方式,数学公式:
D K L ( p ∣ ∣ q ) = ∑ i = 1 N p ( x i ) log ⁡ p ( x i ) q ( x i ) D_{KL}(p||q) = \sum_{i=1}^N p(x_i)\log \frac{p(x_i)}{q(x_i)} DKL(pq)=i=1Np(xi)logq(xi)p(xi)
所以,忽略常数项,我们得到以下的等效优化函数:
O 1 = − ∑ ( i , j ) ∈ E w i j l o g ( p 1 ( v i , v j ) ) O_1 = -\sum_{(i,j)\in E}w_{ij}log\big(p_1(v_i, v_j)\big) O1=(i,j)Ewijlog(p1(vi,vj))
一阶相似度的优化目标就是最小化 O 1 O_1 O1。从这个过程看出,一阶相似度只能用于描述无向图

二阶相似度

二阶相似度描述的是顶点与领域的关系,两个顶点之间不存在边,即一阶相似度为0时,若,这两个顶点之间存在公共的邻接顶点(顶点5,6),这二者具有二阶相似度。因此,对于每一个顶点都有两个向量,一个是顶点本身的表示向量,一个是该顶点作为其他顶点邻居时的表示向量,我们称之为上下文的向量表示。

回顾一阶相似度的思想:通过sigmoid函数两个节点的向量内积转换为概率来拟合两个节点边的权重。而在二阶相似度中,则需要表示当前节点与周围多个节点的相似度,所以节点 v i v_i vi产生节点 v j v_j vj的概率为:
p 2 ( v j ∣ v i ) = e x p ( u j ′ T ⋅ u i ) ∑ k = 1 ∣ V ∣ e x p ( u k ′ T ⋅ u i ) p_2(v_j|v_i) = \frac{exp(u_j^{'T}\cdot u_i)}{\sum_{k=1}^{|V|}exp(u_k^{'T}\cdot u_i)} p2(vjvi)=k=1Vexp(ukTui)exp(ujTui)
其中, u i , u j ′ u_i, u_j' ui,uj 为节点 i , j i, j i,j 低维向量表示,且 u j ′ u'_j uj 为节点 j 表示为上下文时的向量表示。 ∣ V ∣ |V| V 表示图中所有节点的个数或者节点 i i i的邻接节点的个数。

此时,经验分布为:
p ^ 2 ( v j ∣ v i ) = w i j d i \hat p_2(v_j|v_i)=\frac{w_{ij}}{d_i} p^2(vjvi)=diwij
其中, w i j w_{ij} wij 是边 ( i , j ) (i, j) (i,j) 的权重, d i = ∑ k ∈ N ( i ) w i k d_i = \sum_{k\in N(i)} w_{ik} di=kN(i)wik N ( i ) N(i) N(i) 为与节点 i i i 相连的邻居节点(有向图中是以节点 i i i为起点的所有节点)集合。对于无权图而言, d i d_i di 是节点 v i v_i vi 的出度。

同样用KL散度来衡量二者之间的关系,所以,忽略常数项,我们得到以下的等效优化函数:
O 2 = − ∑ ( i , j ) ∈ E w i j l o g ( p 2 ( v j ∣ v i ) ) O_2 = -\sum_{(i,j)\in E}w_{ij}log\big(p_2(v_j| v_i)\big) O2=(i,j)Ewijlog(p2(vjvi))

在Graph Embedding方法中,例如DeepWalk、Node2Vec、EGES,都是采用随机游走的方式来生成序列再做训练,而LINE直接用边来构造样本,这也是他们的一点区别。

优化技巧

负采样

计算二阶相似度时,softmax 函数的分母计算需要遍历所有顶点,计算量太大了,论文采用了与 word2vec 论文类似的负采样优化的技巧,对边进行抽样生成负样本,每条边被抽中的概率为边的权重。

边采样

从上面的公式可以看到,每个样本都有一个权重 w i j w_{ij} wij,有的样本w很高,有的样本w很低。在进行反向传播的时候,如果学习率过高,会导致w很大的样本梯度爆炸,如果学习率设置很小,会导致w很低的样本训练缓慢。为了解决这个问题,文中提出了边缘采样(Edge Sampling)的方法,将所有样本的系数都置为1,对图中的边重复采样来构造多个相同的正样本,采样率与权重 w i j w_{ij} wij 成正比。

核心代码

论文中的实现是把一阶相似度和二阶相似度融合到了一起,可以通过order进行控制。

使用负采样后的loss函数

def line_loss(y_true, y_pred):
    return -K.mean(K.log(K.sigmoid(y_true*y_pred)))

模型代码:


def create_model(numNodes, embedding_size, order='second'):

    # 声明变量
    v_i = Input(shape=(1,))
    v_j = Input(shape=(1,))

    first_emb = Embedding(numNodes, embedding_size, name='first_emb')
    second_emb = Embedding(numNodes, embedding_size, name='second_emb')
    context_emb = Embedding(numNodes, embedding_size, name='context_emb')

    v_i_emb = first_emb(v_i)
    v_j_emb = first_emb(v_j)

    v_i_emb_second = second_emb(v_i)
    v_j_context_emb = context_emb(v_j)

    # 计算相似度
    first = Lambda(lambda x: tf.reduce_sum(
        x[0]*x[1], axis=-1, keep_dims=False), name='first_order')([v_i_emb, v_j_emb])
    second = Lambda(lambda x: tf.reduce_sum(
        x[0]*x[1], axis=-1, keep_dims=False), name='second_order')([v_i_emb_second, v_j_context_emb])

    if order == 'first':
        output_list = [first]
    elif order == 'second':
        output_list = [second]
    else:
        output_list = [first, second]

    model = Model(inputs=[v_i, v_j], outputs=output_list)

库实现

使用github库实现:https://github.com/shenweichen/GraphEmbedding

将项目clone到本地,依次执行:

python setup.py install
cd examples
python deepwalk_wiki.py

然后,即可通过下面代码实现LINE:

G = nx.read_edgelist('../data/wiki/Wiki_edgelist.txt',create_using=nx.DiGraph(),nodetype=None,data=[('weight',int)])#read graph

model = LINE(G,embedding_size=128,order='second') #init model,order can be ['first','second','all']
model.train(batch_size=1024,epochs=50,verbose=2)# train model
embeddings = model.get_embeddings()# get embedding vectors

参考:

LINE: Large-scale Information Network Embedding

【图嵌入】Graph Embedding 方法之 LINE 原理解读

【Graph Embedding】LINE:算法原理,实现和应用

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值