Node2Vec笔记

node2vec: Scalable Feature Learning for Networks

Github整理代码链接,欢迎讨论和交流,觉得有用的可以Star一下。

1.主要思想

       目的:是将图中的顶点映射到一个低维连续空间,并且能够保存图的空间结构。

       论文的主要亮点,设计了与Deepwalk不同的随机游走方式,每次随机游走会选择是进行宽度游走Breadth-first Sampling (BFS)还是深度游走Depth-first Sampling (DFS) ,如图1所示 。
       获得游走路径集合后,与Deepwalk类似使用Skip-Gram模型进行顶点的Embedding学习

图1 两种游走策略

2.流程

2.1 优化目标

       设 f ( u ) f(u) f(u)是将顶点 u u u映射为Embedding向量的映射函数, N s ( u ) N_{s}(u) Ns(u)为通过采样策略 S S S采样出的顶点 u u u的近邻顶点集合。

       将现有的Skip-gram模型扩展到网络中来,优化以下目标函数

       优化目标函数:给定一个顶点,令其近邻顶点出现的概率最大
max ⁡ f ∑ u ∈ V l o g P r ( N s ( u ) ∣ f ( u ) ) \mathop {\max }\limits_{f}\sum_{u\in V}logPr(N_s(u)|f(u)) fmaxuVlogPr(Ns(u)f(u))
      为了使公式1能够得到很好的优化求解,提出了两个假设:

      1.条件独立

      给定一个顶点,其近邻顶点出现的概率与近邻集合中的其他顶点无关,得到公式2:
P r ( N s ( u ) ∣ f ( u ) ) = ∏ n i ∈ N s ( u ) P r ( n i ∣ f ( u ) ) Pr(N_s(u)|f(u))=\prod_{n_i\in N_s(u)}Pr(n_i|f(u)) Pr(Ns(u)f(u))=niNs(u)Pr(nif(u))
      2.特征空间中的对称性

     源顶点和近邻顶点在特征空间中具有对称性,不管顶点是源顶点还是近邻点Embedding表达是一样的。(对比Line中的二阶相似度有所不同),得到公式3:
P r ( n i ∣ f ( u ) ) = e x p ( f ( n i ) ⋅ f ( u ) ) ∑ v ∈ V e x p ( f ( v ) ⋅ f ( u ) ) Pr(n_i|f(u))=\frac{exp(f(n_i)\cdot f(u))}{\sum_{v\in V}exp(f(v)\cdot f(u))} Pr(nif(u))=vVexp(f(v)f(u))exp(f(ni)f(u))
      根据以上两个假设条件,最终的目标函数公式1简化为公式4,由于 Z u = ∑ v ∈ V e x p ( f ( n i ) ⋅ f ( u ) ) Z_u=\sum_{v\in V}exp(f(n_i)\cdot f(u)) Zu=vVexp(f(ni)f(u))计算复杂度高,所以采用负采样近似优化
max ⁡ f ∑ u ∈ V [ − l o g Z u + ∑ n i ∈ N s ( u ) f ( n i ) ⋅ f ( u ) ] \mathop {\max }\limits_{f}\sum_{u\in V}[-logZ_u+\sum_{n_i\in N_s(u)}f(n_i)\cdot f(u)] fmaxuV[logZu+niNs(u)f(ni)f(u)]

2.2 采样策略

2.2.1 路径采样策略

      Node2vec依然延续了Deepwalk采用随机游走的方式获取顶点的近邻序列,Node2vec不同的是采用的是一种有偏的随机游走。

      给定当前顶点 v v v ,访问下一个顶点 x x x 的概率为公式5,其中 π v x \pi_{vx} πvx为顶点 v v v和顶点 x x x为归一化的转移概率, Z Z Z为一个常量,设 π v x = α p q ( t , x ) ⋅ w v x \pi_{vx}=\alpha_{pq}(t,x)\cdot w_{vx} πvx=αpq(t,x)wvx α p q ( t , x ) \alpha_{pq}(t,x) αpq(t,x) t t t x x x的游走策略生成的概率, w v x w_{vx} wvx是顶点 v v v和顶点 x x x之间的边权。
P ( c i = x ∣ c i − 1 = v ) = { π v x Z ( v , x ) ∈ V 0 ( v , x ) ∉ V P(c_i=x|c_{i-1}=v)=\left\{\begin{matrix} \frac{\pi_{vx}}{Z} &(v,x)\in V \\ 0 & (v,x)\notin V \end{matrix}\right. P(ci=xci1=v)={Zπvx0(v,x)V(v,x)/V
      Node2vec引入两个超参数 p p p q q q来控制随机游走的策略。如图2所示,假设当前随机游走顶点 t t t经过边 ( t , v ) (t,v) (t,v) 到达顶点 v v v,顶点 v v v的下一个访问顶点 x x x的概率根据公式6计算得到,公式6中 d t x d_{tx} dtx为下一个访问顶点 x x x和当前顶点 v v v的上一个顶点 t t t之间的距离
α p q ( t , x ) = { 1 p d t x = 0 1 d t x = 1 1 q d t x = 2 \alpha_{pq}(t,x)=\left\{\begin{matrix} \frac{1}{p}& d_{tx}=0 \\ 1&d_{tx}=1\\ \frac{1}{q}&d_{tx}=2 \end{matrix}\right. αpq(t,x)=p11q1dtx=0dtx=1dtx=2

图2 p和q参数示意
  • 返回参数 p p p
          仅作用于 d t x = 0 d_{tx}=0 dtx=0的情况,控制顶点 v v v重复访问上一步顶点的概率,如果 p p p较大,则下一步游走访问上一步顶点的概率越小,反之越大。
  • 输入输出参数 q q q
    仅作用于 d t x = 2 d_{tx}=2 dtx=2的情况,控制顶点 v v v随机游走下一步的游走策略类型,BFS和DFS
  1. Breadth-first Sampling (BFS)
    如果 q q q较大,则顶点 v v v下一步游走倾向于访问顶点 v v v上一步顶点近邻顶点,构成了宽度游走策略
  2. Depth-first Sampling (DFS)
    如果 q q q较小,则顶点 v v v下一步游走倾向于访问顶点 v v v上一步顶点距离远的顶点,构成了深度游走策略
2.2.2 顶点采样策略

      顶点采样策略区别于Deepwalk,不是随机采样顶点,使用Alias Sample方法进行采样。Alias Sample具体实现方式见Line论文整理3.3.4。本文中Alias Sample与Line中不同之处在于创建邻居顶点的Node Alias Sample Table,而Line中是创建的全局Node Alias Sample Table。

3.向量学习

      通过带策略的随机游走获得路径集合,根据所获得的路径集合,与Deepwalk类似使用Skip-Gram模型进行顶点的Embedding学习。具体Skip-Gram模型见Deepwalk论文整理。

4.代码实现和实验

4.1 游走策略代码

     Node2Vec中Edge Alias Sample根据公式6计算,给定一个顶点src,计算src的邻居顶点访问概率,为了在随机游走下一个顶点中使用;Node Alias Sample根据顶点的出度归一化生成概率计算得到

# _*_ coding: utf-8 _*_
"""
Time:     2020/9/9 17:50
Author:   Cheng Ding(Deeachain)
Version:  V 0.1
File:     node2vec.py
Describe: Write during the internship at Hikvison, Github link: https://github.com/Deeachain/GraphEmbeddings
"""
# Edge Alias Sample
def get_alias_edge(self, src, dst):
    '''
    Get the alias edge setup lists for a given edge.
    '''
    G = self.G
    p = self.p
    q = self.q

    unnormalized_probs = []
    for dst_nbr in sorted(G.neighbors(dst)):
        if dst_nbr == src:  # dx=0
            unnormalized_probs.append(G[dst][dst_nbr]['weight'] / p)
        elif G.has_edge(dst_nbr, src):  # dx=1
            unnormalized_probs.append(G[dst][dst_nbr]['weight'])
        else:  # dx=2
            unnormalized_probs.append(G[dst][dst_nbr]['weight'] / q)
    norm_const = sum(unnormalized_probs)
    normalized_probs = [float(u_prob) / norm_const for u_prob in unnormalized_probs]

    return alias_setup(normalized_probs)

'''
Node Alias Sample
'''
alias_nodes = {}
for node in G.nodes():
    unnormalized_probs = [G[node][nbr]['weight'] for nbr in sorted(G.neighbors(node))]
    norm_const = sum(unnormalized_probs)
    normalized_probs = [float(u_prob) / norm_const for u_prob in unnormalized_probs]
    alias_nodes[node] = alias_setup(normalized_probs)
  • 游走策略代码
# _*_ coding: utf-8 _*_
"""
Time:     2020/9/9 17:50
Author:   Cheng Ding(Deeachain)
Version:  V 0.1
File:     node2vec.py
Describe: Write during the internship at Hikvison, Github link: https://github.com/Deeachain/GraphEmbeddings
"""
def node2vec_walk(self, walk_length, start_node):

    G = self.G
    alias_nodes = self.alias_nodes
    alias_edges = self.alias_edges

    walk = [start_node]
    while len(walk) < walk_length:
        cur = walk[-1]
        cur_nbrs = list(G.neighbors(cur))
        if len(cur_nbrs) > 0:
            if len(walk) == 1:  # 路径中只有一个顶点时,从邻居顶点中根据边权生成概率,使用alias采样下一个顶点,不直接使用第二种情况采样的原因是为了构成采样策略
                walk.append(
                    cur_nbrs[alias_sample(alias_nodes[cur][0], alias_nodes[cur][1])])
            else:	# 路径中大于一个顶点时,根据邻居顶点p和q的采样策略生成概率,使用alias采样下一个顶点
                prev = walk[-2]
                edge = (prev, cur)
                next_node = cur_nbrs[alias_sample(alias_edges[edge][0],  
                                                  alias_edges[edge][1])]
                walk.append(next_node)
        else:
            break

    return walk
4.2 实验

        Node2Vec源码[1]中仅使用karate.edges数据集,该数据集是关于跆拳道俱乐部成员之间关系的社交网络,节点没有标签,作者源码没有复现原文中的数据集。整理代码采用了另外的三个公开数据集,分别是:Cora数据集由机器学习论文组成,总共有2708篇论文,应用关系有5429个,论文总共七类(基于案例、遗传算法、神经网络、概率方法、强化学习、规则学习、理论);DBLP数据集也是引文网络组成的图,只选用了4类;BlogCatalog数据集是Blog用户之间关系构成的社交网络,相关详细参数见表1

表1 整理代码使用数据集
数据集coradblpBlogCatalog
V27081772510312
E5429105781333983
Class7439

        实验参数:

  • Deepwalk:词向量维度 d = 128 d=128 d=128、每个顶点游走路径数 γ = 50 \gamma=50 γ=50、游走路径长度 t = 20 t=20 t=20 E p o c h = 5 Epoch=5 Epoch=5、SkipGram窗口大小 w = 10 w=10 w=10
  • Line:词向量维度 d = 128 d=128 d=128、二阶相似度生成128维词向量、 E p o c h = 150 Epoch=150 Epoch=150 l r = 0.005 lr=0.005 lr=0.005 n u m _ n e g a t i v e = 5 num\_negative=5 num_negative=5。(目前Line模型存在一定问题,不能复现论文效果。)
    1. Cora数据集有向图实验,一阶相似度:节点分类 f 1 = 0.44 f1=0.44 f1=0.44,可视化能区分一部分节点,;二阶相似度节点分类 f 1 = 0.52 f1=0.52 f1=0.52,,可视化能区分一部分节点
    2. COra数据集无向图实验,一阶相似度:节点分类 f 1 = 0.48 f1=0.48 f1=0.48,可视化能区分一部分节点,;二阶相似度节点分类 f 1 = 0.62 f1=0.62 f1=0.62,,可视化能区分一部分节点
  • Node2vec:词向量维度 d = 128 d=128 d=128、返回参数 p = 0.25 p=0.25 p=0.25、输入输出参数 q = 0.25 q=0.25 q=0.25 p 、 q ∈ ( 0.25 , 0.5 , 1 , 2 , 4 ) p、q\in ({0.25,0.5,1,2,4}) pq(0.25,0.5,1,2,4)文中实验证明 p p p q q q越小越好)、每个顶点游走路径数 γ = 50 \gamma=50 γ=50、游走路径长度 t = 20 t=20 t=20 E p o c h = 5 Epoch=5 Epoch=5、SkipGram窗口大小 w = 10 w=10 w=10

        Node2Vec通过带偏策略的游走得到路径集合,接着SkipGram模型学习顶点的Embedding,最后使用Embedding设计顶点分类任务。数据集划分80%的数据用于训练,20%用于评估,分类任务使用SVM分类,得到顶点的分类指标f1-score如表2所示。

表2 顶点分类f1-score指标
coradblp
Deepwalk(f1-micro)0.85420.8327
Line(f1-micro)0.62180.6262
Node2vec(f1-micro)0.85610.8386

        节点Embedding表达在空间维度上,相同类别的节点距离会越靠近,最后将学习得到的Embedding进行可视化展示。可视化使用的是TSNE实现,将向量降维到二维平面上。可视化效果如图3所示。

在这里插入图片描述
在这里插入图片描述

图3 Embedding可视化

参考和引用

[1]. 论文源码

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值