node2vec的一些理解

article/2025/11/6 20:44:16

node2vec

node2vec也是一种网络嵌入的表示方法,它是基于DeepWalk的基础上进行改进的。主要改进的地方在于它在随机游走的过程中加入了一个权重,使得游走可以采用深度优先和广度优先的策略进行游走。

Search bias α

使得随机游走产生片偏差的最简单的方法是根据静态边缘权重 W v x W_vx Wvx进行采样,在未加权图的情况下 W v x = 1 W_{vx}=1 Wvx=1,但是这并不能解释我们的网络结构,并且指导我们探索不同的网络邻居。此外,与BFS和DFS不同,BFS和DFS是分别适用于结构等价性和同质性的极端抽样范式,我们的随机游动应该适应这样一个事实:这些等价性的概念不是竞争的或排他的,而现实世界的网络通常表现出两者的混合。
所以我们定义了一个2阶随机游走,并且定义了两个参数分别是p和q用来指导我们进行随机游走。
search bias α
假设我们有一个随机游走已经穿过了(t,v)节点并且现在暂时居住在如图所示的V节点。我们现在要考虑下一步怎么走,那么我们可以使用边(v,x)的转移概率 Π v x Π_{vx} Πvx用来引导我们从v的下一步怎么走。我们假定了一个转移概率 Π v x = α p q ( t , x ) ∗ W v x Π_vx=α_{pq}(t,x)*W_{vx} Πvx=αpq(t,x)Wvx 其中 α p q ( t , x ) α_{pq}(t,x) αpq(t,x)定义如下:

其中 d t x d_{tx} dtx表示t和x之间的最短路径,注意的是 d t x d_{tx} dtx的取值一定是{0,1,2}的其中一个,所以p,q两个参数能够很好的指导游走。
例如当终点为t时,我们相当于往回走了,不为t时我们则是向外游走或是向深游走。
返回参数 p:p代表我们游走时重复游走的可能性,如果我们把p设置为一个很高的值(> max(q,1))则可以用来确保我们有极小的可能性重复游走一个节点(除非下一个节点没有其他邻居)。这个策略鼓励我们适度探索,而不是产生冗余。另一方面,如果我们把p的值设为很小(< min(q,1)),则他会使得walk接近我们的起始位置。
In-Out参数 q:他更倾向于访问距离节点t更远的节点,这种行为反映了鼓励向外探索的DFS。然而,这里的一个本质区别是,我们在随机行走框架中实现了类似DFS的探索。

node2vec 算法流程

node2vec算法流程
如上图所示,我们一开始主要是要进行我们的静态权重的赋值,用它来引导我们继续随机游走得到随机游走序列,然后我们将得到的序列利用skip-gram模型进行嵌入,最后得到嵌入矩阵。

    def _precompute_probabilities(self):"""Precomputes transition probabilities for each node."""d_graph = self.d_graphnodes_generator = self.graph.nodes() if self.quiet \else tqdm(self.graph.nodes(), desc='Computing transition probabilities')for source in nodes_generator:# Init probabilities dict for first travelif self.PROBABILITIES_KEY not in d_graph[source]:d_graph[source][self.PROBABILITIES_KEY] = dict()for current_node in self.graph.neighbors(source):# Init probabilities dictif self.PROBABILITIES_KEY not in d_graph[current_node]:d_graph[current_node][self.PROBABILITIES_KEY] = dict()unnormalized_weights = list()d_neighbors = list()# Calculate unnormalized weightsfor destination in self.graph.neighbors(current_node):p = self.sampling_strategy[current_node].get(self.P_KEY,self.p) if current_node in self.sampling_strategy else self.pq = self.sampling_strategy[current_node].get(self.Q_KEY,self.q) if current_node in self.sampling_strategy else self.qif destination == source:  # Backwards probabilityss_weight = self.graph[current_node][destination].get(self.weight_key, 1) * 1 / pelif destination in self.graph[source]:  # If the neighbor is connected to the sourcess_weight = self.graph[current_node][destination].get(self.weight_key, 1)else:ss_weight = self.graph[current_node][destination].get(self.weight_key, 1) * 1 / q# Assign the unnormalized sampling strategy weight, normalize during random walkunnormalized_weights.append(ss_weight)d_neighbors.append(destination)# Normalizeunnormalized_weights = np.array(unnormalized_weights)d_graph[current_node][self.PROBABILITIES_KEY][source] = unnormalized_weights / unnormalized_weights.sum()# Save neighborsd_graph[current_node][self.NEIGHBORS_KEY] = d_neighbors# Calculate first_travel weights for sourcefirst_travel_weights = []for destination in self.graph.neighbors(source):first_travel_weights.append(self.graph[source][destination].get(self.weight_key, 1))first_travel_weights = np.array(first_travel_weights)d_graph[source][self.FIRST_TRAVEL_KEY] = first_travel_weights / first_travel_weights.sum()

具体代码实现如图所示,我们首先进入函数利用d_graph生成一个字典,在其中加入概率标签,然后我们通过循环节点以及节点的邻居对权重进行赋值,同时对我们的p,q进行策略的更改。最后的d_graph则是我们修改之后的带有我们设置的权重的重要参数,然后我们将d_graph带入到我们的游走序列生成的函数当中去。

def parallel_generate_walks(d_graph: dict, global_walk_length: int, num_walks: int, cpu_num: int,sampling_strategy: dict = None, num_walks_key: str = None, walk_length_key: str = None,neighbors_key: str = None, probabilities_key: str = None, first_travel_key: str = None,quiet: bool = False) -> list:"""Generates the random walks which will be used as the skip-gram input.:return: List of walks. Each walk is a list of nodes."""walks = list()if not quiet:pbar = tqdm(total=num_walks, desc='Generating walks (CPU: {})'.format(cpu_num))for n_walk in range(num_walks):# Update progress barif not quiet:pbar.update(1)# Shuffle the nodesshuffled_nodes = list(d_graph.keys())random.shuffle(shuffled_nodes)# Start a random walk from every nodefor source in shuffled_nodes:# Skip nodes with specific num_walksif source in sampling_strategy and \num_walks_key in sampling_strategy[source] and \sampling_strategy[source][num_walks_key] <= n_walk:continue# Start walkwalk = [source]# Calculate walk lengthif source in sampling_strategy:walk_length = sampling_strategy[source].get(walk_length_key, global_walk_length)else:walk_length = global_walk_length# Perform walkwhile len(walk) < walk_length:walk_options = d_graph[walk[-1]].get(neighbors_key, None)# Skip dead end nodesif not walk_options:breakif len(walk) == 1:  # For the first stepprobabilities = d_graph[walk[-1]][first_travel_key]walk_to = np.random.choice(walk_options, size=1, p=probabilities)[0]else:probabilities = d_graph[walk[-1]][probabilities_key][walk[-2]]walk_to = np.random.choice(walk_options, size=1, p=probabilities)[0]walk.append(walk_to)walk = list(map(str, walk))  # Convert all to stringswalks.append(walk)if not quiet:pbar.close()return walks

生成游走的序列的代码如上图所示,我们可以看出将d_graph当中的概率取出,然后带入到np.random.choice这个函数当中去,这样我们就是按照一定的概率进行随机游走,而游走的概率是可以通过修改p,q两个参数进而进行修改的。最后我们则将我们得到的游走序列walks带入skip-gram模型进行训练,得到我们想要的嵌入矩阵。

    def fit(self, **skip_gram_params):"""Creates the embeddings using gensim's Word2Vec.:param skip_gram_params: Parameteres for gensim.models.Word2Vec - do not supply 'size' it is taken from the Node2Vec 'dimensions' parameter:type skip_gram_params: dict:return: A gensim word2vec model"""if 'workers' not in skip_gram_params:skip_gram_params['workers'] = self.workersif 'size' not in skip_gram_params:skip_gram_params['size'] = self.dimensionsreturn gensim.models.Word2Vec(self.walks, **skip_gram_params)

http://chatgpt.dhexx.cn/article/MoBAVVg7.shtml

相关文章

从word2vec到node2vec

word2vec 1. 什么是word2vec 在自然语言处理任务&#xff08;NLP&#xff09;中&#xff0c;最细粒度是词语&#xff0c;所以处理NLP问题&#xff0c;首先要处理好词语。 由于所有自然语言中的词语&#xff0c;都是人类的抽象总结&#xff0c;是符号形式的。而对于数学模型&a…

详解Node2vec以及优缺点

1. 论文介绍 首先介绍了复杂网络面对的几种任务&#xff1a; 网络节点的分类&#xff0c;通俗点说就是将网络中的节点进行聚类&#xff0c;我们关心的是哪些节点具有类似的属性&#xff0c;就将其分到同一个类别中。链接预测&#xff0c;就是预测网络中哪些顶点有潜在的关联。…

node2vec论文阅读

本文要阅读的论文来自数据挖掘领域的顶级会议KDD-2016. 论文介绍了一种Graph representation方法 得益于CNN以及Seq2seq等模型&#xff0c;深度学习在图像和自然语言处理等领域有很好的应用。然而在涉及到图&#xff08;有向图&#xff0c;无向图&#xff09;结构的应用比如社…

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

前面介绍过基于DFS邻域的DeepWalk和基于BFS邻域的LINE。 DeepWalk&#xff1a;算法原理&#xff0c;实现和应用 LINE&#xff1a;算法原理&#xff0c;实现和应用 node2vec是一种综合考虑DFS邻域和BFS邻域的graph embedding方法。简单来说&#xff0c;可以看作是eepwalk的一…

图与推荐系统(一):Graph Embedding之node2vec (原理 + 代码实战)

文章目录 一. 介绍二. 公式三. 代码细节四. 代码 一. 介绍 node2vec是一种综合考虑DFS邻域和BFS邻域的graph embedding方法。简单来说&#xff0c;可以看作是deepwalk的一种扩展&#xff0c;是结合了DFS和BFS随机游走的deepwalk。node2vec通过调整方向的参数来控制模型更倾向B…

图神经网络之Node2Vec详解

目录 背景传统算法存在的问题算法背景动机 算法随机序列的生成Node2Vec算法算法的具体流程&#xff1a; 总结相关资料 背景 传统算法存在的问题 一些方法中所提出的特征需要依赖人手工定义&#xff0c;这需要特定领域内专业人士来完成&#xff0c;而且依靠人手工定义特征的有…

node2vec算法

图嵌入算法 一、背景1.提出2.应用3.特点 二、DeepWalkRandomWalk 三、node2vec引言node2walkskip-gram(用中心词预测周围词) 一、背景 1.提出 ①使用邻接矩阵表示网络时&#xff0c;由于矩阵中大多数元素是0&#xff0c;难以体现节点间关系&#xff0c;同时数据的稀疏性使得计…

node2vec代码实现及详细解析

目录 前言1.数据导入2.node2vecWalk2.1 归一化转移概率2.1.1 原理解析2.1.2 Alias采样2.1.3 代码实现 2.2 node2vecWalk的实现 3.LearnFeatures4.参数选择5.完整代码 前言 在KDD 2016 | node2vec&#xff1a;Scalable Feature Learning for Networks 中我们详细讨论了node2vec…

Node2vec原理剖析,代码实现

DeepWalk原理介绍 与词嵌入类似&#xff0c;图嵌入基本理念是基于相邻顶点的关系&#xff0c;将目的顶点映射为稠密向量&#xff0c;以数值化的方式表达图中的信息&#xff0c;以便在下游任务中运用。 Word2Vec根据词与词的共现关系学习向量的表示&#xff0c;DeepWalk受其启…

Python(Pycharm)常用快捷键

1. Pycharm一键给所有代码加# CtrlA或者Ctrl/ 2. Pycharm格式化代码快捷键&#xff08;即标准化&#xff09; CtrlAltL 【注】qq也可能有此快捷键&#xff0c;把qq删掉就行 其实改掉Pycharm的里面的设置也可以&#xff08;这样就不会冲突了&#xff09; add keyboard shor…

python 中常见的快捷方式

相信大家在写代码的时候经常会用到快捷键&#xff0c;这不仅使编写代码的效率提高不少&#xff0c;还能装 X...下面整理了部分常见快捷键&#xff0c;后期会接着更新。废话不多说&#xff1a; 1.ctrlshiftA:万能命令行 可以新建一个python文件 2. shift两次:查看资源文件 3…

python的快捷键总结

电脑是解决众多问题的工具&#xff0c;尤其对于程序员而言&#xff0c;拥有一套快捷方式&#xff0c;在编程时&#xff0c;可以事半功倍&#xff0c;从而高效地完成工作任务&#xff0c;今天就带来一套快捷方式&#xff0c;仅供大家参考&#xff1a; 常见快捷方式&#xff1a; …

Python快捷键

1.注释(添加/消除)(Ctrl /) 这里说下Python的单行注释是 # , 多行注释是 注释内容 , java的单行注释是 // , 多行注释 /* 注释内容 */, 文档注释 /** 注释内容 */ 这里说的注释快捷键主要用于多行注释, 当你想把一段代码暂时注释掉的时候, 可以直接选中这段代码, 利用此快…

python 常用快捷键和设置

pycharm常用快捷键 转载自 大哥 1、编辑&#xff08;Editing&#xff09; Ctrl Space 基本的代码完成&#xff08;类、方法、属性&#xff09; Ctrl Alt Space 快速导入任意类 Ctrl Shift Enter 语句完成 Ctrl P 参数信息&#xff08;在方法中调用参数&#…

Python常用快捷键整理

Python常用快捷键整理 文章目录 Python常用快捷键整理一、注释二、删除三、格式四、 查看其它1. 代码自动整理 本文列举了常用的快捷键&#xff0c;暂时刚入门&#xff0c;还没有写太多&#xff0c;如有不足之处还请多多指教。 一、注释 行注释/取消行注释: Ctrl / 多行注释&…

python常用快捷键

一、编辑&#xff08;Editing&#xff09; Ctrl Space 基本的代码完成&#xff08;类、方法、属性&#xff09; Ctrl Alt Space 快速导入任意类 Ctrl Shift Enter 语句完成 Ctrl P 参数信息&#xff08;在方法中调用参数&#xff09; Ctrl Q 快速查看文档 F1 外部文档 S…

python常用快捷键,写代码事半功倍

今天就为大家带来一篇Python常用快捷键。觉得挺不错的&#xff0c;现在就分享给大家&#xff0c;也给大家做个参考。 最重要的快捷键 ctrlshiftA:万能命令行shift两次:查看资源文件 新建工程第一步操作 module设置把空包分层去掉,compact empty middle package设置当前的工…

OSGB数据的纹理压缩

运行环境 OSG3.4.1 VS2017 对osgb数据的压缩关键在于纹理的压缩&#xff0c;即可在writeNodeFIie方法中进行操作。 osgDB::writeNodeFile(*rootNode, f_path, new osgDB::Options("WriteImageHintIncludeFile"));osg老版本中的 writeImageHintIncludeFile 有缺陷(…

unity 加载倾斜摄影-C#解析osgb(一)

下载 https://download.csdn.net/download/WantFK/87009338https://download.csdn.net/download/WantFK/87009338 1.提取osgb的图片信息\mesh顶点 \UV\ 三角序列\下一级name\bounds\视距 和保存 &#xff08;提取 目的 解析osgb的流程过于麻烦 真正用地到的就这几个数据 2.un…

osg加载osgb数据_PCM点云数据处理软件功能使用第十六弹

好久不见!今日为大家带来PCM点云数据处理软件功能使用第十六弹——建筑物应用,快跟小编一起学习吧! 该菜单包含两个建筑物应用模块:建筑点云提取、建筑简易模型一 建筑点云提取 建筑物点云提取输入数据为原始点云文件和地面文件,利用法向量对非地面点进行建筑物墙面点云检…